diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..191381ee --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.git \ No newline at end of file diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md deleted file mode 100644 index 1165dd4e..00000000 --- a/.github/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at neuhart.julien@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index 624d84f8..00000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,39 +0,0 @@ -# Contributing - -Hi! Thank you for considering contributing to Gotenberg. You'll -find below useful information about how to contribute to the Gotenberg project. - -## Contributing code - -### Install from sources - -1. Install and run the latest version of Docker -2. Verify your Go version (>= 1.14) -3. Fork this repository -4. Clone it outside of your `GOPATH` (we're using Go modules) - -### Working with git - -1. Create your feature branch (`git checkout -b my-new-feature`) -2. Commit your changes (`git commit -am 'Add some feature'`) -3. Push to the branch (`git push origin my-new-feature`) -4. Create a new pull request - -### Testing - -1. Run all linters (`make lint`) -2. Run all tests (`make tests`) - -## Reporting bugs and feature request - -Your issue or feature request may already be reported! -Please search on the [issue tracker](../../../issues) before creating one. - -If you do not find any relevant issue or feature request, feel free to -add a new one! - -## Additional resources - -* [Code of conduct](CODE_OF_CONDUCT.md) -* [Issue template](ISSUE_TEMPLATE.md) -* [Pull request template](PULL_REQUEST_TEMPLATE.md) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index fe595d44..00000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,35 +0,0 @@ -Your issue may already be reported! -Please search on the [issue tracker](../../../issues) before creating one. - -## Expected Behavior - - - -## Current Behavior - - - -## Possible Solution - - - -## Steps to Reproduce (for bugs) - - -1. -2. -3. -4. - -## Logs (LOG_LEVEL="DEBUG") - - -## Context - - - -## Your Environment - -* Version used: -* Operating System and version: -* Link to your project: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index e768c49b..00000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,45 +0,0 @@ -A similar PR may already be submitted! -Please search among the [pull requests](../../../pulls) before creating one. - -Thanks for submitting a pull request! Please provide enough information so that others can review your pull request: - -For more information, see the [CONTRIBUTING](CONTRIBUTING.md) guide. - -**Summary** - - - -This PR fixes/implements the following **bugs/features** - -* [ ] Bug 1 -* [ ] Bug 2 -* [ ] Feature 1 -* [ ] Feature 2 -* [ ] Breaking changes - - - -Explain the **motivation** for making this change. What existing problem does the pull request solve? - - - -**Test plan (required)** - -Demonstrate the code is solid. Example: The exact commands you ran and their output. - - - -**Closing issues** - - -Fixes # - -**Checklist** - -- [ ] Have you followed the guidelines in our [CONTRIBUTING](CONTRIBUTING.md) guide? -- [ ] Have you lint your code locally prior to submission (`make lint`)? -- [ ] Have you written new tests for your core changes, as applicable? -- [ ] Have you successfully ran tests with your changes locally (`make tests`)? -- [ ] Have you updated the documentation (Markdown files under `build > docs > content` and then `make doc`)? -- [ ] I have squashed any insignificant commits -- [ ] This change has comments for package types, values, functions, and non-obvious lines of code diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 1fa95085..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: 2 -updates: -- package-ecosystem: gomod - directory: "/" - schedule: - interval: daily - time: "04:00" - open-pull-requests-limit: 10 - ignore: - - dependency-name: github.com/microcosm-cc/bluemonday - versions: - - 1.0.4 - - 1.0.5 - - 1.0.6 - - 1.0.7 - - 1.0.8 - - dependency-name: golang.org/x/text - versions: - - 0.3.5 - - dependency-name: github.com/labstack/echo/v4 - versions: - - 4.1.17 - - 4.2.0 - - 4.2.1 - - dependency-name: github.com/sirupsen/logrus - versions: - - 1.7.0 - - 1.7.1 - - 1.8.0 - - dependency-name: github.com/mafredri/cdp - versions: - - 0.30.0 diff --git a/.github/workflows/continuous_delivery.yml b/.github/workflows/continuous_delivery.yml new file mode 100644 index 00000000..7f7b44ee --- /dev/null +++ b/.github/workflows/continuous_delivery.yml @@ -0,0 +1,27 @@ +name: Continuous Delivery + +on: + release: + types: [ published ] + +jobs: + + release: + name: Release Docker image + runs-on: ubuntu-latest + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Checkout source code + uses: actions/checkout@v2 + - name: Log in to Docker Hub Container Registry + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push Docker image + run: | + make release GOTENBERG_VERSION=${{ github.event.release.tag_name }} + make release GOTENBERG_VERSION=${{ github.event.release.tag_name }} DOCKER_REGISTRY=thecodingmachine diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml new file mode 100644 index 00000000..e130c413 --- /dev/null +++ b/.github/workflows/continuous_integration.yml @@ -0,0 +1,43 @@ +name: Continuous Integration + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v2 + - name: Run linters + uses: golangci/golangci-lint-action@v2 + with: + version: v1.39 + + tests: + needs: + - Lint + name: Tests + # TODO: once arm64 actions are available, also run the tests on this architecture. + # See: https://github.com/actions/virtual-environments/issues/2552#issuecomment-771478000. + runs-on: ubuntu-latest + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Checkout source code + uses: actions/checkout@v2 + - name: Build testing environment + run: make build build-tests + - name: Run tests + run: | + make tests-once + bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/.github/workflows/tests_maybe_release.yml b/.github/workflows/tests_maybe_release.yml deleted file mode 100644 index b562239a..00000000 --- a/.github/workflows/tests_maybe_release.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: tests_maybe_release - -on: - push: - pull_request: - release: - types: [published] - -jobs: - tests_maybe_release: - runs-on: ubuntu-latest - steps: - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - uses: actions/checkout@v1 - - name: Lint code - run: make lint - - name: Run tests - run: | - make tests CODE_COVERAGE=1 - bash <(curl -s https://codecov.io/bash) - - name: Release - if: ${{ github.event_name == 'release' }} - run: make publish VERSION=${{ github.event.release.tag_name }} DOCKER_USER=${{ secrets.DOCKER_USER }} DOCKER_PASSWORD=${{ secrets.DOCKER_PASSWORD }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c56ae0d..24fd0f00 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -.idea -coverage.txt \ No newline at end of file +/coverage.html +/coverage.txt \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..db948573 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,30 @@ +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - errcheck + - gofmt + - goimports + - gosec + - gosimple + - govet + - ineffassign + - misspell + - prealloc + - staticcheck + - structcheck + - typecheck + - unconvert + - unused + - varcheck + +run: + deadline: 5m + issues-exit-code: 1 + tests: false + +output: + format: 'colored-line-number' + print-issued-lines: true + print-linter-name: true \ No newline at end of file diff --git a/LICENSE b/LICENSE index b756c5a5..cc678f87 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 TheCodingMachine +Copyright (c) 2021 Julien Neuhart 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/Makefile b/Makefile index 4478b495..3d2203fb 100644 --- a/Makefile +++ b/Makefile @@ -1,66 +1,133 @@ -GOLANG_VERSION=1.14 -VERSION=snapshot -DOCKER_USER= -DOCKER_PASSWORD= -DOCKER_REGISTRY=thecodingmachine +.PHONY: help +help: ## Show the help + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: it +it: build build-tests ## Initialize the development environment + +GOLANG_VERSION=1.16 +DOCKER_REGISTRY=gotenberg +GOTENBERG_VERSION=snapshot GOTENBERG_USER_GID=1001 GOTENBERG_USER_UID=1001 -GOLANGCI_LINT_VERSION=1.27.0 -CODE_COVERAGE=0 -TINI_VERSION=0.19.0 -MAXIMUM_WAIT_TIMEOUT=30.0 -MAXIMUM_WAIT_DELAY=10.0 -MAXIMUM_WEBHOOK_URL_TIMEOUT=30.0 -DEFAULT_WAIT_TIMEOUT=10.0 -DEFAULT_WEBHOOK_URL_TIMEOUT=10.0 -DEFAULT_LISTEN_PORT=3000 -DISABLE_GOOGLE_CHROME=0 -DISABLE_UNOCONV=0 -LOG_LEVEL=INFO -ROOT_PATH=/ -DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE=1048576 -GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS=0 +PDFTK_VERSION=1353200058 # See https://gitlab.com/pdftk-java/pdftk/-/releases - Binary package. +GOLANGCI_LINT_VERSION=v1.39.0 # See https://github.com/golangci/golangci-lint/releases. -# build the base Docker image. -base: - docker build --build-arg GOTENBERG_USER_GID=$(GOTENBERG_USER_GID) --build-arg GOTENBERG_USER_UID=$(GOTENBERG_USER_UID) -t $(DOCKER_REGISTRY)/gotenberg:base -f build/base/Dockerfile . +.PHONY: build +build: ## Build the Gotenberg's Docker image + docker build \ + --build-arg GOLANG_VERSION=$(GOLANG_VERSION) \ + --build-arg GOTENBERG_VERSION=$(GOTENBERG_VERSION) \ + --build-arg GOTENBERG_USER_GID=$(GOTENBERG_USER_GID) \ + --build-arg GOTENBERG_USER_UID=$(GOTENBERG_USER_UID) \ + --build-arg PDFTK_VERSION=$(PDFTK_VERSION) \ + -t $(DOCKER_REGISTRY)/gotenberg:$(GOTENBERG_VERSION) \ + -f build/Dockerfile . -# build the workspace Docker image. -workspace: - make base - docker build --build-arg GOLANG_VERSION=$(GOLANG_VERSION) -t $(DOCKER_REGISTRY)/gotenberg:workspace -f build/workspace/Dockerfile . +GOTENBERG_GRACEFUL_SHUTDOWN_DURATION=30s +API_PORT=3000 +API_PORT_FROM_ENV= +API_READ_TIMEOUT=30s +API_PROCESS_TIMEOUT=30s +API_WRITE_TIMEOUT=30s +API_ROOT_PATH=/ +API_TRACE_HEADER=Gotenberg-Trace +API_DISABLE_HEALTH_CHECK_LOGGING=false +API_WEBHOOK_ALLOW_LIST= +API_WEBHOOK_DENY_LIST= +API_WEBHOOK_ERROR_ALLOW_LIST= +API_WEBHOOK_ERROR_DENY_LIST= +API_WEBHOOK_MAX_RETRY=4 +API_WEBHOOK_RETRY_MIN_WAIT=1s +API_WEBHOOK_RETRY_MAX_WAIT=30s +API_DISABLE_WEBHOOK=false +CHROMIUM_USER_AGENT= +CHROMIUM_INCOGNITO=false +CHROMIUM_IGNORE_CERTIFICATE_ERRORS=false +CHROMIUM_ALLOW_LIST= +CHROMIUM_DENY_LIST="^file:///[^tmp].*" +CHROMIUM_DISABLE_ROUTES=false +LIBREOFFICE_DISABLES_ROUTES=false +LOG_LEVEL=info +LOG_FORMAT=auto +PDFENGINES_ENGINES= +PDFENGINES_DISABLE_ROUTES=false -# gofmt and goimports all go files. -fmt: +.PHONY: run +run: ## Start a Gotenberg container + docker run --rm -it \ + -p $(API_PORT):$(API_PORT) \ + $(DOCKER_REGISTRY)/gotenberg:$(GOTENBERG_VERSION) \ + gotenberg \ + --gotenberg-graceful-shutdown-duration=$(GOTENBERG_GRACEFUL_SHUTDOWN_DURATION) \ + --api-port=$(API_PORT) \ + --api-port-from-env=$(API_PORT_FROM_ENV) \ + --api-read-timeout=$(API_READ_TIMEOUT) \ + --api-process-timeout=$(API_PROCESS_TIMEOUT) \ + --api-write-timeout=$(API_WRITE_TIMEOUT) \ + --api-root-path=$(API_ROOT_PATH) \ + --api-trace-header=$(API_TRACE_HEADER) \ + --api-disable-health-check-logging=$(API_DISABLE_HEALTH_CHECK_LOGGING) \ + --api-webhook-allow-list=$(API_WEBHOOK_ALLOW_LIST) \ + --api-webhook-deny-list=$(API_WEBHOOK_DENY_LIST) \ + --api-webhook-error-allow-list=$(API_WEBHOOK_ERROR_ALLOW_LIST) \ + --api-webhook-error-deny-list=$(API_WEBHOOK_ERROR_DENY_LIST) \ + --api-webhook-max-retry=$(API_WEBHOOK_MAX_RETRY) \ + --api-webhook-retry-min-wait=$(API_WEBHOOK_RETRY_MIN_WAIT) \ + --api-webhook-retry-max-wait=$(API_WEBHOOK_RETRY_MAX_WAIT) \ + --api-disable-webhook=$(API_DISABLE_WEBHOOK) \ + --chromium-user-agent=$(CHROMIUM_USER_AGENT) \ + --chromium-incognito=$(CHROMIUM_INCOGNITO) \ + --chromium-ignore-certificate-errors=$(CHROMIUM_IGNORE_CERTIFICATE_ERRORS) \ + --chromium-allow-list=$(CHROMIUM_ALLOW_LIST) \ + --chromium-deny-list=$(CHROMIUM_DENY_LIST) \ + --chromium-disable-routes=$(CHROMIUM_DISABLE_ROUTES) \ + --libreoffice-disable-routes=$(LIBREOFFICE_DISABLES_ROUTES) \ + --log-level=$(LOG_LEVEL) \ + --log-format=$(LOG_FORMAT) \ + --pdfengines-engines=$(PDFENGINES_ENGINES) \ + --pdfengines-disable-routes=$(PDFENGINES_DISABLE_ROUTES) + +.PHONY: build-tests +build-tests: ## Build the tests' Docker image + docker build \ + --build-arg GOLANG_VERSION=$(GOLANG_VERSION) \ + --build-arg DOCKER_REGISTRY=$(DOCKER_REGISTRY) \ + --build-arg GOTENBERG_VERSION=$(GOTENBERG_VERSION) \ + --build-arg GOLANGCI_LINT_VERSION=$(GOLANGCI_LINT_VERSION) \ + -t $(DOCKER_REGISTRY)/gotenberg:$(GOTENBERG_VERSION)-tests \ + -f test/Dockerfile . + +.PHONY: tests +tests: ## Start the testing environment + docker run --rm -it \ + -v $(PWD):/tests \ + $(DOCKER_REGISTRY)/gotenberg:$(GOTENBERG_VERSION)-tests \ + bash + +.PHONY: tests-once +tests-once: ## Run the tests once (prefer the "tests" command while developing) + docker run --rm \ + -v $(PWD):/tests \ + $(DOCKER_REGISTRY)/gotenberg:$(GOTENBERG_VERSION)-tests \ + gotest + +.PHONY: fmt +fmt: ## Format the code and "optimize" the dependencies go fmt ./... go mod tidy -# run all linters. -lint: - docker build --build-arg GOLANGCI_LINT_VERSION=$(GOLANGCI_LINT_VERSION) -t $(DOCKER_REGISTRY)/gotenberg:lint -f build/lint/Dockerfile . - docker run --rm $(DOCKER_REGISTRY)/gotenberg:lint +.PHONY: godoc +godoc: ## Run a webserver with Gotenberg godoc (go get golang.org/x/tools/cmd/godoc) + $(info http://localhost:6060/pkg/github.com/gotenberg/gotenberg/v7) + godoc -http=:6060 -# run all tests. -tests: - make workspace - ./scripts/tests.sh $(DOCKER_REGISTRY) $(CODE_COVERAGE) - -# generate documentation. -doc: - make workspace - docker build -t $(DOCKER_REGISTRY)/gotenberg:docs -f build/docs/Dockerfile . - docker run --rm -it -v "$(PWD):/gotenberg/docs" $(DOCKER_REGISTRY)/gotenberg:docs - -# build Gotenberg Docker image. -image: - make workspace - docker build --build-arg VERSION=$(VERSION) --build-arg TINI_VERSION=$(TINI_VERSION) -t $(DOCKER_REGISTRY)/gotenberg:$(VERSION) -f build/package/Dockerfile . - -# start the API using previously built Docker image. -gotenberg: - docker run -it --rm -e MAXIMUM_WAIT_TIMEOUT=$(MAXIMUM_WAIT_TIMEOUT) -e MAXIMUM_WAIT_DELAY=$(MAXIMUM_WAIT_DELAY) -e MAXIMUM_WEBHOOK_URL_TIMEOUT=$(MAXIMUM_WEBHOOK_URL_TIMEOUT) -e DEFAULT_WEBHOOK_URL_TIMEOUT=$(DEFAULT_WEBHOOK_URL_TIMEOUT) -e MAXIMUM_WEBHOOK_URL_TIMEOUT=$(MAXIMUM_WEBHOOK_URL_TIMEOUT) -e DEFAULT_LISTEN_PORT=$(DEFAULT_LISTEN_PORT) -e DISABLE_GOOGLE_CHROME=$(DISABLE_GOOGLE_CHROME) -e DISABLE_UNOCONV=$(DISABLE_UNOCONV) -e LOG_LEVEL=$(LOG_LEVEL) -e ROOT_PATH=$(ROOT_PATH) -e DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE=$(DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE) -e GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS=$(GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS) -p "$(DEFAULT_LISTEN_PORT):$(DEFAULT_LISTEN_PORT)" $(DOCKER_REGISTRY)/gotenberg:$(VERSION) - -# publish Gotenberg images according to version. -publish: - make workspace - ./scripts/publish.sh $(GOLANG_VERSION) $(TINI_VERSION) $(DOCKER_REGISTRY) $(VERSION) $(DOCKER_USER) $(DOCKER_PASSWORD) \ No newline at end of file +.PHONY: release +release: ## Build the Gotenberg's Docker image for linux/amd64 and linux/arm64 platforms, then push it to a Docker Registry + ./scripts/release.sh \ + $(GOLANG_VERSION) \ + $(GOTENBERG_VERSION) \ + $(GOTENBERG_USER_GID) \ + $(GOTENBERG_USER_UID) \ + $(PDFTK_VERSION) \ + $(DOCKER_REGISTRY) diff --git a/README.md b/README.md index 89d1bf7b..08553b0f 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,46 @@

- Gotenberg logo -

+ Gotenberg Logo

Gotenberg

-

A Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF.

-

Documentation · Contributing

+

A Docker-powered stateless API for PDF files

+

Documentation +

--- -At TheCodingMachine, we build a lot of web applications (intranets, extranets and so on) which require to generate PDF from various sources. Each time, we ended up using some well known libraries and kind of lost time by reimplementing a solution from a project to another project. Meh. +Gotenberg provides a developer-friendly API to interact with powerful tools like Chromium and LibreOffice to convert many +documents to PDF, transform them, merge them, and more! -## Features - -* HTML and Markdown conversions using Google Chrome headless -* Office conversions (.txt, .rtf, .docx, .doc, .odt, .pptx, .ppt, .odp and so on) using [unoconv](https://github.com/dagwieers/unoconv) -* Assets :package:: send your header, footer, images, fonts, stylesheets and so on for converting your HTML and Markdown to beautiful PDFs! -* Easily interact with the API using our [Go](https://github.com/thecodingmachine/gotenberg-go-client) and [PHP](https://github.com/thecodingmachine/gotenberg-php-client) libraries - -## Quick start +## Quick Start Open a terminal and run the following command: -```bash -$ docker run --rm -p 3000:3000 thecodingmachine/gotenberg:6 +``` +docker run --rm -p 3000:3000 gotenberg/gotenberg:7 ``` -The API is now available on your host at `http://localhost:3000`. +Alternatively, using the historic Docker registry from our sponsor [TheCodingMachine](https://www.thecodingmachine.com): -Head to the [documentation](https://gotenberg.dev/) -to learn how to interact with it! +``` +docker run --rm -p 3000:3000 thecodingmachine/gotenberg:7 +``` + +The API is now available on your host at http://localhost:3000. + +Head to the [documentation](https://gotenberg.dev/docs/about) to learn how to interact with it 🚀 + +## Sponsors + +

+ + TheCodingMachine Logo + +

## Badges +[![Docker pulls](https://img.shields.io/docker/pulls/gotenberg/gotenberg)](https://hub.docker.com/r/gotenberg/gotenberg) [![Docker pulls](https://img.shields.io/docker/pulls/thecodingmachine/gotenberg)](https://hub.docker.com/r/thecodingmachine/gotenberg) -[![Docker image layers](https://images.microbadger.com/badges/image/thecodingmachine/gotenberg:6.svg)](https://microbadger.com/images/thecodingmachine/gotenberg:6) -[![GitHub Actions](https://github.com/thecodingmachine/gotenberg/workflows/tests_maybe_release/badge.svg)](https://github.com/thecodingmachine/gotenberg/workflows/tests_maybe_release) -[![GoDoc](https://godoc.org/github.com/thecodingmachine/gotenberg?status.svg)](https://godoc.org/github.com/thecodingmachine/gotenberg) -[![Codecov](https://codecov.io/gh/thecodingmachine/gotenberg/branch/master/graph/badge.svg)](https://codecov.io/gh/thecodingmachine/gotenberg) -[![Go Report Card](https://goreportcard.com/badge/github.com/thecodingmachine/gotenberg)](https://goreportcard.com/report/thecodingmachine/gotenberg) - ---- - -

- Gotenberg logo -

+[![Continuous Integration](https://github.com/gotenberg/gotenberg/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/gotenberg/gotenberg/actions/workflows/continuous_integration.yml) +[![Go Reference](https://pkg.go.dev/badge/github.com/gotenberg/gotenberg.svg)](https://pkg.go.dev/github.com/gotenberg/gotenberg/v7) +[![Codecov](https://codecov.io/gh/gotenberg/gotenberg/branch/main/graph/badge.svg)](https://codecov.io/gh/gotenberg/gotenberg) +[![Go Report Card](https://goreportcard.com/badge/github.com/gotenberg/gotenberg)](https://goreportcard.com/report/gotenberg/gotenberg) diff --git a/assets/logo.png b/assets/logo.png deleted file mode 100644 index 4dacc2ee..00000000 Binary files a/assets/logo.png and /dev/null differ diff --git a/assets/logo2.png b/assets/logo2.png deleted file mode 100644 index de91ad06..00000000 Binary files a/assets/logo2.png and /dev/null differ diff --git a/build/Dockerfile b/build/Dockerfile new file mode 100644 index 00000000..15ff6e1a --- /dev/null +++ b/build/Dockerfile @@ -0,0 +1,145 @@ +# Note: ARG instructions do not create additional layers. +# Instead, next layers will concatenate them. +ARG GOLANG_VERSION +ARG GOTENBERG_VERSION + +FROM golang:$GOLANG_VERSION AS builder + +ENV CGO_ENABLED 0 + +# Define the working directory outside of $GOPATH (we're using go modules). +WORKDIR /home + +# Install module dependencies. +COPY go.mod go.sum ./ + +RUN go mod download &&\ + go mod verify + +# Copy the source code. +COPY cmd ./cmd +COPY internal ./internal +COPY pkg ./pkg + +# Build the binary. +RUN go build -o gotenberg -ldflags "-X gotenberg.version=$GOTENBERG_VERSION" cmd/gotenberg/main.go + +FROM debian:buster-slim + +LABEL author="Julien Neuhart" \ + description="A Docker-powered stateless API for PDF files." \ + github="https://github.com/gotenberg/gotenberg" \ + version="$GOTENBER_VERSION" \ + website="https://gotenberg.dev" + +# Improve fonts subpixel hinting and smoothing. +# Credits: +# https://github.com/arachnys/athenapdf/issues/69. +# https://github.com/arachnys/athenapdf/commit/ba25a8d80a25d08d58865519c4cd8756dc9a336d. +COPY build/fonts.conf /etc/fonts/conf.d/100-gotenberg.conf + +# Simple wrapper around Java and PDFtk. +COPY build/pdftk.sh /usr/bin/pdftk + +# Setup the Docker image. +ARG GOTENBERG_USER_GID +ARG GOTENBERG_USER_UID +ARG PDFTK_VERSION + +RUN \ + # Create a non-root user. + # All processes in the Docker container will run with this dedicated user. + groupadd --gid "$GOTENBERG_USER_GID" gotenberg &&\ + useradd --uid "$GOTENBERG_USER_UID" --gid gotenberg --shell /bin/bash --home /home/gotenberg --no-create-home gotenberg &&\ + mkdir /home/gotenberg &&\ + chown gotenberg: /home/gotenberg &&\ + # Install dependencies required for the next instructions or debugging. + # Note: procps for "top" command (useful when debugging processes). + # Note: tini is a helper for reaping zombie processes. + apt-get update -qq &&\ + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends curl gnupg procps tini &&\ + # Install fonts. + # Credits: + # https://github.com/arachnys/athenapdf/blob/master/cli/Dockerfile. + # https://help.accusoft.com/PrizmDoc/v12.1/HTML/Installing_Asian_Fonts_on_Ubuntu_and_Debian.html. + curl -o ./ttf-mscorefonts-installer_3.8_all.deb http://httpredir.debian.org/debian/pool/contrib/m/msttcorefonts/ttf-mscorefonts-installer_3.8_all.deb &&\ + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends \ + ./ttf-mscorefonts-installer_3.8_all.deb \ + culmus \ + fonts-beng \ + fonts-hosny-amiri \ + fonts-lklug-sinhala \ + fonts-lohit-guru \ + fonts-lohit-knda \ + fonts-samyak-gujr \ + fonts-samyak-mlym \ + fonts-samyak-taml \ + fonts-sarai \ + fonts-sil-abyssinica \ + fonts-sil-padauk \ + fonts-telu \ + fonts-thai-tlwg \ + ttf-wqy-zenhei \ + fonts-arphic-uming \ + fonts-ipafont-mincho \ + fonts-ipafont-gothic \ + fonts-unfonts-core \ + # LibreOffice recommends. + fonts-crosextra-caladea \ + fonts-crosextra-carlito \ + fonts-dejavu \ + fonts-dejavu-extra \ + fonts-liberation \ + fonts-liberation2 \ + fonts-linuxlibertine \ + fonts-noto-core \ + fonts-noto-mono \ + fonts-noto-ui-core \ + fonts-sil-gentium \ + fonts-sil-gentium-basic &&\ + rm -f ./ttf-mscorefonts-installer_3.8_all.deb &&\ + echo "deb https://httpredir.debian.org/debian/ buster-backports main contrib non-free" >> /etc/apt/sources.list &&\ + apt-get update -qq &&\ + # Install Chromium and LibreOffice. + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends chromium &&\ + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends -t buster-backports libreoffice &&\ + # Download unoconv (Python script). + curl -Ls https://raw.githubusercontent.com/dagwieers/unoconv/master/unoconv -o /usr/bin/unoconv &&\ + chmod +x /usr/bin/unoconv &&\ + # unoconv will look for the Python binary, which has to be at version 3. + ln -s /usr/bin/python3 /usr/bin/python &&\ + # Download PDFtk. + # Credits: https://github.com/thecodingmachine/gotenberg/pull/273. + curl -o /usr/bin/pdftk-all.jar "https://gitlab.com/pdftk-java/pdftk/-/jobs/$PDFTK_VERSION/artifacts/raw/build/libs/pdftk-all.jar" &&\ + chmod a+x /usr/bin/pdftk-all.jar &&\ + # See https://github.com/nextcloud/docker/issues/380. + mkdir -p /usr/share/man/man1mkdir -p /usr/share/man/man1 &&\ + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends default-jre-headless &&\ + # Cleanup. + # Note: the Debian image does automatically a clean after each install thanks to a hook. + # Therefore, there is no need for apt-get clean. + # See https://stackoverflow.com/a/24417119/3248473. + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* &&\ + # Print versions of main dependencies. + chromium --version &&\ + libreoffice --version &&\ + unoconv --version &&\ + pdftk --version + +# Copy the Gotenberg binary from the builder stage. +COPY --from=builder /home/gotenberg /usr/bin/ + +# Environment variables required by modules or else. +ENV GC_EXCLUDE_SUBSTR "hsperfdata_root,hsperfdata_gotenberg" +ENV CHROMIUM_BIN_PATH /usr/bin/chromium +ENV UNOCONV_BIN_PATH /usr/bin/unoconv +ENV PDFTK_BIN_PATH /usr/bin/pdftk + +USER gotenberg +WORKDIR /home/gotenberg + +# Default API port. +EXPOSE 3000 + +ENTRYPOINT [ "/usr/bin/tini", "--" ] +CMD [ "gotenberg" ] \ No newline at end of file diff --git a/build/Dockerfile.cloudrun b/build/Dockerfile.cloudrun new file mode 100644 index 00000000..722e879a --- /dev/null +++ b/build/Dockerfile.cloudrun @@ -0,0 +1,15 @@ +# Note: ARG instructions do not create additional layers. +# Instead, next layers will concatenate them. +ARG DOCKER_REGISTRY +ARG GOTENBERG_VERSION + +FROM $DOCKER_REGISTRY/gotenberg:$GOTENBERG_VERSION + +USER root + +# For security reasons, the non-root user gotenberg does not own the Tini binary by default. +# However, some providers like Cloud Run from Google Cloud cannot start a Docker container in that case. +# See https://github.com/gotenberg/gotenberg/issues/90#issuecomment-543551353. +RUN chown gotenberg: /usr/bin/tini + +USER gotenberg diff --git a/build/base/Dockerfile b/build/base/Dockerfile deleted file mode 100644 index 85d2be8b..00000000 --- a/build/base/Dockerfile +++ /dev/null @@ -1,138 +0,0 @@ -FROM debian:buster-slim - -# |-------------------------------------------------------------------------- -# | Common libraries -# |-------------------------------------------------------------------------- -# | -# | Libraries used in the build process of this image. -# | -RUN apt-get update &&\ - apt-get --no-install-recommends install -y ca-certificates curl gnupg procps &&\ - rm -rf /var/lib/apt/lists/* - -# |-------------------------------------------------------------------------- -# | Microsoft font installer -# |-------------------------------------------------------------------------- -RUN apt-get update &&\ - curl -o ./ttf-mscorefonts-installer_3.8_all.deb https://httpredir.debian.org/debian/pool/contrib/m/msttcorefonts/ttf-mscorefonts-installer_3.8_all.deb &&\ - apt --no-install-recommends install -y ./ttf-mscorefonts-installer_3.8_all.deb && rm ./ttf-mscorefonts-installer_3.8_all.deb &&\ - rm -rf /var/lib/apt/lists/* - -# |-------------------------------------------------------------------------- -# | Chrome -# |-------------------------------------------------------------------------- -# | -# | Installs Chrome. -# | -RUN curl https://dl.google.com/linux/linux_signing_key.pub | apt-key add - &&\ - echo "deb https://dl.google.com/linux/chrome/deb/ stable main" | tee /etc/apt/sources.list.d/google-chrome.list &&\ - apt-get update &&\ - apt-get install --no-install-recommends -y --allow-unauthenticated google-chrome-stable &&\ - rm -rf /var/lib/apt/lists/* - -# |-------------------------------------------------------------------------- -# | LibreOffice -# |-------------------------------------------------------------------------- -# | -# | Installs LibreOffice. -# | - -# https://github.com/nextcloud/docker/issues/380 -RUN mkdir -p /usr/share/man/man1mkdir -p /usr/share/man/man1 &&\ - echo "deb https://httpredir.debian.org/debian/ buster-backports main contrib non-free" >> /etc/apt/sources.list &&\ - apt-get update &&\ - apt-get --no-install-recommends -t buster-backports -y install libreoffice &&\ - rm -rf /var/lib/apt/lists/* - -# |-------------------------------------------------------------------------- -# | Unoconv -# |-------------------------------------------------------------------------- -# | -# | Installs unoconv. -# | - -ENV UNO_URL=https://raw.githubusercontent.com/dagwieers/unoconv/master/unoconv - -RUN curl -Ls $UNO_URL -o /usr/bin/unoconv &&\ - chmod +x /usr/bin/unoconv &&\ - ln -s /usr/bin/python3 /usr/bin/python &&\ - unoconv --version - -# |-------------------------------------------------------------------------- -# | PDFtk -# |-------------------------------------------------------------------------- -# | -# | Installs PDFtk as an alternative to pdfcpu for merging PDFs. -# | https://github.com/thecodingmachine/gotenberg/issues/29 -# | - -ARG PDFTK_VERSION=924565150 - -RUN curl -o /usr/bin/pdftk "https://gitlab.com/pdftk-java/pdftk/-/jobs/${PDFTK_VERSION}/artifacts/raw/build/native-image/pdftk" \ - && chmod a+x /usr/bin/pdftk - -# |-------------------------------------------------------------------------- -# | Fonts -# |-------------------------------------------------------------------------- -# | -# | Installs a handful of fonts. -# | Note: ttf-mscorefonts-installer are installed on top of this Dockerfile. -# | - -# Credits: -# https://github.com/arachnys/athenapdf/blob/master/cli/Dockerfile -# https://help.accusoft.com/PrizmDoc/v12.1/HTML/Installing_Asian_Fonts_on_Ubuntu_and_Debian.html -RUN apt-get update &&\ - apt-get install --no-install-recommends -y \ - culmus \ - fonts-beng \ - fonts-hosny-amiri \ - fonts-lklug-sinhala \ - fonts-lohit-guru \ - fonts-lohit-knda \ - fonts-samyak-gujr \ - fonts-samyak-mlym \ - fonts-samyak-taml \ - fonts-sarai \ - fonts-sil-abyssinica \ - fonts-sil-padauk \ - fonts-telu \ - fonts-thai-tlwg \ - ttf-wqy-zenhei \ - fonts-arphic-uming \ - fonts-ipafont-mincho \ - fonts-ipafont-gothic \ - fonts-unfonts-core \ - # LibreOffice recommends. - fonts-crosextra-caladea \ - fonts-crosextra-carlito \ - fonts-dejavu \ - fonts-dejavu-extra \ - fonts-liberation \ - fonts-liberation2 \ - fonts-linuxlibertine \ - fonts-noto-core \ - fonts-noto-mono \ - fonts-noto-ui-core \ - fonts-sil-gentium \ - fonts-sil-gentium-basic &&\ - rm -rf /var/lib/apt/lists/* - -COPY build/base/fonts/* /usr/local/share/fonts/ -COPY build/base/fonts.conf /etc/fonts/conf.d/100-gotenberg.conf - -# |-------------------------------------------------------------------------- -# | Default user -# |-------------------------------------------------------------------------- -# | -# | All processes in the Docker container will run as a dedicated -# | non-root user. -# | - -ARG GOTENBERG_USER_GID=1001 -ARG GOTENBERG_USER_UID=1001 - -RUN groupadd --gid ${GOTENBERG_USER_GID} gotenberg \ - && useradd --uid ${GOTENBERG_USER_UID} --gid gotenberg --shell /bin/bash --home /gotenberg --no-create-home gotenberg \ - && mkdir /gotenberg \ - && chown gotenberg: /gotenberg diff --git a/build/base/fonts/NotoColorEmoji.ttf b/build/base/fonts/NotoColorEmoji.ttf deleted file mode 100644 index 69cf21a1..00000000 Binary files a/build/base/fonts/NotoColorEmoji.ttf and /dev/null differ diff --git a/build/docs/Dockerfile b/build/docs/Dockerfile deleted file mode 100644 index 6c6a2df8..00000000 --- a/build/docs/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM thecodingmachine/gotenberg:workspace - -# |-------------------------------------------------------------------------- -# | static -# |-------------------------------------------------------------------------- -# | -# | Installs the static site anti-framework – general-purpose library, -# | purpose-built commands for various domains. -# | - -RUN go get github.com/apex/static/cmd/static-docs - -# |-------------------------------------------------------------------------- -# | Final touch -# |-------------------------------------------------------------------------- -# | -# | Last instructions of this build. -# | - -WORKDIR /gotenberg/docs - -CMD [ "static-docs", "--in", "build/docs/content", "--out", "docs", "--theme", "gotenberg", "--title", "Gotenberg", "--subtitle", "A Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF." ] \ No newline at end of file diff --git a/build/docs/content/00-introduction.md b/build/docs/content/00-introduction.md deleted file mode 100644 index 21b6a0a4..00000000 --- a/build/docs/content/00-introduction.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Introduction ---- - -[Gotenberg](https://github.com/thecodingmachine/gotenberg/) is a Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF. - -* HTML and Markdown conversions using Google Chrome headless -* Office conversions (.txt, .rtf, .docx, .doc, .odt, .pptx, .ppt, .odp and so on) using [unoconv](https://github.com/dagwieers/unoconv) -* Assets: send your header, footer, images, fonts, stylesheets and so on for converting your HTML and Markdown to beaufitul PDFs! -* Easily interact with the API using our [Go](https://github.com/thecodingmachine/gotenberg-go-client) and [PHP](https://github.com/thecodingmachine/gotenberg-php-client) libraries diff --git a/build/docs/content/01-install.md b/build/docs/content/01-install.md deleted file mode 100644 index b56606b8..00000000 --- a/build/docs/content/01-install.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Install ---- - -Gotenberg is shipped within a Docker image. - -**[Gotenberg should ONLY be used in a trusted network by trusted applications. Do NOT expose Gotenberg to the external world.](https://blazej-adamczyk.medium.com/0-day-bug-breaks-multi-million-dollar-system-38c9e31b27e9)** - -You may start it with: - -```bash -$ docker run --rm -p 3000:3000 thecodingmachine/gotenberg:6 -``` - -> The API will be available at [http://localhost:3000](http://localhost:3000). - -The image uses a dedicated non-root user called `gotenberg` with uid and gid `1001`. - -If you wish to change those uid and gid, you will have to: - -* clone the project -* re-build the image -* publish the image in your own Docker registry - -For instance: - -```bash -$ git clone https://github.com/thecodingmachine/gotenberg.git -$ make publish GOTENBERG_USER_GID=your_custom_gid GOTENBERG_USER_UID=your_custom_uid DOCKER_REGISTRY=your_registry DOCKER_USER=registry_user DOCKER_PASSWORD=registry_password VERSION=version -``` - -> `master` branch is always up-to-date with the latest version of the API. - -## Docker Compose - -You may also add it in your Docker Compose stack: - -```yaml -version: '3' - -services: - - # your other services - - gotenberg: - image: thecodingmachine/gotenberg:6 -``` - -> The API will be available under `gotenberg:3000` in your Docker Compose network. - -## Kubernetes - -It may also be deployed with Kubernetes. - -Make sure to provide enough memory and CPU requests (for instance `512Mi` and `0.2` CPU). - -> The more resources are granted, the quicker will be the conversions. - -In the deployment specification of the pod, also specify the uid of the user `gotenberg`: - -``` -securityContext: - privileged: false - runAsUser: 1001 -``` - -## Cloud Run (Google Cloud) - -If you're looking for cost savings, you might be interested by [Cloud Run](https://cloud.google.com/run). -However, according to some users, doing asynchronous conversion (with a webhook) might not working. - -In the following examples, we will assume your -Gotenberg API is available at [http://localhost:3000](http://localhost:3000). diff --git a/build/docs/content/02-clients.md b/build/docs/content/02-clients.md deleted file mode 100644 index 0f4ce7d2..00000000 --- a/build/docs/content/02-clients.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Clients ---- - -We provide clients in various languages for easing the interactions with the API. - -## Go client - -```bash -$ go get -u github.com/thecodingmachine/gotenberg-go-client/v7 -``` - -See also the example from the [README](https://github.com/thecodingmachine/gotenberg-go-client/blob/master/README.md). - -## PHP client - -Unless your project already has a PSR7 `HttpClient`, install `php-http/guzzle6-adapter`: - -```bash -$ composer require php-http/guzzle6-adapter -``` - -Then the [PHP client](https://github.com/thecodingmachine/gotenberg-php-client): - -```bash -$ composer require thecodingmachine/gotenberg-php-client -``` - -See also the example from the [README](https://github.com/thecodingmachine/gotenberg-php-client/blob/master/README.md). - -## Community clients - -* [JavaScript/TypeScript client](https://github.com/yumauri/gotenberg-js-client) by [yumauri](https://github.com/yumauri) -* [C# client](https://github.com/ChangemakerStudios/GotenbergSharpApiClient) by [ChangemakerStudios](https://github.com/ChangemakerStudios) diff --git a/build/docs/content/03-environment-variables.md b/build/docs/content/03-environment-variables.md deleted file mode 100644 index 415dd020..00000000 --- a/build/docs/content/03-environment-variables.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: Environment variables ---- - -You may customize the API behaviour thanks to environment variables. - -## Log level - -The API provides structured logging allowing you to have relevant information -about what's going on. - -> If a TTY is attached, the log entries are displayed in text format with colors, otherwise in JSON format. - -You may customize the severity of the log entries thanks to the environment variable `LOG_LEVEL`. - -It accepts one of the following severities: `"DEBUG"`, `"INFO"` (default) and `"ERROR"`. - -## Default listen port - -By default, the API will listen on port `3000`. - -You may customize this value with the environment variable `DEFAULT_LISTEN_PORT`. - -This environment variable accepts any string that can be turned into a port number. - -## Root path - -By default, the API root path is `/`. - -You may customize this value with the environment variable `ROOT_PATH`. - -This environment variable accepts a string starting and ending with `/`. - -For instance, `/gotenberg/` is a valid value while `gotenberg` is not. - -> This is useful if you wish to do service discovery via URL paths. - -## Disable Google Chrome - -In order to save some resources, the Gotenberg image accepts the environment variable `DISABLE_GOOGLE_CHROME` -for disabling Google Chrome. - -It takes the strings `"0"` or `"1"` as value where `1` means `true` - -> If Google Chrome is disabled, the following conversions will **not** be available anymore: -> [HTML](#html), [URL](#url) and [Markdown](#markdown) - -## Default Google Chrome rpcc buffer size - -When performing a [HTML](#html), [URL](#url) or [Markdown](#markdown) conversion, the API might return -a `400` HTTP code with the message `increase the Google Chrome rpcc buffer size`. - -If so, you may increase this buffer size with the environment variable `DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE`. - -It takes a string representation of an int as value (e.g. `"1048576"` for 1 MB). -The hard limit is 100 MB and is defined by Google Chrome itself. - -> The default Google Chrome rpcc buffer size may also be overridden per request thanks to the form field `googleChromeRpccBufferSize`. -> See the [rpcc buffer size section](#html.rpcc_buffer_size). - -## Google Chrome ignore certificate errors - -When performing a [URL](#url) conversion, Google Chrome will not accept certificate errors. - -You may allow insecure connections by setting the `GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS` environment variable to `"1"`. - -**You should be careful with this feature and only enable it in your development environment.** - -## Disable LibreOffice (unoconv) - -You may also disable LibreOffice (unoconv) with `DISABLE_UNOCONV`. - -> If LibreOffice (unoconv) is disabled, the following conversion will **not** be available anymore: -> [Office](#office) - -## Default wait timeout - -By default, the API will wait 10 seconds before it considers the conversion to be unsuccessful. -If unsucessful, it returns a `504` HTTP code. - -You may customize this timeout thanks to the environment variable `DEFAULT_WAIT_TIMEOUT`. - -It takes a string representation of a float as value (e.g `"2.5"` for 2.5 seconds). - -> The default timeout may also be overridden per request thanks to the form field `waitTimeout`. -> See the [timeout section](#timeout). - -## Maximum wait timeout - -By default, the value of the form field `waitTimeout` cannot be more than 30 seconds. - -You may increase or decrease this limit thanks to the environment variable `MAXIMUM_WAIT_TIMEOUT`. - -It takes a string representation of a float as value (e.g `"2.5"` for 2.5 seconds). - -## Default webhook URL timeout - -By default, the API will wait 10 seconds before it considers the sending of the resulting PDF to be unsuccessful. - -> See the [webhook section](#webhook). - -You may customize this timeout thanks to the environment variable `DEFAULT_WEBHOOK_URL_TIMEOUT`. - -It takes a string representation of a float as value (e.g `"2.5"` for 2.5 seconds). - -> The default timeout may also be overridden per request thanks to the form field `webhookURLTimeout`. -> See the [webhook timeout section](#webhook.timeout). - -## Maximum webhook URL timeout - -By default, the value of the form field `webhookURLTimeout` cannot be more than 30 seconds. - -You may increase or decrease this limit thanks to the environment variable `MAXIMUM_WEBHOOK_URL_TIMEOUT`. - -It takes a string representation of a float as value (e.g `"2.5"` for 2.5 seconds). - -## Maximum wait delay - -By default, the value of the form field `waitDelay` cannot be more than 10 seconds. - -> See the [wait delay section](#html.wait_delay). - -You may increase or decrease this limit thanks to the environment variable `MAXIMUM_WAIT_DELAY`. - -It takes a string representation of a float as value (e.g `"2.5"` for 2.5 seconds). diff --git a/build/docs/content/04-html.md b/build/docs/content/04-html.md deleted file mode 100644 index 688b8ae4..00000000 --- a/build/docs/content/04-html.md +++ /dev/null @@ -1,451 +0,0 @@ ---- -title: HTML ---- - -Gotenberg provides the endpoint `/convert/html` for HTML conversions. - -It accepts `POST` requests with a `multipart/form-data` Content-Type. - -## Basic - -The only requirement is to send a file named `index.html`: it is the file -which will be converted to PDF. - -For instance: - -```html - - - - - My PDF - - -

Hello world!

- - -``` - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Header and footer - -You may also add a header and/or a footer in the resulting PDF. -Respectively, a file named `header.html` and `footer.html`. - -Each of them **has to be a complete HTML document**: - -```html - - - - - -

- of -

- - -``` - -The following classes allow you to inject printing values: - -* `date`: formatted print date -* `title`: document title -* `pageNumber`: current page number -* `totalPage`: total pages in the document - -There are some limitations: - -* JavaScript is not executed -* external resources are not loaded -* the CSS properties are independant of the ones used in the `index.html` file -* `footer.html` CSS properties override the ones from `header.html` -* only fonts installed in the Docker image are loaded (see the [fonts section](#fonts)) -* images only work using a `base64` encoded source (`setHeader($header); -$request->setFooter($footer); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Assets - -You may also send additional files. For instance: images, fonts, stylesheets and so on. - -The only requirement is to make sure that their paths -are on the same level as the `index.html` file. - -In other words, this will work: - -```html - - - - - My PDF - - -

Hello world!

- - - -``` - -But this won't: - -```html - - - - - My PDF - - -

Hello world!

- - - -``` - -You may also use *remote* paths for Google fonts, images and so on. - -> If you want to install fonts directly in the Gotenberg Docker image, -> see to the [fonts section](#fonts). - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form files=@style.css \ - --form files=@img.png \ - --form files=@font.woff \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -style, _ := gotenberg.NewDocumentFromPath("style.css", "/path/to/file") -img, _ := gotenberg.NewDocumentFromPath("img.png", "/path/to/file") -font, _ := gotenberg.NewDocumentFromPath("font.woff", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.Assets(style, img, font) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$assets = [ - DocumentFactory::makeFromPath('style.css', '/path/to/file'), - DocumentFactory::makeFromPath('img.png', '/path/to/file'), - DocumentFactory::makeFromPath('font.woff', '/path/to/file'), -]; -$request = new HTMLRequest($index); -$request->setAssets($assets); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Paper size, margins, orientation, scaling - -You may also customize the resulting PDF format. - -By default, it will be rendered with `A4` size, `1 inch` margins and `portrait` orientation and 100% (`1.0`) page scale. - -> Paper size and margins have to be provided in `inches`. Same for margins. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form paperWidth=8.27 \ - --form paperHeight=11.69 \ - --form marginTop=0 \ - --form marginBottom=0 \ - --form marginLeft=0 \ - --form marginRight=0 \ - --form landscape=true \ - --form scale=0.75 \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.PaperSize(gotenberg.A4) -req.Margins(gotenberg.NoMargins) -req.Landscape(true) -req.Scale(0.75) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; -use TheCodingMachine\Gotenberg\Request; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setPaperSize(Request::A4); -$request->setMargins(Request::NO_MARGINS); -$request->setLandscape(true); -$request->setScale(0.75); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Page ranges - -You may specify the page ranges to convert. - -The format is the same as the one from the print options -of Google Chrome, e.g. `1-5,8,11-13`. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form pageRanges='1-3,5' \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.PageRanges("1-3,5") -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; -use TheCodingMachine\Gotenberg\Request; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setPageRanges('1-3,5'); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Wait delay - -In some cases, you may want to wait a certain amount of time to make sure the -page you're trying to generate is fully rendered. For instance, if your page relies -a lot on JavaScript for rendering. - -> The wait delay is a duration in **seconds** (e.g `2.5` for 2.5 seconds). - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form waitDelay=5.5 \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.WaitDelay(5.5) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; -use TheCodingMachine\Gotenberg\Request; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setWaitDelay(5.5); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Rpcc buffer size - -The API might return a `400` HTTP code with the message `increase the Google Chrome rpcc buffer size`. - -If so, you may increase this buffer size with a form field named `googleChromeRpccBufferSize`. - -It takes an int as value (e.g. `1048576` for 1 MB). -The hard limit is 100 MB and is defined by Google Chrome itself. - -> You may also define this value globally: see the [environment variables](#environment_variables.default_google_chrome_rpcc_buffer_size) section. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form googleChromeRpccBufferSize=1048576 \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.GoogleChromeRpccBufferSize(1048576) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; -use TheCodingMachine\Gotenberg\Request; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setGoogleChromeRpccBufferSize(1048576); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` diff --git a/build/docs/content/05-url.md b/build/docs/content/05-url.md deleted file mode 100644 index be892405..00000000 --- a/build/docs/content/05-url.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: URL ---- - -Gotenberg provides the endpoint `/convert/url` for remote URL conversions. - -It accepts `POST` requests with a `multipart/form-data` Content-Type. - -## Basic - -This endpoint does not accept an `index.html` file nor assets files but a form field -named `remoteURL` instead. Otherwise, URL conversions work the same as HTML conversions. - -> **Attention:** when converting a website to PDF, you should remove all margins. -> If not, some of the content of the page might be hidden. - -> **Attention:** if you try to convert a URL from a Docker Compose service named `app` (i.e. `removeURL` = `http://app/an/entrypoint`), -> the resulting PDF will be blank. Make sure to rename your service to avoid this issue. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/url \ - --header 'Content-Type: multipart/form-data' \ - --form remoteURL=https://google.com \ - --form marginTop=0 \ - --form marginBottom=0 \ - --form marginLeft=0 \ - --form marginRight=0 \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -req := gotenberg.NewURLRequest("https://google.com") -req.Margins(gotenberg.NoMargins) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\URLRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$request = new URLRequest('https://google.com'); -$request->setMargins(Request::NO_MARGINS); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Custom HTTP headers - -You may send your own HTTP headers to the `remoteURL`. - -For instance, by adding the HTTP header `Gotenberg-Remoteurl-Your-Header` to your request, -the API will send a request to the `remoteURL` with the HTTP header `Your-Header`. - -> **Attention:** the API uses a canonical format for the HTTP headers: -> it transforms the first -> letter and any letter following a hyphen to upper case; -> the rest are converted to lowercase. For example, the -> canonical key for `accept-encoding` is `Accept-Encoding`. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/url \ - --header 'Content-Type: multipart/form-data' \ - --header 'Gotenberg-Remoteurl-Your-Header: Foo' \ - --form remoteURL=https://google.com \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -req := gotenberg.NewURLRequest("https://google.com") -req.AddRemoteURLHTTPHeader("Your-Header", "Foo") -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\URLRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$request = new URLRequest('https://google.com'); -$request->addRemoteURLHTTPHeader('Your-Header', 'Foo') -$dest = 'result.pdf'; -$client->store($request, $dest); -``` diff --git a/build/docs/content/06-markdown.md b/build/docs/content/06-markdown.md deleted file mode 100644 index 5838ea7b..00000000 --- a/build/docs/content/06-markdown.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Markdown ---- - -Gotenberg provides the endpoint `/convert/markdown` for Markdown conversions. - -It accepts `POST` requests with a `multipart/form-data` Content-Type. - -## Basic - -Markdown conversions work the same as HTML conversions. - -Only difference is that you have access to the Go template function `toHTML` -in the file `index.html`. This function will convert a given markdown file to HTML. - -For instance: - -```html - - - - - My PDF - - - {{ toHTML .DirPath "file.md" }} - - -``` - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/markdown \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form files=@file.md \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -markdown, _ := gotenberg.NewDocumentFromPath("file.md", "/path/to/file") -req := gotenberg.NewMarkdownRequest(index, markdown) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\MarkdownRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$markdowns = [ - DocumentFactory::makeFromPath('file.md', '/path/to/file'), -]; -$request = new MarkdownRequest($index, $markdowns); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` diff --git a/build/docs/content/07-office.md b/build/docs/content/07-office.md deleted file mode 100644 index 1dbae793..00000000 --- a/build/docs/content/07-office.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Office ---- - -Gotenberg provides the endpoint `/convert/office` for Office document conversions. - -It accepts `POST` requests with a `multipart/form-data` Content-Type. - -## Basic - -You may send one or more Office documents. Following file extensions are accepted: - -* `.txt` -* `.rtf` -* `.fodt` -* `.doc` -* `.docx` -* `.odt` -* `.xls` -* `.xlsx` -* `.ods` -* `.ppt` -* `.pptx` -* `.odp` - -All files will be merged into a single resulting PDF. - -> **Attention:** Gotenberg merges the PDF files alphabetically. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/office \ - --header 'Content-Type: multipart/form-data' \ - --form files=@document.docx \ - --form files=@document2.docx \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -doc, _ := gotenberg.NewDocumentFromPath("document.docx", "/path/to/file") -doc2, _ := gotenberg.NewDocumentFromPath("document2.docx", "/path/to/file") -req := gotenberg.NewOfficeRequest(doc, doc2) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\OfficeRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$files = [ - DocumentFactory::makeFromPath('document.docx', '/path/to/file'), - DocumentFactory::makeFromPath('document2.docx', '/path/to/file'), -]; -$request = new OfficeRequest($files); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Orientation - -You may also customize the resulting PDF format. - -By default, it will be rendered with `portrait` orientation. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/office \ - --header 'Content-Type: multipart/form-data' \ - --form files=@document.docx \ - --form landscape=true \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -doc, _ := gotenberg.NewDocumentFromPath("document.docx", "/path/to/file") -req := gotenberg.NewOfficeRequest(doc) -req.Landscape(true) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\OfficeRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$files = [ - DocumentFactory::makeFromPath('document.docx', '/path/to/file'), -]; -$request = new OfficeRequest($files); -$request->setLandscape(true); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` - -## Page ranges - -You may specify the page ranges to convert. - -The format is the same as the one from the print options -of LibreOffice, e.g. `1-1` or `1-4`. - -> **Attention:** if more than one document, the page ranges will be -> applied for each document. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/office \ - --header 'Content-Type: multipart/form-data' \ - --form files=@document.docx \ - --form pageRanges='1-3' \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -doc, _ := gotenberg.NewDocumentFromPath("document.docx", "/path/to/file") -req := gotenberg.NewOfficeRequest(doc) -req.PageRanges("1-3") -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\OfficeRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$files = [ - DocumentFactory::makeFromPath('document.docx', '/path/to/file'), -]; -$request = new OfficeRequest($files); -$request->setPageRanges('1-3'); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` diff --git a/build/docs/content/08-merge.md b/build/docs/content/08-merge.md deleted file mode 100644 index 8e693743..00000000 --- a/build/docs/content/08-merge.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Merge ---- - -Gotenberg provides the endpoint `/merge` for merging PDFs. - -It accepts `POST` requests with a `multipart/form-data` Content-Type. - -## Basic - -Nothing fancy here: you may send one or more PDF files and the API -will merge them and return the resulting PDF file. - -> **Attention:** Gotenberg merges the PDF files alphabetically. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/merge \ - --header 'Content-Type: multipart/form-data' \ - --form files=@file.pdf \ - --form files=@file2.pdf \ - -o result.pdf -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -pdf, _ := gotenberg.NewDocumentFromPath("file.pdf", "/path/to/file") -pdf2, _ := gotenberg.NewDocumentFromPath("file2.pdf", "/path/to/file") -req := gotenberg.NewMergeRequest(pdf, pdf2) -dest := "result.pdf" -c.Store(req, dest) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\MergeRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$files = [ - DocumentFactory::makeFromPath('file.pdf', '/path/to/file'), - DocumentFactory::makeFromPath('file2.pdf', '/path/to/file'), -]; -$request = new MergeRequest($files); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` diff --git a/build/docs/content/09-timeout.md b/build/docs/content/09-timeout.md deleted file mode 100644 index c7cbbd70..00000000 --- a/build/docs/content/09-timeout.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Timeout ---- - -All endpoints accept a form field named `waitTimeout`. - -The API will wait the given **seconds** before it considers the conversion to be unsucessful. -If unsucessful, it returns a `504` HTTP code. - -It takes a float as value (e.g `2.5` for 2.5 seconds). - -> You may also define this value globally: see the [environment variables](#environment_variables.default_wait_timeout) section. - -## Examples - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form waitTimeout=2.5 -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.WaitTimeout(2.5) -resp, _ := c.Post(req) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; -use TheCodingMachine\Gotenberg\Request; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setWaitTimeout(2.5); -$dest = 'result.pdf'; -$client->store($request, $dest); -``` diff --git a/build/docs/content/10-webhook.md b/build/docs/content/10-webhook.md deleted file mode 100644 index 3d5e69e1..00000000 --- a/build/docs/content/10-webhook.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Webhook ---- - -All endpoints accept a form field named `webhookURL`. - -If provided, the API will send the resulting PDF file in a `POST` request with the `application/pdf` Content-Type -to given URL. - -By doing so, your requests to the API will be over before the conversions are actually done! - -## Examples - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form webhookURL='http://myapp.com/webhook/' -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.WebhookURL("http://myapp.com/webhook/") -resp, _ := c.Post(req) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setWebhookURL('http://myapp.com/webhook/'); -$resp = $client->post($request); -``` - -## Timeout - -If a `webhookURL` is provided, you may also send a form field named `webhookURLTimeout`. - -The API will wait the given **seconds** before it considers the sending of the resulting PDF to be unsucessful. - -It takes a float as value (e.g `2.5` for 2.5 seconds). - -> You may also define this value globally: see the [environment variables](#environment_variables.default_webhook_url_timeout) section. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form webhookURL='http://myapp.com/webhook/' \ - --form webhookURLTimeout=2.5 -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.WebhookURL("http://myapp.com/webhook/") -req.WebhookURLTimeout(2.5) -resp, _ := c.Post(req) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setWebhookURL('http://myapp.com/webhook/'); -$request->setWebhookURLTimeout(2.5); -$resp = $client->post($request); -``` - -## Custom HTTP headers - -You may send your own HTTP headers to the `webhookURL`. - -For instance, by adding the HTTP header `Gotenberg-Webhookurl-Your-Header` to your request, -the API will send a request to the `webhookURL` with the HTTP header `Your-Header`. - -> **Attention:** the API uses a canonical format for the HTTP headers: -> it transforms the first -> letter and any letter following a hyphen to upper case; -> the rest are converted to lowercase. For example, the -> canonical key for `accept-encoding` is `Accept-Encoding`. - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --header 'Gotenberg-Webhookurl-Your-Header: Foo' \ - --form files=@index.html \ - --form webhookURL='http://myapp.com/webhook/' -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.WebhookURL("http://myapp.com/webhook/") -req.AddWebhookURLHTTPHeader("Your-Header", "Foo") -resp, _ := c.Post(req) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setWebhookURL('http://myapp.com/webhook/'); -$request->addWebhookURLHTTPHeader('Your-Header', 'Foo'); -$resp = $client->post($request); -``` \ No newline at end of file diff --git a/build/docs/content/11-result-filename.md b/build/docs/content/11-result-filename.md deleted file mode 100644 index 94bc230f..00000000 --- a/build/docs/content/11-result-filename.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Result filename ---- - -All endpoints accept a form field named `resultFilename`. - -If provided, the API will return the resulting PDF file with the given filename. -Otherwise a random filename is used. - -> **Attention:** this feature does not work if the form field `webhookURL` is given. - -## Examples - -### cURL - -```bash -$ curl --request POST \ - --url http://localhost:3000/convert/html \ - --header 'Content-Type: multipart/form-data' \ - --form files=@index.html \ - --form resultFilename='foo.pdf' -``` - -### Go - -```golang -import "github.com/thecodingmachine/gotenberg-go-client/v7" - -c := &gotenberg.Client{Hostname: "http://localhost:3000"} -index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file") -req := gotenberg.NewHTMLRequest(index) -req.ResultFilename("foo.pdf") -resp, _ := c.Post(req) -``` - -### PHP - -```php -use TheCodingMachine\Gotenberg\Client; -use TheCodingMachine\Gotenberg\DocumentFactory; -use TheCodingMachine\Gotenberg\HTMLRequest; -use TheCodingMachine\Gotenberg\Request; - -$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()); -$index = DocumentFactory::makeFromPath('index.html', '/path/to/file'); -$request = new HTMLRequest($index); -$request->setResultFilename('foo.pdf'); -$resp = $client->post($request); -``` diff --git a/build/docs/content/12-scalability.md b/build/docs/content/12-scalability.md deleted file mode 100644 index 9c35545e..00000000 --- a/build/docs/content/12-scalability.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Scalability ---- - -The API uses under the hood intricate programs. - -Gotenberg tries to abstract as much complexity as possible but it can -only do it to a certain extent. - -For instance, [Office](#office) and [Merge](#merge) endpoints will start respectively as many LibreOffice (unoconv) and PDTk -instances as there are requests. The limitation here is the available memory and CPU usage. - -On another hand, for the [HTML](#html), [URL](#url) and [Markdown](#markdown) endpoints, the API does only 6 conversions in parallel. -Indeed, Google Chrome misbehaves if there are too many concurrent conversions. - -**The more concurrent requests, the more `504` HTTP codes the API will return.** - -> See our [load testing use case](https://github.com/thecodingmachine/gotenberg/tree/master/loadtesting) for more details about the API behaviour under heavy load. - -## Strategies - -### Increase timeout - -You may increase the conversion timeout. In other words, you accept that a conversion takes more time -if the API is under heavy load. - -> See [timeout section](#timeout). - -### Scaling - -The API being stateless, you may scale it as much as you want. - -For instance, using the following Docker Compose file: - -```yaml -version: '3' - -services: - - # your other services - - gotenberg: - image: thecodingmachine/gotenberg:6 -``` - -You may now launch your services using: - -```bash -$ docker-compose up --scale gotenberg=your_number_of_instances -``` - -When requesting the Gotenberg service with your client(s), Docker will automatically -redirect a request to a Gotenberg container according to the round-robin strategy. diff --git a/build/docs/content/13-ping.md b/build/docs/content/13-ping.md deleted file mode 100644 index 1535b607..00000000 --- a/build/docs/content/13-ping.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Ping ---- - -Gotenberg provides the endpoint `/ping` for checking the API availability with -a simple `GET` request. - -Currently this endpoint does nothing special. A better way to monitor -Gotenberg would be by checking the memory usage. - -Also, as the API uses under the hood intricate programs, you should -restart your Gotenberg instances from time to time to ensure a nominal behaviour. diff --git a/build/docs/content/14-fonts.md b/build/docs/content/14-fonts.md deleted file mode 100644 index 2a88ab11..00000000 --- a/build/docs/content/14-fonts.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Fonts ---- - -By default, a handful of fonts are installed. Asian characters are also supported out of the box. - -If you wish to use more fonts, you will have to create your own image: - -```Dockerfile -FROM thecodingmachine/gotenberg:6 - -USER root - -RUN apt-get -y install yourfonts - -USER gotenberg -``` diff --git a/build/docs/content/15-links.md b/build/docs/content/15-links.md deleted file mode 100644 index 68a855e8..00000000 --- a/build/docs/content/15-links.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Links ---- - -

- Gotenberg logo -

- -* Follow the progress on the [GitHub repository](https://github.com/thecodingmachine/gotenberg) -* Follow [@gulnap](https://twitter.com/gulnap) on Twitter -* Thanks to [@mafredri](https://github.com/mafredri) for his help and his wonderful [cdp](https://github.com/mafredri/cdp) library -* OpenAPI documentation for the API can be found [on GitHub](https://github.com/thecodingmachine/gotenberg/blob/master/docs/openapi.yaml) diff --git a/build/base/fonts.conf b/build/fonts.conf similarity index 100% rename from build/base/fonts.conf rename to build/fonts.conf diff --git a/build/lint/Dockerfile b/build/lint/Dockerfile deleted file mode 100644 index 0abf3718..00000000 --- a/build/lint/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -ARG GOLANGCI_LINT_VERSION - -FROM golangci/golangci-lint:v$GOLANGCI_LINT_VERSION - -# |-------------------------------------------------------------------------- -# | Final touch -# |-------------------------------------------------------------------------- -# | -# | Last instructions of this build. -# | - -# Define our working directory outside of $GOPATH (we're using go modules). -WORKDIR /gotenberg/lint - -# Copy our code source. -COPY . . - -# Install module dependencies. -RUN go mod download &&\ - go mod verify - -CMD ["golangci-lint", "run" ,"--tests=false", "--enable-all", "--disable=dupl", "--disable=funlen", "--disable=wsl", "--disable=gocognit", "--disable=gomnd", "--disable=goimports" ] \ No newline at end of file diff --git a/build/package/Dockerfile b/build/package/Dockerfile deleted file mode 100644 index 67a686d2..00000000 --- a/build/package/Dockerfile +++ /dev/null @@ -1,62 +0,0 @@ -# |-------------------------------------------------------------------------- -# | Binary -# |-------------------------------------------------------------------------- -# | -# | Builds Gotenberg binary. -# | - -FROM thecodingmachine/gotenberg:workspace AS workspace - -ARG VERSION - -ENV GOOS=linux \ - GOARCH=amd64 \ - CGO_ENABLED=0 - -# Define our workding outside of $GOPATH (we're using go modules). -WORKDIR /gotenberg/package - -# Install module dependencies. -COPY go.mod go.sum ./ - -RUN go mod download &&\ - go mod verify - -# Copy our source code. -COPY internal ./internal -COPY cmd ./cmd - -# Build our binary. -RUN go build -o gotenberg -ldflags "-X main.version=${VERSION}" cmd/gotenberg/main.go - -FROM thecodingmachine/gotenberg:base - -LABEL authors="Julien Neuhart " - -# |-------------------------------------------------------------------------- -# | Tini -# |-------------------------------------------------------------------------- -# | -# | An helper for reaping zombie processes. -# | - -ARG TINI_VERSION - -ADD https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-static /tini -RUN chmod +x /tini -ENTRYPOINT [ "/tini", "--" ] - -# |-------------------------------------------------------------------------- -# | Final touch -# |-------------------------------------------------------------------------- -# | -# | Last instructions of this build. -# | - -COPY --from=workspace /gotenberg/package/gotenberg /usr/local/bin/ - -USER gotenberg -WORKDIR /gotenberg - -EXPOSE 3000 -CMD [ "gotenberg" ] diff --git a/build/pdftk.sh b/build/pdftk.sh new file mode 100755 index 00000000..8c24b0ec --- /dev/null +++ b/build/pdftk.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +exec java -jar /usr/bin/pdftk-all.jar "$@" \ No newline at end of file diff --git a/build/tests/Dockerfile b/build/tests/Dockerfile deleted file mode 100644 index cccf031a..00000000 --- a/build/tests/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM thecodingmachine/gotenberg:workspace - -# Define our workding outside of $GOPATH (we're using go modules). -USER gotenberg -WORKDIR /gotenberg/tests - -# Install module dependencies. -COPY --chown=gotenberg:gotenberg go.mod go.sum ./ - -RUN go mod download &&\ - go mod verify - -# Copy our code source. -COPY --chown=gotenberg:gotenberg . . - -ENTRYPOINT [ "build/tests/docker-entrypoint.sh" ] \ No newline at end of file diff --git a/build/tests/docker-entrypoint.sh b/build/tests/docker-entrypoint.sh deleted file mode 100755 index f51b3776..00000000 --- a/build/tests/docker-entrypoint.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -xe - -# Make sure the user running the -# tests is the Gotenberg user. -CURRENT_USER=$(whoami) -if [ "$CURRENT_USER" != "gotenberg" ]; then - exit 1 -fi - -# Start Google Chrome headless. -go run test/cmd/chrome.go - -# Run our tests. -if [ "$CODE_COVERAGE" = "1" ]; then - go test -race -coverprofile=coverage.txt -covermode=atomic ./... -else - go test -race -cover ./... -fi \ No newline at end of file diff --git a/build/workspace/Dockerfile b/build/workspace/Dockerfile deleted file mode 100644 index ecf13478..00000000 --- a/build/workspace/Dockerfile +++ /dev/null @@ -1,52 +0,0 @@ -ARG GOLANG_VERSION - -FROM golang:${GOLANG_VERSION}-stretch as golang - -FROM thecodingmachine/gotenberg:base - -# |-------------------------------------------------------------------------- -# | Common libraries -# |-------------------------------------------------------------------------- -# | -# | Libraries used in the build process of this image. -# | - -RUN apt-get update && apt-get install -y --no-install-recommends \ - git \ - g++ \ - gcc \ - libc6-dev \ - make \ - pkg-config \ - && rm -rf /var/lib/apt/lists/* - -# |-------------------------------------------------------------------------- -# | Golang -# |-------------------------------------------------------------------------- -# | -# | Installs Golang. -# | - -COPY --from=golang /usr/local/go /usr/local/go - -ENV GOPATH /gotenberg/go -ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH - -RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" &&\ - chmod -R 777 "$GOPATH" - -# |-------------------------------------------------------------------------- -# | Final touch -# |-------------------------------------------------------------------------- -# | -# | Last instructions of this build. -# | - -# Make sure the Gotenber user is able to -# call the Go binary. -USER gotenberg - -RUN go version &&\ - go env - -USER root \ No newline at end of file diff --git a/cmd/gotenberg/main.go b/cmd/gotenberg/main.go index f6c0d3fd..0630f5cc 100644 --- a/cmd/gotenberg/main.go +++ b/cmd/gotenberg/main.go @@ -1,64 +1,16 @@ package main import ( - "errors" - "fmt" - "net/http" - "os" - "os/signal" + gotenbergapp "github.com/gotenberg/gotenberg/v7/internal/app/gotenberg" - "github.com/thecodingmachine/gotenberg/internal/app/xhttp" - "github.com/thecodingmachine/gotenberg/internal/pkg/chrome" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xcontext" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" + // Gotenberg modules. + _ "github.com/gotenberg/gotenberg/v7/pkg/standard" + // PDF engines. + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/pdfengine" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/pdfcpu" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/pdftk" ) -// version will be set on build time. -// nolint: gochecknoglobals -var version = "snapshot" - func main() { - const op string = "main" - config, err := conf.FromEnv() - systemLogger := xlog.New(config.LogLevel(), "system") - if err != nil { - systemLogger.FatalOp(op, err) - } - systemLogger.InfoOpf(op, "Gotenberg %s", version) - systemLogger.DebugOpf(op, "configuration: %+v", config) - if !config.DisableGoogleChrome() { - // start Google Chrome headless. - if err := chrome.Start(systemLogger, config.GoogleChromeIgnoreCertificateErrors()); err != nil { - systemLogger.FatalOp(op, err) - } - } - // create our API. - srv := xhttp.New(config) - // run our API in a goroutine so that it doesn't block. - go func() { - systemLogger.InfoOpf(op, "http server started on port '%d'", config.DefaultListenPort()) - if err := srv.Start(fmt.Sprintf(":%d", config.DefaultListenPort())); err != nil { - if errors.Is(err, http.ErrServerClosed) { - systemLogger.FatalOp(op, err) - } - } - }() - quit := make(chan os.Signal, 1) - // we'll accept graceful shutdowns when quit via SIGINT (Ctrl+C) - // SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught. - signal.Notify(quit, os.Interrupt) - // block until we receive our signal. - <-quit - // create a deadline to wait for. - ctx, cancel := xcontext.WithTimeout(systemLogger, 120) - defer cancel() - // doesn't block if no connections, but will otherwise wait - // until the timeout deadline. - systemLogger.InfoOp(op, "shutting down http server...") - if err := srv.Shutdown(ctx); err != nil { - systemLogger.FatalOp(op, err) - } - systemLogger.InfoOp(op, "bye!") - os.Exit(0) + gotenbergapp.Run() } diff --git a/docs/index.html b/docs/index.html deleted file mode 100755 index b2171dd3..00000000 --- a/docs/index.html +++ /dev/null @@ -1,1797 +0,0 @@ - - - - - - - - Gotenberg · A Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF. - - - - - - - - - - - - - - - - -
-
-
-
- Gotenberg logo - Gotenberg - A Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF. -
-
- -
- - -
- -
-

Introduction

-

Gotenberg is a Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF.

- -
    -
  • HTML and Markdown conversions using Google Chrome headless
  • -
  • Office conversions (.txt, .rtf, .docx, .doc, .odt, .pptx, .ppt, .odp and so on) using unoconv
  • -
  • Assets: send your header, footer, images, fonts, stylesheets and so on for converting your HTML and Markdown to beaufitul PDFs!
  • -
  • Easily interact with the API using our Go and PHP libraries
  • -
- -
- -
-

Install

-

Gotenberg is shipped within a Docker image.

- -

Gotenberg should ONLY be used in a trusted network by trusted applications. Do NOT expose Gotenberg to the external world.

- -

You may start it with:

- -
$ docker run --rm -p 3000:3000 thecodingmachine/gotenberg:6
-
- -
-

The API will be available at http://localhost:3000.

-
- -

The image uses a dedicated non-root user called gotenberg with uid and gid 1001.

- -

If you wish to change those uid and gid, you will have to:

- -
    -
  • clone the project
  • -
  • re-build the image
  • -
  • publish the image in your own Docker registry
  • -
- -

For instance:

- -
$ git clone https://github.com/thecodingmachine/gotenberg.git
-$ make publish GOTENBERG_USER_GID=your_custom_gid GOTENBERG_USER_UID=your_custom_uid DOCKER_REGISTRY=your_registry DOCKER_USER=registry_user DOCKER_PASSWORD=registry_password VERSION=version
-
- -
-

master branch is always up-to-date with the latest version of the API.

-
- -

Docker Compose

- -

You may also add it in your Docker Compose stack:

- -
version: '3'
-
-services:
-
-  # your other services
-
-  gotenberg:
-    image: thecodingmachine/gotenberg:6
-
- -
-

The API will be available under gotenberg:3000 in your Docker Compose network.

-
- -

Kubernetes

- -

It may also be deployed with Kubernetes.

- -

Make sure to provide enough memory and CPU requests (for instance 512Mi and 0.2 CPU).

- -
-

The more resources are granted, the quicker will be the conversions.

-
- -

In the deployment specification of the pod, also specify the uid of the user gotenberg:

- -
securityContext:
-  privileged: false
-  runAsUser: 1001
-
- -

Cloud Run (Google Cloud)

- -

If you’re looking for cost savings, you might be interested by Cloud Run. -However, according to some users, doing asynchronous conversion (with a webhook) might not working.

- -

In the following examples, we will assume your -Gotenberg API is available at http://localhost:3000.

- -
- -
-

Clients

-

We provide clients in various languages for easing the interactions with the API.

- -

Go client

- -
$ go get -u github.com/thecodingmachine/gotenberg-go-client/v7
-
- -

See also the example from the README.

- -

PHP client

- -

Unless your project already has a PSR7 HttpClient, install php-http/guzzle6-adapter:

- -
$ composer require php-http/guzzle6-adapter
-
- -

Then the PHP client:

- -
$ composer require thecodingmachine/gotenberg-php-client
-
- -

See also the example from the README.

- -

Community clients

- - - -
- -
-

Environment variables

-

You may customize the API behaviour thanks to environment variables.

- -

Log level

- -

The API provides structured logging allowing you to have relevant information -about what’s going on.

- -
-

If a TTY is attached, the log entries are displayed in text format with colors, otherwise in JSON format.

-
- -

You may customize the severity of the log entries thanks to the environment variable LOG_LEVEL.

- -

It accepts one of the following severities: "DEBUG", "INFO" (default) and "ERROR".

- -

Default listen port

- -

By default, the API will listen on port 3000.

- -

You may customize this value with the environment variable DEFAULT_LISTEN_PORT.

- -

This environment variable accepts any string that can be turned into a port number.

- -

Root path

- -

By default, the API root path is /.

- -

You may customize this value with the environment variable ROOT_PATH.

- -

This environment variable accepts a string starting and ending with /.

- -

For instance, /gotenberg/ is a valid value while gotenberg is not.

- -
-

This is useful if you wish to do service discovery via URL paths.

-
- -

Disable Google Chrome

- -

In order to save some resources, the Gotenberg image accepts the environment variable DISABLE_GOOGLE_CHROME -for disabling Google Chrome.

- -

It takes the strings "0" or "1" as value where 1 means true

- -
-

If Google Chrome is disabled, the following conversions will not be available anymore: -HTML, URL and Markdown

-
- -

Default Google Chrome rpcc buffer size

- -

When performing a HTML, URL or Markdown conversion, the API might return -a 400 HTTP code with the message increase the Google Chrome rpcc buffer size.

- -

If so, you may increase this buffer size with the environment variable DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE.

- -

It takes a string representation of an int as value (e.g. "1048576" for 1 MB). -The hard limit is 100 MB and is defined by Google Chrome itself.

- -
-

The default Google Chrome rpcc buffer size may also be overridden per request thanks to the form field googleChromeRpccBufferSize. -See the rpcc buffer size section.

-
- -

Google Chrome ignore certificate errors

- -

When performing a URL conversion, Google Chrome will not accept certificate errors.

- -

You may allow insecure connections by setting the GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS environment variable to "1".

- -

You should be careful with this feature and only enable it in your development environment.

- -

Disable LibreOffice (unoconv)

- -

You may also disable LibreOffice (unoconv) with DISABLE_UNOCONV.

- -
-

If LibreOffice (unoconv) is disabled, the following conversion will not be available anymore: -Office

-
- -

Default wait timeout

- -

By default, the API will wait 10 seconds before it considers the conversion to be unsuccessful. -If unsucessful, it returns a 504 HTTP code.

- -

You may customize this timeout thanks to the environment variable DEFAULT_WAIT_TIMEOUT.

- -

It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).

- -
-

The default timeout may also be overridden per request thanks to the form field waitTimeout. -See the timeout section.

-
- -

Maximum wait timeout

- -

By default, the value of the form field waitTimeout cannot be more than 30 seconds.

- -

You may increase or decrease this limit thanks to the environment variable MAXIMUM_WAIT_TIMEOUT.

- -

It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).

- -

Default webhook URL timeout

- -

By default, the API will wait 10 seconds before it considers the sending of the resulting PDF to be unsuccessful.

- -
-

See the webhook section.

-
- -

You may customize this timeout thanks to the environment variable DEFAULT_WEBHOOK_URL_TIMEOUT.

- -

It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).

- -
-

The default timeout may also be overridden per request thanks to the form field webhookURLTimeout. -See the webhook timeout section.

-
- -

Maximum webhook URL timeout

- -

By default, the value of the form field webhookURLTimeout cannot be more than 30 seconds.

- -

You may increase or decrease this limit thanks to the environment variable MAXIMUM_WEBHOOK_URL_TIMEOUT.

- -

It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).

- -

Maximum wait delay

- -

By default, the value of the form field waitDelay cannot be more than 10 seconds.

- -
-

See the wait delay section.

-
- -

You may increase or decrease this limit thanks to the environment variable MAXIMUM_WAIT_DELAY.

- -

It takes a string representation of a float as value (e.g "2.5" for 2.5 seconds).

- -
- -
-

HTML

-

Gotenberg provides the endpoint /convert/html for HTML conversions.

- -

It accepts POST requests with a multipart/form-data Content-Type.

- -

Basic

- -

The only requirement is to send a file named index.html: it is the file -which will be converted to PDF.

- -

For instance:

- -
<!doctype html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <title>My PDF</title>
-  </head>
-  <body>
-    <h1>Hello world!</h1>
-  </body>
-</html>
-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Header and footer

- -

You may also add a header and/or a footer in the resulting PDF. -Respectively, a file named header.html and footer.html.

- -

Each of them has to be a complete HTML document:

- -
<html>
-    <head>
-        <style>
-            body {
-                font-size: 8rem;
-                margin: 4rem auto;
-            }
-        </style>
-    </head>
-    <body>
-        <p>
-            <span class="pageNumber"></span> of <span class="totalPages"></span>
-        </p>
-    </body>
-</html>
-
- -

The following classes allow you to inject printing values:

- -
    -
  • date: formatted print date
  • -
  • title: document title
  • -
  • pageNumber: current page number
  • -
  • totalPage: total pages in the document
  • -
- -

There are some limitations:

- -
    -
  • JavaScript is not executed
  • -
  • external resources are not loaded
  • -
  • the CSS properties are independant of the ones used in the index.html file
  • -
  • footer.html CSS properties override the ones from header.html
  • -
  • only fonts installed in the Docker image are loaded (see the fonts section)
  • -
  • images only work using a base64 encoded source (<img src="data:image/png;base64, iVBORw0K... />)
  • -
  • background-color and color CSS properties require an additional -webkit-print-color-adjust: exact CSS property in order to work
  • -
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form files=@header.html \
-    --form files=@footer.html \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-header, _ := gotenberg.NewDocumentFromPath("header.html", "/path/to/file")
-footer, _ := gotenberg.NewDocumentFromPath("footer.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.Header(header)
-req.Footer(footer)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$header = DocumentFactory::makeFromPath('header.html', '/path/to/file');
-$footer = DocumentFactory::makeFromPath('footer.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setHeader($header);
-$request->setFooter($footer);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Assets

- -

You may also send additional files. For instance: images, fonts, stylesheets and so on.

- -

The only requirement is to make sure that their paths -are on the same level as the index.html file.

- -

In other words, this will work:

- -
<!doctype html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <title>My PDF</title>
-  </head>
-  <body>
-    <h1>Hello world!</h1>
-    <img src="img.png">
-  </body>
-</html>
-
- -

But this won’t:

- -
<!doctype html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <title>My PDF</title>
-  </head>
-  <body>
-    <h1>Hello world!</h1>
-    <img src="/foo/img.png">
-  </body>
-</html>
-
- -

You may also use remote paths for Google fonts, images and so on.

- -
-

If you want to install fonts directly in the Gotenberg Docker image, -see to the fonts section.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form files=@style.css \
-    --form files=@img.png \
-    --form files=@font.woff \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-style, _ := gotenberg.NewDocumentFromPath("style.css", "/path/to/file")
-img, _ := gotenberg.NewDocumentFromPath("img.png", "/path/to/file")
-font, _ := gotenberg.NewDocumentFromPath("font.woff", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.Assets(style, img, font)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$assets = [
-    DocumentFactory::makeFromPath('style.css', '/path/to/file'),
-    DocumentFactory::makeFromPath('img.png', '/path/to/file'),
-    DocumentFactory::makeFromPath('font.woff', '/path/to/file'),
-];
-$request = new HTMLRequest($index);
-$request->setAssets($assets);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Paper size, margins, orientation, scaling

- -

You may also customize the resulting PDF format.

- -

By default, it will be rendered with A4 size, 1 inch margins and portrait orientation and 100% (1.0) page scale.

- -
-

Paper size and margins have to be provided in inches. Same for margins.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form paperWidth=8.27 \
-    --form paperHeight=11.69 \
-    --form marginTop=0 \
-    --form marginBottom=0 \
-    --form marginLeft=0 \
-    --form marginRight=0 \
-    --form landscape=true \
-    --form scale=0.75 \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.PaperSize(gotenberg.A4)
-req.Margins(gotenberg.NoMargins)
-req.Landscape(true)
-req.Scale(0.75)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-use TheCodingMachine\Gotenberg\Request;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setPaperSize(Request::A4);
-$request->setMargins(Request::NO_MARGINS);
-$request->setLandscape(true);
-$request->setScale(0.75);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Page ranges

- -

You may specify the page ranges to convert.

- -

The format is the same as the one from the print options -of Google Chrome, e.g. 1-5,8,11-13.

- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form pageRanges='1-3,5' \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.PageRanges("1-3,5")
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-use TheCodingMachine\Gotenberg\Request;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setPageRanges('1-3,5');
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Wait delay

- -

In some cases, you may want to wait a certain amount of time to make sure the -page you’re trying to generate is fully rendered. For instance, if your page relies -a lot on JavaScript for rendering.

- -
-

The wait delay is a duration in seconds (e.g 2.5 for 2.5 seconds).

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form waitDelay=5.5 \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.WaitDelay(5.5)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-use TheCodingMachine\Gotenberg\Request;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setWaitDelay(5.5);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Rpcc buffer size

- -

The API might return a 400 HTTP code with the message increase the Google Chrome rpcc buffer size.

- -

If so, you may increase this buffer size with a form field named googleChromeRpccBufferSize.

- -

It takes an int as value (e.g. 1048576 for 1 MB). -The hard limit is 100 MB and is defined by Google Chrome itself.

- -
-

You may also define this value globally: see the environment variables section.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form googleChromeRpccBufferSize=1048576 \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.GoogleChromeRpccBufferSize(1048576)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-use TheCodingMachine\Gotenberg\Request;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setGoogleChromeRpccBufferSize(1048576);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -
- -
-

URL

-

Gotenberg provides the endpoint /convert/url for remote URL conversions.

- -

It accepts POST requests with a multipart/form-data Content-Type.

- -

Basic

- -

This endpoint does not accept an index.html file nor assets files but a form field -named remoteURL instead. Otherwise, URL conversions work the same as HTML conversions.

- -
-

Attention: when converting a website to PDF, you should remove all margins. -If not, some of the content of the page might be hidden.

- -

Attention: if you try to convert a URL from a Docker Compose service named app (i.e. removeURL = http://app/an/entrypoint), -the resulting PDF will be blank. Make sure to rename your service to avoid this issue.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/url \
-    --header 'Content-Type: multipart/form-data' \
-    --form remoteURL=https://google.com \
-    --form marginTop=0 \
-    --form marginBottom=0 \
-    --form marginLeft=0 \
-    --form marginRight=0 \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-req := gotenberg.NewURLRequest("https://google.com")
-req.Margins(gotenberg.NoMargins)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\URLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$request = new URLRequest('https://google.com');
-$request->setMargins(Request::NO_MARGINS);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Custom HTTP headers

- -

You may send your own HTTP headers to the remoteURL.

- -

For instance, by adding the HTTP header Gotenberg-Remoteurl-Your-Header to your request, -the API will send a request to the remoteURL with the HTTP header Your-Header.

- -
-

Attention: the API uses a canonical format for the HTTP headers: -it transforms the first -letter and any letter following a hyphen to upper case; -the rest are converted to lowercase. For example, the -canonical key for accept-encoding is Accept-Encoding.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/url \
-    --header 'Content-Type: multipart/form-data' \
-    --header 'Gotenberg-Remoteurl-Your-Header: Foo' \
-    --form remoteURL=https://google.com \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-req := gotenberg.NewURLRequest("https://google.com")
-req.AddRemoteURLHTTPHeader("Your-Header", "Foo")
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\URLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$request = new URLRequest('https://google.com');
-$request->addRemoteURLHTTPHeader('Your-Header', 'Foo')
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -
- -
-

Markdown

-

Gotenberg provides the endpoint /convert/markdown for Markdown conversions.

- -

It accepts POST requests with a multipart/form-data Content-Type.

- -

Basic

- -

Markdown conversions work the same as HTML conversions.

- -

Only difference is that you have access to the Go template function toHTML -in the file index.html. This function will convert a given markdown file to HTML.

- -

For instance:

- -
<!doctype html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <title>My PDF</title>
-  </head>
-  <body>
-    {{ toHTML .DirPath "file.md" }}
-  </body>
-</html>
-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/markdown \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form files=@file.md \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-markdown, _ := gotenberg.NewDocumentFromPath("file.md", "/path/to/file")
-req := gotenberg.NewMarkdownRequest(index, markdown)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\MarkdownRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$markdowns = [
-    DocumentFactory::makeFromPath('file.md', '/path/to/file'),
-];
-$request = new MarkdownRequest($index, $markdowns);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -
- -
-

Office

-

Gotenberg provides the endpoint /convert/office for Office document conversions.

- -

It accepts POST requests with a multipart/form-data Content-Type.

- -

Basic

- -

You may send one or more Office documents. Following file extensions are accepted:

- -
    -
  • .txt
  • -
  • .rtf
  • -
  • .fodt
  • -
  • .doc
  • -
  • .docx
  • -
  • .odt
  • -
  • .xls
  • -
  • .xlsx
  • -
  • .ods
  • -
  • .ppt
  • -
  • .pptx
  • -
  • .odp
  • -
- -

All files will be merged into a single resulting PDF.

- -
-

Attention: Gotenberg merges the PDF files alphabetically.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/office \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@document.docx \
-    --form files=@document2.docx \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-doc, _ := gotenberg.NewDocumentFromPath("document.docx", "/path/to/file")
-doc2, _ := gotenberg.NewDocumentFromPath("document2.docx", "/path/to/file")
-req := gotenberg.NewOfficeRequest(doc, doc2)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\OfficeRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$files = [
-    DocumentFactory::makeFromPath('document.docx', '/path/to/file'),
-    DocumentFactory::makeFromPath('document2.docx', '/path/to/file'),
-];
-$request = new OfficeRequest($files);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Orientation

- -

You may also customize the resulting PDF format.

- -

By default, it will be rendered with portrait orientation.

- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/office \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@document.docx \
-    --form landscape=true \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-doc, _ := gotenberg.NewDocumentFromPath("document.docx", "/path/to/file")
-req := gotenberg.NewOfficeRequest(doc)
-req.Landscape(true)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\OfficeRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$files = [
-    DocumentFactory::makeFromPath('document.docx', '/path/to/file'),
-];
-$request = new OfficeRequest($files);
-$request->setLandscape(true);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -

Page ranges

- -

You may specify the page ranges to convert.

- -

The format is the same as the one from the print options -of LibreOffice, e.g. 1-1 or 1-4.

- -
-

Attention: if more than one document, the page ranges will be -applied for each document.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/office \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@document.docx \
-    --form pageRanges='1-3' \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-doc, _ := gotenberg.NewDocumentFromPath("document.docx", "/path/to/file")
-req := gotenberg.NewOfficeRequest(doc)
-req.PageRanges("1-3")
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\OfficeRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$files = [
-    DocumentFactory::makeFromPath('document.docx', '/path/to/file'),
-];
-$request = new OfficeRequest($files);
-$request->setPageRanges('1-3');
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -
- -
-

Merge

-

Gotenberg provides the endpoint /merge for merging PDFs.

- -

It accepts POST requests with a multipart/form-data Content-Type.

- -

Basic

- -

Nothing fancy here: you may send one or more PDF files and the API -will merge them and return the resulting PDF file.

- -
-

Attention: Gotenberg merges the PDF files alphabetically.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/merge \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@file.pdf \
-    --form files=@file2.pdf \
-    -o result.pdf
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-pdf, _ := gotenberg.NewDocumentFromPath("file.pdf", "/path/to/file")
-pdf2, _ := gotenberg.NewDocumentFromPath("file2.pdf", "/path/to/file")
-req := gotenberg.NewMergeRequest(pdf, pdf2)
-dest := "result.pdf"
-c.Store(req, dest)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\MergeRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$files = [
-    DocumentFactory::makeFromPath('file.pdf', '/path/to/file'),
-    DocumentFactory::makeFromPath('file2.pdf', '/path/to/file'),
-];
-$request = new MergeRequest($files);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -
- -
-

Timeout

-

All endpoints accept a form field named waitTimeout.

- -

The API will wait the given seconds before it considers the conversion to be unsucessful. -If unsucessful, it returns a 504 HTTP code.

- -

It takes a float as value (e.g 2.5 for 2.5 seconds).

- -
-

You may also define this value globally: see the environment variables section.

-
- -

Examples

- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form waitTimeout=2.5
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.WaitTimeout(2.5)
-resp, _ := c.Post(req)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-use TheCodingMachine\Gotenberg\Request;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setWaitTimeout(2.5);
-$dest = 'result.pdf';
-$client->store($request, $dest);
-
- -
- -
-

Webhook

-

All endpoints accept a form field named webhookURL.

- -

If provided, the API will send the resulting PDF file in a POST request with the application/pdf Content-Type -to given URL.

- -

By doing so, your requests to the API will be over before the conversions are actually done!

- -

Examples

- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form webhookURL='http://myapp.com/webhook/'
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.WebhookURL("http://myapp.com/webhook/")
-resp, _ := c.Post(req)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setWebhookURL('http://myapp.com/webhook/');
-$resp = $client->post($request);
-
- -

Timeout

- -

If a webhookURL is provided, you may also send a form field named webhookURLTimeout.

- -

The API will wait the given seconds before it considers the sending of the resulting PDF to be unsucessful.

- -

It takes a float as value (e.g 2.5 for 2.5 seconds).

- -
-

You may also define this value globally: see the environment variables section.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form webhookURL='http://myapp.com/webhook/' \
-    --form webhookURLTimeout=2.5
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.WebhookURL("http://myapp.com/webhook/")
-req.WebhookURLTimeout(2.5)
-resp, _ := c.Post(req)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setWebhookURL('http://myapp.com/webhook/');
-$request->setWebhookURLTimeout(2.5);
-$resp = $client->post($request);
-
- -

Custom HTTP headers

- -

You may send your own HTTP headers to the webhookURL.

- -

For instance, by adding the HTTP header Gotenberg-Webhookurl-Your-Header to your request, -the API will send a request to the webhookURL with the HTTP header Your-Header.

- -
-

Attention: the API uses a canonical format for the HTTP headers: -it transforms the first -letter and any letter following a hyphen to upper case; -the rest are converted to lowercase. For example, the -canonical key for accept-encoding is Accept-Encoding.

-
- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --header 'Gotenberg-Webhookurl-Your-Header: Foo' \
-    --form files=@index.html \
-    --form webhookURL='http://myapp.com/webhook/'
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.WebhookURL("http://myapp.com/webhook/")
-req.AddWebhookURLHTTPHeader("Your-Header", "Foo")
-resp, _ := c.Post(req)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setWebhookURL('http://myapp.com/webhook/');
-$request->addWebhookURLHTTPHeader('Your-Header', 'Foo');
-$resp = $client->post($request);
-
- -
- -
-

Result filename

-

All endpoints accept a form field named resultFilename.

- -

If provided, the API will return the resulting PDF file with the given filename. -Otherwise a random filename is used.

- -
-

Attention: this feature does not work if the form field webhookURL is given.

-
- -

Examples

- -

cURL

- -
$ curl --request POST \
-    --url http://localhost:3000/convert/html \
-    --header 'Content-Type: multipart/form-data' \
-    --form files=@index.html \
-    --form resultFilename='foo.pdf'
-
- -

Go

- -
import "github.com/thecodingmachine/gotenberg-go-client/v7"
-
-c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
-req := gotenberg.NewHTMLRequest(index)
-req.ResultFilename("foo.pdf")
-resp, _ := c.Post(req)
-
- -

PHP

- -
use TheCodingMachine\Gotenberg\Client;
-use TheCodingMachine\Gotenberg\DocumentFactory;
-use TheCodingMachine\Gotenberg\HTMLRequest;
-use TheCodingMachine\Gotenberg\Request;
-
-$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
-$index = DocumentFactory::makeFromPath('index.html', '/path/to/file');
-$request = new HTMLRequest($index);
-$request->setResultFilename('foo.pdf');
-$resp = $client->post($request);
-
- -
- -
-

Scalability

-

The API uses under the hood intricate programs.

- -

Gotenberg tries to abstract as much complexity as possible but it can -only do it to a certain extent.

- -

For instance, Office and Merge endpoints will start respectively as many LibreOffice (unoconv) and PDTk -instances as there are requests. The limitation here is the available memory and CPU usage.

- -

On another hand, for the HTML, URL and Markdown endpoints, the API does only 6 conversions in parallel. -Indeed, Google Chrome misbehaves if there are too many concurrent conversions.

- -

The more concurrent requests, the more 504 HTTP codes the API will return.

- -
-

See our load testing use case for more details about the API behaviour under heavy load.

-
- -

Strategies

- -

Increase timeout

- -

You may increase the conversion timeout. In other words, you accept that a conversion takes more time -if the API is under heavy load.

- -
-

See timeout section.

-
- -

Scaling

- -

The API being stateless, you may scale it as much as you want.

- -

For instance, using the following Docker Compose file:

- -
version: '3'
-
-services:
-
-  # your other services
-
-  gotenberg:
-    image: thecodingmachine/gotenberg:6
-
- -

You may now launch your services using:

- -
$ docker-compose up --scale gotenberg=your_number_of_instances
-
- -

When requesting the Gotenberg service with your client(s), Docker will automatically -redirect a request to a Gotenberg container according to the round-robin strategy.

- -
- -
-

Ping

-

Gotenberg provides the endpoint /ping for checking the API availability with -a simple GET request.

- -

Currently this endpoint does nothing special. A better way to monitor -Gotenberg would be by checking the memory usage.

- -

Also, as the API uses under the hood intricate programs, you should -restart your Gotenberg instances from time to time to ensure a nominal behaviour.

- -
- -
-

Fonts

-

By default, a handful of fonts are installed. Asian characters are also supported out of the box.

- -

If you wish to use more fonts, you will have to create your own image:

- -
FROM thecodingmachine/gotenberg:6
-
-USER root
-
-RUN apt-get -y install yourfonts
-
-USER gotenberg
-
- -
- - - - - -
-
-
- - -
\ No newline at end of file diff --git a/docs/openapi.yaml b/docs/openapi.yaml deleted file mode 100644 index 5e487067..00000000 --- a/docs/openapi.yaml +++ /dev/null @@ -1,569 +0,0 @@ -openapi: 3.0.0 -info: - title: Gotenberg - version: 6.3.1 - license: - name: MIT - url: 'https://github.com/thecodingmachine/gotenberg/blob/master/LICENSE' - contact: - url: 'https://github.com/thecodingmachine/gotenberg' - description: >- - A Docker-powered stateless API for converting HTML, Markdown and Office - documents to PDF. -servers: - - url: 'http://localhost:3000' - description: Local server with the default Docker image and port -paths: - /convert/html: - post: - tags: - - Gotenberg - summary: Convert a given HTML file to PDF - description: >- - Send an HTML file called `index.html` as a multipart form request, and - get the resulting PDF file. You can optionally include `header.html` and - `footer.html` files as part of the request as well. - - - An example `index.html` file can be as follows: - - ```html - - - - - - - My PDF - - -

Hello world!

- - - - ``` - - - You may also add a header and/or a footer in the resulting PDF by - sending a file named `header.html` and `footer.html` respectively. Both - the header and the footer files has to be a complete HTML document. An - example `footer.html` can be as follows: - - ```html - - - - - - -

- of -

- - - - ``` - - - The following classes will allow you to inject printing values in your - document: - - - `date`: Formatted print date. - - - `title`: Document title. - - - `pageNumber`: Current page number. - - - `totalPage`: Total pages in the document. - - - There are some limitations with header and footer files: - - - JavaScript is not executed. - - - External resources are not loaded. - - - The CSS properties are independant of the ones used in the - `index.html` file. - - - `footer.html` CSS properties override the ones from `header.html`. - - - Only fonts installed in the Docker image are loaded (see the fonts - section) - - - Images only work using a `base64` encoded source, e.g. ` - - - My PDF - - - {{ toHTML .DirPath "file.md" }} - - - - ``` - - - Whereas your `file.md` file in the same level would be like: - - ```md - - # Title - - Content - - ``` - - - The API will convert the markdown to HTML and embed it into your - `index.html` file, then render the resulting page. You can include your - own styling and more in your HTML file. - requestBody: - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/MarkdownConvertRequestBody' - description: >- - The request body must have an `index.html` file in the `files` array, - as well as all the referred markdown resources on the same level as - the `index.html` file. - responses: - '200': - $ref: '#/components/responses/SuccessfulPDF' - /convert/office: - post: - tags: - - Gotenberg - summary: Convert an Office document to PDF - description: >- - Send one or more Office documents and get the resulting PDF file by - merging all the files. The following file extensions are accepted: - - - `.txt` - - - `.rtf` - - - `.fodt` - - - `.doc` - - - `.docx` - - - `.odt` - - - `.xls` - - - `.xlsx` - - - `.ods` - - - `.ppt` - - - `.pptx` - - - `.odp` - - - All files will be merged into a single PDF. - - > **Attention:** The files will be merged alphabetically for the - resulting PDF. - - - You may also specify the page ranges to convert from the incoming Office - documents. The expected format is the same as the one from the print - options of LibreOffice, e.g. `1-1` or `1-4`. - - - > **Attention:** if more than one document, the page ranges will be - applied for each document. - requestBody: - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/OfficeConvertRequestBody' - description: >- - The request body must have an `index.html` file in the `files` array, - as well as all the referred markdown resources on the same level as - the `index.html` file. - responses: - '200': - $ref: '#/components/responses/SuccessfulPDF' - content: - application/json: - schema: - type: object - properties: {} - /convert/merge: - post: - tags: - - Gotenberg - summary: Merge multiple PDFs into a single PDF - description: >- - You can send multiple PDF files to this endpoint, the API will merge - them into a single PDF and return the resulting PDF file. - - - > **Attention:** The PDF files will be merged alphabetically. - requestBody: - content: - multipart/form-data: - schema: - type: object - properties: - files: - type: array - description: >- - List of HTML files to be converted to PDF. An `index.html` - file is required, and any other resources that are - referenced through the HTML file must be included as well. - All the referenced files must be on the same level as the - `index.html` file. - items: - type: string - format: binary - resultFilename: - type: string - example: output.pdf - description: >- - If provided, the API will return the resulting PDF file with - the given filename. Otherwise a random filename is used. - required: - - files - description: >- - The request body must have an `index.html` file in the `files` array, - as well as all the referred markdown resources on the same level as - the `index.html` file. - responses: - '200': - $ref: '#/components/responses/SuccessfulPDF' - /ping: - get: - tags: - - Gotenberg - summary: Your GET endpoint - responses: - '200': - description: The API is working fine. - operationId: '' - description: >- - A simple endpoint to use as a healthcheck for the API availability with - a simple request. -components: - schemas: - HTMLConvertRequestBody: - title: HTML Conversion Request Body - type: object - properties: - files: - type: array - description: >- - List of HTML files to be converted to PDF. An `index.html` file is - required, and any other resources that are referenced through the - HTML file must be included as well. All the referenced files must be - on the same level as the `index.html` file. - items: - type: string - format: binary - marginTop: - type: number - example: 0 - default: 1 - description: Top margin for the page in inches. - marginBottom: - type: number - example: 0 - default: 1 - description: Bottom margin for the page in inches. - marginLeft: - type: number - example: 0 - default: 1 - description: Left margin for the page in inches. - marginRight: - type: number - example: 0 - default: 1 - description: Right margin for the page in inches. - paperWidth: - type: number - example: 8.27 - description: >- - Paper width to be used while rendering the PDF. The default page - size is A4. - paperHeight: - type: number - example: 11.69 - description: >- - Paper height to be used while rendering the PDF. The default page - size is A4. - landscape: - type: boolean - example: true - default: false - description: >- - The default orientation for rendering the page is "portrait" mode. - By sending "landscape" parameter, you can ask the output to be - landscape. - resultFilename: - type: string - example: output.pdf - description: >- - If provided, the API will return the resulting PDF file with the - given filename. Otherwise a random filename is used. - required: - - files - MarkdownConvertRequestBody: - title: Markdown Conversion Request Body - type: object - properties: - files: - type: array - description: >- - List of HTML files to be converted to PDF. An `index.html` file is - required, and any other resources that are referenced through the - HTML file must be included as well. All the referenced files must be - on the same level as the `index.html` file. - items: - type: string - format: binary - marginTop: - type: number - example: 0 - default: 1 - description: Top margin for the page in inches. - marginBottom: - type: number - example: 0 - default: 1 - description: Bottom margin for the page in inches. - marginLeft: - type: number - example: 0 - default: 1 - description: Left margin for the page in inches. - marginRight: - type: number - example: 0 - default: 1 - description: Right margin for the page in inches. - paperWidth: - type: number - example: 8.27 - description: >- - Paper width to be used while rendering the PDF. The default page - size is A4. - paperHeight: - type: number - example: 11.69 - description: >- - Paper height to be used while rendering the PDF. The default page - size is A4. - landscape: - type: boolean - example: true - default: false - description: >- - The default orientation for rendering the page is "portrait" mode. - By sending "landscape" parameter, you can ask the output to be - landscape. - resultFilename: - type: string - example: output.pdf - description: >- - If provided, the API will return the resulting PDF file with the - given filename. Otherwise a random filename is used. - required: - - files - URLConvertRequestBody: - title: URL Conversion Request Body - type: object - properties: - remoteURL: - type: string - example: 'https://google.com' - marginTop: - type: number - example: 0 - default: 1 - description: Top margin for the page in inches. - marginBottom: - type: number - example: 0 - default: 1 - description: Bottom margin for the page in inches. - marginLeft: - type: number - example: 0 - default: 1 - description: Left margin for the page in inches. - marginRight: - type: number - example: 0 - default: 1 - description: Right margin for the page in inches. - paperWidth: - type: number - example: 8.27 - description: >- - Paper width to be used while rendering the PDF. The default page - size is A4. - paperHeight: - type: number - example: 11.69 - description: >- - Paper height to be used while rendering the PDF. The default page - size is A4. - landscape: - type: boolean - example: true - default: false - description: >- - The default orientation for rendering the page is "portrait" mode. - By sending "landscape" parameter, you can ask the output to be - landscape. - resultFilename: - type: string - example: output.pdf - description: >- - If provided, the API will return the resulting PDF file with the - given filename. Otherwise a random filename is used. - required: - - remoteURL - OfficeConvertRequestBody: - title: Office Conversion Request Body - type: object - properties: - files: - type: array - description: >- - List of HTML files to be converted to PDF. An `index.html` file is - required, and any other resources that are referenced through the - HTML file must be included as well. All the referenced files must be - on the same level as the `index.html` file. - items: - type: string - format: binary - pageRanges: - type: string - example: 1-3 - description: >- - The page ranges to be converted to PDF for the incoming Office - documents. **If there are multiple files sent to the API, this page - range will apply to all of the documents**. - landscape: - type: boolean - example: true - default: false - description: >- - The default orientation for rendering the page is "portrait" mode. - By sending "landscape" parameter, you can ask the output to be - landscape. - resultFilename: - type: string - example: output.pdf - description: >- - If provided, the API will return the resulting PDF file with the - given filename. Otherwise a random filename is used. - required: - - files - MergeFilesRequestBody: - title: Merge Files Request Body - type: object - properties: - files: - type: array - description: >- - List of HTML files to be converted to PDF. An `index.html` file is - required, and any other resources that are referenced through the - HTML file must be included as well. All the referenced files must be - on the same level as the `index.html` file. - items: - type: string - format: binary - resultFilename: - type: string - example: output.pdf - description: >- - If provided, the API will return the resulting PDF file with the - given filename. Otherwise a random filename is used. - required: - - files - securitySchemes: {} - responses: - SuccessfulPDF: - description: Resulting PDF file from the conversion. - content: - application/pdf: - schema: - type: string - format: binary diff --git a/docs/theme/gotenberg/css/index.css b/docs/theme/gotenberg/css/index.css deleted file mode 100644 index f92e503e..00000000 --- a/docs/theme/gotenberg/css/index.css +++ /dev/null @@ -1,342 +0,0 @@ -:root { - --ease: cubic-bezier(.82, 0, .12, 1); - --width: 800px; - --header-height: 400px; - - --tracking: 0.05rem; - --tracking-medium: 0.5rem; - --tracking-large: 0.8rem; - - --dark: #000; - --blue: #33A9FF; - --light-gray: #fafafa; - - --bg: #fff; - --fg: #868E96; - --fg-dark: #212529; - - --selection-bg: var(--blue); - --selection-fg: white; -} - -* { - box-sizing: border-box; -} - -html, body { - font-family: -apple-system, BlinkMacSystemFont, - "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", - "Droid Sans", "Helvetica Neue", sans-serif; - -webkit-font-smoothing: antialiased; - font-size: 16px; - font-weight: 300; - background: var(--bg); - color: var(--fg-dark); - line-height: 1; - margin: 0; - padding: 0; -} - -::selection { - background: var(--selection-bg); - color: var(--selection-fg); -} - -h1, h2, h3, h4 { - margin-top: 75px; - margin-bottom: 0; - font-size: 1.2rem; - font-weight: 600; - line-height: 1.5rem; - color: var(--fg-dark); -} - -h1 { - margin-top: 0; - font-size: 1.5rem; -} - -h1 + p { - font-size: 1.5rem; - line-height: 1.6; -} - -h3 { - font-size: 1.0rem; - font-style: italic; -} - -a { - color: inherit; - text-decoration: none; -} - -p { - margin: 25px 0; - line-height: 1.6; - color: var(--fg-color-light); -} - -li strong, -p strong { - color: var(--fg-dark); - font-weight: 500; -} - -li a, -p a { - color: var(--fg-dark); - font-weight: 400; - padding-bottom: 3px; - border-bottom: 1px dotted #ddd; -} - -li a:hover, -p a:hover { - color: var(--blue); - border-bottom: none; -} - -p a:hover { - border-bottom-color: var(--color); -} - -ul { - margin: 50px 0 50px 30px; - padding: 0; -} - -ul ul { - margin: 10px 0 10px 30px; -} - -ul li { - margin: 5px 0; - color: var(--fg-color-light); - line-height: 1.5em; -} - -ul li strong { - color: var(--fg-color); - font-weight: 500; -} - -pre { - background: var(--light-gray); - color: var(--dark); - padding: 30px; - border-radius: 2px; - overflow: auto; - font: "Source Code Pro", Menlo, monospace; - font-size: .8em; - line-height: 1.5em; -} - -blockquote { - margin: 0; - padding: 0 1em; - color: var(--fg-dark); - border-left: 0.25em solid var(--dark); -} - -li > code, -p > code { - border: 1px solid #DEE2E6; - font-size: 0.75rem; - padding: 3px 10px; - border-radius: 3px; - white-space: nowrap; - font-weight: 600; - font-family: inherit; -} - -details > summary { - cursor: pointer; - outline: none; - user-select: none; -} - -details > p { - border-left: 3px solid var(--dark); - padding-left: 15px; -} - -.Wrapper { - display: flex; - justify-content: center; -} - -.Container { - width: var(--width); - display: flex; - flex-direction: column; -} - -.Content-wrapper { - display: flex; -} - -.Header { - display: flex; - justify-content: center; - align-items: center; - height: var(--header-height); -} - -.Sidebar { - flex: 1 1 auto; -} - -.Content { - width: 75%; -} - -.Content img { - max-width: 100%; -} - -.Menu { - position: -webkit-sticky; - position: sticky; - top: 50px; - color: var(--fg-dark); -} - -.Menu > .item { - padding-bottom: 15px; -} - -.Menu > .item > a { - position: relative; - user-select: none; - font-weight: 400; - transition: color 200ms; - color: var(--fg); -} - -.Menu > .item > a.active { - color: var(--fg-dark); -} - -.Menu > .item > a:before { - content: ""; - position: absolute; - width: 100%; - height: 1px; - bottom: -5px; - left: 0; - background-color: var(--fg-dark); - visibility: hidden; - transform: scaleX(0); - transform-origin: left center; - transition: all 250ms var(--ease); -} - -.Menu > .item > a:hover { - color: var(--fg-dark); -} - -.Menu > .item > a:hover:before { - visibility: visible; - transform: scaleX(1); -} - -.Page { - margin-top: 100px; - padding-top: 50px; -} - -.Page:first-child { - margin-top: 0; - padding-top: 0; -} - -.Title { - margin: 5px 0; - line-height: 2.2em; -} - -.Title.center { - margin-left: auto; - margin-right: auto; - text-align: center; - max-width: 500px; -} - -.Title.margin { - margin-bottom: 80px; -} - -.Title > span { - display: block; -} - -.Title .subtext { - color: var(--fg-color-light); - font-size: 0.8rem; - text-transform: uppercase; - display: none; -} - -.Title .text { - letter-spacing: var(--tracking); - text-transform: uppercase; - font-weight: bold; - font-size: 16px; -} - -.Title.small .text { - font-size: 14px; - text-transform: none; - letter-spacing: normal; - line-height: 2rem; -} - -.Anchor { - position: relative; - margin-left: -14px; - opacity: 0.15; - display: inline-block; - width: 14px; - height: 14px; -} - -.Anchor svg { - position: absolute; - right: 5px; - top: 0; -} - -.Anchor svg path { - pointer-events: all -} - -.Anchor:hover { - opacity: 1; -} - -.Footer { - height: 100px; -} - -@media screen and (max-width: 850px) { - html, body { - --header-height: 300px; - --width: 80%; - font-size: 14px; - } - - .Content-wrapper { - display: flex; - flex-direction: column; - } - - .Sidebar { - margin-bottom: 30px; - } - - .Content { - width: 100%; - } -} diff --git a/docs/theme/gotenberg/img/apple-touch-icon-114x114.png b/docs/theme/gotenberg/img/apple-touch-icon-114x114.png deleted file mode 100644 index 19944d0b..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-114x114.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/apple-touch-icon-120x120.png b/docs/theme/gotenberg/img/apple-touch-icon-120x120.png deleted file mode 100644 index 51e152dd..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-120x120.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/apple-touch-icon-144x144.png b/docs/theme/gotenberg/img/apple-touch-icon-144x144.png deleted file mode 100644 index f9bb3fa2..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-144x144.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/apple-touch-icon-152x152.png b/docs/theme/gotenberg/img/apple-touch-icon-152x152.png deleted file mode 100644 index f2963741..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-152x152.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/apple-touch-icon-57x57.png b/docs/theme/gotenberg/img/apple-touch-icon-57x57.png deleted file mode 100644 index 5d117aa4..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-57x57.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/apple-touch-icon-60x60.png b/docs/theme/gotenberg/img/apple-touch-icon-60x60.png deleted file mode 100644 index d23bac31..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-60x60.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/apple-touch-icon-72x72.png b/docs/theme/gotenberg/img/apple-touch-icon-72x72.png deleted file mode 100644 index 0dbb5112..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-72x72.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/apple-touch-icon-76x76.png b/docs/theme/gotenberg/img/apple-touch-icon-76x76.png deleted file mode 100644 index b52da04e..00000000 Binary files a/docs/theme/gotenberg/img/apple-touch-icon-76x76.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/favicon-128.png b/docs/theme/gotenberg/img/favicon-128.png deleted file mode 100644 index 30b6905c..00000000 Binary files a/docs/theme/gotenberg/img/favicon-128.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/favicon-16x16.png b/docs/theme/gotenberg/img/favicon-16x16.png deleted file mode 100644 index d0fd1582..00000000 Binary files a/docs/theme/gotenberg/img/favicon-16x16.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/favicon-196x196.png b/docs/theme/gotenberg/img/favicon-196x196.png deleted file mode 100644 index 87b8fd3d..00000000 Binary files a/docs/theme/gotenberg/img/favicon-196x196.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/favicon-32x32.png b/docs/theme/gotenberg/img/favicon-32x32.png deleted file mode 100644 index dcc1ea39..00000000 Binary files a/docs/theme/gotenberg/img/favicon-32x32.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/favicon-96x96.png b/docs/theme/gotenberg/img/favicon-96x96.png deleted file mode 100644 index 2f88c3cf..00000000 Binary files a/docs/theme/gotenberg/img/favicon-96x96.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/favicon.ico b/docs/theme/gotenberg/img/favicon.ico deleted file mode 100644 index f98c6258..00000000 Binary files a/docs/theme/gotenberg/img/favicon.ico and /dev/null differ diff --git a/docs/theme/gotenberg/img/mstile-144x144.png b/docs/theme/gotenberg/img/mstile-144x144.png deleted file mode 100644 index f9bb3fa2..00000000 Binary files a/docs/theme/gotenberg/img/mstile-144x144.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/mstile-150x150.png b/docs/theme/gotenberg/img/mstile-150x150.png deleted file mode 100644 index 89ee85f6..00000000 Binary files a/docs/theme/gotenberg/img/mstile-150x150.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/mstile-310x150.png b/docs/theme/gotenberg/img/mstile-310x150.png deleted file mode 100644 index 43d4c5c0..00000000 Binary files a/docs/theme/gotenberg/img/mstile-310x150.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/mstile-310x310.png b/docs/theme/gotenberg/img/mstile-310x310.png deleted file mode 100644 index a1fb31e0..00000000 Binary files a/docs/theme/gotenberg/img/mstile-310x310.png and /dev/null differ diff --git a/docs/theme/gotenberg/img/mstile-70x70.png b/docs/theme/gotenberg/img/mstile-70x70.png deleted file mode 100644 index 30b6905c..00000000 Binary files a/docs/theme/gotenberg/img/mstile-70x70.png and /dev/null differ diff --git a/docs/theme/gotenberg/js/index.js b/docs/theme/gotenberg/js/index.js deleted file mode 100644 index 54804bf8..00000000 --- a/docs/theme/gotenberg/js/index.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Setup. - */ - -const items = document.querySelectorAll('.Page') -const links = document.querySelectorAll('.Menu a') - -/** - * Check if `el` is out out of view. - */ - -function isBelowScroll(el) { - return el.getBoundingClientRect().bottom > 0 -} - -/** - * Activate item `i`. - */ - -function activateItem(i) { - links.forEach(e => e.classList.remove('active')) - links[i].classList.add('active') -} - -/** - * Activate the correct menu item for the - * contents in the viewport. - */ - -function activate() { - let i = 0 - - for (; i < items.length; i++) { - if (isBelowScroll(items[i])) { - break - } - } - - activateItem(i) -} - -/** - * Activate scroll spy thingy. - */ - -window.addEventListener('scroll', e => activate()) diff --git a/docs/theme/gotenberg/views/index.html b/docs/theme/gotenberg/views/index.html deleted file mode 100644 index f5fb7a3b..00000000 --- a/docs/theme/gotenberg/views/index.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - {{.Title}} · {{.Subtitle}} - - - - - - - - - - - - - - - - -
-
-
-
- Gotenberg logo - {{.Title}} - {{.Subtitle}} -
-
- -
- - -
- {{range .Pages}} -
-

{{.Title}}

- {{.Content}} -
- {{end}} - - -
-
-
- - diff --git a/go.mod b/go.mod index f048f7d6..0d2304c1 100644 --- a/go.mod +++ b/go.mod @@ -1,25 +1,38 @@ -module github.com/thecodingmachine/gotenberg +module github.com/gotenberg/gotenberg/v7 -go 1.14 +go 1.16 require ( - github.com/dustin/go-humanize v1.0.0 - github.com/kr/text v0.2.0 // indirect - github.com/labstack/echo/v4 v4.3.0 + github.com/alexliesenfeld/health v0.6.0 + github.com/andybalholm/brotli v1.0.3 // indirect + github.com/chromedp/cdproto v0.0.0-20210808225517-c36c1bd4c35e + github.com/chromedp/chromedp v0.7.4 + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.3.0 + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.0 + github.com/klauspost/compress v1.13.4 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect + github.com/labstack/echo/v4 v4.5.0 github.com/labstack/gommon v0.3.0 - github.com/mafredri/cdp v0.31.0 - github.com/mattn/go-isatty v0.0.12 - github.com/microcosm-cc/bluemonday v1.0.9 - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect - github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 + github.com/mattn/go-isatty v0.0.13 // indirect + github.com/mholt/archiver/v3 v3.5.0 + github.com/microcosm-cc/bluemonday v1.0.15 + github.com/nwaples/rardecode v1.1.2 // indirect + github.com/pdfcpu/pdfcpu v0.3.12 + github.com/pierrec/lz4/v4 v4.1.8 // indirect github.com/russross/blackfriday/v2 v2.1.0 - github.com/sirupsen/logrus v1.8.1 - github.com/stretchr/testify v1.7.0 - golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect + github.com/spf13/pflag v1.0.5 + github.com/ulikunitz/xz v0.5.10 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 + go.uber.org/zap v1.19.0 + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect + golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect - golang.org/x/text v0.3.6 - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 // indirect + golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b + golang.org/x/text v0.3.7 + golang.org/x/tools v0.1.5 // indirect ) diff --git a/go.sum b/go.sum index 9471aa0b..95d7712f 100644 --- a/go.sum +++ b/go.sum @@ -1,115 +1,198 @@ +github.com/alexliesenfeld/health v0.6.0 h1:HRBTCgybNSe4lqGEk7nU82c3bjwh9W+3b46W6UvD4CQ= +github.com/alexliesenfeld/health v0.6.0/go.mod h1:N4NDIeQtlWumG+6z1ne1v62eQxktz5ylEgGgH9emdMw= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/chromedp/cdproto v0.0.0-20210713064928-7d28b402946a/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U= +github.com/chromedp/cdproto v0.0.0-20210808225517-c36c1bd4c35e h1:uYQIvPKwL7YQh+tQC+EUXmvWosBeOYbJZKrh4NnS0UM= +github.com/chromedp/cdproto v0.0.0-20210808225517-c36c1bd4c35e/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U= +github.com/chromedp/chromedp v0.7.4 h1:U+0d3WbB/Oj4mDuBOI0P7S3PJEued5UZIl5AJ3QulwU= +github.com/chromedp/chromedp v0.7.4/go.mod h1:dBj+SXuQHznp6ZPwZeDDEBZKwclUwDLbZ0hjMialMYs= +github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= +github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hhrutter/lzw v0.0.0-20190827003112-58b82c5a41cc/go.mod h1:yJBvOcu1wLQ9q9XZmfiPfur+3dQJuIhYQsMGLYcItZk= +github.com/hhrutter/lzw v0.0.0-20190829144645-6f07a24e8650 h1:1yY/RQWNSBjJe2GDCIYoLmpWVidrooriUr4QS/zaATQ= +github.com/hhrutter/lzw v0.0.0-20190829144645-6f07a24e8650/go.mod h1:yJBvOcu1wLQ9q9XZmfiPfur+3dQJuIhYQsMGLYcItZk= +github.com/hhrutter/tiff v0.0.0-20190829141212-736cae8d0bc7 h1:o1wMw7uTNyA58IlEdDpxIrtFHTgnvYzA8sCQz8luv94= +github.com/hhrutter/tiff v0.0.0-20190829141212-736cae8d0bc7/go.mod h1:WkUxfS2JUu3qPo6tRld7ISb8HiC0gVSU91kooBMDVok= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.3.0 h1:DCP6cbtT+Zu++K6evHOJzSgA2115cPMuCx0xg55q1EQ= -github.com/labstack/echo/v4 v4.3.0/go.mod h1:PvmtTvhVqKDzDQy4d3bWzPjZLzom4iQbAZy2sgZ/qI8= +github.com/labstack/echo/v4 v4.5.0 h1:JXk6H5PAw9I3GwizqUHhYyS4f45iyGebR/c1xNCeOCY= +github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/mafredri/cdp v0.31.0 h1:Vd+uCnvBWYsitQRuB/Oxx7S83wfx/ZpeDa4JpSclI6s= -github.com/mafredri/cdp v0.31.0/go.mod h1:YTCwLXkZSa18SGSIxCPMOGZcUJODZSNlAhiMqbyxWJg= -github.com/mafredri/go-lint v0.0.0-20180911205320-920981dfc79e/go.mod h1:k/zdyxI3q6dup24o8xpYjJKTCf2F7rfxLp6w/efTiWs= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/microcosm-cc/bluemonday v1.0.9 h1:dpCwruVKoyrULicJwhuY76jB+nIxRVKv/e248Vx/BXg= -github.com/microcosm-cc/bluemonday v1.0.9/go.mod h1:B2riunDr9benLHghZB7hjIgdwSUzzs0pjCxFrWYEZFU= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= +github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= +github.com/microcosm-cc/bluemonday v1.0.15 h1:J4uN+qPng9rvkBZBoBb8YGR+ijuklIMpSOZZLjYpbeY= +github.com/microcosm-cc/bluemonday v1.0.15/go.mod h1:ZLvAzeakRwrGnzQEvstVzVt3ZpqOF2+sdFr0Om+ce30= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= +github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc= +github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/pdfcpu/pdfcpu v0.3.12 h1:B+MdKisilWNSk5OCO58Z9U6H93usH73xqk6hMOaZCls= +github.com/pdfcpu/pdfcpu v0.3.12/go.mod h1:8XVBtVxuuIuSZL4Ez15Q4QoC+H8zeAaGnuiOEwAk8jA= +github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= +github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/image v0.0.0-20190823064033-3a9bac650e44/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4= +golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/app/gotenberg/gotenberg.go b/internal/app/gotenberg/gotenberg.go new file mode 100644 index 00000000..87483968 --- /dev/null +++ b/internal/app/gotenberg/gotenberg.go @@ -0,0 +1,116 @@ +package gotenberg + +import ( + "context" + "fmt" + "os" + "os/signal" + "time" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + flag "github.com/spf13/pflag" +) + +// See https://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Gotenberg. +// Credits: https://github.com/labstack/echo/blob/v4.3.0/echo.go#L240. +const banner = ` + _____ __ __ + / ___/__ / /____ ___ / / ___ _______ _ +/ (_ / _ \/ __/ -_) _ \/ _ \/ -_) __/ _ '/ +\___/\___/\__/\__/_//_/_.__/\__/_/ \_, / + /___/ + +A Docker-powered stateless API for PDF files. +Version: %s +------------------------------------------------------- +` + +var version = "snapshot" + +func Run() { + fmt.Printf(banner, version) + + // Creates the roo` FlagSet and adds the modules flags to it. + fs := flag.NewFlagSet("gotenberg", flag.ExitOnError) + fs.Duration("gotenberg-graceful-shutdown-duration", time.Duration(30)*time.Second, "Set the graceful shutdown duration") + + descriptors := gotenberg.GetModuleDescriptors() + var modsInfo string + for _, desc := range descriptors { + fs.AddFlagSet(desc.FlagSet) + modsInfo += desc.ID + " " + } + + fmt.Printf("[SYSTEM] modules: %s\n", modsInfo) + + // Parses the flags... + err := fs.Parse(os.Args[1:]) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // ...and creates a wrapper around those. + parsedFlags := gotenberg.ParsedFlags{FlagSet: fs} + + // Get the graceful shutdown duration. + gracefulShutdownDuration := parsedFlags.MustDuration("gotenberg-graceful-shutdown-duration") + + ctx := gotenberg.NewContext(parsedFlags, descriptors) + + // Starts application modules. + apps, err := ctx.Modules(new(gotenberg.App)) + if err != nil { + fmt.Printf("[FATAL] %s\n", err) + os.Exit(1) + } + + for _, a := range apps { + go func(app gotenberg.App) { + id := app.(gotenberg.Module).Descriptor().ID + err = app.Start() + + if err != nil { + fmt.Printf("[FATAL] starting %s: %s\n", id, err) + os.Exit(1) + } + + startupMessage := app.StartupMessage() + if startupMessage == "" { + fmt.Printf("[SYSTEM] %s: application started\n", id) + + return + } + + fmt.Printf("[SYSTEM] %s: %s\n", id, startupMessage) + }(a.(gotenberg.App)) + + } + + quit := make(chan os.Signal, 1) + + // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C). + signal.Notify(quit, os.Interrupt) + + // Block until we receive our signal. + <-quit + + gracefulShutdownCtx, cancel := context.WithTimeout(context.Background(), gracefulShutdownDuration) + defer cancel() + + fmt.Printf("[SYSTEM] graceful shutdown of %s\n", gracefulShutdownDuration) + + for _, a := range apps { + id := a.(gotenberg.Module).Descriptor().ID + app := a.(gotenberg.App) + + err = app.Stop(gracefulShutdownCtx) + if err != nil { + fmt.Printf("[ERROR] stopping %s: %s\n", id, err) + } + + fmt.Printf("[SYSTEM] %s: application stopped\n", id) + } + + os.Exit(0) +} diff --git a/internal/app/xhttp/doc.go b/internal/app/xhttp/doc.go deleted file mode 100644 index 62383c98..00000000 --- a/internal/app/xhttp/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package xhttp defines our own implementation -// of echo.Echo. -package xhttp diff --git a/internal/app/xhttp/handler.go b/internal/app/xhttp/handler.go deleted file mode 100644 index dbf0e7b6..00000000 --- a/internal/app/xhttp/handler.go +++ /dev/null @@ -1,383 +0,0 @@ -package xhttp - -import ( - "fmt" - "net/http" - "os" - - "github.com/labstack/echo/v4" - "github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/context" - "github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/resource" - "github.com/thecodingmachine/gotenberg/internal/pkg/chrome" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/printer" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xrand" - "github.com/thecodingmachine/gotenberg/internal/pkg/xtime" -) - -func pingEndpoint(config conf.Config) string { - return fmt.Sprintf("%s%s", config.RootPath(), "ping") -} - -func mergeEndpoint(config conf.Config) string { - return fmt.Sprintf("%s%s", config.RootPath(), "merge") -} - -func htmlEndpoint(config conf.Config) string { - return fmt.Sprintf("%s%s", config.RootPath(), "convert/html") -} - -func urlEndpoint(config conf.Config) string { - return fmt.Sprintf("%s%s", config.RootPath(), "convert/url") -} - -func markdownEndpoint(config conf.Config) string { - return fmt.Sprintf("%s%s", config.RootPath(), "convert/markdown") -} - -func officeEndpoint(config conf.Config) string { - return fmt.Sprintf("%s%s", config.RootPath(), "convert/office") -} - -func isMultipartFormDataEndpoint(config conf.Config, path string) bool { - var multipartFormDataEndpoints []string - multipartFormDataEndpoints = append(multipartFormDataEndpoints, mergeEndpoint(config)) - if !config.DisableGoogleChrome() { - multipartFormDataEndpoints = append( - multipartFormDataEndpoints, - htmlEndpoint(config), - urlEndpoint(config), - markdownEndpoint(config), - ) - } - if !config.DisableUnoconv() { - multipartFormDataEndpoints = append( - multipartFormDataEndpoints, - officeEndpoint(config), - ) - } - for _, endpoint := range multipartFormDataEndpoints { - if endpoint == path { - return true - } - } - return false -} - -// pingHandler is the handler for healthcheck. -func pingHandler(c echo.Context) error { - const op string = "xhttp.pingHandler" - ctx := context.MustCastFromEchoContext(c) - logger := ctx.XLogger() - config := ctx.Config() - - logger.DebugOp(op, "handling ping request...") - - if !config.DisableGoogleChrome() { - _, err := chrome.IsViable(logger) - if err != nil { - return xerror.New(op, err) - } - } - - return nil -} - -// mergeHandler is the handler for merging -// PDF files. -func mergeHandler(c echo.Context) error { - const op string = "xhttp.mergeHandler" - resolver := func() error { - ctx := context.MustCastFromEchoContext(c) - logger := ctx.XLogger() - logger.DebugOp(op, "handling merge request...") - r := ctx.MustResource() - opts, err := mergePrinterOptions(r, ctx.Config()) - if err != nil { - return xerror.New(op, err) - } - fpaths, err := r.Fpaths(".pdf") - if err != nil { - return err - } - p := printer.NewMergePrinter(logger, fpaths, opts) - return convert(ctx, p) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// htmlHandler is the handler for converting -// HTML to PDF. -func htmlHandler(c echo.Context) error { - const op string = "xhttp.htmlHandler" - resolver := func() error { - ctx := context.MustCastFromEchoContext(c) - logger := ctx.XLogger() - logger.DebugOp(op, "handling HTML request...") - r := ctx.MustResource() - opts, err := chromePrinterOptions(r, ctx.Config()) - if err != nil { - return err - } - fpath, err := r.Fpath("index.html") - if err != nil { - return err - } - p := printer.NewHTMLPrinter(logger, fpath, opts) - return convert(ctx, p) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// urlHandler is the handler for converting -// a URL to PDF. -func urlHandler(c echo.Context) error { - const op string = "xhttp.urlHandler" - resolver := func() error { - ctx := context.MustCastFromEchoContext(c) - logger := ctx.XLogger() - logger.DebugOp(op, "handling URL request...") - r := ctx.MustResource() - opts, err := chromePrinterOptions(r, ctx.Config()) - if err != nil { - return err - } - opts.CustomHTTPHeaders = resource.RemoteURLCustomHTTPHeaders(r) - if !r.HasArg(resource.RemoteURLArgKey) { - return xerror.Invalid( - op, - fmt.Sprintf("'%s' not found or empty", resource.RemoteURLArgKey), - nil, - ) - } - remoteURL, err := r.StringArg(resource.RemoteURLArgKey, "") - if err != nil { - return err - } - p := printer.NewURLPrinter(logger, remoteURL, opts) - return convert(ctx, p) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// markdownHandler is the handler for converting -// Markdown to PDF. -func markdownHandler(c echo.Context) error { - const op string = "xhttp.markdownHandler" - resolver := func() error { - ctx := context.MustCastFromEchoContext(c) - logger := ctx.XLogger() - logger.DebugOp(op, "handling Markdown request...") - r := ctx.MustResource() - opts, err := chromePrinterOptions(r, ctx.Config()) - if err != nil { - return err - } - fpath, err := r.Fpath("index.html") - if err != nil { - return err - } - p, err := printer.NewMarkdownPrinter(logger, fpath, opts) - if err != nil { - return err - } - return convert(ctx, p) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// officeHandler is the handler for converting -// Office documents to PDF. -func officeHandler(c echo.Context) error { - const op string = "xhttp.officeHandler" - resolver := func() error { - ctx := context.MustCastFromEchoContext(c) - logger := ctx.XLogger() - logger.DebugOp(op, "handling Office request...") - r := ctx.MustResource() - opts, err := officePrinterOptions(r, ctx.Config()) - if err != nil { - return err - } - fpaths, err := r.Fpaths( - ".txt", - ".rtf", - ".fodt", - ".doc", - ".docx", - ".odt", - ".xls", - ".xlsx", - ".ods", - ".ppt", - ".pptx", - ".odp", - ) - if err != nil { - return err - } - p := printer.NewOfficePrinter(logger, fpaths, opts) - return convert(ctx, p) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func convert(ctx context.Context, p printer.Printer) error { - const op string = "xhttp.convert" - resolver := func() error { - logger := ctx.XLogger() - r := ctx.MustResource() - baseFilename := xrand.Get() - filename := fmt.Sprintf("%s.pdf", baseFilename) - fpath := fmt.Sprintf("%s/%s", r.DirPath(), filename) - // if no webhook URL given, run conversion - // and directly return the resulting PDF file - // or an error. - if !r.HasArg(resource.WebhookURLArgKey) { - logger.DebugOpf(op, "no '%s' found, converting synchronously", resource.WebhookURLArgKey) - return convertSync(ctx, p, filename, fpath) - } - // as a webhook URL has been given, we - // run the following lines in a goroutine so that - // it doesn't block. - logger.DebugOpf(op, "'%s' found, converting asynchronously", resource.WebhookURLArgKey) - return convertAsync(ctx, p, filename, fpath) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func convertSync(ctx context.Context, p printer.Printer, filename, fpath string) error { - const op = "xhttp.convertSync" - resolver := func() error { - logger := ctx.XLogger() - r := ctx.MustResource() - - if err := p.Print(fpath); err != nil { - return err - } - if !r.HasArg(resource.ResultFilenameArgKey) { - logger.DebugOpf( - op, - "no '%s' found, using generated filename '%s'", - resource.RemoteURLArgKey, - filename, - ) - if err := ctx.Attachment(fpath, filename); err != nil { - return err - } - return nil - } - logger.DebugOpf( - op, - "'%s' found, so not using generated filename", - resource.ResultFilenameArgKey, - ) - filename, err := r.StringArg(resource.ResultFilenameArgKey, filename) - if err != nil { - return err - } - if err := ctx.Attachment(fpath, filename); err != nil { - return err - } - return nil - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func convertAsync(ctx context.Context, p printer.Printer, filename, fpath string) error { - const op = "xhttp.convertAsync" - logger := ctx.XLogger() - r := ctx.MustResource() - webhookURL, err := r.StringArg(resource.WebhookURLArgKey, "") - if err != nil { - return xerror.New(op, err) - } - webhookURLTimeout, err := resource.WebhookURLTimeoutArg(r, ctx.Config()) - if err != nil { - return xerror.New(op, err) - } - go func() { - defer r.Close() - if err := p.Print(fpath); err != nil { - xerr := xerror.New(op, err) - logger.ErrorOp(xerror.Op(xerr), xerr) - return - } - f, err := os.Open(fpath) - if err != nil { - xerr := xerror.New(op, err) - logger.ErrorOp(xerror.Op(xerr), xerr) - return - } - defer f.Close() - logger.DebugOpf( - op, - "preparing to send result file '%s' to '%s'...", - filename, - webhookURL, - ) - httpClient := &http.Client{ - Timeout: xtime.Duration(webhookURLTimeout), - } - req, err := http.NewRequest(http.MethodPost, webhookURL, f) - if err != nil { - xerr := xerror.New(op, err) - logger.ErrorOp(xerror.Op(xerr), xerr) - return - } - req.Header.Set(echo.HeaderContentType, "application/pdf") - // set custom headers (if any). - customHTTPHeaders := resource.WebhookURLCustomHTTPHeaders(r) - if len(customHTTPHeaders) > 0 { - for key, value := range customHTTPHeaders { - req.Header.Set(key, value) - logger.DebugOpf(op, "set '%s' to custom HTTP header '%s'", value, key) - } - } else { - logger.DebugOp(op, "skipping custom HTTP headers as none have been provided...") - } - // send the result file. - logger.DebugOpf( - op, - "sending result file '%s' to '%s'...", - filename, - webhookURL, - ) - resp, err := httpClient.Do(req) /* #nosec */ - if err != nil { - xerr := xerror.New(op, err) - logger.ErrorOp(xerror.Op(xerr), xerr) - return - } - defer resp.Body.Close() - logger.DebugOpf( - op, - "result file '%s' sent to '%s'", - filename, - webhookURL, - ) - }() - return nil -} diff --git a/internal/app/xhttp/handler_test.go b/internal/app/xhttp/handler_test.go deleted file mode 100644 index 7cba003e..00000000 --- a/internal/app/xhttp/handler_test.go +++ /dev/null @@ -1,635 +0,0 @@ -package xhttp - -import ( - "errors" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - - "github.com/labstack/echo/v4" - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/resource" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestPingHandler(t *testing.T) { - // should return 200. - config := conf.DefaultConfig() - srv := New(config) - endpoint := pingEndpoint(config) - req := httptest.NewRequest(http.MethodGet, endpoint, nil) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // should return 405 as Method is wrong. - req = httptest.NewRequest(http.MethodPost, endpoint, nil) - test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req) -} - -func TestMergeHandler(t *testing.T) { - config := conf.DefaultConfig() - srv := New(config) - endpoint := mergeEndpoint(config) - // should return 200. - body, contentType := test.MergeMultipartForm(t, nil) - req := httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // should return 405 as Method is wrong. - req = httptest.NewRequest(http.MethodGet, endpoint, nil) - test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req) - // should return 415 as Content-Type is wrong. - body, _ = test.MergeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - test.AssertStatusCode(t, http.StatusUnsupportedMediaType, srv, req) - // should return 400 as "waitTimeout" form field - // value is < 0. - body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is is > config.MaximumWaitTimeout(). - body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is invalid. - body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 504. - body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "0"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusGatewayTimeout, srv, req) -} - -func TestHTMLHandler(t *testing.T) { - config := conf.DefaultConfig() - srv := New(config) - endpoint := htmlEndpoint(config) - // should return 200. - body, contentType := test.HTMLMultipartForm(t, nil) - req := httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // should return 405 as Method is wrong. - req = httptest.NewRequest(http.MethodGet, endpoint, nil) - test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req) - // should return 415 as Content-Type is wrong. - body, _ = test.HTMLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - test.AssertStatusCode(t, http.StatusUnsupportedMediaType, srv, req) - // should return 400 as "waitTimeout" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is is > config.MaximumWaitTimeout(). - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 504. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "0"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusGatewayTimeout, srv, req) - // should return 400 as "waitDelay" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitDelay" form field - // value is is > config.MaximumWaitDelay(). - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitDelay" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperWidth" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.PaperWidthArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperWidth" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.PaperWidthArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperHeight" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.PaperHeightArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperHeight" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.PaperHeightArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginTop" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginTopArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginTop" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginTopArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginBottom" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginBottomArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginBottom" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginBottomArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginLeft" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginLeftArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginLeft" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginLeftArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginRight" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginRightArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginRight" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.MarginRightArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "landscape" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.LandscapeArgKey): "not a boolean"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is < 0. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is is > config.MaximumGoogleChromeRpccBufferSize(). - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "104857601"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is invalid. - body, contentType = test.HTMLMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "not an int"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) -} - -func TestURLHandler(t *testing.T) { - config := conf.DefaultConfig() - srv := New(config) - endpoint := urlEndpoint(config) - // should return 200. - body, contentType := test.URLMultipartForm(t, nil) - req := httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // should return 405 as Method is wrong. - req = httptest.NewRequest(http.MethodGet, endpoint, nil) - test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req) - // should return 415 as Content-Type is wrong. - body, _ = test.URLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - test.AssertStatusCode(t, http.StatusUnsupportedMediaType, srv, req) - // should return 400 as "waitTimeout" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is is > config.MaximumWaitTimeout(). - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 504. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "0"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusGatewayTimeout, srv, req) - // should return 400 as "waitDelay" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitDelay" form field - // value is is > config.MaximumWaitDelay(). - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitDelay" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperWidth" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.PaperWidthArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperWidth" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.PaperWidthArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperHeight" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.PaperHeightArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperHeight" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.PaperHeightArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginTop" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginTopArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginTop" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginTopArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginBottom" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginBottomArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginBottom" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginBottomArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginLeft" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginLeftArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginLeft" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginLeftArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginRight" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginRightArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginRight" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.MarginRightArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "landscape" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.LandscapeArgKey): "not a boolean"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is < 0. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is is > config.MaximumGoogleChromeRpccBufferSize(). - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "104857601"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is invalid. - body, contentType = test.URLMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "not an int"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) -} - -func TestMarkdownHandler(t *testing.T) { - config := conf.DefaultConfig() - srv := New(config) - endpoint := markdownEndpoint(config) - // should return 200. - body, contentType := test.MarkdownMultipartForm(t, nil) - req := httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // should return 405 as Method is wrong. - req = httptest.NewRequest(http.MethodGet, endpoint, nil) - test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req) - // should return 415 as Content-Type is wrong. - body, _ = test.MarkdownMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - test.AssertStatusCode(t, http.StatusUnsupportedMediaType, srv, req) - // should return 400 as "waitTimeout" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is is > config.MaximumWaitTimeout(). - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 504. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "0"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusGatewayTimeout, srv, req) - // should return 400 as "waitDelay" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitDelay" form field - // value is is > config.MaximumWaitDelay(). - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitDelay" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.WaitDelayArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperWidth" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.PaperWidthArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperWidth" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.PaperWidthArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperHeight" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.PaperHeightArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "paperHeight" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.PaperHeightArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginTop" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginTopArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginTop" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginTopArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginBottom" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginBottomArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginBottom" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginBottomArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginLeft" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginLeftArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginLeft" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginLeftArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginRight" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginRightArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "marginRight" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.MarginRightArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "landscape" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.LandscapeArgKey): "not a boolean"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is < 0. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is is > config.MaximumGoogleChromeRpccBufferSize(). - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "104857601"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "googleChromeRpccBufferSize" form field - // value is invalid. - body, contentType = test.MarkdownMultipartForm(t, map[string]string{string(resource.GoogleChromeRpccBufferSizeArgKey): "not an int"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) -} - -func TestOfficeHandler(t *testing.T) { - config := conf.DefaultConfig() - srv := New(config) - endpoint := officeEndpoint(config) - // should return 200. - // note: increased the wait timeout as it happens to timeout from time to time. - body, contentType := test.OfficeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "30"}) - req := httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // should return 405 as Method is wrong. - req = httptest.NewRequest(http.MethodGet, endpoint, nil) - test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req) - // should return 415 as Content-Type is wrong. - body, _ = test.OfficeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - test.AssertStatusCode(t, http.StatusUnsupportedMediaType, srv, req) - // should return 400 as "waitTimeout" form field - // value is < 0. - body, contentType = test.OfficeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "-1"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is is > config.MaximumWaitTimeout(). - body, contentType = test.OfficeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "31"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 400 as "waitTimeout" form field - // value is invalid. - body, contentType = test.OfficeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "not a float"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) - // should return 504. - body, contentType = test.OfficeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "0"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusGatewayTimeout, srv, req) - // should return 400 as "landscape" form field - // value is invalid. - body, contentType = test.OfficeMultipartForm(t, map[string]string{string(resource.LandscapeArgKey): "not a boolean"}) - req = httptest.NewRequest(http.MethodPost, endpoint, body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusBadRequest, srv, req) -} - -func TestWebhook(t *testing.T) { - customHeaderRealKey := http.CanonicalHeaderKey("MyCustomHeader") - customHeaderKey := fmt.Sprintf("%s%s", resource.WebhookURLCustomHTTPHeaderCanonicalBaseKey, customHeaderRealKey) - customHeaderValue := "foo" - status := make(chan error, 2) - rcv := echo.New() - rcv.POST("/foo", func(c echo.Context) error { - if c.Request().Header.Get(echo.HeaderContentType) != "application/pdf" { - status <- fmt.Errorf("wrong Content-type: got '%s' want '%s'", c.Request().Header.Get(echo.HeaderContentType), "application/pdf") - return nil - } - if c.Request().Header.Get(customHeaderRealKey) != customHeaderValue { - status <- fmt.Errorf("wrong '%s': got '%s' want '%s'", customHeaderRealKey, c.Request().Header.Get(customHeaderRealKey), customHeaderValue) - return nil - } - body, err := ioutil.ReadAll(c.Request().Body) - if err != nil { - status <- err - return nil - } - if body == nil || len(body) == 0 { - status <- errors.New("empty body") - return nil - } - status <- nil - return nil - }) - go func() { - rcv.Start(":3001") - }() - config := conf.DefaultConfig() - srv := New(config) - // our custom server should receive the PDF. - body, contentType := test.MergeMultipartForm(t, map[string]string{string(resource.WebhookURLArgKey): "http://localhost:3001/foo"}) - req := httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - req.Header.Set(customHeaderKey, customHeaderValue) - test.AssertStatusCode(t, http.StatusOK, srv, req) - err := <-status - assert.NoError(t, err) -} - -func TestResultFilename(t *testing.T) { - config := conf.DefaultConfig() - srv := New(config) - body, contentType := test.MergeMultipartForm(t, map[string]string{string(resource.ResultFilenameArgKey): "foo.pdf"}) - req := httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - rec := httptest.NewRecorder() - srv.ServeHTTP(rec, req) - assert.Equal(t, "attachment; filename=\"foo.pdf\"", rec.Header().Get(echo.HeaderContentDisposition)) -} diff --git a/internal/app/xhttp/middleware.go b/internal/app/xhttp/middleware.go deleted file mode 100644 index 4049b9ac..00000000 --- a/internal/app/xhttp/middleware.go +++ /dev/null @@ -1,153 +0,0 @@ -package xhttp - -import ( - "net/http" - "strings" - - "github.com/labstack/echo/v4" - "github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/context" - "github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/resource" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/internal/pkg/xrand" -) - -// contextMiddleware extends the default echo.Context with -// our custom context.Context. -func contextMiddleware(config conf.Config) echo.MiddlewareFunc { - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - // generate a unique identifier for the request. - trace := xrand.Get() - // create the logger for this request using - // the previous identifier as trace. - logger := xlog.New(config.LogLevel(), trace) - // extend the current echo context with our custom - // context. - ctx := context.New(c, logger, config) - // if it's not a multipart/form-data request, - // there is no need to create a Resource. - if !isMultipartFormDataEndpoint(config, ctx.Path()) { - // validate method for healthcheck endpoint. - if ctx.Path() == pingEndpoint(config) && ctx.Request().Method != http.MethodGet { - err := doErr(ctx, echo.NewHTTPError(http.StatusMethodNotAllowed)) - return ctx.LogRequestResult(err, false) - } - return next(ctx) - } - // validate method. - if ctx.Request().Method != http.MethodPost { - err := doErr(ctx, echo.NewHTTPError(http.StatusMethodNotAllowed)) - return ctx.LogRequestResult(err, false) - } - // validate Content-Type. - contentType := ctx.Request().Header.Get("Content-Type") - if !strings.Contains(contentType, "multipart/form-data") { - err := doErr(ctx, echo.NewHTTPError(http.StatusUnsupportedMediaType)) - return ctx.LogRequestResult(err, false) - } - // it's a multipart/form-data request, create a - // Resource. - if err := ctx.WithResource(trace); err != nil { - err = doCleanup(ctx, err) - err = doErr(ctx, err) - return ctx.LogRequestResult(err, false) - } - return next(ctx) - } - } -} - -// loggerMiddleware logs the result of a request. -func loggerMiddleware(config conf.Config) echo.MiddlewareFunc { - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - ctx := context.MustCastFromEchoContext(c) - err := next(ctx) - // we do not want to log healthcheck requests if - // log level is not set to DEBUG. - isDebug := ctx.Path() == pingEndpoint(config) - return ctx.LogRequestResult(err, isDebug) - } - } -} - -// cleanupMiddleware removes a resource.Resource -// at the end of a request. -func cleanupMiddleware() echo.MiddlewareFunc { - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - err := next(c) - ctx := context.MustCastFromEchoContext(c) - return doCleanup(ctx, err) - } - } -} - -// errorMiddleware handles errors (if any). -func errorMiddleware() echo.MiddlewareFunc { - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - ctx := context.MustCastFromEchoContext(c) - err := next(ctx) - if err == nil { - // so far so good! - return nil - } - return doErr(ctx, err) - } - } -} - -func doCleanup(ctx context.Context, err error) error { - const op string = "xhttp.cleanup" - if !ctx.HasResource() { - // nothing to remove. - return err - } - r := ctx.MustResource() - // if a webhook URL has been given, - // do not remove the resource.Resource here because - // we don't know if the result file has been - // generated or sent. - if r.HasArg(resource.WebhookURLArgKey) { - return err - } - // a resource.Resource is associated with our custom context. - if resourceErr := r.Close(); resourceErr != nil { - xerr := xerror.New(op, resourceErr) - ctx.XLogger().ErrorOp(xerror.Op(xerr), xerr) - } - return err -} - -func doErr(ctx context.Context, err error) error { - // if it's an error from echo - // like 404 not found and so on. - if echoHTTPErr, ok := err.(*echo.HTTPError); ok { - // required to have a correct status code. - ctx.Error(echoHTTPErr) - return echoHTTPErr - } - // we log the initial error before returning - // the HTTP error. - errOp := xerror.Op(err) - logger := ctx.XLogger() - logger.ErrorOp(errOp, err) - // handle our custom HTTP error. - var httpErr error - errCode := xerror.Code(err) - errMessage := xerror.Message(err) - switch errCode { - case xerror.InvalidCode: - httpErr = echo.NewHTTPError(http.StatusBadRequest, errMessage) - case xerror.TimeoutCode: - httpErr = echo.NewHTTPError(http.StatusGatewayTimeout, errMessage) - default: - httpErr = echo.NewHTTPError(http.StatusInternalServerError, errMessage) - } - // required to have a correct status code. - ctx.Error(httpErr) - return httpErr -} diff --git a/internal/app/xhttp/option.go b/internal/app/xhttp/option.go deleted file mode 100644 index 335c7cd0..00000000 --- a/internal/app/xhttp/option.go +++ /dev/null @@ -1,114 +0,0 @@ -package xhttp - -import ( - "github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/resource" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/printer" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -func mergePrinterOptions(r resource.Resource, config conf.Config) (printer.MergePrinterOptions, error) { - const op string = "xhttp.mergePrinterOptions" - waitTimeout, err := resource.WaitTimeoutArg(r, config) - if err != nil { - return printer.MergePrinterOptions{}, xerror.New(op, err) - } - return printer.MergePrinterOptions{ - WaitTimeout: waitTimeout, - }, nil -} - -func chromePrinterOptions(r resource.Resource, config conf.Config) (printer.ChromePrinterOptions, error) { - const op string = "xhttp.chromePrinterOptions" - resolver := func() (printer.ChromePrinterOptions, error) { - waitTimeout, err := resource.WaitTimeoutArg(r, config) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - waitDelay, err := resource.WaitDelayArg(r, config) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - headerHTML, footerHTML, - err := resource.HeaderFooterContents(r, config) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - paperWidth, paperHeight, - err := resource.PaperSizeArgs(r, config) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - marginTop, marginBottom, marginLeft, marginRight, - err := resource.MarginArgs(r, config) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - landscape, err := r.BoolArg(resource.LandscapeArgKey, false) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - pageRanges, err := r.StringArg(resource.PageRangesArgKey, "") - if err != nil { - return printer.ChromePrinterOptions{}, err - } - googleChromeRpccBufferSize, err := resource.GoogleChromeRpccBufferSizeArg(r, config) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - scale, err := resource.ScaleArg(r, config) - if err != nil { - return printer.ChromePrinterOptions{}, err - } - return printer.ChromePrinterOptions{ - WaitTimeout: waitTimeout, - WaitDelay: waitDelay, - HeaderHTML: headerHTML, - FooterHTML: footerHTML, - PaperWidth: paperWidth, - PaperHeight: paperHeight, - MarginTop: marginTop, - MarginBottom: marginBottom, - MarginLeft: marginLeft, - MarginRight: marginRight, - Landscape: landscape, - PageRanges: pageRanges, - RpccBufferSize: googleChromeRpccBufferSize, - CustomHTTPHeaders: make(map[string]string), - Scale: scale, - }, nil - } - opts, err := resolver() - if err != nil { - return opts, xerror.New(op, err) - } - return opts, nil -} - -func officePrinterOptions(r resource.Resource, config conf.Config) (printer.OfficePrinterOptions, error) { - const op string = "xhttp.officePrinterOptions" - resolver := func() (printer.OfficePrinterOptions, error) { - waitTimeout, err := resource.WaitTimeoutArg(r, config) - if err != nil { - return printer.OfficePrinterOptions{}, err - } - landscape, err := r.BoolArg(resource.LandscapeArgKey, false) - if err != nil { - return printer.OfficePrinterOptions{}, err - } - pageRanges, err := r.StringArg(resource.PageRangesArgKey, "") - if err != nil { - return printer.OfficePrinterOptions{}, err - } - return printer.OfficePrinterOptions{ - WaitTimeout: waitTimeout, - Landscape: landscape, - PageRanges: pageRanges, - }, nil - } - opts, err := resolver() - if err != nil { - return opts, xerror.New(op, err) - } - return opts, nil -} diff --git a/internal/app/xhttp/pkg/context/context.go b/internal/app/xhttp/pkg/context/context.go deleted file mode 100644 index 908db2d7..00000000 --- a/internal/app/xhttp/pkg/context/context.go +++ /dev/null @@ -1,210 +0,0 @@ -package context - -import ( - "fmt" - "io" - "net/http" - "path/filepath" - "reflect" - "strconv" - "strings" - "time" - - "github.com/labstack/echo/v4" - "github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/resource" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -// Context extends the default echo.Context. -type Context struct { - echo.Context - logger xlog.Logger - config conf.Config - resource resource.Resource - startTime time.Time -} - -// New creates a new Context. -func New(c echo.Context, logger xlog.Logger, config conf.Config) Context { - return Context{ - c, - logger, - config, - resource.Resource{}, - time.Now(), - } -} - -/* -MustCastFromEchoContext cast an echo.Context -to our custom Context. - -It panics if casting goes wrong. -*/ -func MustCastFromEchoContext(c echo.Context) Context { - const op string = "context.MustCastFromEchoContext" - ctx, ok := c.(Context) - if !ok { - panic(fmt.Sprintf("%s: unable to cast an echo.Context to our custom context.Context", op)) - } - return ctx -} - -/* -XLogger returns the xlog.Logger associated -with the Context. - -This method should be used instead of the -default Logger() method coming from -the echo.Context. -*/ -func (ctx Context) XLogger() xlog.Logger { - return ctx.logger -} - -// Config returns the conf.Config associated -// with the Context. -func (ctx Context) Config() conf.Config { - return ctx.config -} - -// WithResource creates a resource.Resource and -// adds it to the Context. -func (ctx *Context) WithResource(directoryName string) error { - const op string = "context.Context.WithResource" - resolver := func() (resource.Resource, error) { - r, err := resource.New(ctx.logger, directoryName) - if err != nil { - return r, err - } - // retrieve custom headers from request. - for key, value := range ctx.Request().Header { - r.WithCustomHTTPHeader(key, value[0]) - } - // retrieve form values from request. - for _, key := range resource.ArgKeys() { - r.WithArg(key, ctx.FormValue(string(key))) - } - // write form files from request. - form, err := ctx.MultipartForm() - if err != nil { - /* - (very) special case: one and - only one file has been sent - and it is empty. - */ - if strings.Contains(err.Error(), io.EOF.Error()) { - return r, xerror.Invalid(op, "one file has been sent but it is empty: does it exist?", err) - } - return r, err - } - for _, files := range form.File { - for _, fh := range files { - in, err := fh.Open() - if err != nil { - return r, err - } - defer in.Close() - // avoid directory traversal. - filename := filepath.Base(fh.Filename) - if err := r.WithFile(filename, in); err != nil { - return r, err - } - } - } - return r, nil - } - resource, err := resolver() - ctx.resource = resource - if err != nil { - return xerror.New(op, err) - } - return nil -} - -// HasResource returns true if the Context -// has a resource.Resource. -func (ctx Context) HasResource() bool { - return !reflect.DeepEqual(ctx.resource, resource.Resource{}) -} - -/* -MustResource returns the resource.Resource -associated with the Context. - -It panics if no resource.Resource. -*/ -func (ctx Context) MustResource() resource.Resource { - const op string = "context.Context.MustResource" - if !ctx.HasResource() { - panic(fmt.Sprintf("%s: unable to retrieve the resource.Resource from our custom context.Context", op)) - } - return ctx.resource -} - -/* -LogRequestResult logs the result of a request. -This method should only be used by a middleware! - -If an error is given, returns the exact same error. -*/ -func (ctx Context) LogRequestResult(err error, isDebug bool) error { - const op string = "context.Context.LogRequestResult" - req := ctx.Request() - resp := ctx.Response() - stopTime := time.Now() - fields := map[string]interface{}{ - "remote_ip": ctx.RealIP(), - "host": req.Host, - "uri": req.RequestURI, - "method": req.Method, - "path": path(req), - "referer": req.Referer(), - "user_agent": req.UserAgent(), - "status": resp.Status, - "latency": lantency(ctx.startTime, stopTime), - "latency_human": latencyHuman(ctx.startTime, stopTime), - "bytes_in": bytesIn(req), - "bytes_out": bytesOut(resp), - } - if err != nil { - ctx.logger.WithFields(fields).ErrorOpf(op, "request failed") - return err - } - if isDebug { - ctx.logger.WithFields(fields).DebugOpf(op, "request handled") - return nil - } - ctx.logger.WithFields(fields).InfoOpf(op, "request handled") - return nil -} - -func path(r *http.Request) string { - path := r.URL.Path - if path == "" { - path = "/" - } - return path -} - -func lantency(startTime time.Time, stopTime time.Time) string { - return strconv.FormatInt(int64(stopTime.Sub(startTime)), 10) -} - -func latencyHuman(startTime time.Time, stopTime time.Time) string { - return stopTime.Sub(startTime).String() -} - -func bytesIn(r *http.Request) string { - bytesIn := r.Header.Get(echo.HeaderContentLength) - if bytesIn == "" { - bytesIn = "0" - } - return bytesIn -} - -func bytesOut(r *echo.Response) string { - return strconv.FormatInt(r.Size, 10) -} diff --git a/internal/app/xhttp/pkg/context/context_test.go b/internal/app/xhttp/pkg/context/context_test.go deleted file mode 100644 index 9b803460..00000000 --- a/internal/app/xhttp/pkg/context/context_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package context - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestMustCastFromEchoContext(t *testing.T) { - // should be OK. - ctx := New( - test.DummyEchoContext(), - test.DebugLogger(), - conf.DefaultConfig(), - ) - assert.NotPanics(t, func() { - result := MustCastFromEchoContext(ctx) - assert.Equal(t, ctx, result) - }) - // should not be OK. - assert.Panics(t, func() { - MustCastFromEchoContext(test.DummyEchoContext()) - }) -} - -func TestLogRequestResult(t *testing.T) { - ctx := New( - test.DummyEchoContext(), - test.DebugLogger(), - conf.DefaultConfig(), - ) - // Info log. - err := ctx.LogRequestResult(nil, false) - assert.Nil(t, err) - // Debug log. - err = ctx.LogRequestResult(nil, true) - assert.Nil(t, err) - // Error log. - err = ctx.LogRequestResult(errors.New("foo"), true) - assert.NotNil(t, err) -} - -func TestGetters(t *testing.T) { - const resourceDirectoryName string = "foo" - logger := test.DebugLogger() - config := conf.DefaultConfig() - ctx := New( - test.DummyEchoContext(), - logger, - config, - ) - // Logger. - assert.Equal(t, logger, ctx.XLogger()) - // Config. - assert.Equal(t, config, ctx.Config()) - // Context should not have a resource.Resource. - assert.Equal(t, false, ctx.HasResource()) - assert.Panics(t, func() { - ctx.MustResource() - }) - // Context should have a resource.Resource. - ctx = New( - test.EchoContextMultipart(t), - logger, - config, - ) - err := ctx.WithResource(resourceDirectoryName) - assert.Nil(t, err) - assert.Equal(t, true, ctx.HasResource()) - assert.NotPanics(t, func() { - r := ctx.MustResource() - err = r.Close() - assert.Nil(t, err) - }) -} diff --git a/internal/app/xhttp/pkg/context/doc.go b/internal/app/xhttp/pkg/context/doc.go deleted file mode 100644 index 294bb860..00000000 --- a/internal/app/xhttp/pkg/context/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Package context extends the default echo.Context. - -All functions return our standard xerror.Error -in case of error. -*/ -package context diff --git a/internal/app/xhttp/pkg/resource/arg.go b/internal/app/xhttp/pkg/resource/arg.go deleted file mode 100644 index 2b4b70d1..00000000 --- a/internal/app/xhttp/pkg/resource/arg.go +++ /dev/null @@ -1,319 +0,0 @@ -package resource - -import ( - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/printer" - "github.com/thecodingmachine/gotenberg/internal/pkg/xassert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -// ArgKey is a type for -// arguments' keys. -type ArgKey string - -const ( - // ResultFilenameArgKey is the key - // of the argument "resultFilename". - ResultFilenameArgKey ArgKey = "resultFilename" - // WaitTimeoutArgKey is the key - // of the argument "waitTimeout". - WaitTimeoutArgKey ArgKey = "waitTimeout" - // WebhookURLArgKey is the key - // of the argument "webhookURL". - WebhookURLArgKey ArgKey = "webhookURL" - // WebhookURLTimeoutArgKey is the key - // of the argument "webhookURLTimeout". - WebhookURLTimeoutArgKey ArgKey = "webhookURLTimeout" - // RemoteURLArgKey is the key - // of the argument "remoteURL". - RemoteURLArgKey ArgKey = "remoteURL" - // WaitDelayArgKey is the key - // of the argument "waitDelay". - WaitDelayArgKey ArgKey = "waitDelay" - // PaperWidthArgKey is the key - // of the argument "paperWidth". - PaperWidthArgKey ArgKey = "paperWidth" - // PaperHeightArgKey is the key - // of the argument "paperHeight". - PaperHeightArgKey ArgKey = "paperHeight" - // MarginTopArgKey is the key - // of the argument "marginTop". - MarginTopArgKey ArgKey = "marginTop" - // MarginBottomArgKey is the key - // of the argument "marginBottom". - MarginBottomArgKey ArgKey = "marginBottom" - // MarginLeftArgKey is the key - // of the argument "marginLeft". - MarginLeftArgKey ArgKey = "marginLeft" - // MarginRightArgKey is the key - // of the argument "marginRight". - MarginRightArgKey ArgKey = "marginRight" - // LandscapeArgKey is the key - // of the argument "landscape". - LandscapeArgKey ArgKey = "landscape" - // PageRangesArgKey is the key - // of the argument "pageRanges". - PageRangesArgKey ArgKey = "pageRanges" - // GoogleChromeRpccBufferSizeArgKey is the key - // of the argument "googleChromeRpccBufferSize". - GoogleChromeRpccBufferSizeArgKey ArgKey = "googleChromeRpccBufferSize" - // ScaleArgKey is the key - // of the argument "scale". - ScaleArgKey ArgKey = "scale" -) - -/* -ArgKeys returns a slice -containing all available -arguments' keys. -*/ -func ArgKeys() []ArgKey { - return []ArgKey{ - ResultFilenameArgKey, - WaitTimeoutArgKey, - WebhookURLArgKey, - WebhookURLTimeoutArgKey, - RemoteURLArgKey, - WaitDelayArgKey, - PaperWidthArgKey, - PaperHeightArgKey, - MarginTopArgKey, - MarginBottomArgKey, - MarginLeftArgKey, - MarginRightArgKey, - LandscapeArgKey, - PageRangesArgKey, - GoogleChromeRpccBufferSizeArgKey, - ScaleArgKey, - } -} - -/* -WaitTimeoutArg is a helper for retrieving -the "waitTimeout" argument as float64. - -It also validates it against the application -configuration. -*/ -func WaitTimeoutArg(r Resource, config conf.Config) (float64, error) { - const op string = "resource.WaitTimeoutArg" - result, err := r.Float64Arg( - WaitTimeoutArgKey, - config.DefaultWaitTimeout(), - xassert.Float64NotInferiorTo(0), - xassert.Float64NotSuperiorTo(config.MaximumWaitTimeout()), - ) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -WaitDelayArg is a helper for retrieving -the "waitDelay" argument as float64. - -It also validates it against the application -configuration. -*/ -func WaitDelayArg(r Resource, config conf.Config) (float64, error) { - const ( - op string = "resource.WaitDelayArg" - defaultWaitDelay float64 = 0.0 - ) - result, err := r.Float64Arg( - WaitDelayArgKey, - defaultWaitDelay, - xassert.Float64NotInferiorTo(0.0), - xassert.Float64NotSuperiorTo(config.MaximumWaitDelay()), - ) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -WebhookURLTimeoutArg is a helper for retrieving -the "webhookURLTimeout" argument as float64. - -It also validates it against the application -configuration. -*/ -func WebhookURLTimeoutArg(r Resource, config conf.Config) (float64, error) { - const op string = "resource.WebhookURLTimeoutArg" - result, err := r.Float64Arg( - WebhookURLTimeoutArgKey, - config.DefaultWebhookURLTimeout(), - xassert.Float64NotInferiorTo(0), - xassert.Float64NotSuperiorTo(config.MaximumWebhookURLTimeout()), - ) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -PaperSizeArgs is a helper for retrieving -the "paperWidth" and "paperHeight" arguments -as float64. -*/ -func PaperSizeArgs(r Resource, config conf.Config) (float64, float64, error) { - const op string = "resource.PaperSizeArgs" - opts := printer.DefaultChromePrinterOptions(config) - resolver := func() (float64, float64, error) { - paperWidth, err := r.Float64Arg( - PaperWidthArgKey, - opts.PaperWidth, - xassert.Float64NotInferiorTo(0.0), - ) - if err != nil { - return opts.PaperWidth, - opts.PaperHeight, - err - } - paperHeight, err := r.Float64Arg( - PaperHeightArgKey, - opts.PaperHeight, - xassert.Float64NotInferiorTo(0.0), - ) - if err != nil { - return opts.PaperWidth, - opts.PaperHeight, - err - } - return paperWidth, - paperHeight, - nil - } - paperWidth, paperHeight, - err := resolver() - if err != nil { - return paperWidth, - paperHeight, - xerror.New(op, err) - } - return paperWidth, - paperHeight, - nil -} - -/* -MarginArgs is a helper for retrieving -the "marginTop", "marginBottom", "marginLeft" -and "marginRight" arguments as float64. -*/ -func MarginArgs(r Resource, config conf.Config) (float64, float64, float64, float64, error) { - const op string = "resource.MarginArgs" - opts := printer.DefaultChromePrinterOptions(config) - resolver := func() (float64, float64, float64, float64, error) { - marginTop, err := r.Float64Arg( - MarginTopArgKey, - opts.MarginTop, - xassert.Float64NotInferiorTo(0.0), - ) - if err != nil { - return opts.MarginTop, - opts.MarginBottom, - opts.MarginLeft, - opts.MarginRight, - err - } - marginBottom, err := r.Float64Arg( - MarginBottomArgKey, - opts.MarginBottom, - xassert.Float64NotInferiorTo(0.0), - ) - if err != nil { - return opts.MarginTop, - opts.MarginBottom, - opts.MarginLeft, - opts.MarginRight, - err - } - marginLeft, err := r.Float64Arg( - MarginLeftArgKey, - opts.MarginLeft, - xassert.Float64NotInferiorTo(0.0), - ) - if err != nil { - return opts.MarginTop, - opts.MarginBottom, - opts.MarginLeft, - opts.MarginRight, - err - } - marginRight, err := r.Float64Arg( - MarginRightArgKey, - opts.MarginRight, - xassert.Float64NotInferiorTo(0.0), - ) - if err != nil { - return opts.MarginTop, - opts.MarginBottom, - opts.MarginLeft, - opts.MarginRight, - err - } - return marginTop, - marginBottom, - marginLeft, - marginRight, - nil - } - marginTop, marginBottom, marginLeft, marginRight, - err := resolver() - if err != nil { - return marginTop, - marginBottom, - marginLeft, - marginRight, - xerror.New(op, err) - } - return marginTop, - marginBottom, - marginLeft, - marginRight, - nil -} - -/* -GoogleChromeRpccBufferSizeArg is a helper for retrieving -the "googleChromeRpccBufferSize" argument as int64. - -It also validates it against the application -configuration. -*/ -func GoogleChromeRpccBufferSizeArg(r Resource, config conf.Config) (int64, error) { - const op string = "resource.GoogleChromeRpccBufferSizeArg" - result, err := r.Int64Arg( - GoogleChromeRpccBufferSizeArgKey, - config.DefaultGoogleChromeRpccBufferSize(), - xassert.Int64NotInferiorTo(0.0), - xassert.Int64NotSuperiorTo(config.MaximumGoogleChromeRpccBufferSize()), - ) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -ScaleArg is a helper for retrieving -the "scale" argument as float64. -*/ -func ScaleArg(r Resource, config conf.Config) (float64, error) { - const op string = "resource.ScaleArg" - opts := printer.DefaultChromePrinterOptions(config) - result, err := r.Float64Arg( - ScaleArgKey, - opts.Scale, - xassert.Float64NotInferiorTo(0.1), - xassert.Float64NotSuperiorTo(2.0), - ) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} diff --git a/internal/app/xhttp/pkg/resource/arg_test.go b/internal/app/xhttp/pkg/resource/arg_test.go deleted file mode 100644 index 0fefba18..00000000 --- a/internal/app/xhttp/pkg/resource/arg_test.go +++ /dev/null @@ -1,396 +0,0 @@ -package resource - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/printer" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestArgKeys(t *testing.T) { - expected := []ArgKey{ - ResultFilenameArgKey, - WaitTimeoutArgKey, - WebhookURLArgKey, - WebhookURLTimeoutArgKey, - RemoteURLArgKey, - WaitDelayArgKey, - PaperWidthArgKey, - PaperHeightArgKey, - MarginTopArgKey, - MarginBottomArgKey, - MarginLeftArgKey, - MarginRightArgKey, - LandscapeArgKey, - PageRangesArgKey, - GoogleChromeRpccBufferSizeArgKey, - ScaleArgKey, - } - assert.Equal(t, expected, ArgKeys()) -} - -func TestWaitTimeoutArg(t *testing.T) { - const resourceDirectoryName string = "foo" - var expected float64 - logger := test.DebugLogger() - config := conf.DefaultConfig() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // argument does not exist. - expected = config.DefaultWaitTimeout() - v, err := WaitTimeoutArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // argument exist. - expected = 5.0 - r.WithArg(WaitTimeoutArgKey, "5.0") - v, err = WaitTimeoutArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is < 0. - expected = config.DefaultWaitTimeout() - r.WithArg(WaitTimeoutArgKey, "-1.0") - v, err = WaitTimeoutArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is > config.MaximumWaitTimeout(). - expected = config.DefaultWaitTimeout() - r.WithArg(WaitTimeoutArgKey, "31.0") - v, err = WaitTimeoutArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as - // argument value is invalid. - expected = config.DefaultWaitTimeout() - r.WithArg(WaitTimeoutArgKey, "foo") - v, err = WaitTimeoutArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestWaitDelayArg(t *testing.T) { - const ( - resourceDirectoryName string = "foo" - defaultValue float64 = 0.0 - ) - var expected float64 - logger := test.DebugLogger() - config := conf.DefaultConfig() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // argument does not exist. - expected = defaultValue - v, err := WaitDelayArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // argument exist. - expected = 5.0 - r.WithArg(WaitDelayArgKey, "5.0") - v, err = WaitDelayArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is < 0. - expected = defaultValue - r.WithArg(WaitDelayArgKey, "-1.0") - v, err = WaitDelayArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is > config.MaximumWaitDelay(). - expected = defaultValue - r.WithArg(WaitDelayArgKey, "31.0") - v, err = WaitDelayArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as - // argument value is invalid. - expected = defaultValue - r.WithArg(WaitDelayArgKey, "foo") - v, err = WaitDelayArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestWebhookURLTimeoutArg(t *testing.T) { - const resourceDirectoryName string = "foo" - var expected float64 - logger := test.DebugLogger() - config := conf.DefaultConfig() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // argument does not exist. - expected = config.DefaultWebhookURLTimeout() - v, err := WebhookURLTimeoutArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // argument exist. - expected = 5.0 - r.WithArg(WebhookURLTimeoutArgKey, "5.0") - v, err = WebhookURLTimeoutArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is < 0. - expected = config.DefaultWebhookURLTimeout() - r.WithArg(WebhookURLTimeoutArgKey, "-1.0") - v, err = WebhookURLTimeoutArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is > config.MaximumWebhookURLTimeout(). - expected = config.DefaultWebhookURLTimeout() - r.WithArg(WebhookURLTimeoutArgKey, "31.0") - v, err = WebhookURLTimeoutArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as - // argument value is invalid. - expected = config.DefaultWebhookURLTimeout() - r.WithArg(WebhookURLTimeoutArgKey, "foo") - v, err = WebhookURLTimeoutArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestPaperSizeArgs(t *testing.T) { - const resourceDirectoryName string = "foo" - var expected float64 - logger := test.DebugLogger() - config := conf.DefaultConfig() - opts := printer.DefaultChromePrinterOptions(config) - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // arguments do not exist. - width, height, err := PaperSizeArgs(r, config) - assert.Nil(t, err) - assert.Equal(t, opts.PaperWidth, width) - assert.Equal(t, opts.PaperHeight, height) - // arguments exist. - expected = 5.0 - r.WithArg(PaperWidthArgKey, "5.0") - r.WithArg(PaperHeightArgKey, "5.0") - width, height, err = PaperSizeArgs(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, width) - assert.Equal(t, expected, height) - // should not be OK as arguments - // value are < 0. - expected = opts.PaperWidth - r.WithArg(PaperWidthArgKey, "-1.0") - width, _, err = PaperSizeArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, width) - r.WithArg(PaperWidthArgKey, "5.0") - expected = opts.PaperHeight - r.WithArg(PaperHeightArgKey, "-1.0") - _, height, err = PaperSizeArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, height) - r.WithArg(PaperHeightArgKey, "5.0") - // should not be OK as - // arguments value are invalids. - expected = opts.PaperWidth - r.WithArg(PaperWidthArgKey, "foo") - width, _, err = PaperSizeArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, width) - r.WithArg(PaperWidthArgKey, "5.0") - expected = opts.PaperHeight - r.WithArg(PaperHeightArgKey, "foo") - _, height, err = PaperSizeArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, height) - r.WithArg(PaperHeightArgKey, "5.0") - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestMarginArgs(t *testing.T) { - const resourceDirectoryName string = "foo" - var expected float64 - logger := test.DebugLogger() - config := conf.DefaultConfig() - opts := printer.DefaultChromePrinterOptions(config) - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // arguments do not exist. - top, bottom, left, right, err := MarginArgs(r, config) - assert.Nil(t, err) - assert.Equal(t, opts.MarginTop, top) - assert.Equal(t, opts.MarginBottom, bottom) - assert.Equal(t, opts.MarginLeft, left) - assert.Equal(t, opts.MarginRight, right) - // arguments exist. - expected = 5.0 - r.WithArg(MarginTopArgKey, "5.0") - r.WithArg(MarginBottomArgKey, "5.0") - r.WithArg(MarginLeftArgKey, "5.0") - r.WithArg(MarginRightArgKey, "5.0") - top, bottom, left, right, err = MarginArgs(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, top) - assert.Equal(t, expected, bottom) - assert.Equal(t, expected, left) - assert.Equal(t, expected, right) - // should not be OK as arguments - // value are < 0. - expected = opts.MarginTop - r.WithArg(MarginTopArgKey, "-1.0") - top, _, _, _, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, top) - r.WithArg(MarginTopArgKey, "5.0") - expected = opts.MarginBottom - r.WithArg(MarginBottomArgKey, "-1.0") - _, bottom, _, _, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, bottom) - r.WithArg(MarginBottomArgKey, "5.0") - expected = opts.MarginLeft - r.WithArg(MarginLeftArgKey, "-1.0") - _, _, left, _, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, left) - r.WithArg(MarginLeftArgKey, "5.0") - expected = opts.MarginRight - r.WithArg(MarginRightArgKey, "-1.0") - _, _, _, right, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, right) - r.WithArg(MarginRightArgKey, "5.0") - // should not be OK as - // arguments value are invalids. - expected = opts.MarginTop - r.WithArg(MarginTopArgKey, "foo") - top, _, _, _, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, top) - r.WithArg(MarginTopArgKey, "5.0") - expected = opts.MarginBottom - r.WithArg(MarginBottomArgKey, "foo") - _, bottom, _, _, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, bottom) - r.WithArg(MarginBottomArgKey, "5.0") - expected = opts.MarginLeft - r.WithArg(MarginLeftArgKey, "foo") - _, _, left, _, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, left) - r.WithArg(MarginLeftArgKey, "5.0") - expected = opts.MarginRight - r.WithArg(MarginRightArgKey, "foo") - _, _, _, right, err = MarginArgs(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, right) - r.WithArg(MarginRightArgKey, "5.0") - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestGoogleChromeRpccBufferSizeArg(t *testing.T) { - const resourceDirectoryName string = "foo" - var expected int64 - logger := test.DebugLogger() - config := conf.DefaultConfig() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // argument does not exist. - expected = config.DefaultGoogleChromeRpccBufferSize() - v, err := GoogleChromeRpccBufferSizeArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // argument exist. - expected = 10 - r.WithArg(GoogleChromeRpccBufferSizeArgKey, "10") - v, err = GoogleChromeRpccBufferSizeArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is < 0. - expected = config.DefaultGoogleChromeRpccBufferSize() - r.WithArg(GoogleChromeRpccBufferSizeArgKey, "-1") - v, err = GoogleChromeRpccBufferSizeArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is > config.MaximumGoogleChromeRpccBufferSize(). - expected = config.DefaultGoogleChromeRpccBufferSize() - r.WithArg(GoogleChromeRpccBufferSizeArgKey, "104857601") - v, err = GoogleChromeRpccBufferSizeArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as - // argument value is invalid. - expected = config.DefaultGoogleChromeRpccBufferSize() - r.WithArg(GoogleChromeRpccBufferSizeArgKey, "foo") - v, err = GoogleChromeRpccBufferSizeArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestScaleArg(t *testing.T) { - const ( - resourceDirectoryName string = "foo" - defaultValue float64 = 1.0 - ) - var expected float64 - logger := test.DebugLogger() - config := conf.DefaultConfig() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // argument does not exist. - expected = defaultValue - v, err := ScaleArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // argument exist. - expected = 0.5 - r.WithArg(ScaleArgKey, "0.5") - v, err = ScaleArg(r, config) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is < 0.1. - expected = defaultValue - r.WithArg(ScaleArgKey, "-1.0") - v, err = ScaleArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as argument - // value is > 2.0. - expected = defaultValue - r.WithArg(ScaleArgKey, "2.1") - v, err = ScaleArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // should not be OK as - // argument value is invalid. - expected = defaultValue - r.WithArg(ScaleArgKey, "foo") - v, err = ScaleArg(r, config) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // finally... - err = r.Close() - assert.Nil(t, err) -} diff --git a/internal/app/xhttp/pkg/resource/doc.go b/internal/app/xhttp/pkg/resource/doc.go deleted file mode 100644 index 3ec7b2c9..00000000 --- a/internal/app/xhttp/pkg/resource/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -/* -Package resource helps managing -arguments and files for a conversion. - -All functions return our standard xerror.Error -in case of error. -*/ -package resource diff --git a/internal/app/xhttp/pkg/resource/file.go b/internal/app/xhttp/pkg/resource/file.go deleted file mode 100644 index 5526cf90..00000000 --- a/internal/app/xhttp/pkg/resource/file.go +++ /dev/null @@ -1,91 +0,0 @@ -package resource - -import ( - "io" - "io/ioutil" - "os" - - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/printer" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -// file represents a file within the resource. -type file struct { - fpath string -} - -// write writes given content to the -// resourceFile location. -func (f file) write(in io.Reader) error { - const op string = "resource.file.write" - resolver := func() error { - out, err := os.Create(f.fpath) - if err != nil { - return err - } - defer out.Close() - if err := out.Chmod(0600); err != nil { - return err - } - if _, err := io.Copy(out, in); err != nil { - return err - } - if _, err := out.Seek(0, 0); err != nil { - return err - } - return nil - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// content returns the string content of -// the file. -func (f file) content() (string, error) { - const op string = "resource.file.content" - b, err := ioutil.ReadFile(f.fpath) - if err != nil { - return "", xerror.New(op, err) - } - return string(b), nil -} - -/* -HeaderFooterContents is a helper for retrieving -the content of the files "header.html" -and "footer.html". -*/ -func HeaderFooterContents(r Resource, config conf.Config) (string, string, error) { - const op string = "resource.HeaderFooterContents" - opts := printer.DefaultChromePrinterOptions(config) - resolver := func() (string, string, error) { - headerHTML, err := r.Fcontent("header.html", opts.HeaderHTML) - if err != nil { - return opts.HeaderHTML, - opts.FooterHTML, - err - } - footerHTML, err := r.Fcontent("footer.html", opts.FooterHTML) - if err != nil { - return opts.HeaderHTML, - opts.FooterHTML, - err - } - return headerHTML, - footerHTML, - nil - } - headerHTML, footerHTML, - err := resolver() - if err != nil { - return headerHTML, - footerHTML, - xerror.New(op, err) - } - return headerHTML, - footerHTML, - nil -} diff --git a/internal/app/xhttp/pkg/resource/file_test.go b/internal/app/xhttp/pkg/resource/file_test.go deleted file mode 100644 index a376f8f2..00000000 --- a/internal/app/xhttp/pkg/resource/file_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package resource - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/printer" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestHeaderFooterContents(t *testing.T) { - const resourceDirectoryName string = "foo" - var expected string - logger := test.DebugLogger() - config := conf.DefaultConfig() - opts := printer.DefaultChromePrinterOptions(config) - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // arguments do not exist. - header, footer, err := HeaderFooterContents(r, config) - assert.Nil(t, err) - assert.Equal(t, opts.HeaderHTML, header) - assert.Equal(t, opts.FooterHTML, footer) - // arguments exist. - expected = "Gutenberg" - fpath := test.OfficeFpaths(t)[2] - f1, err := os.Open(fpath) - assert.Nil(t, err) - defer f1.Close() // nolint: errcheck - err = r.WithFile("header.html", f1) - assert.Nil(t, err) - f2, err := os.Open(fpath) - assert.Nil(t, err) - defer f2.Close() // nolint: errcheck - err = r.WithFile("footer.html", f2) - assert.Nil(t, err) - header, footer, err = HeaderFooterContents(r, config) - assert.Nil(t, err) - assert.Contains(t, header, expected) - assert.Contains(t, footer, expected) - // finally... - err = r.Close() - assert.Nil(t, err) -} diff --git a/internal/app/xhttp/pkg/resource/header.go b/internal/app/xhttp/pkg/resource/header.go deleted file mode 100644 index fa4c8814..00000000 --- a/internal/app/xhttp/pkg/resource/header.go +++ /dev/null @@ -1,37 +0,0 @@ -package resource - -import ( - "strings" -) - -const ( - // RemoteURLCustomHTTPHeaderCanonicalBaseKey is the base key - // of custom headers send to the remote URL. - RemoteURLCustomHTTPHeaderCanonicalBaseKey string = "Gotenberg-Remoteurl-" - // WebhookURLCustomHTTPHeaderCanonicalBaseKey is the base key - // of custom headers send to the webhook URL. - WebhookURLCustomHTTPHeaderCanonicalBaseKey string = "Gotenberg-Webhookurl-" -) - -func fetchCustomHTTPHeaders(r Resource, baseKey string) map[string]string { - customHeaders := make(map[string]string) - for key, value := range r.customHeaders { - if strings.Contains(key, baseKey) { - realKey := strings.Replace(key, baseKey, "", 1) - customHeaders[realKey] = value - } - } - return customHeaders -} - -// RemoteURLCustomHTTPHeaders is a helper for retrieving -// the custom headers for the URL conversion. -func RemoteURLCustomHTTPHeaders(r Resource) map[string]string { - return fetchCustomHTTPHeaders(r, RemoteURLCustomHTTPHeaderCanonicalBaseKey) -} - -// WebhookURLCustomHTTPHeaders is a helper for retrieving -// the custom headers for the webhook URL. -func WebhookURLCustomHTTPHeaders(r Resource) map[string]string { - return fetchCustomHTTPHeaders(r, WebhookURLCustomHTTPHeaderCanonicalBaseKey) -} diff --git a/internal/app/xhttp/pkg/resource/header_test.go b/internal/app/xhttp/pkg/resource/header_test.go deleted file mode 100644 index 35a944f8..00000000 --- a/internal/app/xhttp/pkg/resource/header_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package resource - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestRemoteURLCustomHeaders(t *testing.T) { - const resourceDirectoryName string = "foo" - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // should find the custom header. - customHeaderValue := "bar" - customHeaderCanonicalRealKey := "Foo" - customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", RemoteURLCustomHTTPHeaderCanonicalBaseKey, customHeaderCanonicalRealKey)) - r.WithCustomHTTPHeader(customHeaderCanonicalKey, customHeaderValue) - r.WithCustomHTTPHeader("Bar", "Bar") - expected := map[string]string{ - customHeaderCanonicalRealKey: customHeaderValue, - } - notExpected := map[string]string{ - customHeaderCanonicalKey: customHeaderValue, - } - v := RemoteURLCustomHTTPHeaders(r) - assert.Equal(t, expected, v) - assert.NotEqual(t, notExpected, v) -} - -func TestWebhookURLCustomHeaders(t *testing.T) { - const resourceDirectoryName string = "foo" - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // should find the custom header. - customHeaderValue := "bar" - customHeaderCanonicalRealKey := "Foo" - customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", WebhookURLCustomHTTPHeaderCanonicalBaseKey, customHeaderCanonicalRealKey)) - r.WithCustomHTTPHeader(customHeaderCanonicalKey, customHeaderValue) - r.WithCustomHTTPHeader("Bar", "Bar") - expected := map[string]string{ - customHeaderCanonicalRealKey: customHeaderValue, - } - notExpected := map[string]string{ - customHeaderCanonicalKey: customHeaderValue, - } - v := WebhookURLCustomHTTPHeaders(r) - assert.Equal(t, expected, v) - assert.NotEqual(t, notExpected, v) -} diff --git a/internal/app/xhttp/pkg/resource/resource.go b/internal/app/xhttp/pkg/resource/resource.go deleted file mode 100644 index 44b64599..00000000 --- a/internal/app/xhttp/pkg/resource/resource.go +++ /dev/null @@ -1,258 +0,0 @@ -package resource - -import ( - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "strings" - - "github.com/thecodingmachine/gotenberg/internal/pkg/normalize" - "github.com/thecodingmachine/gotenberg/internal/pkg/xassert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -/* -TemporaryDirectory is the directory -where all the resources directory -are located. -*/ -const TemporaryDirectory string = "tmp" - -// Resource helps managing -// arguments and files for a conversion. -type Resource struct { - logger xlog.Logger - dirPath string - customHeaders map[string]string - args map[ArgKey]string - files map[string]file -} - -// New creates a Resource where its files will -// be located in the given directory name. -func New(logger xlog.Logger, directoryName string) (Resource, error) { - const op string = "resource.New" - resolver := func() (string, error) { - dirPath := fmt.Sprintf("%s/%s", TemporaryDirectory, directoryName) - if err := os.MkdirAll(dirPath, 0755); err != nil { - return "", err - } - absDirPath, err := filepath.Abs(dirPath) - if err != nil { - return "", err - } - return absDirPath, nil - } - dirPath, err := resolver() - if err != nil { - return Resource{}, xerror.New(op, err) - } - logger.DebugOpf(op, "resource directory '%s' created", directoryName) - return Resource{ - logger: logger, - dirPath: dirPath, - customHeaders: make(map[string]string), - args: make(map[ArgKey]string), - files: make(map[string]file), - }, nil -} - -// Close removes the working directory of the -// Resource if it exists. -func (r Resource) Close() error { - const op string = "resource.Resource.Close" - if _, err := os.Stat(r.dirPath); os.IsNotExist(err) { - r.logger.DebugOpf(op, "resource directory '%s' does not exist, nothing to remove", r.dirPath) - return nil - } - if err := os.RemoveAll(r.dirPath); err != nil { - return xerror.New(op, err) - } - r.logger.DebugOpf(op, "resource directory '%s' removed", r.dirPath) - return nil -} - -// WithCustomHTTPHeader add a new custom header to the Resource. -// Given key should be in canonical format. -func (r *Resource) WithCustomHTTPHeader(key string, value string) { - const op string = "resource.Resource.WithCustomHTTPHeader" - // should already be in canonical format. - canonicalKey := http.CanonicalHeaderKey(key) - if strings.Contains(canonicalKey, RemoteURLCustomHTTPHeaderCanonicalBaseKey) || - strings.Contains(canonicalKey, WebhookURLCustomHTTPHeaderCanonicalBaseKey) { - r.customHeaders[canonicalKey] = value - r.logger.DebugOpf(op, "added '%s' with value '%s' to resource custom HTTP headers", canonicalKey, value) - return - } - r.logger.DebugOpf(op, "skipping '%s' as it is not a custom HTTP header...", canonicalKey) -} - -// WithArg add a new argument to the Resource. -func (r *Resource) WithArg(key ArgKey, value string) { - const op string = "resource.Resource.WithArg" - r.args[key] = value - r.logger.DebugOpf(op, "added '%s' with value '%s' to resource args", key, value) -} - -// WithFile add a new file to the Resource. -func (r *Resource) WithFile(filename string, in io.Reader) error { - const op string = "resource.Resource.WithFile" - resolver := func() error { - // see https://github.com/thecodingmachine/gotenberg/issues/104. - normalized, err := normalize.String(filename) - if err != nil { - return err - } - fpath := fmt.Sprintf("%s/%s", r.dirPath, normalized) - file := file{fpath: fpath} - if err := file.write(in); err != nil { - return err - } - r.files[filename] = file - r.logger.DebugOpf(op, "resource file '%s' created", filename) - return nil - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// DirPath returns the directory path -// of the Resource. -func (r Resource) DirPath() string { - return r.dirPath -} - -// HasArg returns true if given key exists -// among the Resource and its value is not empty. -func (r Resource) HasArg(key ArgKey) bool { - if v, ok := r.args[key]; ok { - return v != "" - } - return false -} - -/* -StringArg returns the value of the -argument identified by given key. - -It works in the same manner as xassert.String. -*/ -func (r Resource) StringArg(key ArgKey, defaultValue string, rules ...xassert.RuleString) (string, error) { - const op string = "resource.Resource.StringArg" - result, err := xassert.String(string(key), r.args[key], defaultValue, rules...) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -Int64Arg returns the int64 representation of the -argument identified by given key. - -It works in the same manner as xassert.Int64. -*/ -func (r Resource) Int64Arg(key ArgKey, defaultValue int64, rules ...xassert.RuleInt64) (int64, error) { - const op string = "resource.Resource.Int64Arg" - result, err := xassert.Int64(string(key), r.args[key], defaultValue, rules...) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -Float64Arg returns the float64 representation of the -argument identified by given key. - -It works in the same manner as xassert.Float64. -*/ -func (r Resource) Float64Arg(key ArgKey, defaultValue float64, rules ...xassert.RuleFloat64) (float64, error) { - const op string = "resource.Resource.Float64Arg" - result, err := xassert.Float64(string(key), r.args[key], defaultValue, rules...) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -BoolArg returns the boolean representation of the -argument identified by given key. - -It works in the same manner as xassert.Bool. -*/ -func (r Resource) BoolArg(key ArgKey, defaultValue bool) (bool, error) { - const op string = "resource.Resource.BoolArg" - result, err := xassert.Bool(string(key), r.args[key], defaultValue) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -// Fpath returns the path of the given filename. -// This filename should exist whithin the Resource. -func (r Resource) Fpath(filename string) (string, error) { - const op string = "resource.Resource.Fpath" - file, ok := r.files[filename] - if !ok { - return "", xerror.Invalid( - op, - fmt.Sprintf("resource file '%s' does not exist", filename), - nil, - ) - } - return file.fpath, nil -} - -/* -Fpaths returns the paths of the files -having one of the given file extensions. - -It should found at least one path. -*/ -func (r Resource) Fpaths(exts ...string) ([]string, error) { - const op string = "resource.Resource.Fpaths" - var fpaths []string - for filename, file := range r.files { - for _, ext := range exts { - if filepath.Ext(filename) == ext { - fpaths = append(fpaths, file.fpath) - } - } - } - if len(fpaths) == 0 { - return nil, xerror.Invalid( - op, - fmt.Sprintf("no resource file found for extensions '%v'", exts), - nil, - ) - } - return fpaths, nil -} - -/* -Fcontent returns the string content of the -given filename. - -If filename does not exist within the Resource, -returns the default value. -*/ -func (r Resource) Fcontent(filename, defaultValue string) (string, error) { - const op string = "resource.Resource.Fcontent" - file, ok := r.files[filename] - if !ok { - return defaultValue, nil - } - content, err := file.content() - if err != nil { - return "", xerror.New(op, err) - } - return content, nil -} diff --git a/internal/app/xhttp/pkg/resource/resource_test.go b/internal/app/xhttp/pkg/resource/resource_test.go deleted file mode 100644 index 14b51dcd..00000000 --- a/internal/app/xhttp/pkg/resource/resource_test.go +++ /dev/null @@ -1,287 +0,0 @@ -package resource - -import ( - "fmt" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xassert" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestStringArg(t *testing.T) { - const ( - resourceDirectoryName string = "foo" - defaultValue string = "FOO" - ) - var expected string - rule := xassert.StringOneOf([]string{"FOO", "BAR"}) - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // empty value, result should be equal - // to the default value. - r.WithArg(ResultFilenameArgKey, "") - v, err := r.StringArg(ResultFilenameArgKey, defaultValue) - assert.Nil(t, err) - assert.Equal(t, defaultValue, v) - // result should be equal to given value - // as it is one of "FOO" and "BAR". - expected = "BAR" - r.WithArg(ResultFilenameArgKey, expected) - v, err = r.StringArg(ResultFilenameArgKey, defaultValue, rule) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // should not be OK as given value is not - // one of "FOO" and "BAR". - expected = defaultValue - r.WithArg(ResultFilenameArgKey, "BAZ") - v, err = r.StringArg(ResultFilenameArgKey, defaultValue, rule) - test.AssertError(t, err) - assert.Equal(t, expected, v) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestInt64Arg(t *testing.T) { - const ( - resourceDirectoryName string = "foo" - defaultValue int64 = 10 - ) - var expected int64 - rule := xassert.Int64NotInferiorTo(6) - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // empty value, result should be equal - // to the default value. - r.WithArg(WaitTimeoutArgKey, "") - v, err := r.Int64Arg(WaitTimeoutArgKey, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to given value - // but as integer. - r.WithArg(WaitTimeoutArgKey, "5") - v, err = r.Int64Arg(WaitTimeoutArgKey, defaultValue) - expected = 5 - assert.Equal(t, expected, v) - assert.Nil(t, err) - // should not be OK as given value is not - // a string representation of an integer. - r.WithArg(WaitTimeoutArgKey, "foo") - v, err = r.Int64Arg(WaitTimeoutArgKey, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - // should not be OK as given value does not - // validate the rule x >= 6. - r.WithArg(WaitTimeoutArgKey, "5") - v, err = r.Int64Arg(WaitTimeoutArgKey, defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestFloat64Arg(t *testing.T) { - const ( - resourceDirectoryName string = "foo" - defaultValue float64 = 10.0 - ) - var expected float64 - rule := xassert.Float64NotInferiorTo(6.0) - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // empty value, result should be equal - // to the default value. - r.WithArg(WaitTimeoutArgKey, "") - v, err := r.Float64Arg(WaitTimeoutArgKey, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to given value - // but as float. - r.WithArg(WaitTimeoutArgKey, "5.5") - v, err = r.Float64Arg(WaitTimeoutArgKey, defaultValue) - expected = 5.5 - assert.Equal(t, expected, v) - assert.Nil(t, err) - // should not be OK as given value is not - // a string representation of a float. - r.WithArg(WaitTimeoutArgKey, "foo") - v, err = r.Float64Arg(WaitTimeoutArgKey, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - // should not be OK as given value does not - // validate the rule x >= 6. - r.WithArg(WaitTimeoutArgKey, "5.0") - v, err = r.Float64Arg(WaitTimeoutArgKey, defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestBoolArg(t *testing.T) { - const ( - resourceDirectoryName string = "foo" - defaultValue bool = true - ) - var expected bool - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // empty value, result should be equal - // to the default value. - r.WithArg(LandscapeArgKey, "") - v, err := r.BoolArg(LandscapeArgKey, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to given value - // but as boolean. - r.WithArg(LandscapeArgKey, "1") - v, err = r.BoolArg(LandscapeArgKey, defaultValue) - expected = true - assert.Equal(t, expected, v) - assert.Nil(t, err) - r.WithArg(LandscapeArgKey, "true") - v, err = r.BoolArg(LandscapeArgKey, defaultValue) - expected = true - assert.Equal(t, expected, v) - assert.Nil(t, err) - r.WithArg(LandscapeArgKey, "0") - v, err = r.BoolArg(LandscapeArgKey, defaultValue) - expected = false - assert.Equal(t, expected, v) - assert.Nil(t, err) - r.WithArg(LandscapeArgKey, "false") - v, err = r.BoolArg(LandscapeArgKey, defaultValue) - expected = false - assert.Equal(t, expected, v) - assert.Nil(t, err) - // should not be OK as given value is not - // a string representation of a boolean. - r.WithArg(LandscapeArgKey, "foo") - v, err = r.BoolArg(LandscapeArgKey, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestFpath(t *testing.T) { - const resourceDirectoryName string = "foo" - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // file exists. - fpath := test.MergeFpaths(t)[0] - f, err := os.Open(fpath) - assert.Nil(t, err) - filename := "foo.pdf" - err = r.WithFile(filename, f) - assert.Nil(t, err) - absDirPath, err := filepath.Abs(fmt.Sprintf("%s/%s", TemporaryDirectory, resourceDirectoryName)) - assert.Nil(t, err) - expected := fmt.Sprintf("%s/%s", absDirPath, filename) - v, err := r.Fpath(filename) - assert.Nil(t, err) - assert.Equal(t, expected, v) - // should not be OK as file does - // not exist. - _, err = r.Fpath("bar.pdf") - test.AssertError(t, err) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestFpaths(t *testing.T) { - const resourceDirectoryName string = "foo" - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - fpath := test.MergeFpaths(t)[0] - f, err := os.Open(fpath) - assert.Nil(t, err) - defer f.Close() // nolint: errcheck - filename := "foo.pdf" - err = r.WithFile(filename, f) - assert.Nil(t, err) - // file extension exists. - absDirPath, err := filepath.Abs(fmt.Sprintf("%s/%s", TemporaryDirectory, resourceDirectoryName)) - assert.Nil(t, err) - expected := []string{ - fmt.Sprintf("%s/%s", absDirPath, filename), - } - fpaths, err := r.Fpaths(".pdf") - assert.Nil(t, err) - assert.Equal(t, expected, fpaths) - // should not be OK as file extension - // does not exist. - _, err = r.Fpaths(".html") - test.AssertError(t, err) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestFcontent(t *testing.T) { - const ( - resourceDirectoryName string = "foo" - defaultValue string = "Gutenberg" - ) - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - filename := "foo.txt" - // file does not exist, expecting - // value. - v, err := r.Fcontent(filename, defaultValue) - assert.Nil(t, err) - assert.Equal(t, defaultValue, v) - // file exists. - fpath := test.OfficeFpaths(t)[2] - f, err := os.Open(fpath) - assert.Nil(t, err) - defer f.Close() // nolint: errcheck - err = r.WithFile(filename, f) - assert.Nil(t, err) - v, err = r.Fcontent(filename, defaultValue) - assert.Nil(t, err) - assert.Contains(t, v, defaultValue) - // finally... - err = r.Close() - assert.Nil(t, err) -} - -func TestGetters(t *testing.T) { - const resourceDirectoryName string = "foo" - logger := test.DebugLogger() - r, err := New(logger, resourceDirectoryName) - assert.Nil(t, err) - // has arg. - assert.Equal(t, false, r.HasArg(LandscapeArgKey)) - r.WithArg(LandscapeArgKey, "foo") - assert.Equal(t, true, r.HasArg(LandscapeArgKey)) - // directory path. - absDirPath, err := filepath.Abs(fmt.Sprintf("%s/%s", TemporaryDirectory, resourceDirectoryName)) - assert.Nil(t, err) - assert.Equal(t, absDirPath, r.DirPath()) - // finally... - err = r.Close() - assert.Nil(t, err) -} diff --git a/internal/app/xhttp/xhttp.go b/internal/app/xhttp/xhttp.go deleted file mode 100644 index 02db10e1..00000000 --- a/internal/app/xhttp/xhttp.go +++ /dev/null @@ -1,31 +0,0 @@ -package xhttp - -import ( - "github.com/labstack/echo/v4" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" -) - -// New returns a custom echo.Echo. -func New(config conf.Config) *echo.Echo { - srv := echo.New() - srv.HideBanner = true - srv.HidePort = true - srv.Use(contextMiddleware(config)) - srv.Use(loggerMiddleware(config)) - srv.Use(cleanupMiddleware()) - srv.Use(errorMiddleware()) - srv.GET(pingEndpoint(config), pingHandler) - srv.POST(mergeEndpoint(config), mergeHandler) - if config.DisableGoogleChrome() && config.DisableUnoconv() { - return srv - } - if !config.DisableGoogleChrome() { - srv.POST(htmlEndpoint(config), htmlHandler) - srv.POST(urlEndpoint(config), urlHandler) - srv.POST(markdownEndpoint(config), markdownHandler) - } - if !config.DisableUnoconv() { - srv.POST(officeEndpoint(config), officeHandler) - } - return srv -} diff --git a/internal/app/xhttp/xhttp_test.go b/internal/app/xhttp/xhttp_test.go deleted file mode 100644 index f4fe3df0..00000000 --- a/internal/app/xhttp/xhttp_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package xhttp - -import ( - "net/http" - "net/http/httptest" - "os" - "testing" - - "github.com/labstack/echo/v4" - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestNonExistingEndpoint(t *testing.T) { - config, err := conf.FromEnv() - assert.Nil(t, err) - srv := New(config) - // "/" endpoint should return 404. - req := httptest.NewRequest(http.MethodGet, "/", nil) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) -} - -func TestDisableChromeEndpoints(t *testing.T) { - os.Setenv(conf.DisableGoogleChromeEnvVar, "1") - config, err := conf.FromEnv() - assert.Nil(t, err) - srv := New(config) - // Ping endpoint should return 200. - req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Merge endpoint should return 200. - body, contentType := test.MergeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // HTML endpoint should return 404. - body, contentType = test.HTMLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // URL endpoint should return 404. - body, contentType = test.URLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // Markdown endpoint should return 404. - body, contentType = test.MarkdownMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // Office endpoint should return 200. - body, contentType = test.OfficeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // finally... - os.Setenv(conf.DisableGoogleChromeEnvVar, "0") -} - -func TestDisableUnoconvEndpoints(t *testing.T) { - os.Setenv(conf.DisableUnoconvEnvVar, "1") - config, err := conf.FromEnv() - assert.Nil(t, err) - srv := New(config) - // Ping endpoint should return 200. - req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Merge endpoint should return 200. - body, contentType := test.MergeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // HTML endpoint should return 200. - body, contentType = test.HTMLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // URL endpoint should return 200. - body, contentType = test.URLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Markdown endpoint should return 200. - body, contentType = test.MarkdownMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Office endpoint should return 404. - body, contentType = test.OfficeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // finally... - os.Setenv(conf.DisableUnoconvEnvVar, "0") -} -func TestDisableChromeAndUnoconvEndpoints(t *testing.T) { - os.Setenv(conf.DisableGoogleChromeEnvVar, "1") - os.Setenv(conf.DisableUnoconvEnvVar, "1") - config, err := conf.FromEnv() - assert.Nil(t, err) - srv := New(config) - // Ping endpoint should return 200. - req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Merge endpoint should return 200. - body, contentType := test.MergeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // HTML endpoint should return 404. - body, contentType = test.HTMLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // URL endpoint should return 404. - body, contentType = test.URLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // Markdown endpoint should return 404. - body, contentType = test.MarkdownMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // Office endpoint should return 404. - body, contentType = test.OfficeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusNotFound, srv, req) - // finally... - os.Setenv(conf.DisableGoogleChromeEnvVar, "0") - os.Setenv(conf.DisableUnoconvEnvVar, "0") -} - -func TestCustomRootPath(t *testing.T) { - os.Setenv(conf.RootPathEnvVar, "/foo/") - config, err := conf.FromEnv() - assert.Nil(t, err) - srv := New(config) - // Ping endpoint should return 200. - req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Merge endpoint should return 200. - body, contentType := test.MergeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // HTML endpoint should return 200. - body, contentType = test.HTMLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // URL endpoint should return 200. - body, contentType = test.URLMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Markdown endpoint should return 200. - body, contentType = test.MarkdownMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // Office endpoint should return 200. - body, contentType = test.OfficeMultipartForm(t, nil) - req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body) - req.Header.Set(echo.HeaderContentType, contentType) - test.AssertStatusCode(t, http.StatusOK, srv, req) - // finally... - os.Setenv(conf.RootPathEnvVar, "/") -} diff --git a/internal/pkg/chrome/chrome.go b/internal/pkg/chrome/chrome.go deleted file mode 100644 index ffbe30c1..00000000 --- a/internal/pkg/chrome/chrome.go +++ /dev/null @@ -1,186 +0,0 @@ -package chrome - -import ( - "context" - "os" - "os/exec" - "strings" - "syscall" - "time" - - "github.com/mafredri/cdp/devtool" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xexec" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/internal/pkg/xtime" -) - -// Start starts Google Chrome headless in background. -func Start(logger xlog.Logger, ignoreCertificateErrors bool) error { - const op string = "chrome.Start" - logger.DebugOp(op, "starting new Google Chrome headless process on port 9222...") - resolver := func() error { - cmd, err := cmd(logger, ignoreCertificateErrors) - if err != nil { - return err - } - // we try to start the process. - xexec.LogBeforeExecute(logger, cmd) - if err := cmd.Start(); err != nil { - return err - } - // if the process failed to start correctly, - // we have to restart it. - isViable, _ := IsViable(logger) - if !isViable { - return restart(logger, cmd.Process, ignoreCertificateErrors) - } - return nil - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func cmd(logger xlog.Logger, ignoreCertificateErrors bool) (*exec.Cmd, error) { - const op string = "chrome.cmd" - binary := "google-chrome-stable" - args := []string{ - "--no-sandbox", - "--headless", - // see https://github.com/thecodingmachine/gotenberg/issues/157. - "--disable-dev-shm-usage", - // See https://github.com/puppeteer/puppeteer/issues/661 - // and https://github.com/puppeteer/puppeteer/issues/2410. - "--font-render-hinting=none", - "--remote-debugging-port=9222", - "--disable-gpu", - "--disable-translate", - "--disable-extensions", - "--disable-background-networking", - "--safebrowsing-disable-auto-update", - "--disable-sync", - "--disable-default-apps", - "--hide-scrollbars", - "--metrics-recording-only", - "--mute-audio", - "--no-first-run", - } - - if ignoreCertificateErrors { - args = append(args, "--ignore-certificate-errors") - } - - cmd, err := xexec.Command(logger, binary, args...) - if err != nil { - return nil, xerror.New(op, err) - } - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - return cmd, nil -} - -func kill(logger xlog.Logger, proc *os.Process) error { - const op string = "chrome.kill" - logger.DebugOp(op, "killing Google Chrome headless process using port 9222...") - resolver := func() error { - err := syscall.Kill(-proc.Pid, syscall.SIGKILL) - if err == nil { - return nil - } - if strings.Contains(err.Error(), "no such process") { - return nil - } - return err - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func restart(logger xlog.Logger, proc *os.Process, ignoreCertificateErrors bool) error { - const op string = "chrome.restart" - logger.DebugOp(op, "restarting Google Chrome headless process using port 9222...") - resolver := func() error { - // kill the existing process first. - if err := kill(logger, proc); err != nil { - return err - } - cmd, err := cmd(logger, ignoreCertificateErrors) - if err != nil { - return err - } - // we try to restart the process. - xexec.LogBeforeExecute(logger, cmd) - if err := cmd.Start(); err != nil { - return err - } - // if the process failed to restart correctly, - // we have to restart it again. - isViable, _ := IsViable(logger) - if !isViable { - return restart(logger, cmd.Process, ignoreCertificateErrors) - } - return nil - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// IsViable checks if Google Chrome is healthy. -func IsViable(logger xlog.Logger) (bool, error) { - const ( - op string = "chrome.IsViable" - maxViabilityTests int = 20 - ) - viable := func() (bool, error) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - endpoint := "http://localhost:9222" - logger.DebugOpf( - op, - "checking Google Chrome headless process viability via endpoint '%s/json/version'", - endpoint, - ) - v, err := devtool.New(endpoint).Version(ctx) - if err != nil { - logger.DebugOpf( - op, - "Google Chrome headless is not viable as endpoint returned '%v'", - err.Error(), - ) - return false, err - } - logger.DebugOpf( - op, - "Google Chrome headless is viable as endpoint returned '%v'", - v, - ) - return true, nil - } - result := false - var err error - - for i := 0; i < maxViabilityTests && !result; i++ { - warmup(logger) - result, err = viable() - } - return result, err -} - -func warmup(logger xlog.Logger) { - const ( - op string = "chrome.warmup" - seconds float64 = 0.5 - ) - warmupTime := xtime.Duration(seconds) - logger.DebugOpf( - op, - "waiting '%v' for allowing Google Chrome to warmup", - warmupTime, - ) - time.Sleep(warmupTime) -} diff --git a/internal/pkg/chrome/doc.go b/internal/pkg/chrome/doc.go deleted file mode 100644 index c5431149..00000000 --- a/internal/pkg/chrome/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package chrome helps starting -// Google Chrome headless in background. -package chrome diff --git a/internal/pkg/conf/conf.go b/internal/pkg/conf/conf.go deleted file mode 100644 index 7e974309..00000000 --- a/internal/pkg/conf/conf.go +++ /dev/null @@ -1,293 +0,0 @@ -package conf - -import ( - "github.com/thecodingmachine/gotenberg/internal/pkg/xassert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -const ( - // MaximumWaitTimeoutEnvVar contains the name - // of the environment variable "MAXIMUM_WAIT_TIMEOUT". - MaximumWaitTimeoutEnvVar string = "MAXIMUM_WAIT_TIMEOUT" - // MaximumWaitDelayEnvVar contains the name - // of the environment variable "MAXIMUM_WAIT_DELAY". - MaximumWaitDelayEnvVar string = "MAXIMUM_WAIT_DELAY" - // MaximumWebhookURLTimeoutEnvVar contains the name - // of the environment variable "MAXIMUM_WEBHOOK_URL_TIMEOUT". - MaximumWebhookURLTimeoutEnvVar string = "MAXIMUM_WEBHOOK_URL_TIMEOUT" - // DefaultWaitTimeoutEnvVar contains the name - // of the environment variable "DEFAULT_WAIT_TIMEOUT". - DefaultWaitTimeoutEnvVar string = "DEFAULT_WAIT_TIMEOUT" - // DefaultWebhookURLTimeoutEnvVar contains the name - // of the environment variable "DEFAULT_WEBHOOK_URL_TIMEOUT". - DefaultWebhookURLTimeoutEnvVar string = "DEFAULT_WEBHOOK_URL_TIMEOUT" - // DefaultListenPortEnvVar contains the name - // of the environment variable "DEFAULT_LISTEN_PORT". - DefaultListenPortEnvVar string = "DEFAULT_LISTEN_PORT" - // DisableGoogleChromeEnvVar contains the name - // of the environment variable "DISABLE_GOOGLE_CHROME". - DisableGoogleChromeEnvVar string = "DISABLE_GOOGLE_CHROME" - // DisableUnoconvEnvVar contains the name - // of the environment variable "DISABLE_UNOCONV". - DisableUnoconvEnvVar string = "DISABLE_UNOCONV" - // LogLevelEnvVar contains the name - // of the environment variable "LOG_LEVEL". - LogLevelEnvVar string = "LOG_LEVEL" - // RootPathEnvVar contains the name - // of the environment variable "ROOT_PATH". - RootPathEnvVar string = "ROOT_PATH" - // DefaultGoogleChromeRpccBufferSizeEnvVar contains the name - // of the environment variable "DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE". - DefaultGoogleChromeRpccBufferSizeEnvVar string = "DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE" - // GoogleChromeIgnoreCertificateErrorsEnvVar contains the name - // of the environment variable "GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS". - GoogleChromeIgnoreCertificateErrorsEnvVar string = "GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS" -) - -// Config contains the application -// configuration. -type Config struct { - maximumWaitTimeout float64 - maximumWaitDelay float64 - maximumWebhookURLTimeout float64 - defaultWaitTimeout float64 - defaultWebhookURLTimeout float64 - defaultListenPort int64 - disableGoogleChrome bool - disableUnoconv bool - googleChromeIgnoreCertificateErrors bool - logLevel xlog.Level - rootPath string - maximumGoogleChromeRpccBufferSize int64 - defaultGoogleChromeRpccBufferSize int64 -} - -// DefaultConfig returns the default -// configuration. -func DefaultConfig() Config { - return Config{ - maximumWaitTimeout: 30.0, - maximumWaitDelay: 10.0, - maximumWebhookURLTimeout: 30.0, - defaultWaitTimeout: 10.0, - defaultWebhookURLTimeout: 10.0, - defaultListenPort: 3000, - disableGoogleChrome: false, - disableUnoconv: false, - logLevel: xlog.InfoLevel, - rootPath: "/", - maximumGoogleChromeRpccBufferSize: 104857600, // ~100 MB - defaultGoogleChromeRpccBufferSize: 1048576, // 1 MB - googleChromeIgnoreCertificateErrors: false, - } -} - -/* -FromEnv returns a Conf according -to environment variables. -*/ -func FromEnv() (Config, error) { - const op string = "conf.FromEnv" - resolver := func() (Config, error) { - c := DefaultConfig() - maximumWaitTimeout, err := xassert.Float64FromEnv( - MaximumWaitTimeoutEnvVar, - c.maximumWaitTimeout, - xassert.Float64NotInferiorTo(0.0), - ) - c.maximumWaitTimeout = maximumWaitTimeout - if err != nil { - return c, err - } - maximumWaitDelay, err := xassert.Float64FromEnv( - MaximumWaitDelayEnvVar, - c.maximumWaitDelay, - xassert.Float64NotInferiorTo(0.0), - ) - c.maximumWaitDelay = maximumWaitDelay - if err != nil { - return c, err - } - maximumWebhookURLTimeout, err := xassert.Float64FromEnv( - MaximumWebhookURLTimeoutEnvVar, - c.maximumWebhookURLTimeout, - xassert.Float64NotInferiorTo(0.0), - ) - c.maximumWebhookURLTimeout = maximumWebhookURLTimeout - if err != nil { - return c, err - } - defaultWaitTimeout, err := xassert.Float64FromEnv( - DefaultWaitTimeoutEnvVar, - c.defaultWaitTimeout, - xassert.Float64NotInferiorTo(0.0), - xassert.Float64NotSuperiorTo(c.maximumWaitTimeout), - ) - c.defaultWaitTimeout = defaultWaitTimeout - if err != nil { - return c, err - } - defaultWebhookURLTimeout, err := xassert.Float64FromEnv( - DefaultWebhookURLTimeoutEnvVar, - c.defaultWebhookURLTimeout, - xassert.Float64NotInferiorTo(0.0), - xassert.Float64NotSuperiorTo(c.defaultWebhookURLTimeout), - ) - c.defaultWebhookURLTimeout = defaultWebhookURLTimeout - if err != nil { - return c, err - } - defaultListenPort, err := xassert.Int64FromEnv( - DefaultListenPortEnvVar, - c.defaultListenPort, - xassert.Int64NotInferiorTo(0), - xassert.Int64NotSuperiorTo(65535), - ) - c.defaultListenPort = defaultListenPort - if err != nil { - return c, err - } - disableGoogleChrome, err := xassert.BoolFromEnv( - DisableGoogleChromeEnvVar, - c.disableGoogleChrome, - ) - c.disableGoogleChrome = disableGoogleChrome - if err != nil { - return c, err - } - disableUnoconv, err := xassert.BoolFromEnv( - DisableUnoconvEnvVar, - c.disableUnoconv, - ) - c.disableUnoconv = disableUnoconv - if err != nil { - return c, err - } - logLevel, err := xassert.StringFromEnv( - LogLevelEnvVar, - string(c.logLevel), - xassert.StringOneOf(xlog.Levels()), - ) - c.logLevel = xlog.MustParseLevel(logLevel) - if err != nil { - return c, err - } - rootPath, err := xassert.StringFromEnv( - RootPathEnvVar, - c.rootPath, - xassert.StringStartWith("/"), - xassert.StringEndWith("/"), - ) - c.rootPath = rootPath - if err != nil { - return c, err - } - defaultGoogleChromeRpccBufferSize, err := xassert.Int64FromEnv( - DefaultGoogleChromeRpccBufferSizeEnvVar, - c.defaultGoogleChromeRpccBufferSize, - xassert.Int64NotInferiorTo(0), - xassert.Int64NotSuperiorTo(c.MaximumGoogleChromeRpccBufferSize()), - ) - c.defaultGoogleChromeRpccBufferSize = defaultGoogleChromeRpccBufferSize - if err != nil { - return c, err - } - googleChromeIgnoreCertificateErrors, err := xassert.BoolFromEnv( - GoogleChromeIgnoreCertificateErrorsEnvVar, - c.googleChromeIgnoreCertificateErrors, - ) - c.googleChromeIgnoreCertificateErrors = googleChromeIgnoreCertificateErrors - if err != nil { - return c, err - } - return c, nil - } - result, err := resolver() - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -// MaximumWaitTimeout returns the maximum -// wait timeout from the configuration. -func (c Config) MaximumWaitTimeout() float64 { - return c.maximumWaitTimeout -} - -// MaximumWaitDelay returns the maximum -// wait timeout from the configuration. -func (c Config) MaximumWaitDelay() float64 { - return c.maximumWaitDelay -} - -// MaximumWebhookURLTimeout returns the maximum -// webhook URL wait timeout from the configuration. -func (c Config) MaximumWebhookURLTimeout() float64 { - return c.maximumWebhookURLTimeout -} - -// DefaultWaitTimeout returns the default -// wait timeout from the configuration. -func (c Config) DefaultWaitTimeout() float64 { - return c.defaultWaitTimeout -} - -// DefaultWebhookURLTimeout returns the default -// webhook URL wait timeout from the configuration. -func (c Config) DefaultWebhookURLTimeout() float64 { - return c.defaultWebhookURLTimeout -} - -// DefaultListenPort returns the default -// listen port from the configuration. -func (c Config) DefaultListenPort() int64 { - return c.defaultListenPort -} - -/* -DisableGoogleChrome returns true if -Google Chrome is disabled in the -configuration. -*/ -func (c Config) DisableGoogleChrome() bool { - return c.disableGoogleChrome -} - -/* -DisableUnoconv returns true if -Unoconv is disabled in the -configuration. -*/ -func (c Config) DisableUnoconv() bool { - return c.disableUnoconv -} - -// LogLevel returns the xlog.Level from -// the configuration. -func (c Config) LogLevel() xlog.Level { - return c.logLevel -} - -// RootPath returns the rooth path from -// the configuration. -func (c Config) RootPath() string { - return c.rootPath -} - -// MaximumGoogleChromeRpccBufferSize returns the maximum -// Google Chrome rpcc buffer size from the configuration. -func (c Config) MaximumGoogleChromeRpccBufferSize() int64 { - return c.maximumGoogleChromeRpccBufferSize -} - -// DefaultGoogleChromeRpccBufferSize returns the default -// Google Chrome rpcc buffer size from the configuration. -func (c Config) DefaultGoogleChromeRpccBufferSize() int64 { - return c.defaultGoogleChromeRpccBufferSize -} - -func (c Config) GoogleChromeIgnoreCertificateErrors() bool { - return c.googleChromeIgnoreCertificateErrors -} diff --git a/internal/pkg/conf/conf_test.go b/internal/pkg/conf/conf_test.go deleted file mode 100644 index a8d2e6b4..00000000 --- a/internal/pkg/conf/conf_test.go +++ /dev/null @@ -1,435 +0,0 @@ -package conf - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestEmptyFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // no environment variables set, - // values should be equal to default config. - expected = DefaultConfig() - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) -} - -func TestMaximumWaitTimeoutFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // MAXIMUM_WAIT_TIMEOUT correctly set. - os.Setenv(MaximumWaitTimeoutEnvVar, "10.0") - expected = DefaultConfig() - expected.maximumWaitTimeout = 10.0 - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWaitTimeoutEnvVar) - // MAXIMUM_WAIT_TIMEOUT wrongly set. - os.Setenv(MaximumWaitTimeoutEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWaitTimeoutEnvVar) - // MAXIMUM_WAIT_TIMEOUT < 0. - os.Setenv(MaximumWaitTimeoutEnvVar, "-1.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWaitTimeoutEnvVar) -} - -func TestMaximumWaitDelayFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // MAXIMUM_WAIT_DELAY correctly set. - os.Setenv(MaximumWaitDelayEnvVar, "10.0") - expected = DefaultConfig() - expected.maximumWaitDelay = 10.0 - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWaitDelayEnvVar) - // MAXIMUM_WAIT_DELAY wrongly set. - os.Setenv(MaximumWaitDelayEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWaitDelayEnvVar) - // MAXIMUM_WAIT_DELAY < 0. - os.Setenv(MaximumWaitDelayEnvVar, "-1.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWaitDelayEnvVar) -} - -func TestMaximumWebhookURLTimeoutFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // MAXIMUM_WEBHOOK_URL_TIMEOUT correctly set. - os.Setenv(MaximumWebhookURLTimeoutEnvVar, "10.0") - expected = DefaultConfig() - expected.maximumWebhookURLTimeout = 10.0 - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWebhookURLTimeoutEnvVar) - // MAXIMUM_WEBHOOK_URL_TIMEOUT wrongly set. - os.Setenv(MaximumWebhookURLTimeoutEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWebhookURLTimeoutEnvVar) - // MAXIMUM_WEBHOOK_URL_TIMEOUT < 0. - os.Setenv(MaximumWebhookURLTimeoutEnvVar, "-1.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(MaximumWebhookURLTimeoutEnvVar) -} - -func TestDefaultWaitTimeoutFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // DEFAULT_WAIT_TIMEOUT correctly set. - os.Setenv(DefaultWaitTimeoutEnvVar, "10.0") - expected = DefaultConfig() - expected.defaultWaitTimeout = 10.0 - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWaitTimeoutEnvVar) - // DEFAULT_WAIT_TIMEOUT wrongly set. - os.Setenv(DefaultWaitTimeoutEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWaitTimeoutEnvVar) - // DEFAULT_WAIT_TIMEOUT < 0. - os.Setenv(DefaultWaitTimeoutEnvVar, "-1.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWaitTimeoutEnvVar) - // DEFAULT_WAIT_TIMEOUT > MAXIMUM_WAIT_TIMEOUT. - os.Setenv(DefaultWaitTimeoutEnvVar, "40.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWaitTimeoutEnvVar) -} - -func TestDefaultWebhookURLTimeoutFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // DEFAULT_WEBHOOK_URL_TIMEOUT correctly set. - os.Setenv(DefaultWebhookURLTimeoutEnvVar, "10.0") - expected = DefaultConfig() - expected.defaultWebhookURLTimeout = 10.0 - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWebhookURLTimeoutEnvVar) - // DEFAULT_WEBHOOK_URL_TIMEOUT wrongly set. - os.Setenv(DefaultWebhookURLTimeoutEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWebhookURLTimeoutEnvVar) - // DEFAULT_WEBHOOK_URL_TIMEOUT < 0. - os.Setenv(DefaultWebhookURLTimeoutEnvVar, "-1.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWebhookURLTimeoutEnvVar) - // DEFAULT_WEBHOOK_URL_TIMEOUT > MAXIMUM_WEBHOOK_URL_TIMEOUT. - os.Setenv(DefaultWebhookURLTimeoutEnvVar, "40.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultWebhookURLTimeoutEnvVar) -} - -func TestDefaultListenPortFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // DEFAULT_LISTEN_PORT correctly set. - os.Setenv(DefaultListenPortEnvVar, "80") - expected = DefaultConfig() - expected.defaultListenPort = 80 - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultListenPortEnvVar) - // DEFAULT_LISTEN_PORT wrongly set. - os.Setenv(DefaultListenPortEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultListenPortEnvVar) - // DEFAULT_LISTEN_PORT < 0. - os.Setenv(DefaultListenPortEnvVar, "-1.0") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultListenPortEnvVar) - // DEFAULT_LISTEN_PORT > 65535. - os.Setenv(DefaultListenPortEnvVar, "65536") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultListenPortEnvVar) -} - -func TestDisableGoogleChromeFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // DISABLE_GOOGLE_CHROME correctly set. - os.Setenv(DisableGoogleChromeEnvVar, "1") - expected = DefaultConfig() - expected.disableGoogleChrome = true - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DisableGoogleChromeEnvVar) - os.Setenv(DisableGoogleChromeEnvVar, "0") - expected = DefaultConfig() - expected.disableGoogleChrome = false - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DisableGoogleChromeEnvVar) - // DISABLE_GOOGLE_CHROME wrongly set. - os.Setenv(DisableGoogleChromeEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DisableGoogleChromeEnvVar) -} - -func TestDisableUnoconvFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // DISABLE_UNOCONV correctly set. - os.Setenv(DisableUnoconvEnvVar, "1") - expected = DefaultConfig() - expected.disableUnoconv = true - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DisableUnoconvEnvVar) - os.Setenv(DisableUnoconvEnvVar, "0") - expected = DefaultConfig() - expected.disableUnoconv = false - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DisableUnoconvEnvVar) - // DISABLE_UNOCONV wrongly set. - os.Setenv(DisableUnoconvEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DisableUnoconvEnvVar) -} - -func TestLogLevelFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // LOG_LEVEL correctly set. - os.Setenv(LogLevelEnvVar, "DEBUG") - expected = DefaultConfig() - expected.logLevel = xlog.DebugLevel - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(LogLevelEnvVar) - os.Setenv(LogLevelEnvVar, "INFO") - expected = DefaultConfig() - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(LogLevelEnvVar) - os.Setenv(LogLevelEnvVar, "ERROR") - expected = DefaultConfig() - expected.logLevel = xlog.ErrorLevel - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(LogLevelEnvVar) - // LOG_LEVEL wrongly set. - os.Setenv(LogLevelEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(LogLevelEnvVar) -} - -func TestRootPathFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // ROOT_PATH correctly set. - os.Setenv(RootPathEnvVar, "/foo/") - expected = DefaultConfig() - expected.rootPath = "/foo/" - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(RootPathEnvVar) - // ROOT_PATH wrongly set. - os.Setenv(RootPathEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(RootPathEnvVar) -} - -func TestDefaultGoogleChromeRpccBufferSizeFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE correctly set. - os.Setenv(DefaultGoogleChromeRpccBufferSizeEnvVar, "100") - expected = DefaultConfig() - expected.defaultGoogleChromeRpccBufferSize = 100 - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultGoogleChromeRpccBufferSizeEnvVar) - // DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE wrongly set. - os.Setenv(DefaultGoogleChromeRpccBufferSizeEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultGoogleChromeRpccBufferSizeEnvVar) - // DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE < 0. - os.Setenv(DefaultGoogleChromeRpccBufferSizeEnvVar, "-1") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultGoogleChromeRpccBufferSizeEnvVar) - // DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE > 100 MB (maximumGoogleChromeRpccBufferSize). - os.Setenv(DefaultGoogleChromeRpccBufferSizeEnvVar, "104857601") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(DefaultGoogleChromeRpccBufferSizeEnvVar) -} - -func TestGoogleChromeIgnoreCertificateErrorsFromEnv(t *testing.T) { - var ( - expected Config - result Config - err error - ) - // GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS correctly set to true. - os.Setenv(GoogleChromeIgnoreCertificateErrorsEnvVar, "1") - expected = DefaultConfig() - expected.googleChromeIgnoreCertificateErrors = true - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(GoogleChromeIgnoreCertificateErrorsEnvVar) - // GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS correctly set to false. - os.Setenv(GoogleChromeIgnoreCertificateErrorsEnvVar, "0") - expected = DefaultConfig() - expected.googleChromeIgnoreCertificateErrors = false - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(GoogleChromeIgnoreCertificateErrorsEnvVar) - // GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS wrongly set. - os.Setenv(GoogleChromeIgnoreCertificateErrorsEnvVar, "foo") - expected = DefaultConfig() - result, err = FromEnv() - test.AssertError(t, err) - assert.Equal(t, expected, result) - os.Unsetenv(GoogleChromeIgnoreCertificateErrorsEnvVar) - // GOOGLE_CHROME_IGNORE_CERTIFICATE_ERRORS not set at all. - expected = DefaultConfig() - expected.googleChromeIgnoreCertificateErrors = false - result, err = FromEnv() - assert.Nil(t, err) - assert.Equal(t, expected, result) -} - -func TestGetters(t *testing.T) { - result := DefaultConfig() - assert.Equal(t, result.maximumWaitTimeout, result.MaximumWaitTimeout()) - assert.Equal(t, result.maximumWaitDelay, result.MaximumWaitDelay()) - assert.Equal(t, result.maximumWebhookURLTimeout, result.MaximumWebhookURLTimeout()) - assert.Equal(t, result.defaultWaitTimeout, result.DefaultWaitTimeout()) - assert.Equal(t, result.defaultWebhookURLTimeout, result.DefaultWebhookURLTimeout()) - assert.Equal(t, result.defaultListenPort, result.DefaultListenPort()) - assert.Equal(t, result.disableGoogleChrome, result.DisableGoogleChrome()) - assert.Equal(t, result.disableUnoconv, result.DisableUnoconv()) - assert.Equal(t, result.logLevel, result.LogLevel()) - assert.Equal(t, result.rootPath, result.RootPath()) - assert.Equal(t, result.maximumGoogleChromeRpccBufferSize, result.MaximumGoogleChromeRpccBufferSize()) - assert.Equal(t, result.defaultGoogleChromeRpccBufferSize, result.DefaultGoogleChromeRpccBufferSize()) - assert.Equal(t, result.googleChromeIgnoreCertificateErrors, result.GoogleChromeIgnoreCertificateErrors()) -} diff --git a/internal/pkg/conf/doc.go b/internal/pkg/conf/doc.go deleted file mode 100644 index 352ce083..00000000 --- a/internal/pkg/conf/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package conf gathers all -// configuration data. -package conf diff --git a/internal/pkg/normalize/doc.go b/internal/pkg/normalize/doc.go deleted file mode 100644 index f5e6f4ab..00000000 --- a/internal/pkg/normalize/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -/* -Package normalize helps removing special -characters from a string. - -Fixes: https://github.com/thecodingmachine/gotenberg/issues/104 - -Credits: https://medium.com/@swdream/golang-remove-all-accents-in-string-319abf6a7f5b -*/ -package normalize diff --git a/internal/pkg/normalize/normalize.go b/internal/pkg/normalize/normalize.go deleted file mode 100644 index 5b58c55b..00000000 --- a/internal/pkg/normalize/normalize.go +++ /dev/null @@ -1,21 +0,0 @@ -package normalize - -import ( - "unicode" - - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "golang.org/x/text/runes" - "golang.org/x/text/transform" - "golang.org/x/text/unicode/norm" -) - -// String normalizes given string. -func String(str string) (string, error) { - const op string = "normalize.String" - t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) - result, _, err := transform.String(t, str) - if err != nil { - return "", xerror.New(op, err) - } - return result, nil -} diff --git a/internal/pkg/normalize/normalize_test.go b/internal/pkg/normalize/normalize_test.go deleted file mode 100644 index 087ad509..00000000 --- a/internal/pkg/normalize/normalize_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package normalize - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestString(t *testing.T) { - const ( - toNormalize string = "analise da aplicação" - expected string = "analise da aplicacao" - ) - v, err := String(toNormalize) - assert.Nil(t, err) - assert.Equal(t, expected, v) -} diff --git a/internal/pkg/printer/chrome.go b/internal/pkg/printer/chrome.go deleted file mode 100644 index 5fe3ca73..00000000 --- a/internal/pkg/printer/chrome.go +++ /dev/null @@ -1,397 +0,0 @@ -package printer - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "strings" - "time" - - "github.com/mafredri/cdp" - "github.com/mafredri/cdp/devtool" - "github.com/mafredri/cdp/protocol/network" - "github.com/mafredri/cdp/protocol/page" - "github.com/mafredri/cdp/protocol/target" - "github.com/mafredri/cdp/rpcc" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xcontext" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/internal/pkg/xtime" - "golang.org/x/sync/errgroup" -) - -type chromePrinter struct { - logger xlog.Logger - url string - opts ChromePrinterOptions -} - -// ChromePrinterOptions helps customizing the -// Google Chrome Printer behaviour. -type ChromePrinterOptions struct { - WaitTimeout float64 - WaitDelay float64 - HeaderHTML string - FooterHTML string - PaperWidth float64 - PaperHeight float64 - MarginTop float64 - MarginBottom float64 - MarginLeft float64 - MarginRight float64 - Landscape bool - PageRanges string - RpccBufferSize int64 - CustomHTTPHeaders map[string]string - Scale float64 -} - -// DefaultChromePrinterOptions returns the default -// Google Chrome Printer options. -func DefaultChromePrinterOptions(config conf.Config) ChromePrinterOptions { - const defaultHeaderFooterHTML string = "" - return ChromePrinterOptions{ - WaitTimeout: config.DefaultWaitTimeout(), - WaitDelay: 0.0, - HeaderHTML: defaultHeaderFooterHTML, - FooterHTML: defaultHeaderFooterHTML, - PaperWidth: 8.27, - PaperHeight: 11.7, - MarginTop: 1.0, - MarginBottom: 1.0, - MarginLeft: 1.0, - MarginRight: 1.0, - Landscape: false, - PageRanges: "", - RpccBufferSize: config.DefaultGoogleChromeRpccBufferSize(), - CustomHTTPHeaders: make(map[string]string), - Scale: 1.0, - } -} - -// nolint: gochecknoglobals -var lockChrome = make(chan struct{}, 1) - -const maxDevtConnections int = 5 - -// nolint: gochecknoglobals -var devtConnections int - -func (p chromePrinter) Print(destination string) error { - const op string = "printer.chromePrinter.Print" - logOptions(p.logger, p.opts) - ctx, cancel := xcontext.WithTimeout(p.logger, p.opts.WaitTimeout+p.opts.WaitDelay) - defer cancel() - resolver := func() error { - devt, err := devtool.New("http://localhost:9222").Version(ctx) - if err != nil { - return err - } - // connect to WebSocket URL (page) that speaks the Chrome DevTools Protocol. - devtConn, err := rpcc.DialContext(ctx, devt.WebSocketDebuggerURL) - if err != nil { - return err - } - defer devtConn.Close() - // create a new CDP Client that uses conn. - devtClient := cdp.NewClient(devtConn) - createBrowserContextArgs := target.NewCreateBrowserContextArgs() - newContextTarget, err := devtClient.Target.CreateBrowserContext(ctx, createBrowserContextArgs) - if err != nil { - return err - } - /* - close the browser context when done. - we're not using the "default" context - as it may timeout before actually closing - the browser context. - see: https://github.com/mafredri/cdp/issues/101#issuecomment-524533670 - */ - disposeBrowserContextArgs := target.NewDisposeBrowserContextArgs(newContextTarget.BrowserContextID) - defer devtClient.Target.DisposeBrowserContext(context.Background(), disposeBrowserContextArgs) // nolint: errcheck - // create a new blank target with the new browser context. - createTargetArgs := target. - NewCreateTargetArgs("about:blank"). - SetBrowserContextID(newContextTarget.BrowserContextID) - newTarget, err := devtClient.Target.CreateTarget(ctx, createTargetArgs) - if err != nil { - return err - } - // connect the client to the new target. - newTargetWsURL := fmt.Sprintf("ws://127.0.0.1:9222/devtools/page/%s", newTarget.TargetID) - newContextConn, err := rpcc.DialContext( - ctx, - newTargetWsURL, - /* - see: - https://github.com/thecodingmachine/gotenberg/issues/108 - https://github.com/mafredri/cdp/issues/4 - https://github.com/ChromeDevTools/devtools-protocol/issues/24 - */ - rpcc.WithWriteBufferSize(int(p.opts.RpccBufferSize)), - rpcc.WithCompression(), - ) - if err != nil { - return err - } - defer newContextConn.Close() - // create a new CDP Client that uses newContextConn. - targetClient := cdp.NewClient(newContextConn) - /* - close the target when done. - we're not using the "default" context - as it may timeout before actually closing - the target. - see: https://github.com/mafredri/cdp/issues/101#issuecomment-524533670 - */ - closeTargetArgs := target.NewCloseTargetArgs(newTarget.TargetID) - defer targetClient.Target.CloseTarget(context.Background(), closeTargetArgs) // nolint: errcheck - // enable all events. - if err := p.enableEvents(ctx, targetClient); err != nil { - return err - } - // add custom headers (if any). - if err := p.setCustomHTTPHeaders(ctx, targetClient); err != nil { - return err - } - // listen for all events. - if err := p.listenEvents(ctx, targetClient); err != nil { - return err - } - // apply a wait delay (if any). - if p.opts.WaitDelay > 0.0 { - // wait for a given amount of time (useful for javascript delay). - p.logger.DebugOpf(op, "applying a wait delay of '%.2fs'...", p.opts.WaitDelay) - time.Sleep(xtime.Duration(p.opts.WaitDelay)) - } else { - p.logger.DebugOp(op, "no wait delay to apply, moving on...") - } - printToPdfArgs := page.NewPrintToPDFArgs(). - SetPaperWidth(p.opts.PaperWidth). - SetPaperHeight(p.opts.PaperHeight). - SetMarginTop(p.opts.MarginTop). - SetMarginBottom(p.opts.MarginBottom). - SetMarginLeft(p.opts.MarginLeft). - SetMarginRight(p.opts.MarginRight). - SetLandscape(p.opts.Landscape). - SetDisplayHeaderFooter(true). - SetHeaderTemplate(p.opts.HeaderHTML). - SetFooterTemplate(p.opts.FooterHTML). - SetPrintBackground(true). - SetScale(p.opts.Scale) - if p.opts.PageRanges != "" { - printToPdfArgs.SetPageRanges(p.opts.PageRanges) - } - // printToPDF the page to PDF. - printToPDF, err := targetClient.Page.PrintToPDF( - ctx, - printToPdfArgs, - ) - if err != nil { - // find a way to check it in the handlers? - if strings.Contains(err.Error(), "Page range syntax error") { - return xerror.Invalid( - op, - fmt.Sprintf("'%s' is not a valid Google Chrome page ranges", p.opts.PageRanges), - err, - ) - } - if strings.Contains(err.Error(), "rpcc: message too large") { - return xerror.Invalid( - op, - fmt.Sprintf( - "'%d' bytes are not enough: increase the Google Chrome rpcc buffer size (up to 100 MB)", - p.opts.RpccBufferSize, - ), - err, - ) - } - return err - } - if err := ioutil.WriteFile(destination, printToPDF.Data, 0600); err != nil { - return err - } - return nil - } - if devtConnections < maxDevtConnections { - p.logger.DebugOp(op, "skipping lock acquisition...") - devtConnections++ - err := resolver() - devtConnections-- - if err != nil { - return xcontext.MustHandleError( - ctx, - xerror.New(op, err), - ) - } - return nil - } - p.logger.DebugOp(op, "waiting lock to be acquired...") - select { - case lockChrome <- struct{}{}: - // lock acquired. - p.logger.DebugOp(op, "lock acquired") - devtConnections++ - err := resolver() - devtConnections-- - <-lockChrome // we release the lock. - if err != nil { - return xcontext.MustHandleError( - ctx, - xerror.New(op, err), - ) - } - return nil - case <-ctx.Done(): - // failed to acquire lock before - // deadline. - p.logger.DebugOp(op, "failed to acquire lock before context.Context deadline") - return xcontext.MustHandleError( - ctx, - ctx.Err(), - ) - } -} - -func (p chromePrinter) enableEvents(ctx context.Context, client *cdp.Client) error { - const op string = "printer.chromePrinter.enableEvents" - // enable all the domain events that we're interested in. - if err := runBatch( - func() error { return client.DOM.Enable(ctx) }, - func() error { return client.Network.Enable(ctx, network.NewEnableArgs()) }, - func() error { return client.Page.Enable(ctx) }, - func() error { - return client.Page.SetLifecycleEventsEnabled(ctx, page.NewSetLifecycleEventsEnabledArgs(true)) - }, - func() error { return client.Runtime.Enable(ctx) }, - ); err != nil { - return xerror.New(op, err) - } - return nil -} - -func (p chromePrinter) setCustomHTTPHeaders(ctx context.Context, client *cdp.Client) error { - const op string = "printer.chromePrinter.setCustomHTTPHeaders" - resolver := func() error { - if len(p.opts.CustomHTTPHeaders) == 0 { - p.logger.DebugOp(op, "skipping custom HTTP headers as none have been provided...") - return nil - } - customHTTPHeaders := make(map[string]string) - // useless but for the logs. - for key, value := range p.opts.CustomHTTPHeaders { - customHTTPHeaders[key] = value - p.logger.DebugOpf(op, "set '%s' to custom HTTP header '%s'", value, key) - } - b, err := json.Marshal(customHTTPHeaders) - if err != nil { - return err - } - // should always be called after client.Network.Enable. - return client.Network.SetExtraHTTPHeaders(ctx, network.NewSetExtraHTTPHeadersArgs(b)) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func (p chromePrinter) listenEvents(ctx context.Context, client *cdp.Client) error { - const op string = "printer.chromePrinter.listenEvents" - resolver := func() error { - // make sure Page events are enabled. - if err := client.Page.Enable(ctx); err != nil { - return err - } - // make sure Network events are enabled. - if err := client.Network.Enable(ctx, nil); err != nil { - return err - } - // create all clients for events. - domContentEventFired, err := client.Page.DOMContentEventFired(ctx) - if err != nil { - return err - } - defer domContentEventFired.Close() - loadEventFired, err := client.Page.LoadEventFired(ctx) - if err != nil { - return err - } - defer loadEventFired.Close() - lifecycleEvent, err := client.Page.LifecycleEvent(ctx) - if err != nil { - return err - } - defer lifecycleEvent.Close() - loadingFinished, err := client.Network.LoadingFinished(ctx) - if err != nil { - return err - } - defer loadingFinished.Close() - if _, err := client.Page.Navigate(ctx, page.NewNavigateArgs(p.url)); err != nil { - return err - } - // wait for all events. - return runBatch( - func() error { - _, err := domContentEventFired.Recv() - if err != nil { - return err - } - p.logger.DebugOp(op, "event 'domContentEventFired' received") - return nil - }, - func() error { - _, err := loadEventFired.Recv() - if err != nil { - return err - } - p.logger.DebugOp(op, "event 'loadEventFired' received") - return nil - }, - func() error { - const networkIdleEventName string = "networkIdle" - for { - ev, err := lifecycleEvent.Recv() - if err != nil { - return err - } - p.logger.DebugOpf(op, "event '%s' received", ev.Name) - if ev.Name == networkIdleEventName { - break - } - } - return nil - }, - func() error { - _, err := loadingFinished.Recv() - if err != nil { - return err - } - p.logger.DebugOp(op, "event 'loadingFinished' received") - return nil - }, - ) - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func runBatch(fn ...func() error) error { - // run all functions simultaneously and wait until - // execution has completed or an error is encountered. - eg := errgroup.Group{} - for _, f := range fn { - eg.Go(f) - } - return eg.Wait() -} - -// Compile-time checks to ensure type implements desired interfaces. -var ( - _ = Printer(new(chromePrinter)) -) diff --git a/internal/pkg/printer/doc.go b/internal/pkg/printer/doc.go deleted file mode 100644 index d36329e3..00000000 --- a/internal/pkg/printer/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package printer helps converting -// a specific file type to PDF. -package printer diff --git a/internal/pkg/printer/html.go b/internal/pkg/printer/html.go deleted file mode 100644 index edad5ebf..00000000 --- a/internal/pkg/printer/html.go +++ /dev/null @@ -1,18 +0,0 @@ -package printer - -import ( - "fmt" - - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -// NewHTMLPrinter returns a Printer which -// is able to convert an HTML file to PDF. -func NewHTMLPrinter(logger xlog.Logger, fpath string, opts ChromePrinterOptions) Printer { - URL := fmt.Sprintf("file://%s", fpath) - return chromePrinter{ - logger: logger, - url: URL, - opts: opts, - } -} diff --git a/internal/pkg/printer/html_test.go b/internal/pkg/printer/html_test.go deleted file mode 100644 index e69539fa..00000000 --- a/internal/pkg/printer/html_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package printer - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestHTMLPrinter(t *testing.T) { - var ( - logger xlog.Logger = test.DebugLogger() - config conf.Config = conf.DefaultConfig() - fpath string = test.HTMLFpaths(t)[0] - opts ChromePrinterOptions - dest string - p Printer - err error - ) - // default options. - opts = DefaultChromePrinterOptions(config) - p = NewHTMLPrinter(logger, fpath, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with a wait delay. - opts = DefaultChromePrinterOptions(config) - opts.WaitDelay = 0.5 - p = NewHTMLPrinter(logger, fpath, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with a page ranges. - opts = DefaultChromePrinterOptions(config) - opts.PageRanges = "1" - p = NewHTMLPrinter(logger, fpath, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as options have - // a wrong page ranges. - opts = DefaultChromePrinterOptions(config) - opts.PageRanges = "foo" - p = NewHTMLPrinter(logger, fpath, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.InvalidCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as context.Context - // should timeout. - opts = DefaultChromePrinterOptions(config) - opts.WaitTimeout = 0.0 - p = NewHTMLPrinter(logger, fpath, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.TimeoutCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) -} diff --git a/internal/pkg/printer/markdown.go b/internal/pkg/printer/markdown.go deleted file mode 100644 index 4bffdcce..00000000 --- a/internal/pkg/printer/markdown.go +++ /dev/null @@ -1,71 +0,0 @@ -package printer - -import ( - "bytes" - "fmt" - "github.com/microcosm-cc/bluemonday" - "github.com/russross/blackfriday/v2" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/internal/pkg/xrand" - "html/template" - "io/ioutil" - "path/filepath" -) - -// NewMarkdownPrinter returns a Printer which -// is able to convert Markdown files to PDF. -func NewMarkdownPrinter(logger xlog.Logger, fpath string, opts ChromePrinterOptions) (Printer, error) { - const op string = "printer.NewMarkdownPrinter" - resolver := func() (string, error) { - tmpl, err := template. - New(filepath.Base(fpath)). - Funcs(template.FuncMap{"toHTML": markdownToHTML}). - ParseFiles(fpath) - if err != nil { - return "", err - } - dirPath := filepath.Dir(fpath) - data := &templateData{DirPath: dirPath} - logger.DebugOp(op, "converting Markdown files to HTML...") - var buffer bytes.Buffer - if err := tmpl.Execute(&buffer, data); err != nil { - return "", err - } - baseFilename := xrand.Get() - dst := fmt.Sprintf("%s/%s.html", dirPath, baseFilename) - logger.DebugOp(op, "writing the HTML from previous conversion(s) into new file...") - if err := ioutil.WriteFile(dst, buffer.Bytes(), 0600); err != nil { - return "", err - } - return fmt.Sprintf("file://%s", dst), nil - } - URL, err := resolver() - if err != nil { - return chromePrinter{}, xerror.New(op, err) - } - return chromePrinter{ - logger: logger, - url: URL, - opts: opts, - }, nil -} - -type templateData struct { - DirPath string -} - -func markdownToHTML(dirPath, filename string) (template.HTML, error) { - const op string = "printer.markdownToHTML" - // avoid directory traversal. - filename = filepath.Base(filename) - fpath := fmt.Sprintf("%s/%s", dirPath, filename) - b, err := ioutil.ReadFile(fpath) - if err != nil { - return "", xerror.New(op, err) - } - unsafe := blackfriday.Run(b) - content := bluemonday.UGCPolicy().SanitizeBytes(unsafe) - /* #nosec */ - return template.HTML(content), nil -} diff --git a/internal/pkg/printer/markdown_test.go b/internal/pkg/printer/markdown_test.go deleted file mode 100644 index 9627cdea..00000000 --- a/internal/pkg/printer/markdown_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package printer - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestMarkdownPrinter(t *testing.T) { - var ( - logger xlog.Logger = test.DebugLogger() - config conf.Config = conf.DefaultConfig() - fpath string = test.MarkdownFpaths(t)[0] - opts ChromePrinterOptions - dest string - p Printer - err error - ) - // default options. - opts = DefaultChromePrinterOptions(config) - p, err = NewMarkdownPrinter(logger, fpath, opts) - assert.Nil(t, err) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with a wait delay. - opts = DefaultChromePrinterOptions(config) - opts.WaitDelay = 0.5 - p, err = NewMarkdownPrinter(logger, fpath, opts) - assert.Nil(t, err) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with a page ranges. - opts = DefaultChromePrinterOptions(config) - opts.PageRanges = "1" - p, err = NewMarkdownPrinter(logger, fpath, opts) - assert.Nil(t, err) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as options have - // a wrong page ranges. - opts = DefaultChromePrinterOptions(config) - opts.PageRanges = "foo" - p, err = NewMarkdownPrinter(logger, fpath, opts) - assert.Nil(t, err) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.InvalidCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as context.Context - // should timeout. - opts = DefaultChromePrinterOptions(config) - opts.WaitTimeout = 0.0 - p, err = NewMarkdownPrinter(logger, fpath, opts) - assert.Nil(t, err) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.TimeoutCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) -} diff --git a/internal/pkg/printer/merge.go b/internal/pkg/printer/merge.go deleted file mode 100644 index 6fab9a83..00000000 --- a/internal/pkg/printer/merge.go +++ /dev/null @@ -1,79 +0,0 @@ -package printer - -import ( - "context" - "sort" - - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xcontext" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xexec" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -type mergePrinter struct { - ctx context.Context - logger xlog.Logger - fpaths []string - opts MergePrinterOptions -} - -// MergePrinterOptions helps customizing the -// merge Printer behaviour. -type MergePrinterOptions struct { - WaitTimeout float64 -} - -// DefaultMergePrinterOptions returns the default -// merge Printer options. -func DefaultMergePrinterOptions(config conf.Config) MergePrinterOptions { - return MergePrinterOptions{ - WaitTimeout: config.DefaultWaitTimeout(), - } -} - -// NewMergePrinter returns a Printer which -// is able to merge PDFs. -func NewMergePrinter(logger xlog.Logger, fpaths []string, opts MergePrinterOptions) Printer { - return mergePrinter{ - logger: logger, - fpaths: fpaths, - opts: opts, - } -} - -func (p mergePrinter) Print(destination string) error { - const op string = "printer.mergePrinter.Print" - /* - context.Context may be providen from - an officePrinter which needs to merge - its result files. - */ - if p.ctx == nil { - logOptions(p.logger, p.opts) - ctx, cancel := xcontext.WithTimeout(p.logger, p.opts.WaitTimeout) - defer cancel() - p.ctx = ctx - } - // see https://github.com/thecodingmachine/gotenberg/issues/139. - sort.Strings(p.fpaths) - p.logger.DebugOpf(op, "merging '%v'...", p.fpaths) - resolver := func() error { - var args []string - args = append(args, p.fpaths...) - args = append(args, "cat", "output", destination) - return xexec.Run(p.ctx, p.logger, "pdftk", args...) - } - if err := resolver(); err != nil { - return xcontext.MustHandleError( - p.ctx, - xerror.New(op, err), - ) - } - return nil -} - -// Compile-time checks to ensure type implements desired interfaces. -var ( - _ = Printer(new(mergePrinter)) -) diff --git a/internal/pkg/printer/merge_test.go b/internal/pkg/printer/merge_test.go deleted file mode 100644 index 71399a32..00000000 --- a/internal/pkg/printer/merge_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package printer - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestMergePrinter(t *testing.T) { - var ( - logger xlog.Logger = test.DebugLogger() - config conf.Config = conf.DefaultConfig() - fpaths []string = test.MergeFpaths(t) - opts MergePrinterOptions - dest string - p Printer - err error - ) - // default options. - opts = DefaultMergePrinterOptions(config) - p = NewMergePrinter(logger, fpaths, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as context.Context - // should timeout. - opts = DefaultMergePrinterOptions(config) - opts.WaitTimeout = 0.0 - p = NewMergePrinter(logger, fpaths, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.TimeoutCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) -} diff --git a/internal/pkg/printer/office.go b/internal/pkg/printer/office.go deleted file mode 100644 index 52fffa56..00000000 --- a/internal/pkg/printer/office.go +++ /dev/null @@ -1,152 +0,0 @@ -package printer - -import ( - "context" - "fmt" - "os" - "path/filepath" - "sort" - "strings" - - "github.com/phayes/freeport" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xcontext" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xexec" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/internal/pkg/xrand" -) - -type officePrinter struct { - logger xlog.Logger - fpaths []string - opts OfficePrinterOptions -} - -// OfficePrinterOptions helps customizing the -// Office Printer behaviour. -type OfficePrinterOptions struct { - WaitTimeout float64 - Landscape bool - PageRanges string -} - -// DefaultOfficePrinterOptions returns the default -// Office Printer options. -func DefaultOfficePrinterOptions(config conf.Config) OfficePrinterOptions { - return OfficePrinterOptions{ - WaitTimeout: config.DefaultWaitTimeout(), - Landscape: false, - PageRanges: "", - } -} - -// NewOfficePrinter returns a Printer which -// is able to convert Office documents to PDF. -func NewOfficePrinter(logger xlog.Logger, fpaths []string, opts OfficePrinterOptions) Printer { - return officePrinter{ - logger: logger, - fpaths: fpaths, - opts: opts, - } -} - -func (p officePrinter) Print(destination string) error { - const op string = "printer.officePrinter.Print" - logOptions(p.logger, p.opts) - ctx, cancel := xcontext.WithTimeout(p.logger, p.opts.WaitTimeout) - defer cancel() - resolver := func() error { - // see https://github.com/thecodingmachine/gotenberg/issues/139. - sort.Strings(p.fpaths) - fpaths := make([]string, len(p.fpaths)) - dirPath := filepath.Dir(destination) - for i, fpath := range p.fpaths { - baseFilename := xrand.Get() - tmpDest := fmt.Sprintf("%s/%d%s.pdf", dirPath, i, baseFilename) - p.logger.DebugOpf(op, "converting '%s' to PDF...", fpath) - if err := p.unoconv(ctx, fpath, tmpDest); err != nil { - return err - } - p.logger.DebugOpf(op, "'%s.pdf' created", baseFilename) - fpaths[i] = tmpDest - } - if len(fpaths) == 1 { - p.logger.DebugOp(op, "only one PDF created, nothing to merge") - return os.Rename(fpaths[0], destination) - } - m := mergePrinter{ - logger: p.logger, - ctx: ctx, - fpaths: fpaths, - } - return m.Print(destination) - } - if err := resolver(); err != nil { - return xcontext.MustHandleError( - ctx, - xerror.New(op, err), - ) - } - return nil -} - -func (p officePrinter) unoconv(ctx context.Context, fpath, destination string) error { - const op string = "printer.unoconv" - resolver := func() error { - dirName := xrand.Get() - port, err := freeport.GetFreePort() - if err != nil { - return err - } - args := []string{ - "--user-profile", - fmt.Sprintf("///tmp/%s", dirName), - "--port", - fmt.Sprintf("%d", port), - "--format", - "pdf", - } - if p.opts.Landscape { - args = append(args, "--printer", "PaperOrientation=landscape") - } - if p.opts.PageRanges != "" { - args = append(args, "--export", fmt.Sprintf("PageRange=%s", p.opts.PageRanges)) - } - args = append(args, "--output", destination, fpath) - err = xexec.Run(ctx, p.logger, "unoconv", args...) - // always remove user profile folders created by LibreOffice. - // see https://github.com/thecodingmachine/gotenberg/issues/192. - go cleanupUserProfile(p.logger, dirName) - if err != nil { - // find a way to check it in the handlers? - if p.opts.PageRanges != "" && strings.Contains(err.Error(), "exit status 5") { - return xerror.Invalid( - op, - fmt.Sprintf("'%s' is not a valid LibreOffice page ranges", p.opts.PageRanges), - err, - ) - } - return err - } - return nil - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func cleanupUserProfile(logger xlog.Logger, dirName string) { - const op = "printer.cleanupUserProfile" - path := fmt.Sprintf("/tmp/%s", dirName) - if err := os.RemoveAll(path); err != nil { - // find a way to bubble up this error? - logger.ErrorOpf(op, "failed to remove user profile directory '%s': %s", path, err.Error()) - } -} - -// Compile-time checks to ensure type implements desired interfaces. -var ( - _ = Printer(new(officePrinter)) -) diff --git a/internal/pkg/printer/office_test.go b/internal/pkg/printer/office_test.go deleted file mode 100644 index 5eb8992e..00000000 --- a/internal/pkg/printer/office_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package printer - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestOfficePrinter(t *testing.T) { - var ( - logger xlog.Logger = test.DebugLogger() - config conf.Config = conf.DefaultConfig() - fpaths []string = test.OfficeFpaths(t) - opts OfficePrinterOptions - dest string - p Printer - err error - ) - // default options. - opts = DefaultOfficePrinterOptions(config) - p = NewOfficePrinter(logger, fpaths, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // using one file. - opts = DefaultOfficePrinterOptions(config) - p = NewOfficePrinter(logger, []string{fpaths[0]}, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with landscape. - opts = DefaultOfficePrinterOptions(config) - opts.Landscape = true - p = NewOfficePrinter(logger, fpaths, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with page ranges. - opts = DefaultOfficePrinterOptions(config) - opts.PageRanges = "1-1" - p = NewOfficePrinter(logger, []string{fpaths[0]}, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as options have - // a wrong page ranges. - opts = DefaultOfficePrinterOptions(config) - opts.PageRanges = "foo" - p = NewOfficePrinter(logger, []string{fpaths[0]}, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.InvalidCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as context.Context - // should timeout. - opts = DefaultOfficePrinterOptions(config) - opts.WaitTimeout = 0.0 - p = NewOfficePrinter(logger, fpaths, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.TimeoutCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) -} diff --git a/internal/pkg/printer/printer.go b/internal/pkg/printer/printer.go deleted file mode 100644 index 97c05a93..00000000 --- a/internal/pkg/printer/printer.go +++ /dev/null @@ -1,16 +0,0 @@ -package printer - -import ( - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -// Printer is a type that can create a PDF file from a source. -// The source is defined in the underlying implementation. -type Printer interface { - Print(destination string) error -} - -func logOptions(logger xlog.Logger, opts interface{}) { - const op string = "printer.logOptions" - logger.DebugOpf(op, "options: %+v", opts) -} diff --git a/internal/pkg/printer/url.go b/internal/pkg/printer/url.go deleted file mode 100644 index 191fb93b..00000000 --- a/internal/pkg/printer/url.go +++ /dev/null @@ -1,15 +0,0 @@ -package printer - -import ( - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -// NewURLPrinter returns a Printer which -// is able to convert a URL to PDF. -func NewURLPrinter(logger xlog.Logger, url string, opts ChromePrinterOptions) Printer { - return chromePrinter{ - logger: logger, - url: url, - opts: opts, - } -} diff --git a/internal/pkg/printer/url_test.go b/internal/pkg/printer/url_test.go deleted file mode 100644 index ef477e75..00000000 --- a/internal/pkg/printer/url_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package printer - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestURLPrinter(t *testing.T) { - var ( - logger xlog.Logger = test.DebugLogger() - config conf.Config = conf.DefaultConfig() - URL = "https://google.com" - opts ChromePrinterOptions - dest string - p Printer - err error - ) - // default options. - opts = DefaultChromePrinterOptions(config) - p = NewURLPrinter(logger, URL, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with a wait delay. - opts = DefaultChromePrinterOptions(config) - opts.WaitDelay = 0.5 - p = NewURLPrinter(logger, URL, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // options with a pages ranges. - opts = DefaultChromePrinterOptions(config) - opts.PageRanges = "1" - p = NewURLPrinter(logger, URL, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - assert.Nil(t, err) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as options have - // a wrong page ranges. - opts = DefaultChromePrinterOptions(config) - opts.PageRanges = "foo" - p = NewURLPrinter(logger, URL, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.InvalidCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) - // should not be OK as context.Context - // should timeout. - opts = DefaultChromePrinterOptions(config) - opts.WaitTimeout = 0.0 - p = NewURLPrinter(logger, URL, opts) - dest = test.GenerateDestination() - err = p.Print(dest) - test.AssertError(t, err) - assert.Equal(t, xerror.TimeoutCode, xerror.Code(err)) - err = os.RemoveAll(dest) - assert.Nil(t, err) -} diff --git a/internal/pkg/xassert/doc.go b/internal/pkg/xassert/doc.go deleted file mode 100644 index 14b2417e..00000000 --- a/internal/pkg/xassert/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -/* -Package xassert is a helper for converting -and/or validating strings. - -All functions return our standard xerror.Error -in case of error. -*/ -package xassert diff --git a/internal/pkg/xassert/float64.go b/internal/pkg/xassert/float64.go deleted file mode 100644 index e8521b7e..00000000 --- a/internal/pkg/xassert/float64.go +++ /dev/null @@ -1,88 +0,0 @@ -package xassert - -import ( - "fmt" - - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -// RuleFloat64 is an interface for -// validating a float64. -type RuleFloat64 interface { - with(key string, value float64) - validate() error -} - -type baseRuleFloat64 struct { - key string - value float64 -} - -func (r *baseRuleFloat64) with(key string, value float64) { - r.key = key - r.value = value -} - -type ruleFloat64NotInferiorTo struct { - *baseRuleFloat64 - lowerBound float64 -} - -func (r ruleFloat64NotInferiorTo) validate() error { - const op string = "xassert.ruleFloat64NotInferiorTo.validate" - if r.value < r.lowerBound { - return xerror.Invalid( - op, - fmt.Sprintf("'%s' should be > '%f', got '%f'", r.key, r.lowerBound, r.value), - nil, - ) - } - return nil -} - -/* -Float64NotInferiorTo returns a RuleFloat64 for -validating that a float64 is not inferior to -given lower bound. -*/ -func Float64NotInferiorTo(lowerBound float64) RuleFloat64 { - return ruleFloat64NotInferiorTo{ - &baseRuleFloat64{}, - lowerBound, - } -} - -type ruleFloat64NotSuperiorTo struct { - *baseRuleFloat64 - upperBound float64 -} - -func (r ruleFloat64NotSuperiorTo) validate() error { - const op string = "xassert.ruleFloat64NotSuperiorTo.validate" - if r.value > r.upperBound { - return xerror.Invalid( - op, - fmt.Sprintf("'%s' should be < '%f', got '%f'", r.key, r.upperBound, r.value), - nil, - ) - } - return nil -} - -/* -Float64NotSuperiorTo returns a RuleFloat64 for -validating that a float64 is not superior to -given upper bound. -*/ -func Float64NotSuperiorTo(upperBound float64) RuleFloat64 { - return ruleFloat64NotSuperiorTo{ - &baseRuleFloat64{}, - upperBound, - } -} - -// Compile-time checks to ensure type implements desired interfaces. -var ( - _ = RuleFloat64(new(ruleFloat64NotInferiorTo)) - _ = RuleFloat64(new(ruleFloat64NotSuperiorTo)) -) diff --git a/internal/pkg/xassert/float64_test.go b/internal/pkg/xassert/float64_test.go deleted file mode 100644 index 78aba945..00000000 --- a/internal/pkg/xassert/float64_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package xassert - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestFloat64NotInferiorTo(t *testing.T) { - rule := Float64NotInferiorTo(0.0) - // should be OK. - rule.with("FOO", 10.0) - err := rule.validate() - assert.Nil(t, err) - // should not be OK. - rule.with("FOO", -10.0) - err = rule.validate() - test.AssertError(t, err) -} - -func TestFloat64NotSuperiorTo(t *testing.T) { - rule := Float64NotSuperiorTo(0.0) - // should be OK. - rule.with("FOO", -10.0) - err := rule.validate() - assert.Nil(t, err) - // should not be OK. - rule.with("FOO", 10.0) - err = rule.validate() - test.AssertError(t, err) -} diff --git a/internal/pkg/xassert/int64.go b/internal/pkg/xassert/int64.go deleted file mode 100644 index c3fc3ae7..00000000 --- a/internal/pkg/xassert/int64.go +++ /dev/null @@ -1,88 +0,0 @@ -package xassert - -import ( - "fmt" - - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -// RuleInt64 is an interface for -// validating an int64. -type RuleInt64 interface { - with(key string, value int64) - validate() error -} - -type baseRuleInt64 struct { - key string - value int64 -} - -func (r *baseRuleInt64) with(key string, value int64) { - r.key = key - r.value = value -} - -type ruleInt64NotInferiorTo struct { - *baseRuleInt64 - lowerBound int64 -} - -func (r ruleInt64NotInferiorTo) validate() error { - const op string = "xassert.ruleInt64NotInferiorTo.validate" - if r.value < r.lowerBound { - return xerror.Invalid( - op, - fmt.Sprintf("'%s' should be > '%d', got '%d'", r.key, r.lowerBound, r.value), - nil, - ) - } - return nil -} - -/* -Int64NotInferiorTo returns a RuleInt64 for -validating that an int64 is not inferior to -given lower bound. -*/ -func Int64NotInferiorTo(lowerBound int64) RuleInt64 { - return &ruleInt64NotInferiorTo{ - &baseRuleInt64{}, - lowerBound, - } -} - -type ruleInt64NotSuperiorTo struct { - *baseRuleInt64 - upperBound int64 -} - -func (r ruleInt64NotSuperiorTo) validate() error { - const op string = "xassert.ruleInt64NotSuperiorTo.validate" - if r.value > r.upperBound { - return xerror.Invalid( - op, - fmt.Sprintf("'%s' should be < '%d', got '%d'", r.key, r.upperBound, r.value), - nil, - ) - } - return nil -} - -/* -Int64NotSuperiorTo returns a RuleInt64 for -validating that an int64 is not superior to -given upper bound. -*/ -func Int64NotSuperiorTo(upperBound int64) RuleInt64 { - return ruleInt64NotSuperiorTo{ - &baseRuleInt64{}, - upperBound, - } -} - -// Compile-time checks to ensure type implements desired interfaces. -var ( - _ = RuleInt64(new(ruleInt64NotInferiorTo)) - _ = RuleInt64(new(ruleInt64NotSuperiorTo)) -) diff --git a/internal/pkg/xassert/int64_test.go b/internal/pkg/xassert/int64_test.go deleted file mode 100644 index 2b5244dd..00000000 --- a/internal/pkg/xassert/int64_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package xassert - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestInt64NotInferiorTo(t *testing.T) { - rule := Int64NotInferiorTo(0) - // should be OK. - rule.with("FOO", 10) - err := rule.validate() - assert.Nil(t, err) - // should not be OK. - rule.with("FOO", -10) - err = rule.validate() - test.AssertError(t, err) -} - -func TestInt64NotSuperiorTo(t *testing.T) { - rule := Int64NotSuperiorTo(0) - // should be OK. - rule.with("FOO", -10) - err := rule.validate() - assert.Nil(t, err) - // should not be OK. - rule.with("FOO", 10) - err = rule.validate() - test.AssertError(t, err) -} diff --git a/internal/pkg/xassert/string.go b/internal/pkg/xassert/string.go deleted file mode 100644 index d59bea8a..00000000 --- a/internal/pkg/xassert/string.go +++ /dev/null @@ -1,121 +0,0 @@ -package xassert - -import ( - "fmt" - "strings" - - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -// RuleString is an interface for -// validating a string. -type RuleString interface { - with(key, value string) - validate() error -} - -type baseRuleString struct { - key string - value string -} - -func (r *baseRuleString) with(key, value string) { - r.key = key - r.value = value -} - -type ruleStringOneOf struct { - *baseRuleString - values []string -} - -func (r ruleStringOneOf) validate() error { - const op string = "xassert.ruleStringOneOf.validate" - for _, v := range r.values { - if r.value == v { - return nil - } - } - return xerror.Invalid( - op, - fmt.Sprintf("'%s' should be one of '%v', got '%s'", r.key, r.values, r.value), - nil, - ) -} - -/* -StringOneOf returns a RuleString for -validating that a string is one of given -values. -*/ -func StringOneOf(values []string) RuleString { - return ruleStringOneOf{ - &baseRuleString{}, - values, - } -} - -type ruleStringStartWith struct { - *baseRuleString - startWith string -} - -func (r ruleStringStartWith) validate() error { - const op string = "xassert.ruleStringStartWith.validate" - if strings.HasPrefix(r.value, r.startWith) { - return nil - } - return xerror.Invalid( - op, - fmt.Sprintf("'%s' should start with '%s', got '%s'", r.key, r.startWith, r.value), - nil, - ) -} - -/* -StringStartWith returns a RuleString for -validating that a string starts with -given string. -*/ -func StringStartWith(startWith string) RuleString { - return ruleStringStartWith{ - &baseRuleString{}, - startWith, - } -} - -type ruleStringEndWith struct { - *baseRuleString - endWith string -} - -func (r ruleStringEndWith) validate() error { - const op string = "xassert.ruleStringEndWith.validate" - if strings.HasSuffix(r.value, r.endWith) { - return nil - } - return xerror.Invalid( - op, - fmt.Sprintf("'%s' should end with '%s', got '%s'", r.key, r.endWith, r.value), - nil, - ) -} - -/* -StringEndWith returns a RuleString for -validating that a string ends with -given string. -*/ -func StringEndWith(endWith string) RuleString { - return ruleStringEndWith{ - &baseRuleString{}, - endWith, - } -} - -// Compile-time checks to ensure type implements desired interfaces. -var ( - _ = RuleString(new(ruleStringOneOf)) - _ = RuleString(new(ruleStringStartWith)) - _ = RuleString(new(ruleStringEndWith)) -) diff --git a/internal/pkg/xassert/string_test.go b/internal/pkg/xassert/string_test.go deleted file mode 100644 index fb1c0d4e..00000000 --- a/internal/pkg/xassert/string_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package xassert - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestStringOfOne(t *testing.T) { - rule := StringOneOf([]string{"foo", "bar", "baz"}) - // should be OK. - rule.with("FOO", "foo") - err := rule.validate() - assert.Nil(t, err) - // should not be OK. - rule.with("FOO", "qux") - err = rule.validate() - test.AssertError(t, err) -} - -func TestStringStartWith(t *testing.T) { - rule := StringStartWith("foo") - // should be OK. - rule.with("FOO", "foobarfoo") - err := rule.validate() - assert.Nil(t, err) - // should not be OK. - rule.with("FOO", "qux") - err = rule.validate() - test.AssertError(t, err) -} - -func TestStringEndWith(t *testing.T) { - rule := StringEndWith("foo") - // should be OK. - rule.with("FOO", "foobarfoo") - err := rule.validate() - assert.Nil(t, err) - // should not be OK. - rule.with("FOO", "qux") - err = rule.validate() - test.AssertError(t, err) -} diff --git a/internal/pkg/xassert/xassert.go b/internal/pkg/xassert/xassert.go deleted file mode 100644 index 8ad5a55a..00000000 --- a/internal/pkg/xassert/xassert.go +++ /dev/null @@ -1,234 +0,0 @@ -package xassert - -import ( - "fmt" - "os" - "strconv" - - "github.com/dustin/go-humanize" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -/* -String applies validation on a string. - -If string is empty or validation fails, -returns the default value. - -The key is used to identify the value. -*/ -func String(key, value, defaultValue string, rules ...RuleString) (string, error) { - const op string = "xassert.String" - result := defaultValue - if value != "" { - result = value - } - for _, rule := range rules { - rule.with(key, result) - if err := rule.validate(); err != nil { - return defaultValue, xerror.New(op, err) - } - } - return result, nil -} - -/* -StringFromEnv returns the value of given environment -variable or the default value if not found or -validation fails. -*/ -func StringFromEnv(envVar, defaultValue string, rules ...RuleString) (string, error) { - const op string = "xassert.StringFromEnv" - value := os.Getenv(envVar) - result, err := String(envVar, value, defaultValue, rules...) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -Int64 tries to convert a string to an int64. - -If string is empty, conversion or validation fails, -returns the default value. - -The key is used to identify the value. -*/ -func Int64(key, value string, defaultValue int64, rules ...RuleInt64) (int64, error) { - const op string = "xassert.Int64" - result := defaultValue - if value != "" { - parsedValue, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return defaultValue, xerror.Invalid( - op, - fmt.Sprintf("'%s' is not an integer, got '%s'", key, value), - err, - ) - } - result = parsedValue - } - for _, rule := range rules { - rule.with(key, result) - if err := rule.validate(); err != nil { - return defaultValue, xerror.New(op, err) - } - } - return result, nil -} - -/* -Int64FromEnv returns the int64 representation of the -value of given environment variable. - -If not found, empty, conversion or validation fails, -returns the default value. -*/ -func Int64FromEnv(envVar string, defaultValue int64, rules ...RuleInt64) (int64, error) { - const op string = "xassert.Int64FromEnv" - value := os.Getenv(envVar) - result, err := Int64(envVar, value, defaultValue, rules...) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -Float64 tries to convert a string to a float64. - -If string is empty, conversion or validation fails, -returns the default value. - -The key is used to identify the value. -*/ -func Float64(key, value string, defaultValue float64, rules ...RuleFloat64) (float64, error) { - const op string = "xassert.Float64" - result := defaultValue - if value != "" { - parsedValue, err := strconv.ParseFloat(value, 64) - if err != nil { - return defaultValue, xerror.Invalid( - op, - fmt.Sprintf("'%s' is not a float, got '%s'", key, value), - err, - ) - } - result = parsedValue - } - for _, rule := range rules { - rule.with(key, result) - if err := rule.validate(); err != nil { - return defaultValue, xerror.New(op, err) - } - } - return result, nil -} - -/* -Float64FromEnv returns the float64 representation of the -value of given environment variable. - -If not found, empty, conversion or validation fails, -returns the default value. -*/ -func Float64FromEnv(envVar string, defaultValue float64, rules ...RuleFloat64) (float64, error) { - const op string = "xassert.Float64FromEnv" - value := os.Getenv(envVar) - result, err := Float64(envVar, value, defaultValue, rules...) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -Bool tries to convert a string to a boolean. - -If string is empty or conversion fails, returns the -default value. - -The key is used to identify the value. -*/ -func Bool(key, value string, defaultValue bool) (bool, error) { - const op string = "xassert.Bool" - result := defaultValue - if value != "" { - parsedValue, err := strconv.ParseBool(value) - if err != nil { - return defaultValue, xerror.Invalid( - op, - fmt.Sprintf("'%s' is not a boolean, got '%s'", key, value), - err, - ) - } - result = parsedValue - } - return result, nil -} - -/* -BoolFromEnv returns the boolean representation of the -value of given environment variable. - -If not found, empty or conversion fails, returns the -default value. -*/ -func BoolFromEnv(envVar string, defaultValue bool) (bool, error) { - const op string = "xassert.BoolFromEnv" - value := os.Getenv(envVar) - result, err := Bool(envVar, value, defaultValue) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} - -/* -Bytes tries to convert a string to a int64. - -If string is empty or conversion fails, returns the -default value. - -The key is used to identify the value. -*/ -func Bytes(key, value string, defaultValue int64, rules ...RuleInt64) (int64, error) { - const op string = "xassert.Bytes" - result := defaultValue - if value != "" { - parsedValue, err := humanize.ParseBigBytes(value) - if err != nil { - return defaultValue, xerror.Invalid( - op, - fmt.Sprintf("'%s' is not a correct bytes representation, got '%s'", key, value), - err, - ) - } - result = parsedValue.Int64() - } - for _, rule := range rules { - rule.with(key, result) - if err := rule.validate(); err != nil { - return defaultValue, xerror.New(op, err) - } - } - return result, nil -} - -/* -BytesFromEnv returns the int64 representation of the -value of given environment variable. - -If not found, empty or conversion fails, returns the -default value. -*/ -func BytesFromEnv(envVar string, defaultValue int64, rules ...RuleInt64) (int64, error) { - const op string = "xassert.BytesFromEnv" - value := os.Getenv(envVar) - result, err := Bytes(envVar, value, defaultValue) - if err != nil { - return result, xerror.New(op, err) - } - return result, nil -} diff --git a/internal/pkg/xassert/xassert_test.go b/internal/pkg/xassert/xassert_test.go deleted file mode 100644 index 32a5e2ac..00000000 --- a/internal/pkg/xassert/xassert_test.go +++ /dev/null @@ -1,289 +0,0 @@ -package xassert - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestString(t *testing.T) { - const ( - defaultValue string = "FOO" - ) - var expected string - rule := StringOneOf([]string{"FOO", "BAR"}) - // empty value, result should be equal - // to the default value. - v, err := String("foo", "", defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to given value - // as it is one of "FOO" and "BAR". - expected = "FOO" - v, err = String("foo", expected, defaultValue, rule) - assert.Equal(t, expected, v) - assert.Nil(t, err) - // should not be OK as given value is not - // one of "FOO" and "BAR". - v, err = String("foo", "BAZ", defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) -} - -func TestStringFromEnv(t *testing.T) { - const ( - envVar string = "FOO" - defaultValue string = "FOO" - ) - var expected string - rule := StringOneOf([]string{"FOO", "BAR"}) - // no environment variable set, - // value should be equal to default value. - v, err := StringFromEnv(envVar, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to environment variable - // value as it is one of "FOO" and "BAR". - expected = "BAR" - os.Setenv(envVar, expected) - v, err = StringFromEnv(envVar, defaultValue, rule) - assert.Equal(t, expected, v) - assert.Nil(t, err) - os.Unsetenv(envVar) - // should not be OK as environment variable - // value is not one of "FOO" and "BAR". - os.Setenv(envVar, "BAZ") - v, err = StringFromEnv(envVar, defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - os.Unsetenv(envVar) -} - -func TestInt64(t *testing.T) { - const ( - defaultValue int64 = 10 - ) - var expected int64 - rule := Int64NotInferiorTo(6) - // empty value, result should be equal - // to the default value. - v, err := Int64("foo", "", defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to given value - // but as integer. - v, err = Int64("foo", "5", defaultValue) - expected = 5 - assert.Equal(t, expected, v) - assert.Nil(t, err) - // should not be OK as given value is not - // a string representation of an integer. - v, err = Int64("foo", "foo", defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - // should not be OK as given value does not - // validate the rule x >= 6. - v, err = Int64("foo", "5", defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) -} - -func TestInt64FromEnv(t *testing.T) { - const ( - envVar string = "FOO" - defaultValue int64 = 10 - ) - var expected int64 - rule := Int64NotInferiorTo(6) - // no environment variable set, - // value should be equal to default value. - v, err := Int64FromEnv(envVar, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to environment variable - // value but as integer. - os.Setenv(envVar, "5") - v, err = Int64FromEnv(envVar, defaultValue) - expected = 5 - assert.Equal(t, expected, v) - assert.Nil(t, err) - os.Unsetenv(envVar) - // should not be OK as environment variable - // value is not a string representation of an integer. - os.Setenv(envVar, "foo") - v, err = Int64FromEnv(envVar, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - os.Unsetenv(envVar) - // should not be OK as environment variable - // value does not validate the rule x >= 6. - os.Setenv(envVar, "5") - v, err = Int64FromEnv(envVar, defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - os.Unsetenv(envVar) -} - -func TestFloat64(t *testing.T) { - const defaultValue float64 = 10.0 - var expected float64 - rule := Float64NotInferiorTo(6.0) - // empty value, result should be equal - // to the default value. - v, err := Float64("foo", "", defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to given value - // but as float. - v, err = Float64("foo", "5.5", defaultValue) - expected = 5.5 - assert.Equal(t, expected, v) - assert.Nil(t, err) - // should not be OK as given value is not - // a string representation of a float. - v, err = Float64("foo", "foo", defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - // should not be OK as given value does not - // validate the rule x >= 6. - v, err = Float64("foo", "5.0", defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) -} - -func TestFloat64FromEnv(t *testing.T) { - const ( - envVar string = "FOO" - defaultValue float64 = 10.0 - ) - var expected float64 - rule := Float64NotInferiorTo(6.0) - // no environment variable set, - // value should be equal to default value. - v, err := Float64FromEnv(envVar, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to environment variable - // value but as float. - os.Setenv(envVar, "5.5") - v, err = Float64FromEnv(envVar, defaultValue) - expected = 5.5 - assert.Equal(t, expected, v) - assert.Nil(t, err) - os.Unsetenv(envVar) - // should not be OK as environment variable - // value is not a string representation of a float. - os.Setenv(envVar, "foo") - v, err = Float64FromEnv(envVar, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - os.Unsetenv(envVar) - // should not be OK as environment variable - // value does not validate the rule x >= 6. - os.Setenv(envVar, "5.0") - v, err = Float64FromEnv(envVar, defaultValue, rule) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - os.Unsetenv(envVar) -} - -func TestBool(t *testing.T) { - const defaultValue bool = true - var expected bool - // empty value, result should be equal - // to the default value. - v, err := Bool("foo", "", defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to given value - // but as boolean. - v, err = Bool("foo", "1", defaultValue) - expected = true - assert.Equal(t, expected, v) - assert.Nil(t, err) - v, err = Bool("foo", "true", defaultValue) - expected = true - assert.Equal(t, expected, v) - assert.Nil(t, err) - v, err = Bool("foo", "0", defaultValue) - expected = false - assert.Equal(t, expected, v) - assert.Nil(t, err) - v, err = Bool("foo", "false", defaultValue) - expected = false - assert.Equal(t, expected, v) - assert.Nil(t, err) - // should not be OK as given value is not - // a string representation of a boolean. - v, err = Bool("foo", "foo", defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) -} - -func TestBoolFromEnv(t *testing.T) { - const ( - envVar string = "FOO" - defaultValue bool = true - ) - var expected bool - // no environment variable set, - // value should be equal to default value. - v, err := BoolFromEnv(envVar, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - assert.Nil(t, err) - // result should be equal to environment variable - // value but as boolean. - os.Setenv(envVar, "1") - v, err = BoolFromEnv(envVar, defaultValue) - expected = true - assert.Equal(t, expected, v) - assert.Nil(t, err) - os.Unsetenv(envVar) - os.Setenv(envVar, "true") - v, err = BoolFromEnv(envVar, defaultValue) - expected = true - assert.Equal(t, expected, v) - assert.Nil(t, err) - os.Unsetenv(envVar) - os.Setenv(envVar, "0") - v, err = BoolFromEnv(envVar, defaultValue) - expected = false - assert.Equal(t, expected, v) - assert.Nil(t, err) - os.Unsetenv(envVar) - os.Setenv(envVar, "false") - v, err = BoolFromEnv(envVar, defaultValue) - expected = false - assert.Equal(t, expected, v) - assert.Nil(t, err) - os.Unsetenv(envVar) - // should not be OK as environment variable - // value is not a string representation of a boolean. - os.Setenv(envVar, "foo") - v, err = BoolFromEnv(envVar, defaultValue) - expected = defaultValue - assert.Equal(t, expected, v) - test.AssertError(t, err) - os.Unsetenv(envVar) -} diff --git a/internal/pkg/xcontext/doc.go b/internal/pkg/xcontext/doc.go deleted file mode 100644 index d6a369d6..00000000 --- a/internal/pkg/xcontext/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package xcontext helps managing -// context.Context with timeout. -package xcontext diff --git a/internal/pkg/xcontext/xcontext.go b/internal/pkg/xcontext/xcontext.go deleted file mode 100644 index 2c4259e4..00000000 --- a/internal/pkg/xcontext/xcontext.go +++ /dev/null @@ -1,56 +0,0 @@ -package xcontext - -import ( - "context" - "fmt" - "strings" - - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" - "github.com/thecodingmachine/gotenberg/internal/pkg/xtime" -) - -// WithTimeout creates a context.Context which -// times out after given seconds. -func WithTimeout(logger xlog.Logger, seconds float64) (context.Context, context.CancelFunc) { - const op string = "xcontext.WithTimeout" - logger.DebugOpf(op, "creating context with '%.2fs' of timeout...", seconds) - return context.WithTimeout(context.Background(), xtime.Duration(seconds)) -} - -/* -MustHandleError checks if there is an error -in the given Context. - -If no error, returns the previous error. - -If context.DeadlineExceeded, wraps the previous -error inside an xerror.Error with xerror.TimeoutCode. - -Otherwise wraps the previous error inside an -xerror.Error. - -It panics if no previous error. -*/ -func MustHandleError(ctx context.Context, previousErr error) error { - const op string = "xcontext.MustHandleError" - if previousErr == nil { - panic(fmt.Sprintf("%s: previous error should not be nil", op)) - } - err := ctx.Err() - if err == nil { - // we do not wrap the previous error - // as it should be wrapped by the caller. - return previousErr - } - // context has timed out - if strings.Contains(err.Error(), context.DeadlineExceeded.Error()) { - return xerror.Timeout(op, "context has timed out", previousErr) - } - /* - context has another error: we do not - wrap the error from the Context as the previous - error should contain it. - */ - return xerror.New(op, previousErr) -} diff --git a/internal/pkg/xcontext/xcontext_test.go b/internal/pkg/xcontext/xcontext_test.go deleted file mode 100644 index 36a7e9d9..00000000 --- a/internal/pkg/xcontext/xcontext_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package xcontext - -import ( - "errors" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xtime" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestMustHandleError(t *testing.T) { - previousErr := errors.New("previous error") - logger := test.DebugLogger() - // context should not have an error. - ctx, cancel := WithTimeout(logger, 5) - defer cancel() - err := MustHandleError(ctx, previousErr) - assert.Equal(t, previousErr, err) - // should panic. - ctx, cancel = WithTimeout(logger, 5) - defer cancel() - assert.Panics(t, func() { - MustHandleError(ctx, nil) - }) - // context should timed out. - ctx, cancel = WithTimeout(logger, 0.5) - defer cancel() - time.Sleep(xtime.Duration(1)) - err = MustHandleError(ctx, previousErr) - xerr := test.AssertError(t, err) - assert.Equal(t, xerror.TimeoutCode, xerror.Code(xerr)) - // context should have an error different - // than context.DeadlineExceeded. - ctx, cancel = WithTimeout(logger, 5) - cancel() - err = MustHandleError(ctx, previousErr) - xerr = test.AssertError(t, err) - assert.Equal(t, xerror.InternalCode, xerror.Code(xerr)) -} diff --git a/internal/pkg/xerror/doc.go b/internal/pkg/xerror/doc.go deleted file mode 100644 index 999decf8..00000000 --- a/internal/pkg/xerror/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Package xerror helps standardizing -the errors through the application. - -Credits: https://middlemost.com/failure-is-your-domain/ -*/ -package xerror diff --git a/internal/pkg/xerror/xerror.go b/internal/pkg/xerror/xerror.go deleted file mode 100644 index f1f9c1ee..00000000 --- a/internal/pkg/xerror/xerror.go +++ /dev/null @@ -1,152 +0,0 @@ -package xerror - -import ( - "bytes" - "fmt" - "strings" -) - -// ErrorCode is machine-readable error code. -type ErrorCode string - -const ( - // InternalCode is an internal error. - InternalCode ErrorCode = "internal" - // InvalidCode occurs when a validation - // failed. - InvalidCode ErrorCode = "invalid" - // TimeoutCode occurs when something - // timed out. - TimeoutCode ErrorCode = "timeout" -) - -// Error defines our standard application -// error. -type Error struct { - code ErrorCode - message string - op string - err error -} - -// Error returns the string representation of the error message. -func (e Error) Error() string { - var buf bytes.Buffer - // if wrapping an error, print its Error() message. - // Otherwise print the error code & message. - if e.err != nil { - buf.WriteString(e.err.Error()) - } else { - if e.code != "" { - fmt.Fprintf(&buf, "<%s> ", e.code) - } - buf.WriteString(e.message) - } - return buf.String() -} - -/* -New returns a xerror.Error. - -Should be used for wrapping an error -at the end of a function. -*/ -func New(op string, previous error) error { - return &Error{ - op: op, - err: previous, - } -} - -/* -Invalid returns a xerror.Error. - -Should be used when an input -is wrong. -*/ -func Invalid(op, message string, previous error) error { - return &Error{ - code: InvalidCode, - message: message, - op: op, - err: previous, - } -} - -/* -Timeout returns a xerror.Error. - -Should be used when a timeout occurs. -*/ -func Timeout(op, message string, previous error) error { - return &Error{ - code: TimeoutCode, - message: message, - op: op, - err: previous, - } -} - -// Code returns the code of the root error, if available. -// Otherwise returns InternalCode. -func Code(err error) ErrorCode { - if err == nil { - return "" - } - e, ok := err.(*Error) - if ok && e.code != "" { - return e.code - } - if ok && e.err != nil { - return Code(e.err) - } - return InternalCode -} - -const defaultMessage string = "an internal error has occurred: please contact technical support" - -// Message returns the human-readable message of the error, if available. -// Otherwise returns a generic error message. -func Message(err error) string { - if err == nil { - return "" - } - e, ok := err.(*Error) - if ok && e.message != "" { - return e.message - } - if ok && e.err != nil { - return Message(e.err) - } - return defaultMessage -} - -// Op returns the logical operation of the error, if available. -// Otherwise returns an empty string. -func Op(err error) string { - if err == nil { - return "" - } - e, ok := err.(*Error) - if !ok { - return "" - } - var buf bytes.Buffer - nestedOp := Op(e.err) - if nestedOp != "" { - // we want to avoid having the same op chained. - if e.op != "" && !strings.Contains(nestedOp, e.op) { - fmt.Fprintf(&buf, "%s: %s", e.op, nestedOp) - } else { - fmt.Fprintf(&buf, "%s", nestedOp) - } - } else if e.op != "" { - fmt.Fprintf(&buf, "%s", e.op) - } - return buf.String() -} - -// Compile-time checks to ensure type implements desired interfaces. -var ( - _ = error(new(Error)) -) diff --git a/internal/pkg/xerror/xerror_test.go b/internal/pkg/xerror/xerror_test.go deleted file mode 100644 index a3727ccf..00000000 --- a/internal/pkg/xerror/xerror_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package xerror - -import ( - "errors" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -/* -Error 1.0: op = "foo" -Error 1.1: op = "bar" -Error 1.2: code = "invalid", op = "baz", message = "nested error" -Error 1.3: message = "root error" -*/ -func scenario1() error { - rootErr := errors.New("root error") - nestedErr := Invalid("baz", "nested error", rootErr) - wrappingErr := New("bar", nestedErr) - return New("foo", wrappingErr) -} - -/* -Error 2.0: op = "foo" -Error 2.1: op = "bar" -Error 2.2: code = "timeout", op = "bar", message = "nested error" -*/ -func scenario2() error { - nestedErr := Timeout("bar", "nested error", nil) - wrappingErr := New("bar", nestedErr) - return New("foo", wrappingErr) -} - -// Error 3.0: code = "", op = "foo" -func scenario3() error { - return New("foo", nil) -} - -func TestError(t *testing.T) { - // should return the Error 1.3 - // message. - err := scenario1() - assert.Equal(t, "root error", err.Error()) - // should return the Error 2.2 message with - // its code. - err = scenario2() - assert.Equal(t, " nested error", err.Error()) -} - -func TestCode(t *testing.T) { - // should be an empty code if no error. - assert.Equal(t, "", fmt.Sprintf("%s", Code(nil))) - // should be the code of Error 1.2. - err := scenario1() - assert.Equal(t, InvalidCode, Code(err)) - // should be the code of Error 2.2. - err = scenario2() - assert.Equal(t, TimeoutCode, Code(err)) - // should be the default code. - err = scenario3() - assert.Equal(t, InternalCode, Code(err)) - err = errors.New("some error") - assert.Equal(t, InternalCode, Code(err)) -} - -func TestMessage(t *testing.T) { - // should be an empty message if no error. - assert.Equal(t, "", Message(nil)) - // should be the message of Error 1.2. - err := scenario1() - assert.Equal(t, "nested error", Message(err)) - // should be the default message. - err = errors.New("some error") - assert.Equal(t, defaultMessage, Message(err)) -} - -func TestOp(t *testing.T) { - // should be an empty op if no error. - assert.Equal(t, "", Op(nil)) - // should be the chain of op in this order: - // Error 1.0 -> Error 1.1 -> Error 1.2. - err := scenario1() - assert.Equal(t, "foo: bar: baz", Op(err)) - /* - should be the chain of op in this order: - Error 2.0 -> Error 2.1. - - As Error 2.1 and Error 2.2 shares the same - op, Error 2.2 op is not displayed. - */ - err = scenario2() - assert.Equal(t, "foo: bar", Op(err)) - // should be an empty op if not Error. - err = errors.New("some error") - assert.Equal(t, "", Op(err)) -} diff --git a/internal/pkg/xexec/doc.go b/internal/pkg/xexec/doc.go deleted file mode 100644 index 9db49c6f..00000000 --- a/internal/pkg/xexec/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -/* -Package xexec helps creating exec.Cmd -with logging and executing those commands -without leaking orphan processes. - -All functions return our standard xerror.Error -in case of error. -*/ -package xexec diff --git a/internal/pkg/xexec/xexec.go b/internal/pkg/xexec/xexec.go deleted file mode 100644 index 31dc7fe7..00000000 --- a/internal/pkg/xexec/xexec.go +++ /dev/null @@ -1,155 +0,0 @@ -package xexec - -import ( - "bufio" - "bytes" - "context" - "fmt" - "io" - "os/exec" - "strings" - "syscall" - - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -/* -Command is a wrapper around exec.Command. - -If given xlog.Logger has a xlog.DebugLevel, -also logs the output from the command. -*/ -func Command(logger xlog.Logger, binary string, args ...string) (*exec.Cmd, error) { - const op string = "xexec.Command" - cmd := exec.Command(binary, args...) - if err := pipe(logger, cmd); err != nil { - return nil, xerror.New(op, err) - } - return cmd, nil -} - -/* -CommandContext is a wrapper around exec.CommandContext. - -If given xlog.Logger has a xlog.DebugLevel, -also logs the output from the command. -*/ -func CommandContext(ctx context.Context, logger xlog.Logger, binary string, args ...string) (*exec.Cmd, error) { - const op string = "xexec.CommandContext" - cmd := exec.CommandContext(ctx, binary, args...) - if err := pipe(logger, cmd); err != nil { - return nil, xerror.New(op, err) - } - return cmd, nil -} - -/* -Run runs a command. - -If command finishes or fails to finish -before context.Context deadline, kill the -corresponding process in a way which does -not leak orphan processes. -*/ -func Run(ctx context.Context, logger xlog.Logger, binary string, args ...string) error { - const op string = "xexec.Run" - resolver := func() error { - cmd, err := Command( - logger, - binary, - args..., - ) - if err != nil { - return err - } - LogBeforeExecute(logger, cmd) - // see https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773. - kill := func() { - err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) - if err == nil { - return - } - if !strings.Contains(err.Error(), "no such process") { - logger.ErrorOp(op, err) - } - } - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - if err := cmd.Start(); err != nil { - return err - } - result := make(chan error, 1) - go func() { - result <- cmd.Wait() - }() - select { - case err := <-result: - logger.DebugOpf(op, "command '%s' finished", strings.Join(cmd.Args, " ")) - kill() - return err - case <-ctx.Done(): - logger.DebugOpf(op, "command '%s' failed to finish before context.Context deadline", strings.Join(cmd.Args, " ")) - kill() - return ctx.Err() - } - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -// LogBeforeExecute logs a command before its execution. -func LogBeforeExecute(logger xlog.Logger, cmd *exec.Cmd) { - const op string = "xexec.LogBeforeExecute" - logger.DebugOpf(op, "executing command: %s", strings.Join(cmd.Args, " ")) -} - -func pipe(logger xlog.Logger, cmd *exec.Cmd) error { - const op string = "xexec.pipe" - if logger.Level() != xlog.DebugLevel { - return nil - } - // if xlog.DebugLevel, log the output - // from the command. - resolver := func() error { - stdout, err := cmd.StdoutPipe() - if err != nil { - return err - } - stderr, err := cmd.StderrPipe() - if err != nil { - return err - } - go logCommandOutput(logger, stdout, "stdout", cmd) - go logCommandOutput(logger, stderr, "stderr", cmd) - return nil - } - if err := resolver(); err != nil { - return xerror.New(op, err) - } - return nil -} - -func logCommandOutput(logger xlog.Logger, reader io.ReadCloser, outputType string, cmd *exec.Cmd) { - var buf bytes.Buffer - buf.WriteString(outputType) - for _, arg := range cmd.Args { - buf.WriteString(fmt.Sprintf(".%s", arg)) - } - op := buf.String() - r := bufio.NewReader(reader) - defer reader.Close() - for { - line, _, err := r.ReadLine() - if err != nil { - if err != io.EOF && !strings.Contains(err.Error(), "file already closed") { - logger.ErrorOp(op, err) - } - break - } - if len(line) != 0 { - logger.DebugOp(op, string(line)) - } - } -} diff --git a/internal/pkg/xexec/xexec_test.go b/internal/pkg/xexec/xexec_test.go deleted file mode 100644 index ceffc5c5..00000000 --- a/internal/pkg/xexec/xexec_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package xexec - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xcontext" - "github.com/thecodingmachine/gotenberg/test" -) - -func TestCommand(t *testing.T) { - logger := test.DebugLogger() - // should pipe command output as - // xlog.Logger has a xlog.DebugLevel. - cmd, err := Command(logger, "echo", "Hello", "World") - assert.Nil(t, err) - LogBeforeExecute(logger, cmd) - // should not pipe command output as - // xlog.Logger has a xlog.InfoLevel. - logger = test.InfoLogger() - cmd, err = Command(logger, "echo", "Hello", "World") - LogBeforeExecute(logger, cmd) - assert.Nil(t, err) -} - -func TestCommandContext(t *testing.T) { - logger := test.DebugLogger() - // should pipe command output as - // xlog.Logger has a xlog.DebugLevel. - cmd, err := CommandContext(context.Background(), logger, "echo", "Hello", "World") - assert.Nil(t, err) - LogBeforeExecute(logger, cmd) - // should not pipe command output as - // xlog.Logger has a xlog.InfoLevel. - logger = test.InfoLogger() - cmd, err = CommandContext(context.Background(), logger, "echo", "Hello", "World") - LogBeforeExecute(logger, cmd) - assert.Nil(t, err) -} - -func TestRun(t *testing.T) { - logger := test.DebugLogger() - // should run without issue. - err := Run(context.Background(), logger, "echo", "Hello", "World") - assert.Nil(t, err) - // should not be OK as context.Context - // should timeout. - ctx, cancel := xcontext.WithTimeout(logger, 0) - defer cancel() - err = Run(ctx, logger, "echo", "Hello", "World") - assert.NotNil(t, err) -} diff --git a/internal/pkg/xlog/doc.go b/internal/pkg/xlog/doc.go deleted file mode 100644 index 7aab9e5c..00000000 --- a/internal/pkg/xlog/doc.go +++ /dev/null @@ -1,17 +0,0 @@ -/* -Package xlog defines a standard logger -for the application. - -It uses structured logging thanks to -https://github.com/sirupsen/logrus. - -All messages have at least two fields: - -A "trace" field which helps to identify -messages belonging to the same context. - -An "op" field which helps to identify -the logical operation associated -with the message. -*/ -package xlog diff --git a/internal/pkg/xlog/xlog.go b/internal/pkg/xlog/xlog.go deleted file mode 100644 index af571d91..00000000 --- a/internal/pkg/xlog/xlog.go +++ /dev/null @@ -1,141 +0,0 @@ -package xlog - -import ( - "fmt" - "os" - - "github.com/mattn/go-isatty" - "github.com/sirupsen/logrus" -) - -// Level helps setting the severity -// of the messages displayed. -type Level string - -const ( - // DebugLevel is the lowest level. - DebugLevel Level = "DEBUG" - // InfoLevel is the intermediate level. - InfoLevel Level = "INFO" - // ErrorLevel is the highest level. - ErrorLevel Level = "ERROR" -) - -// Logger enforces specific log message formats. -type Logger struct { - entry *logrus.Entry - level Level -} - -// New returns a xlog.Logger. -func New(level Level, trace string) Logger { - l := logrus.New() - l.SetLevel(mustLogrusLevel(level)) - if !isatty.IsTerminal(os.Stdout.Fd()) { - l.SetFormatter(&logrus.JSONFormatter{}) - } - return Logger{ - entry: l.WithField("trace", trace), - level: level, - } -} - -func mustLogrusLevel(level Level) logrus.Level { - const op string = "xlog.mustLogrusLevel" - switch level { - case DebugLevel: - return logrus.DebugLevel - case InfoLevel: - return logrus.InfoLevel - case ErrorLevel: - return logrus.ErrorLevel - default: - panic(fmt.Sprintf("%s: '%s' is not associated with any logrus.Level", op, level)) - } -} - -// Levels returns a slice of string -// with all severities. -func Levels() []string { - return []string{ - string(DebugLevel), - string(InfoLevel), - string(ErrorLevel), - } -} - -/* -MustParseLevel returns the Level corresponding -to given string. - -It panics if no correspondence. -*/ -func MustParseLevel(level string) Level { - const op string = "xlog.MustParseLevel" - switch level { - case string(DebugLevel): - return DebugLevel - case string(InfoLevel): - return InfoLevel - case string(ErrorLevel): - return ErrorLevel - default: - panic(fmt.Sprintf("%s: '%s' is not one of '%v'", op, level, Levels())) - } -} - -// Level returns the current Level. -func (l Logger) Level() Level { - return l.level -} - -// WithFields returns a new xlog.Logger with -// given fields. -func (l Logger) WithFields(fields map[string]interface{}) Logger { - return Logger{ - entry: l.entry.WithFields(fields), - level: l.level, - } -} - -// DebugOp logs a debug message for given -// logical operation. -func (l Logger) DebugOp(op, message string) { - l.entry.WithField("op", op).Debug(message) -} - -// DebugOpf logs a debug message for given -// logical operation and format. -func (l Logger) DebugOpf(op, format string, args ...interface{}) { - l.entry.WithField("op", op).Debugf(format, args...) -} - -// InfoOp logs an info message for given -// logical operation. -func (l Logger) InfoOp(op, message string) { - l.entry.WithField("op", op).Info(message) -} - -// InfoOpf logs an info message for given -// logical operation and format. -func (l Logger) InfoOpf(op, format string, args ...interface{}) { - l.entry.WithField("op", op).Infof(format, args...) -} - -// ErrorOp logs an error for given -// logical operation. -func (l Logger) ErrorOp(op string, err error) { - l.entry.WithField("op", op).Error(err.Error()) -} - -// ErrorOpf logs an error message for given -// logical operation and format. -func (l Logger) ErrorOpf(op, format string, args ...interface{}) { - l.entry.WithField("op", op).Errorf(format, args...) -} - -// FatalOp logs an error for given -// logical operation and exit 1. -func (l Logger) FatalOp(op string, err error) { - l.entry.WithField("op", op).Fatal(err.Error()) -} diff --git a/internal/pkg/xrand/doc.go b/internal/pkg/xrand/doc.go deleted file mode 100644 index 672af2b3..00000000 --- a/internal/pkg/xrand/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package xrand helps generating -// random strings. -package xrand diff --git a/internal/pkg/xrand/xrand.go b/internal/pkg/xrand/xrand.go deleted file mode 100644 index bdac8fab..00000000 --- a/internal/pkg/xrand/xrand.go +++ /dev/null @@ -1,10 +0,0 @@ -package xrand - -import ( - "github.com/labstack/gommon/random" -) - -// Get returns a random string. -func Get() string { - return random.String(32) -} diff --git a/internal/pkg/xrand/xrand_test.go b/internal/pkg/xrand/xrand_test.go deleted file mode 100644 index e5880f99..00000000 --- a/internal/pkg/xrand/xrand_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package xrand - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestGet(t *testing.T) { - var rands []string - // use case: for 1 000 concurrent - // requests (which is a big Gotenberg instance), - // none should have the same identifier. - for i := 0; i < 1000; i++ { - rands = append(rands, Get()) - } - unique := func() bool { - for i, rand := range rands { - for j, current := range rands { - if i != j && rand == current { - return false - } - } - } - return true - } - assert.Equal(t, true, unique()) -} diff --git a/internal/pkg/xtime/doc.go b/internal/pkg/xtime/doc.go deleted file mode 100644 index 2dbfa55a..00000000 --- a/internal/pkg/xtime/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -/* -Package xtime helps generating -time.Duration from seconds represented -as float64. -*/ -package xtime diff --git a/internal/pkg/xtime/xtime.go b/internal/pkg/xtime/xtime.go deleted file mode 100644 index c0af3bdb..00000000 --- a/internal/pkg/xtime/xtime.go +++ /dev/null @@ -1,10 +0,0 @@ -package xtime - -import ( - "time" -) - -// Duration creates a time.Duration from seconds. -func Duration(seconds float64) time.Duration { - return time.Duration(1000*seconds) * time.Millisecond -} diff --git a/internal/pkg/xtime/xtime_test.go b/internal/pkg/xtime/xtime_test.go deleted file mode 100644 index 67fee437..00000000 --- a/internal/pkg/xtime/xtime_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package xtime - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestDuration(t *testing.T) { - expected := time.Duration(1500) * time.Millisecond - result := Duration(1.5) - assert.Equal(t, expected.String(), result.String()) -} diff --git a/loadtesting/README.md b/loadtesting/README.md deleted file mode 100644 index eb673c9f..00000000 --- a/loadtesting/README.md +++ /dev/null @@ -1,160 +0,0 @@ -# Load testing - -You may wonder how Gotenberg behaves under load. - -In order to help you having an idea, we created a bunch of scenarios for the -[k6](https://docs.k6.io/docs) load testing tool. - -The Gotenberg container (version `6.0.0` and default options) was hosted on a AWS EC2 `t2.micro` instance (1 vCPU and 1 Go of RAM, low to average network performances). - -The k6 scenarios have been performed on a MacBook Pro 2016 (2 GHz Intel Core i5 and 16 Go 1867 MHz LPDDR3). - -## HTML - -The HTML scenario is quite simple: - -* Ramp up from 0 to 100 virtual users, each one uploading as many time as possible the [HTML test data](../test/testdata/html). -* Stop when at least one response is not an HTTP 200 code. - -```bash -$ k6 run --env MAX_VUS=100 --env BASE_URL=http://ec2-foo.eu-west-1.compute.amazonaws.com html.js - - /\ |‾‾| /‾‾/ /‾/ - /\ / \ | |_/ / / / - / \/ \ | | / ‾‾\ - / \ | |‾\ \ | (_) | - / __________ \ |__| \__\ \___/ .io - - execution: local - output: - - script: html.js - - duration: -, iterations: - - vus: 1, max: 100 - - done [==========================================================] 1m17.9s / 10m0s - - ✗ is status 200 - ↳ 99% — ✓ 201 / ✗ 2 - ✗ is not status 504 - ↳ 99% — ✓ 201 / ✗ 2 - ✓ is not status 500 - - checks.....................: 99.34% ✓ 605 ✗ 4 - data_received..............: 46 MB 594 kB/s - data_sent..................: 9.6 MB 123 kB/s - ✗ failed requests............: 2 0.025646/s - http_req_blocked...........: avg=1.63ms min=2µs med=4µs max=74.77ms p(90)=9.6µs p(95)=19.66ms - http_req_connecting........: avg=1.61ms min=0s med=0s max=74.59ms p(90)=0s p(95)=19.57ms - http_req_duration..........: avg=2.43s min=1.31s med=1.67s max=10.27s p(90)=5.44s p(95)=8.75s - http_req_receiving.........: avg=97.95ms min=103µs med=93.74ms max=202.48ms p(90)=114.51ms p(95)=132.99ms - http_req_sending...........: avg=231.53µs min=92µs med=201µs max=2.33ms p(90)=310.4µs p(95)=333.59µs - http_req_tls_handshaking...: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s - http_req_waiting...........: avg=2.33s min=1.22s med=1.58s max=10.12s p(90)=5.33s p(95)=8.62s - http_reqs..................: 203 2.603019/s - iteration_duration.........: avg=2.43s min=1.31s med=1.68s max=10.27s p(90)=5.45s p(95)=8.75s - iterations.................: 203 2.603019/s - vus........................: 13 min=1 max=13 - vus_max....................: 100 min=100 max=100 -``` - -In our use case, when reaching 13 virtual users (~2,6 requests per second), some incoming requests cannot be fulfilled before 10 seconds (`DEFAULT_WAIT_TIMEOUT` value). -During this test, CPU usage was high and memory usage went from 339 MiB to a peak of 421 MiB before going back to 364 MiB. - -## Office - -The Office scenario is the same as the HTML scenario, but with a [document.docx](../test/testdata/office/document.docx). - -```bash -$ k6 run --env MAX_VUS=100 --env BASE_URL=http://ec2-foo.eu-west-1.compute.amazonaws.com office.js - - /\ |‾‾| /‾‾/ /‾/ - /\ / \ | |_/ / / / - / \/ \ | | / ‾‾\ - / \ | |‾\ \ | (_) | - / __________ \ |__| \__\ \___/ .io - - execution: local - output: - - script: office.js - - duration: -, iterations: - - vus: 1, max: 100 - - done [==========================================================] 47.9s / 10m0s - - ✓ is not status 500 - ✗ is status 200 - ↳ 83% — ✓ 31 / ✗ 6 - ✗ is not status 504 - ↳ 83% — ✓ 31 / ✗ 6 - - checks.....................: 89.18% ✓ 99 ✗ 12 - data_received..............: 2.6 MB 54 kB/s - data_sent..................: 3.4 MB 71 kB/s - ✗ failed requests............: 6 0.125047/s - http_req_blocked...........: avg=4.39ms min=3µs med=4µs max=24.52ms p(90)=23.27ms p(95)=23.62ms - http_req_connecting........: avg=4.34ms min=0s med=0s max=24.42ms p(90)=23.15ms p(95)=23.52ms - http_req_duration..........: avg=5.34s min=1.74s med=4.33s max=10.83s p(90)=10.24s p(95)=10.25s - http_req_receiving.........: avg=42.49ms min=67µs med=49.1ms max=68.87ms p(90)=57.34ms p(95)=62.06ms - http_req_sending...........: avg=341.91µs min=215µs med=341µs max=724µs p(90)=443.99µs p(95)=514.79µs - http_req_tls_handshaking...: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s - http_req_waiting...........: avg=5.3s min=1.7s med=4.27s max=10.83s p(90)=10.24s p(95)=10.25s - http_reqs..................: 37 0.771121/s - iteration_duration.........: avg=5.34s min=1.74s med=4.35s max=10.86s p(90)=10.24s p(95)=10.25s - iterations.................: 37 0.771121/s - vus........................: 8 min=1 max=8 - vus_max....................: 100 min=100 max=100 -``` - -In our use case, when reaching 8 virtual users (~0.8 requests per second), some incoming requests cannot be fulfilled before 10 seconds (`DEFAULT_WAIT_TIMEOUT` value). -During this test, CPU usage was high and memory usage went from 315 MiB to a peak of 788 MiB before going back to 307 MiB. - -## Merge - -The Merge scenario is the same as the previous scenarios, but with a [gotenberg.pdf](../test/testdata/pdf/gotenberg.pdf) and a [gotenberg_bis.pdf](../test/testdata/pdf/gotenberg_bis.pdf). - -```bash -$ k6 run --env MAX_VUS=100 --env BASE_URL=http://ec2-foo.eu-west-1.compute.amazonaws.com merge.js - - /\ |‾‾| /‾‾/ /‾/ - /\ / \ | |_/ / / / - / \/ \ | | / ‾‾\ - / \ | |‾\ \ | (_) | - / __________ \ |__| \__\ \___/ .io - - execution: local - output: - - script: merge.js - - duration: -, iterations: - - vus: 1, max: 100 - - done [==========================================================] 1m45.9s / 10m0s - - ✗ is status 200 - ↳ 98% — ✓ 165 / ✗ 3 - ✗ is not status 504 - ↳ 98% — ✓ 165 / ✗ 3 - ✓ is not status 500 - - checks.....................: 98.80% ✓ 498 ✗ 6 - data_received..............: 69 MB 649 kB/s - data_sent..................: 70 MB 661 kB/s - ✗ failed requests............: 3 0.028302/s - http_req_blocked...........: avg=2.28ms min=2µs med=5µs max=33.24ms p(90)=23.6µs p(95)=23.38ms - http_req_connecting........: avg=2.24ms min=0s med=0s max=33.1ms p(90)=0s p(95)=23.04ms - http_req_duration..........: avg=5.32s min=632.86ms med=5.24s max=10.17s p(90)=9.42s p(95)=9.91s - http_req_receiving.........: avg=122.07ms min=82µs med=114.72ms max=230.35ms p(90)=162.27ms p(95)=188.95ms - http_req_sending...........: avg=16.56ms min=349µs med=1.37ms max=223.25ms p(90)=12ms p(95)=149.76ms - http_req_tls_handshaking...: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s - http_req_waiting...........: avg=5.18s min=573.03ms med=5.09s max=10.13s p(90)=9.29s p(95)=9.78s - http_reqs..................: 168 1.58493/s - iteration_duration.........: avg=5.33s min=633.87ms med=5.24s max=10.17s p(90)=9.43s p(95)=9.91s - iterations.................: 168 1.58493/s - vus........................: 18 min=1 max=18 - vus_max....................: 100 min=100 max=100 -``` - -In our use case, when reaching 18 virtual users (~1.6 requests per second), some incoming requests cannot be fulfilled before 10 seconds (`DEFAULT_WAIT_TIMEOUT` value). -During this test, CPU usage was high and memory usage went from 310 MiB to a peak of 604 MiB before going back to 331 MiB. diff --git a/loadtesting/html.js b/loadtesting/html.js deleted file mode 100644 index b6965a35..00000000 --- a/loadtesting/html.js +++ /dev/null @@ -1,44 +0,0 @@ -import http from "k6/http"; -import { Counter } from "k6/metrics"; -import { check } from "k6"; - -let indexFile = open("../test/testdata/html/index.html", "b"), - styleFile = open("../test/testdata/html/style.css", "b"), - headerFile = open("../test/testdata/html/header.html", "b"), - footerFile = open("../test/testdata/html/footer.html", "b"), - fontFile = open("../test/testdata/html/font.woff", "b"), - imgFile = open("../test/testdata/html/img.gif", "b"); - -let failCounter = new Counter("failed requests"); - -export let options = { - stages: [ - { duration: "10m", target: __ENV.MAX_VUS } - ], - thresholds: { - "failed requests": [{ - threshold: "count<1", - abortOnFail: true, - }] - } -} - -export default function() { - let data = { - "index.html": http.file(indexFile, "index.html"), - "style.css": http.file(styleFile, "style.css"), - "header.html": http.file(headerFile, "header.html"), - "footer.html": http.file(footerFile, "footer.html"), - "font.woff": http.file(fontFile, "font.woff"), - "img.gif": http.file(imgFile, "img.gif") - } - let res = http.post(__ENV.BASE_URL + '/convert/html', data); - check(res, { - "is status 200": (r) => r.status === 200, - "is not status 504": (r) => r.status !== 504, - "is not status 500": (r) => r.status !== 500 - }); - if (res.status !== 200) { - failCounter.add(1); - } -} \ No newline at end of file diff --git a/loadtesting/merge.js b/loadtesting/merge.js deleted file mode 100644 index 29e1db0d..00000000 --- a/loadtesting/merge.js +++ /dev/null @@ -1,36 +0,0 @@ -import http from "k6/http"; -import { Counter } from "k6/metrics"; -import { check } from "k6"; - -let pdf1File = open("../test/testdata/pdf/gotenberg.pdf", "b"), - pdf2File = open("../test/testdata/pdf/gotenberg_bis.pdf", "b"); - -let failCounter = new Counter("failed requests"); - -export let options = { - stages: [ - { duration: "10m", target: __ENV.MAX_VUS } - ], - thresholds: { - "failed requests": [{ - threshold: "count<1", - abortOnFail: true, - }] - } -} - -export default function() { - var data = { - "gotenberg.pdf": http.file(pdf1File, "gotenberg.pdf"), - "gotenberg_bis.pdf": http.file(pdf2File, "gotenberg_bis.pdf") - } - var res = http.post(__ENV.BASE_URL + '/merge', data); - check(res, { - "is status 200": (r) => r.status === 200, - "is not status 504": (r) => r.status !== 504, - "is not status 500": (r) => r.status !== 500, - }); - if (res.status !== 200) { - failCounter.add(1); - } -} \ No newline at end of file diff --git a/loadtesting/office.js b/loadtesting/office.js deleted file mode 100644 index 6df88069..00000000 --- a/loadtesting/office.js +++ /dev/null @@ -1,34 +0,0 @@ -import http from "k6/http"; -import { Counter } from "k6/metrics"; -import { check } from "k6"; - -let documentFile = open("../test/testdata/office/document.docx", "b"); - -let failCounter = new Counter("failed requests"); - -export let options = { - stages: [ - { duration: "10m", target: __ENV.MAX_VUS } - ], - thresholds: { - "failed requests": [{ - threshold: "count<1", - abortOnFail: true, - }] - } -} - -export default function() { - let data = { - "document.docx": http.file(documentFile, "document.docx") - } - let res = http.post(__ENV.BASE_URL + '/convert/office', data); - check(res, { - "is status 200": (r) => r.status === 200, - "is not status 504": (r) => r.status !== 504, - "is not status 500": (r) => r.status !== 500, - }); - if (res.status !== 200) { - failCounter.add(1); - } -} \ No newline at end of file diff --git a/pkg/gotenberg/cmd.go b/pkg/gotenberg/cmd.go new file mode 100644 index 00000000..9788dbab --- /dev/null +++ b/pkg/gotenberg/cmd.go @@ -0,0 +1,187 @@ +package gotenberg + +import ( + "bufio" + "context" + "errors" + "fmt" + "io" + "os/exec" + "strings" + "syscall" + + "go.uber.org/zap" +) + +// Cmd wraps an exec.Cmd. +type Cmd struct { + ctx context.Context + logger *zap.Logger + process *exec.Cmd +} + +// Command creates a Cmd without a context. It configures the internal +// exec.Cmd of Cmd so that we may kill its unix process and all its children +// without creating orphans. +// +// See https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773. +func Command(logger *zap.Logger, binPath string, args ...string) Cmd { + cmd := exec.Command(binPath, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + + return Cmd{ + ctx: nil, + logger: logger.Named("cmd"), + process: cmd, + } +} + +// CommandContext creates a Cmd with a context. It configures the internal +// exec.Cmd of Cmd so that we may kill its unix process and all its children +// without creating orphans. +// +// See https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773. +func CommandContext(ctx context.Context, logger *zap.Logger, binPath string, args ...string) (Cmd, error) { + if ctx == nil { + return Cmd{}, errors.New("nil context") + } + + cmd := exec.CommandContext(ctx, binPath, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + + return Cmd{ + ctx: ctx, + logger: logger.Named("cmd"), + process: cmd, + }, nil +} + +// Start starts the command but does not wait for its completion. +func (cmd Cmd) Start() error { + err := cmd.pipeOutput() + if err != nil { + return fmt.Errorf("pipe unix process output: %w", err) + } + + cmd.logger.Debug(fmt.Sprintf("start unix process: %s", strings.Join(cmd.process.Args, " "))) + + err = cmd.process.Start() + if err != nil { + return fmt.Errorf("start unix process: %w", err) + } + + return nil +} + +// Exec executes the command and wait for its completion or until the context +// is done. In any case, it kills the unix process and all its children. +func (cmd Cmd) Exec() error { + if cmd.ctx == nil { + return errors.New("nil context") + } + + err := cmd.Start() + if err != nil { + return fmt.Errorf("start command: %w", err) + } + + errChan := make(chan error, 1) + + go func() { + errChan <- cmd.process.Wait() + }() + + select { + case err = <-errChan: + errProc := cmd.Kill() + if errProc != nil { + cmd.logger.Error(errProc.Error()) + } + + if err == nil { + return nil + } + + return fmt.Errorf("unix process error: %w", err) + case <-cmd.ctx.Done(): + errProc := cmd.Kill() + if errProc != nil { + cmd.logger.Error(errProc.Error()) + } + + return fmt.Errorf("context done: %w", cmd.ctx.Err()) + } +} + +// pipeOutput creates logs entries according to the process stdout and stderr. +// It does nothing if the logging level is not debug. +func (cmd Cmd) pipeOutput() error { + checkedEntry := cmd.logger.Check(zap.DebugLevel, "check for debug level before piping unix process output") + if checkedEntry == nil { + return nil + } + + stdout, err := cmd.process.StdoutPipe() + if err != nil { + return fmt.Errorf("pipe unix process stdout: %w", err) + } + + stderr, err := cmd.process.StderrPipe() + if err != nil { + return fmt.Errorf("unix process sdterr: %w", err) + } + + // logCommandOutput creates logs entries according to a reader + // (either stdout or stderr). + logCommandOutput := func(logger *zap.Logger, reader io.ReadCloser) { + r := bufio.NewReader(reader) + defer reader.Close() + + for { + line, _, err := r.ReadLine() + + if err != nil { + if err != io.EOF && !strings.Contains(err.Error(), "file already closed") { + logger.Error(fmt.Sprintf("pipe unix process output error: %s", err)) + } + + break + } + + if len(line) != 0 { + logger.Debug(string(line)) + } + } + } + + go logCommandOutput(cmd.logger.Named("stdout"), stdout) + go logCommandOutput(cmd.logger.Named("stderr"), stderr) + + return nil +} + +// Kill kills the unix process and all its children without creating orphans. +// +// See https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773. +func (cmd Cmd) Kill() error { + if cmd.process == nil { + // We cannot use the logger here, because for whatever reason using it + // result to a panic. + // cmd.logger.Debug("no process, skip killing") + return nil + } + + err := syscall.Kill(-cmd.process.Process.Pid, syscall.SIGKILL) + if err == nil { + cmd.logger.Debug("unix process killed") + return nil + } + + // If the process does not exist anymore, the error is irrelevant. + if strings.Contains(err.Error(), "no such process") { + cmd.logger.Debug("unix process already killed") + return nil + } + + return fmt.Errorf("kill unix process: %w", err) +} diff --git a/pkg/gotenberg/cmd_test.go b/pkg/gotenberg/cmd_test.go new file mode 100644 index 00000000..c0c7062f --- /dev/null +++ b/pkg/gotenberg/cmd_test.go @@ -0,0 +1,220 @@ +package gotenberg + +import ( + "context" + "testing" + "time" + + "go.uber.org/zap" +) + +func TestCommand(t *testing.T) { + cmd := Command(zap.NewNop(), "foo") + + if !cmd.process.SysProcAttr.Setpgid { + t.Error("expected Setpgid to be true") + } +} + +func TestCommandContext(t *testing.T) { + for i, tc := range []struct { + ctx context.Context + expectErr bool + }{ + { + ctx: nil, + expectErr: true, + }, + { + ctx: context.TODO(), + }, + } { + cmd, err := CommandContext(tc.ctx, zap.NewNop(), "foo") + + if err == nil && !cmd.process.SysProcAttr.Setpgid { + t.Fatalf("test %d: expected Setpgid to be true", i) + } + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestCmd_Start(t *testing.T) { + for i, tc := range []struct { + cmd Cmd + expectErr bool + }{ + { + cmd: Command(zap.NewNop(), "foo"), + expectErr: true, + }, + { + cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + }, + } { + err := tc.cmd.Start() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestCmd_Exec(t *testing.T) { + for i, tc := range []struct { + cmd Cmd + timeout time.Duration + expectErr bool + }{ + { + cmd: Command(zap.NewNop(), "foo"), + expectErr: true, + }, + { + cmd: Command(zap.NewNop(), "foo"), + timeout: time.Duration(5) * time.Second, + expectErr: true, + }, + { + cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + timeout: time.Duration(5) * time.Second, + }, + { + cmd: Command(zap.NewNop(), "sleep", "3"), + timeout: time.Duration(2) * time.Second, + expectErr: true, + }, + } { + if tc.timeout > 0 { + ctx, cancel := context.WithTimeout(context.TODO(), tc.timeout) + defer cancel() + + tc.cmd.ctx = ctx + } + + err := tc.cmd.Exec() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestCmd_pipeOutput(t *testing.T) { + for i, tc := range []struct { + cmd Cmd + run bool + expectErr bool + }{ + { + cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + }, + { + cmd: func() Cmd { + cmd := Command(zap.NewExample(), "echo", "Hello", "World") + _, err := cmd.process.StdoutPipe() + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return cmd + }(), + expectErr: true, + }, + { + cmd: func() Cmd { + cmd := Command(zap.NewExample(), "echo", "Hello", "World") + _, err := cmd.process.StderrPipe() + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return cmd + }(), + expectErr: true, + }, + { + cmd: Command(zap.NewExample(), "echo", "Hello", "World"), + run: true, + }, + } { + err := tc.cmd.pipeOutput() + + if tc.run { + errStart := tc.cmd.process.Start() + + if errStart != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + } + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestCmd_Kill(t *testing.T) { + for i, tc := range []struct { + cmd Cmd + expectErr bool + }{ + { + cmd: Cmd{logger: zap.NewNop()}, + }, + { + cmd: func() Cmd { + cmd := Command(zap.NewNop(), "sleep", "60") + err := cmd.process.Start() + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return cmd + }(), + }, + { + cmd: func() Cmd { + cmd := Command(zap.NewNop(), "echo", "Hello", "World") + err := cmd.process.Run() + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return cmd + }(), + }, + } { + err := tc.cmd.Kill() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} diff --git a/pkg/gotenberg/context.go b/pkg/gotenberg/context.go new file mode 100644 index 00000000..729d5bb5 --- /dev/null +++ b/pkg/gotenberg/context.go @@ -0,0 +1,125 @@ +package gotenberg + +import ( + "fmt" + "reflect" +) + +// Context is a struct which helps initializing modules. When provisioning, a +// module may use the context to get other modules that it needs internally. +type Context struct { + flags ParsedFlags + descriptors []ModuleDescriptor + moduleInstances map[string]interface{} +} + +// NewContext creates a Context. +// In a module, prefer the Provisioner interface to get a Context. +func NewContext( + flags ParsedFlags, + descriptors []ModuleDescriptor, +) *Context { + return &Context{ + flags: flags, + descriptors: descriptors, + moduleInstances: make(map[string]interface{}), + } +} + +// ParsedFlags returns the parsed flags. +// +// func (m *YourModule) Provision(ctx *gotenberg.Context) error { +// flags := ctx.ParsedFlags() +// m.foo = flags.RequiredString("foo") +// } +func (ctx Context) ParsedFlags() ParsedFlags { + return ctx.flags +} + +// Module returns a module which satisfies the requested interface. +// +// func (m *YourModule) Provision(ctx *gotenberg.Context) error { +// mod, _ := ctx.Module(new(ModuleInterface)) +// real := mod.(ModuleInterface) +// } +// +// If the module has not yet been initialized, this method +// initializes it. Otherwise, returns the already initialized instance. +func (ctx *Context) Module(kind interface{}) (interface{}, error) { + mods, err := ctx.Modules(kind) + + if err != nil { + return nil, fmt.Errorf("get module: %w", err) + } + + if len(mods) != 1 { + return nil, fmt.Errorf("expected to have one and only one %s module", kind) + } + + return mods[0], nil +} + +// Modules returns the list of modules which satisfies the requested interface. +// +// func (m *YourModule) Provision(ctx *gotenberg.Context) error { +// mods, _ := ctx.Modules(new(ModuleInterface)) +// for _, mod := range mods { +// real := mod.(ModuleInterface) +// // ... +// } +// } +// +// If one or more modules have not yet been initialized, this method +// initializes them. Otherwise, returns the already initialized instances. +func (ctx *Context) Modules(kind interface{}) ([]interface{}, error) { + realKind := reflect.TypeOf(kind).Elem() + + var mods []interface{} + + for _, desc := range ctx.descriptors { + newInstance := desc.New() + + if ok := reflect.TypeOf(newInstance).Implements(realKind); ok { + // The module implements the requested interface. + // We check if it has already been initialized. + instance, ok := ctx.moduleInstances[desc.ID] + + if ok { + mods = append(mods, instance) + } else { + err := ctx.loadModule(desc.ID, newInstance) + if err != nil { + return nil, err + } + + mods = append(mods, newInstance) + } + } + } + + return mods, nil +} + +// loadModule calls the Provision and/or Validate methods of the requested +// module if it satisfies the Provisioner and/or Validator interfaces. +func (ctx *Context) loadModule(id string, instance interface{}) error { + if prov, ok := instance.(Provisioner); ok { + // The instance can be provisioned. + err := prov.Provision(ctx) + if err != nil { + return fmt.Errorf("provision module %s: %w", id, err) + } + } + + if validator, ok := instance.(Validator); ok { + // The instance can be validated. + err := validator.Validate() + if err != nil { + return fmt.Errorf("validate module %s: %w", id, err) + } + } + + ctx.moduleInstances[id] = instance + + return nil +} diff --git a/pkg/gotenberg/context_test.go b/pkg/gotenberg/context_test.go new file mode 100644 index 00000000..9c53c20b --- /dev/null +++ b/pkg/gotenberg/context_test.go @@ -0,0 +1,195 @@ +package gotenberg + +import ( + "errors" + "testing" +) + +func TestNewContext(t *testing.T) { + if NewContext(ParsedFlags{}, nil) == nil { + t.Error("expected a non-nil value") + } +} + +func TestContext_ParsedFlags(t *testing.T) { + ctx := NewContext(ParsedFlags{}, nil) + + actual := ctx.ParsedFlags() + expect := ParsedFlags{} + + if actual != expect { + t.Errorf("expected %v but got %v", expect, actual) + } +} + +func TestContext_Module(t *testing.T) { + for i, tc := range []struct { + mods []ModuleDescriptor + kind interface{} + expectErr bool + }{ + { + mods: func() []ModuleDescriptor { + mod := struct{ ProtoProvisioner }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.provision = func(ctx *Context) error { return errors.New("foo") } + + return []ModuleDescriptor{mod.Descriptor()} + }(), + kind: new(Provisioner), + expectErr: true, + }, + { + mods: func() []ModuleDescriptor { + mod := struct{ ProtoProvisioner }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.provision = func(ctx *Context) error { return nil } + + return []ModuleDescriptor{mod.Descriptor(), mod.Descriptor()} + }(), + kind: new(Provisioner), + expectErr: true, + }, + { + mods: func() []ModuleDescriptor { + mod := struct{ ProtoProvisioner }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.provision = func(ctx *Context) error { return nil } + + return []ModuleDescriptor{mod.Descriptor()} + }(), + kind: new(Provisioner), + }, + } { + + ctx := NewContext(ParsedFlags{}, tc.mods) + _, err := ctx.Module(tc.kind) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestContext_Modules(t *testing.T) { + for i, tc := range []struct { + mods []ModuleDescriptor + kind interface{} + expectErr bool + }{ + { + mods: func() []ModuleDescriptor { + mod := struct{ ProtoProvisioner }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.provision = func(ctx *Context) error { return errors.New("foo") } + + return []ModuleDescriptor{mod.Descriptor()} + }(), + kind: new(Provisioner), + expectErr: true, + }, + { + mods: func() []ModuleDescriptor { + mod := struct{ ProtoProvisioner }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.provision = func(ctx *Context) error { return nil } + + return []ModuleDescriptor{mod.Descriptor(), mod.Descriptor()} + }(), + kind: new(Provisioner), + }, + { + mods: func() []ModuleDescriptor { + mod := struct{ ProtoProvisioner }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.provision = func(ctx *Context) error { return nil } + + return []ModuleDescriptor{mod.Descriptor()} + }(), + kind: new(Provisioner), + }, + } { + + ctx := NewContext(ParsedFlags{}, tc.mods) + _, err := ctx.Modules(tc.kind) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestContext_loadModule(t *testing.T) { + for i, tc := range []struct { + instance interface{} + expectErr bool + }{ + { + instance: func() interface{} { + mod := struct{ ProtoProvisioner }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.provision = func(ctx *Context) error { return errors.New("foo") } + + return mod + }(), + expectErr: true, + }, + { + instance: func() interface{} { + mod := struct{ ProtoValidator }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.validate = func() error { return errors.New("foo") } + + return mod + }(), + expectErr: true, + }, + { + instance: func() interface{} { + mod := struct{ ProtoValidator }{} + mod.descriptor = func() ModuleDescriptor { + return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} + } + mod.validate = func() error { return nil } + + return mod + }(), + }, + } { + + ctx := NewContext(ParsedFlags{}, nil) + err := ctx.loadModule("foo", tc.instance) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} diff --git a/pkg/gotenberg/doc.go b/pkg/gotenberg/doc.go new file mode 100644 index 00000000..100ea8f6 --- /dev/null +++ b/pkg/gotenberg/doc.go @@ -0,0 +1,7 @@ +// Package gotenberg provides most of the logic of the module system. +// +// caddyserver/caddy, licensed under the Apache License 2.0, has significantly +// inspired this module system. +// +// More details are available on https://caddyserver.com/. +package gotenberg diff --git a/pkg/gotenberg/flags.go b/pkg/gotenberg/flags.go new file mode 100644 index 00000000..18243139 --- /dev/null +++ b/pkg/gotenberg/flags.go @@ -0,0 +1,109 @@ +package gotenberg + +import ( + "regexp" + "time" + + "github.com/labstack/gommon/bytes" + flag "github.com/spf13/pflag" +) + +// ParsedFlags wraps a flag.FlagSet so that retrieving the typed values is +// easier. +type ParsedFlags struct { + *flag.FlagSet +} + +// MustString returns the string value of a flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustString(name string) string { + val, err := f.GetString(name) + if err != nil { + panic(err) + } + + return val +} + +// MustStringSlice returns the string slice value of a flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustStringSlice(name string) []string { + val, err := f.GetStringSlice(name) + if err != nil { + panic(err) + } + + return val +} + +// MustBool returns the boolean value of a flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustBool(name string) bool { + val, err := f.GetBool(name) + if err != nil { + panic(err) + } + + return val +} + +// MustInt returns the int value of a flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustInt(name string) int { + val, err := f.GetInt(name) + if err != nil { + panic(err) + } + + return val +} + +// MustFloat64 returns the float value of a flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustFloat64(name string) float64 { + val, err := f.GetFloat64(name) + if err != nil { + panic(err) + } + + return val +} + +// MustDuration returns the time.Duration value of a flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustDuration(name string) time.Duration { + val, err := f.GetDuration(name) + if err != nil { + panic(err) + } + + return val +} + +// MustHumanReadableBytesString returns the human-readable bytes string of a +// flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustHumanReadableBytesString(name string) string { + val, err := f.GetString(name) + if err != nil { + panic(err) + } + + _, err = bytes.Parse(val) + if err != nil { + panic(err) + } + + return val +} + +// MustRegexp returns the regular expression of a flag given by name. +// It panics if an error occurs. +func (f *ParsedFlags) MustRegexp(name string) *regexp.Regexp { + val, err := f.GetString(name) + if err != nil { + panic(err) + } + + return regexp.MustCompile(val) +} diff --git a/pkg/gotenberg/flags_test.go b/pkg/gotenberg/flags_test.go new file mode 100644 index 00000000..942ec37d --- /dev/null +++ b/pkg/gotenberg/flags_test.go @@ -0,0 +1,378 @@ +package gotenberg + +import ( + "testing" + "time" + + flag "github.com/spf13/pflag" +) + +func TestParsedFlags_MustString(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.String("foo", "", "") + + err := fs.Parse([]string{"--foo=foo"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustString(tc.name) + }() + } +} + +func TestParsedFlags_MustStringSlice(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.StringSlice("foo", make([]string, 0), "") + + err := fs.Parse([]string{"--foo=foo", "--foo=bar", "--foo=baz"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustStringSlice(tc.name) + }() + } +} + +func TestParsedFlags_MustBool(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Bool("foo", false, "") + + err := fs.Parse([]string{"--foo=true"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustBool(tc.name) + }() + } +} + +func TestParsedFlags_MustInt(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Int("foo", 0, "") + + err := fs.Parse([]string{"--foo=1"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustInt(tc.name) + }() + } +} + +func TestParsedFlags_MustFloat64(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Float64("foo", 1.0, "") + + err := fs.Parse([]string{"--foo=2.0"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustFloat64(tc.name) + }() + } +} + +func TestParsedFlags_MustDuration(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Duration("foo", time.Duration(1)*time.Second, "") + + err := fs.Parse([]string{"--foo=2m"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustDuration(tc.name) + }() + } +} + +func TestParsedFlags_MustHumanReadableBytesString(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.String("foo", "1MB", "") + fs.String("bar", "1MB", "") + + err := fs.Parse([]string{"--foo=1GB", "--bar=foo"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + { + name: "baz", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustHumanReadableBytesString(tc.name) + }() + } +} + +func TestParsedFlags_MustRegexp(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.String("foo", "", "") + fs.String("bar", "", "") + + err := fs.Parse([]string{"--foo=", "--bar=*"}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + parsedFlags := ParsedFlags{FlagSet: fs} + + for i, tc := range []struct { + name string + expectPanic bool + }{ + { + name: "foo", + }, + { + name: "bar", + expectPanic: true, + }, + { + name: "baz", + expectPanic: true, + }, + } { + func() { + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + parsedFlags.MustRegexp(tc.name) + }() + } +} diff --git a/pkg/gotenberg/fs.go b/pkg/gotenberg/fs.go new file mode 100644 index 00000000..b54fc229 --- /dev/null +++ b/pkg/gotenberg/fs.go @@ -0,0 +1,33 @@ +package gotenberg + +import ( + "fmt" + "os" + + "github.com/google/uuid" +) + +// TmpPath returns the default directory to use for temporary files and +// directories. Most if not all files and directories created by the +// application and its dependencies must be based on this default directory. +func TmpPath() string { + return os.TempDir() +} + +// NewDirPath returns a random absolute path based on the temporary path. +func NewDirPath() string { + return fmt.Sprintf("%s/%s", TmpPath(), uuid.New()) +} + +// MkdirAll creates a random directory based on the temporary path and +// returns its absolute path. +func MkdirAll() (string, error) { + path := NewDirPath() + + err := os.MkdirAll(path, 0755) + if err != nil { + return "", fmt.Errorf("create directory %s: %w", path, err) + } + + return path, nil +} diff --git a/pkg/gotenberg/fs_test.go b/pkg/gotenberg/fs_test.go new file mode 100644 index 00000000..5c9acb90 --- /dev/null +++ b/pkg/gotenberg/fs_test.go @@ -0,0 +1,59 @@ +package gotenberg + +import ( + "os" + "strings" + "testing" +) + +func TestTmpPath(t *testing.T) { + osTempDir := os.TempDir() + tmpPath := TmpPath() + + if tmpPath != osTempDir { + t.Errorf("expected path '%s' but got '%s'", osTempDir, tmpPath) + } +} + +func TestNewDirPath(t *testing.T) { + newDirPath := NewDirPath() + tmpPath := TmpPath() + + if !strings.HasPrefix(newDirPath, tmpPath) { + t.Fatalf("expected path '%s' to start with '%s'", newDirPath, tmpPath) + } + + newDirPaths := make([]string, 1000) + for i := range newDirPaths { + newDirPaths[i] = NewDirPath() + } + + for i, newDirPath := range newDirPaths { + for j, comparison := range newDirPaths { + if i == j { + continue + } + + if newDirPath == comparison { + t.Fatalf("expected path '%s' (index %d) to be unique, but found an identical path on index %d", newDirPath, i, j) + } + } + } +} + +func TestMkdirAll(t *testing.T) { + path, err := MkdirAll() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + tmpPath := TmpPath() + if !strings.HasPrefix(path, tmpPath) { + t.Fatalf("expected path '%s' to start with '%s'", path, tmpPath) + } + + _, err = os.Stat(path) + if os.IsNotExist(err) { + t.Errorf("expected path '%s' to exist but got: %v", path, err) + } +} diff --git a/pkg/gotenberg/logging.go b/pkg/gotenberg/logging.go new file mode 100644 index 00000000..37a39da1 --- /dev/null +++ b/pkg/gotenberg/logging.go @@ -0,0 +1,14 @@ +package gotenberg + +import "go.uber.org/zap" + +// LoggerProvider is a module interface which exposes a method for creating a +// zap.Logger for other modules. +// +// func (m *YourModule) Provision(ctx *gotenberg.Context) error { +// provider, _ := ctx.Module(new(gotenberg.LoggerProvider)) +// logger, _ := provider.(gotenberg.LoggerProvider).Logger(m) +// } +type LoggerProvider interface { + Logger(mod Module) (*zap.Logger, error) +} diff --git a/pkg/gotenberg/modules.go b/pkg/gotenberg/modules.go new file mode 100644 index 00000000..8c483611 --- /dev/null +++ b/pkg/gotenberg/modules.go @@ -0,0 +1,135 @@ +package gotenberg + +import ( + "context" + "fmt" + "sort" + "sync" + + flag "github.com/spf13/pflag" +) + +// Module is a sort of plugin which adds new functionalities to the application +// or other modules. +// +// type YourModule struct { +// property string +// } +// +// func (YourModule) Descriptor() gotenberg.ModuleDescriptor { +// return gotenberg.ModuleDescriptor{ +// ID: "your_module", +// FlagSet: func() *flag.FlagSet { +// fs := flag.NewFlagSet("your_module", flag.ExitOnError) +// fs.String("your_module-property", "default value", "flag description") +// +// return fs +// }(), +// New: func() gotenberg.Module { return new(YourModule) }, +// } +// } +type Module interface { + Descriptor() ModuleDescriptor +} + +// ModuleDescriptor describes your module for the application. +type ModuleDescriptor struct { + // ID is the unique name (snake case) of the module. + // Required. + ID string + + // FlagSet is the definition of the flags of the module. + // Optional. + FlagSet *flag.FlagSet + + // New returns a new and empty instance of the module's type. + // Required. + New func() Module +} + +// Provisioner is a module interface for modules which have to be initialized +// according to flags, environment variables, the context, etc. +type Provisioner interface { + Provision(*Context) error +} + +// Validator is a module interface for modules which have to be validated after +// provisioning. +type Validator interface { + Validate() error +} + +// App is a module interface for modules which can be started or stopped by the +// application. +type App interface { + Start() error + // StartupMessage returns a custom message to display on startup. If it + // returns an empty string, a default startup message is used instead. + StartupMessage() string + Stop(ctx context.Context) error +} + +// MustRegisterModule registers a module. +// +// To register a module, create an init() method in the module main go file: +// +// func init() { +// gotenberg.MustRegisterModule(YourModule{}) +// } +// +// Then, in the main command (github.com/gotenberg/gotenberg/v7/cmd/gotenberg), +// import the module: +// +// imports ( +// // Gotenberg modules. +// _ "your_module_path" +// ) +func MustRegisterModule(mod Module) { + desc := mod.Descriptor() + + if desc.ID == "" { + panic("module with an empty ID cannot be registered") + } + + if desc.New == nil { + panic("module New function cannot be nil") + } + + if val := desc.New(); val == nil { + panic("module New function cannot return a nil instance") + } + + descriptorsMu.Lock() + defer descriptorsMu.Unlock() + + if _, ok := descriptors[desc.ID]; ok { + panic(fmt.Sprintf("module %s is already registered", desc.ID)) + } + + descriptors[desc.ID] = desc +} + +// GetModuleDescriptors returns the descriptors of all registered modules. +func GetModuleDescriptors() []ModuleDescriptor { + descriptorsMu.RLock() + defer descriptorsMu.RUnlock() + + mods := make([]ModuleDescriptor, len(descriptors)) + i := 0 + + for _, desc := range descriptors { + mods[i] = desc + i++ + } + + sort.Slice(mods, func(i, j int) bool { + return mods[i].ID < mods[j].ID + }) + + return mods +} + +var ( + descriptors = make(map[string]ModuleDescriptor) + descriptorsMu sync.RWMutex +) diff --git a/pkg/gotenberg/modules_test.go b/pkg/gotenberg/modules_test.go new file mode 100644 index 00000000..725e2045 --- /dev/null +++ b/pkg/gotenberg/modules_test.go @@ -0,0 +1,135 @@ +package gotenberg + +import ( + "reflect" + "testing" +) + +type ProtoModule struct { + descriptor func() ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() ModuleDescriptor { + return mod.descriptor() +} + +type ProtoProvisioner struct { + ProtoModule + provision func(ctx *Context) error +} + +func (mod ProtoProvisioner) Provision(ctx *Context) error { + return mod.provision(ctx) +} + +type ProtoValidator struct { + ProtoModule + validate func() error +} + +func (mod ProtoValidator) Validate() error { + return mod.validate() +} + +func TestMustRegisterModule(t *testing.T) { + descriptorsMu.RLock() + descriptors = map[string]ModuleDescriptor{ + "a": {ID: "a"}, + } + descriptorsMu.RUnlock() + + for i, tc := range []struct { + ID string + New func() Module + expectPanic bool + }{ + { + ID: "", + New: func() Module { return new(ProtoModule) }, + expectPanic: true, + }, + { + ID: "b", + New: nil, + expectPanic: true, + }, + { + ID: "b", + New: func() Module { return nil }, + expectPanic: true, + }, + { + ID: "a", + New: func() Module { return new(ProtoModule) }, + expectPanic: true, + }, + { + ID: "b", + New: func() Module { return new(ProtoModule) }, + }, + } { + func() { + mod := struct{ ProtoModule }{} + mod.descriptor = func() ModuleDescriptor { return ModuleDescriptor{ID: tc.ID, New: tc.New} } + + if tc.expectPanic { + defer func() { + if r := recover(); r == nil { + t.Errorf("test %d: expected panic but got none", i) + } + }() + } + + if !tc.expectPanic { + defer func() { + if r := recover(); r != nil { + t.Errorf("test %d: expected no panic but got: %v", i, r) + } + }() + } + + MustRegisterModule(mod) + }() + } + + descriptorsMu.RLock() + descriptors = make(map[string]ModuleDescriptor) + descriptorsMu.RUnlock() +} + +func TestGetModuleDescriptors(t *testing.T) { + descriptorsMu.RLock() + descriptors = map[string]ModuleDescriptor{ + "d": {ID: "d"}, + "c": {ID: "c"}, + "b": {ID: "b"}, + "a": {ID: "a"}, + } + descriptorsMu.RUnlock() + + expect := []ModuleDescriptor{ + {ID: "a"}, + {ID: "b"}, + {ID: "c"}, + {ID: "d"}, + } + + actual := GetModuleDescriptors() + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %v but got %v", expect, actual) + } + + descriptorsMu.RLock() + descriptors = make(map[string]ModuleDescriptor) + descriptorsMu.RUnlock() +} + +// Interface guards. +var ( + _ Module = (*ProtoModule)(nil) + _ Provisioner = (*ProtoProvisioner)(nil) + _ Module = (*ProtoProvisioner)(nil) + _ Validator = (*ProtoValidator)(nil) + _ Module = (*ProtoValidator)(nil) +) diff --git a/pkg/gotenberg/pdfengine.go b/pkg/gotenberg/pdfengine.go new file mode 100644 index 00000000..be84109c --- /dev/null +++ b/pkg/gotenberg/pdfengine.go @@ -0,0 +1,52 @@ +package gotenberg + +import ( + "context" + "errors" + + "go.uber.org/zap" +) + +var ( + // ErrPDFEngineMethodNotAvailable happens if a PDFEngine method is not + // available in the implementation. + ErrPDFEngineMethodNotAvailable = errors.New("method not available") + + // ErrPDFFormatNotAvailable happens if a PDFEngine Convert's method does + // not handle a specific format. + ErrPDFFormatNotAvailable = errors.New("PDF format not available") +) + +const ( + FormatPDFA1a string = "PDF/A-1a" + FormatPDFA1b string = "PDF/A-1b" + FormatPDFA2a string = "PDF/A-2a" + FormatPDFA2b string = "PDF/A-2b" + FormatPDFA2u string = "PDF/A-2u" + FormatPDFA3a string = "PDF/A-3a" + FormatPDFA3b string = "PDF/A-3b" + FormatPDFA3u string = "PDF/A-3u" +) + +// PDFEngine is a module interface which exposes methods for manipulating one +// or more PDFs. Implementations may abstract powerful tools like PDFtk, or +// fulfill those methods contracts in Golang directly. +type PDFEngine interface { + // Merge merges the given PDFs into a unique PDF. The pages' order reflects + // order of the given files. + Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error + + // Convert converts the given PDF to a specific PDF format. + Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error +} + +// PDFEngineProvider is a module interface which exposes a method for creating a +// PDFEngine for other modules. +// +// func (m *YourModule) Provision(ctx *gotenberg.Context) error { +// provider, _ := ctx.Module(new(gotenberg.PDFEngineProvider)) +// pdfengines, _ := provider.(gotenberg.PDFEngineProvider).PDFEngine() +// } +type PDFEngineProvider interface { + PDFEngine() (PDFEngine, error) +} diff --git a/pkg/modules/api/api.go b/pkg/modules/api/api.go new file mode 100644 index 00000000..816be41a --- /dev/null +++ b/pkg/modules/api/api.go @@ -0,0 +1,494 @@ +package api + +import ( + "context" + "errors" + "fmt" + "net/http" + "os" + "regexp" + "sort" + "strconv" + "strings" + "time" + + "github.com/alexliesenfeld/health" + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/gc" + "github.com/labstack/echo/v4" + flag "github.com/spf13/pflag" + "go.uber.org/multierr" + "go.uber.org/zap" +) + +func init() { + gotenberg.MustRegisterModule(API{}) +} + +// API is a module which provides an HTTP server. Other modules may add +// "multipart/form-data" routes, middlewares or health checks. +type API struct { + port int + readTimeout time.Duration + processTimeout time.Duration + writeTimeout time.Duration + rootPath string + traceHeader string + disableHealthCheckLogging bool + webhookAllowList *regexp.Regexp + webhookDenyList *regexp.Regexp + webhookErrorAllowList *regexp.Regexp + webhookErrorDenyList *regexp.Regexp + webhookMaxRetry int + webhookRetryMinWait time.Duration + webhookRetryMaxWait time.Duration + disableWebhook bool + + multipartFormDataRoutes []MultipartFormDataRoute + externalMiddlewares []Middleware + healthChecks []health.CheckerOption + logger *zap.Logger + srv *echo.Echo +} + +// MultipartFormDataRouter is a module interface which adds +// "multipart/form-data" routes to the API. +type MultipartFormDataRouter interface { + Routes() ([]MultipartFormDataRoute, error) +} + +// MultipartFormDataRoute represents a "multipart/form-data" route. All routes +// uses the HTTP POST method. +type MultipartFormDataRoute struct { + // Path is the sub path of the route. Must start with a slash. + // Required. + Path string + + // Handler is the function which handles the request. + // Required. + Handler func(ctx *Context) error +} + +// MiddlewareProvider is a module interface which adds middlewares to the API. +type MiddlewareProvider interface { + Middlewares() ([]Middleware, error) +} + +// MiddlewarePriority is a type which helps to determine the execution order of +// middlewares provided by the MiddlewareProvider modules. +type MiddlewarePriority uint32 + +const ( + VeryLowPriority MiddlewarePriority = iota + LowPriority + MediumPriority + HighPriority + VeryHighPriority +) + +// Middleware is a middleware which can be added to the API's middlewares +// chain. +// +// middleware := &Middleware{ +// Handler: func() echo.MiddlewareFunc { +// return func(next echo.HandlerFunc) echo.HandlerFunc { +// return func(c echo.Context) error { +// rootPath := c.Get("rootPath").(string) +// healthURI := fmt.Sprintf("%shealth", rootPath) +// +// // Skip the middleware if health check URI. +// if c.Request().RequestURI == healthURI { +// // Call the next middleware in the chain. +// return next(c) +// } +// +// // Your middleware process. +// // ... +// +// // Call the next middleware in the chain. +// return next(c) +// } +// } +// }(), +// } +type Middleware struct { + // RunBeforeRouter tells if the middleware should run before the router + // process an HTTP request. + // Optional. + RunBeforeRouter bool + + // Priority tells if the middleware should be positioned high or not in + // the middlewares chain. + // Default to VeryLowPriority. + // Optional. + Priority MiddlewarePriority + + // Handler is the function of the middleware. + // Required. + Handler echo.MiddlewareFunc +} + +// HealthChecker is a module interface which allows adding health checks to the +// API. +// +// See https://github.com/alexliesenfeld/health for more details. +type HealthChecker interface { + Checks() ([]health.CheckerOption, error) +} + +// Descriptor returns an API's module descriptor. +func (API) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "api", + FlagSet: func() *flag.FlagSet { + fs := flag.NewFlagSet("api", flag.ExitOnError) + fs.Int("api-port", 3000, "Set the port on which the API should listen") + fs.String("api-port-from-env", "", "Set the environment variable with the port on which the API should listen - override the default port") + fs.Duration("api-read-timeout", time.Duration(30)*time.Second, "Set the maximum duration allowed to read a complete request, including the body") + fs.Duration("api-process-timeout", time.Duration(30)*time.Second, "Set the maximum duration allowed to process a request") + fs.Duration("api-write-timeout", time.Duration(30)*time.Second, "Set the maximum duration before timing out writes of the response") + fs.String("api-root-path", "/", "Set the root path of the API - for service discovery via URL paths") + fs.String("api-trace-header", "Gotenberg-Trace", "Set the header name to use for identifying requests") + fs.Bool("api-disable-health-check-logging", false, "Disable health check logging") + fs.String("api-webhook-allow-list", "", "Set the allowed URLs for the webhook feature using a regular expression") + fs.String("api-webhook-deny-list", "", "Set the denied URLs for the webhook feature using a regular expression") + fs.String("api-webhook-error-allow-list", "", "Set the allowed URLs in case of an error for the webhook feature using a regular expression") + fs.String("api-webhook-error-deny-list", "", "Set the denied URLs in case of an error for the webhook feature using a regular expression") + fs.Int("api-webhook-max-retry", 4, "Set the maximum number of retries for the webhook feature") + fs.Duration("api-webhook-retry-min-wait", time.Duration(1)*time.Second, "Set the minimum duration to wait before trying to call the webhook again") + fs.Duration("api-webhook-retry-max-wait", time.Duration(30)*time.Second, "Set the maximum duration to wait before trying to call the webhook again") + fs.Bool("api-disable-webhook", false, "Disable the webhook feature") + + return fs + }(), + New: func() gotenberg.Module { return new(API) }, + } +} + +// Provision sets the module properties. +func (a *API) Provision(ctx *gotenberg.Context) error { + flags := ctx.ParsedFlags() + a.port = flags.MustInt("api-port") + a.readTimeout = flags.MustDuration("api-read-timeout") + a.processTimeout = flags.MustDuration("api-process-timeout") + a.writeTimeout = flags.MustDuration("api-write-timeout") + a.rootPath = flags.MustString("api-root-path") + a.traceHeader = flags.MustString("api-trace-header") + a.disableHealthCheckLogging = flags.MustBool("api-disable-health-check-logging") + a.webhookAllowList = flags.MustRegexp("api-webhook-allow-list") + a.webhookDenyList = flags.MustRegexp("api-webhook-deny-list") + a.webhookErrorAllowList = flags.MustRegexp("api-webhook-error-allow-list") + a.webhookErrorDenyList = flags.MustRegexp("api-webhook-error-deny-list") + a.webhookMaxRetry = flags.MustInt("api-webhook-max-retry") + a.webhookRetryMinWait = flags.MustDuration("api-webhook-retry-min-wait") + a.webhookRetryMaxWait = flags.MustDuration("api-webhook-retry-max-wait") + a.disableWebhook = flags.MustBool("api-disable-webhook") + + // Port from env? + portEnvVar := flags.MustString("api-port-from-env") + if portEnvVar != "" { + val, ok := os.LookupEnv(portEnvVar) + + if !ok { + return fmt.Errorf("environment variable '%s' does not exist", portEnvVar) + } + + if val == "" { + return fmt.Errorf("environment variable '%s' is empty", portEnvVar) + } + + port, err := strconv.Atoi(val) + if err != nil { + return fmt.Errorf("get int value of environment variable '%s': %w", portEnvVar, err) + } + + a.port = port + } + + // Get routes from modules. + mods, err := ctx.Modules(new(MultipartFormDataRouter)) + if err != nil { + return fmt.Errorf("get multipart/form-data routers: %w", err) + } + + routers := make([]MultipartFormDataRouter, len(mods)) + for i, router := range mods { + routers[i] = router.(MultipartFormDataRouter) + } + + for _, router := range routers { + routes, err := router.Routes() + if err != nil { + return fmt.Errorf("get routes: %w", err) + } + + a.multipartFormDataRoutes = append(a.multipartFormDataRoutes, routes...) + } + + // Get middlewares from modules. + mods, err = ctx.Modules(new(MiddlewareProvider)) + if err != nil { + return fmt.Errorf("get middleware providers: %w", err) + } + + middlewareProviders := make([]MiddlewareProvider, len(mods)) + for i, middlewareProvider := range mods { + middlewareProviders[i] = middlewareProvider.(MiddlewareProvider) + } + + for _, middlewareProvider := range middlewareProviders { + middlewares, err := middlewareProvider.Middlewares() + if err != nil { + return fmt.Errorf("get middlewares: %w", err) + } + + a.externalMiddlewares = append(a.externalMiddlewares, middlewares...) + } + + // Sort middlewares by priority. + sort.Slice(a.externalMiddlewares, func(i, j int) bool { + return a.externalMiddlewares[i].Priority > a.externalMiddlewares[j].Priority + }) + + // Get health checks from modules. + mods, err = ctx.Modules(new(HealthChecker)) + if err != nil { + return fmt.Errorf("get health checkers: %w", err) + } + + healthCheckers := make([]HealthChecker, len(mods)) + for i, healthChecker := range mods { + healthCheckers[i] = healthChecker.(HealthChecker) + } + + for _, healthChecker := range healthCheckers { + checks, err := healthChecker.Checks() + if err != nil { + return fmt.Errorf("get health checks: %w", err) + } + + a.healthChecks = append(a.healthChecks, checks...) + } + + loggerProvider, err := ctx.Module(new(gotenberg.LoggerProvider)) + if err != nil { + return fmt.Errorf("get logger provider: %w", err) + } + + logger, err := loggerProvider.(gotenberg.LoggerProvider).Logger(a) + if err != nil { + return fmt.Errorf("get logger: %w", err) + } + + a.logger = logger + + return nil +} + +// Validate validates the module properties. +func (a API) Validate() error { + var err error + + if a.port < 1 || a.port > 65535 { + err = multierr.Append(err, + errors.New("port must be more than 1 and less than 65535"), + ) + } + + if !strings.HasPrefix(a.rootPath, "/") { + err = multierr.Append(err, + errors.New("root path must start with /"), + ) + } + + if !strings.HasSuffix(a.rootPath, "/") { + err = multierr.Append(err, + errors.New("root path must end with /"), + ) + } + + if len(strings.TrimSpace(a.traceHeader)) == 0 { + err = multierr.Append(err, + errors.New("trace header must not be empty"), + ) + } + + if err != nil { + return err + } + + routesMap := make(map[string]MultipartFormDataRoute, len(a.multipartFormDataRoutes)) + + for _, route := range a.multipartFormDataRoutes { + if route.Path == "" { + return errors.New("route with empty path cannot be registered") + } + + if !strings.HasPrefix(route.Path, "/") { + return fmt.Errorf("route %s does not start with /", route.Path) + } + + if route.Handler == nil { + return fmt.Errorf("route %s has a nil handler", route.Path) + } + + if _, ok := routesMap[route.Path]; ok { + return fmt.Errorf("route %s is already registered", route.Path) + } + + routesMap[route.Path] = route + } + + for _, middleware := range a.externalMiddlewares { + if middleware.Handler == nil { + return errors.New("a middleware has a nil handler") + } + } + + return nil +} + +// Start starts the HTTP server. +func (a *API) Start() error { + a.srv = echo.New() + a.srv.HideBanner = true + a.srv.HidePort = true + a.srv.Server.ReadTimeout = a.readTimeout + a.srv.Server.WriteTimeout = a.writeTimeout + a.srv.HTTPErrorHandler = httpErrorHandler(a.traceHeader) + + a.srv.Pre( + latencyMiddleware(), + rootPathMiddleware(a.rootPath), + traceMiddleware(a.traceHeader), + loggerMiddleware(a.logger, a.disableHealthCheckLogging), + ) + + for _, externalMiddleware := range a.externalMiddlewares { + if externalMiddleware.RunBeforeRouter { + a.srv.Pre(externalMiddleware.Handler) + + continue + } + + a.srv.Use(externalMiddleware.Handler) + } + + hardTimeout := a.processTimeout + (time.Duration(5) * time.Second) + + a.srv.GET( + fmt.Sprintf("%shealth", a.rootPath), + func() echo.HandlerFunc { + checks := append(a.healthChecks, health.WithTimeout(a.processTimeout)) + checker := health.NewChecker(checks...) + + return func(echoCtx echo.Context) error { + health.NewHandler(checker).ServeHTTP(echoCtx.Response().Writer, echoCtx.Request()) + + return nil + } + }(), + timeoutMiddleware(hardTimeout), + ) + + formsGroup := a.srv.Group( + fmt.Sprintf("%sforms", a.rootPath), + contextMiddleware( + contextMiddlewareConfig{ + traceHeader: a.traceHeader, + timeout: struct { + process time.Duration + write time.Duration + }{ + process: a.processTimeout, + write: a.writeTimeout, + }, + webhook: struct { + allowList *regexp.Regexp + denyList *regexp.Regexp + errorAllowList *regexp.Regexp + errorDenyList *regexp.Regexp + maxRetry int + retryMinWait time.Duration + retryMaxWait time.Duration + disable bool + }{ + allowList: a.webhookAllowList, + denyList: a.webhookDenyList, + errorAllowList: a.webhookErrorAllowList, + errorDenyList: a.webhookErrorDenyList, + maxRetry: a.webhookMaxRetry, + retryMinWait: a.webhookRetryMinWait, + retryMaxWait: a.webhookRetryMaxWait, + disable: a.disableWebhook, + }, + }, + ), + timeoutMiddleware(hardTimeout), + ) + + // Add routes from other modules. + for _, route := range a.multipartFormDataRoutes { + formsGroup.POST( + route.Path, + func(route MultipartFormDataRoute) echo.HandlerFunc { + return func(c echo.Context) error { + ctx := c.Get("context").(*Context) + + err := route.Handler(ctx) + if err != nil { + return fmt.Errorf("handle request: %w", err) + } + + return nil + } + }(route), + ) + } + + // As the listen method is blocking, run it in a goroutine. + go func() { + err := a.srv.Start(fmt.Sprintf(":%d", a.port)) + if !errors.Is(err, http.ErrServerClosed) { + a.logger.Fatal(err.Error()) + } + }() + + return nil +} + +// StartupMessage returns a custom startup message. +func (a API) StartupMessage() string { + return fmt.Sprintf("server listening on port %d", a.port) +} + +// Stop stops the HTTP server. +func (a API) Stop(ctx context.Context) error { + return a.srv.Shutdown(ctx) +} + +// GraceDuration updates the expiration time of files and directories parsed by +// the gc.GarbageCollector. +func (a API) GraceDuration() time.Duration { + duration := a.readTimeout + a.processTimeout + a.writeTimeout + + if a.disableWebhook { + return duration + } + + for i := 0; i < a.webhookMaxRetry; i++ { + // Yep... Golang does not allow int * time.Duration. + duration += a.webhookRetryMaxWait + } + + return duration +} + +// Interface guards. +var ( + _ gotenberg.Module = (*API)(nil) + _ gotenberg.Provisioner = (*API)(nil) + _ gotenberg.Validator = (*API)(nil) + _ gotenberg.App = (*API)(nil) + _ gc.GarbageCollectorGraceDurationModifier = (*API)(nil) +) diff --git a/pkg/modules/api/api_test.go b/pkg/modules/api/api_test.go new file mode 100644 index 00000000..e242bc3b --- /dev/null +++ b/pkg/modules/api/api_test.go @@ -0,0 +1,793 @@ +package api + +import ( + "bytes" + "context" + "errors" + "mime/multipart" + "net/http" + "net/http/httptest" + "os" + "reflect" + "testing" + "time" + + "github.com/alexliesenfeld/health" + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/labstack/echo/v4" + "go.uber.org/zap" +) + +type ProtoModule struct { + descriptor func() gotenberg.ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() gotenberg.ModuleDescriptor { + return mod.descriptor() +} + +type ProtoValidator struct { + ProtoModule + validate func() error +} + +func (mod ProtoValidator) Validate() error { + return mod.validate() +} + +type ProtoMultipartFormDataRouter struct { + ProtoValidator + routes func() ([]MultipartFormDataRoute, error) +} + +func (mod ProtoMultipartFormDataRouter) Routes() ([]MultipartFormDataRoute, error) { + return mod.routes() +} + +type ProtoMiddlewareProvider struct { + ProtoValidator + middlewares func() ([]Middleware, error) +} + +func (mod ProtoMiddlewareProvider) Middlewares() ([]Middleware, error) { + return mod.middlewares() +} + +type ProtoHealthChecker struct { + ProtoValidator + checks func() ([]health.CheckerOption, error) +} + +func (mod ProtoHealthChecker) Checks() ([]health.CheckerOption, error) { + return mod.checks() +} + +type ProtoLoggerProvider struct { + ProtoModule + logger func(mod gotenberg.Module) (*zap.Logger, error) +} + +func (factory ProtoLoggerProvider) Logger(mod gotenberg.Module) (*zap.Logger, error) { + return factory.logger(mod) +} + +func TestAPI_Descriptor(t *testing.T) { + descriptor := API{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(API)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestAPI_Provision(t *testing.T) { + for i, tc := range []struct { + ctx *gotenberg.Context + setEnv func(i int) + expectPort int + expectMiddlewares []Middleware + expectErr bool + }{ + { + ctx: func() *gotenberg.Context { + fs := new(API).Descriptor().FlagSet + err := fs.Parse([]string{"--api-port-from-env=FOO"}) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: fs, + }, + nil, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + fs := new(API).Descriptor().FlagSet + err := fs.Parse([]string{"--api-port-from-env=PORT"}) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: fs, + }, + nil, + ) + }(), + setEnv: func(i int) { + err := os.Setenv("PORT", "") + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }, + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + fs := new(API).Descriptor().FlagSet + err := fs.Parse([]string{"--api-port-from-env=PORT"}) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: fs, + }, + nil, + ) + }(), + setEnv: func(i int) { + err := os.Setenv("PORT", "foo") + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }, + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + fs := new(API).Descriptor().FlagSet + err := fs.Parse([]string{"--api-port-from-env=PORT"}) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: fs, + }, + nil, + ) + }(), + setEnv: func(i int) { + err := os.Setenv("PORT", "1337") + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }, + expectPort: 1337, + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoMultipartFormDataRouter }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { + return errors.New("foo") + } + mod.routes = func() ([]MultipartFormDataRoute, error) { + return nil, nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoMiddlewareProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { + return errors.New("foo") + } + mod.middlewares = func() ([]Middleware, error) { + return nil, nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoMiddlewareProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { + return nil + } + mod.middlewares = func() ([]Middleware, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoMultipartFormDataRouter }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { + return nil + } + mod.routes = func() ([]MultipartFormDataRoute, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoHealthChecker }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { + return errors.New("foo") + } + mod.checks = func() ([]health.CheckerOption, error) { + return nil, nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoHealthChecker }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { + return nil + } + mod.checks = func() ([]health.CheckerOption, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{}, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoLoggerProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.logger = func(_ gotenberg.Module) (*zap.Logger, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod1 := struct{ ProtoMultipartFormDataRouter }{} + mod1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod1 }} + } + mod1.validate = func() error { + return nil + } + mod1.routes = func() ([]MultipartFormDataRoute, error) { + return []MultipartFormDataRoute{{}}, nil + } + + mod2 := struct{ ProtoMiddlewareProvider }{} + mod2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod2 }} + } + mod2.validate = func() error { + return nil + } + mod2.middlewares = func() ([]Middleware, error) { + return []Middleware{ + { + Priority: VeryLowPriority, + }, + { + Priority: LowPriority, + }, + { + Priority: MediumPriority, + }, + { + Priority: HighPriority, + }, + { + Priority: VeryHighPriority, + }, + }, nil + } + + mod3 := struct{ ProtoHealthChecker }{} + mod3.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "baz", New: func() gotenberg.Module { return mod3 }} + } + mod3.validate = func() error { + return nil + } + mod3.checks = func() ([]health.CheckerOption, error) { + return []health.CheckerOption{health.WithDisabledAutostart()}, nil + } + + mod4 := struct{ ProtoLoggerProvider }{} + mod4.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "qux", New: func() gotenberg.Module { return mod4 }} + } + mod4.logger = func(_ gotenberg.Module) (*zap.Logger, error) { + return zap.NewNop(), nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(API).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod1.Descriptor(), + mod2.Descriptor(), + mod3.Descriptor(), + mod4.Descriptor(), + }, + ) + }(), + expectMiddlewares: []Middleware{ + { + Priority: VeryHighPriority, + }, + { + Priority: HighPriority, + }, + { + Priority: MediumPriority, + }, + { + Priority: LowPriority, + }, + { + Priority: VeryLowPriority, + }, + }, + }, + } { + if tc.setEnv != nil { + tc.setEnv(i) + } + + mod := new(API) + err := mod.Provision(tc.ctx) + + if tc.expectPort != 0 && mod.port != tc.expectPort { + t.Errorf("expected port %d but got %d", tc.expectPort, mod.port) + } + + if !reflect.DeepEqual(mod.externalMiddlewares, tc.expectMiddlewares) { + t.Errorf("expected %+v, but got: %+v", tc.expectMiddlewares, mod.externalMiddlewares) + } + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestAPI_Validate(t *testing.T) { + for i, tc := range []struct { + port int + rootPath string + traceHeader string + routes []MultipartFormDataRoute + middlewares []Middleware + expectErr bool + }{ + { + port: 0, + expectErr: true, + }, + { + port: 65536, + rootPath: "foo", + expectErr: true, + }, + { + port: 10, + rootPath: "/foo/", + traceHeader: "foo", + routes: []MultipartFormDataRoute{ + { + Path: "", + }, + }, + expectErr: true, + }, + { + port: 10, + rootPath: "/foo/", + traceHeader: "foo", + routes: []MultipartFormDataRoute{ + { + Path: "foo", + }, + }, + expectErr: true, + }, + { + port: 10, + rootPath: "/foo/", + traceHeader: "foo", + routes: []MultipartFormDataRoute{ + { + Path: "/foo", + }, + }, + expectErr: true, + }, + { + port: 10, + rootPath: "/foo/", + traceHeader: "foo", + routes: []MultipartFormDataRoute{ + { + Path: "/foo", + Handler: func(_ *Context) error { return nil }, + }, + { + Path: "/foo", + Handler: func(_ *Context) error { return nil }, + }, + }, + expectErr: true, + }, + { + port: 10, + rootPath: "/foo/", + traceHeader: "foo", + middlewares: []Middleware{ + { + Priority: HighPriority, + }, + }, + expectErr: true, + }, + { + port: 10, + rootPath: "/foo/", + traceHeader: "foo", + routes: []MultipartFormDataRoute{ + { + Path: "/foo", + Handler: func(_ *Context) error { return nil }, + }, + }, + middlewares: []Middleware{ + { + Priority: HighPriority, + Handler: func() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + return next(c) + } + } + }(), + }, + }, + }, + } { + mod := API{ + port: tc.port, + rootPath: tc.rootPath, + traceHeader: tc.traceHeader, + multipartFormDataRoutes: tc.routes, + externalMiddlewares: tc.middlewares, + } + + err := mod.Validate() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestAPI_Start(t *testing.T) { + mod := new(API) + mod.port = 3000 + mod.rootPath = "/" + mod.multipartFormDataRoutes = []MultipartFormDataRoute{ + { + Path: "/foo", + Handler: func(ctx *Context) error { + ctx.outputPaths = []string{ + "/tests/test/testdata/api/sample1.txt", + } + + return nil + }, + }, + { + Path: "/bar", + Handler: func(_ *Context) error { return errors.New("foo") }, + }, + } + mod.externalMiddlewares = []Middleware{ + { + RunBeforeRouter: true, + Handler: func() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + return next(c) + } + } + }(), + }, + { + Handler: func() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + return next(c) + } + } + }(), + }, + } + mod.logger = zap.NewNop() + + err := mod.Start() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + // health request. + recorder := httptest.NewRecorder() + healthRequest := httptest.NewRequest(http.MethodGet, "/health", nil) + + mod.srv.ServeHTTP(recorder, healthRequest) + if recorder.Code != http.StatusOK { + t.Errorf("expected %d status code but got %d", http.StatusOK, recorder.Code) + } + + // "multipart/form-data" request. + multipartRequest := func(URL string) *http.Request { + body := &bytes.Buffer{} + + writer := multipart.NewWriter(body) + + defer func() { + err := writer.Close() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + }() + + err := writer.WriteField("foo", "foo") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + part, err := writer.CreateFormFile("foo.txt", "foo.txt") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + _, err = part.Write([]byte("foo")) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + req := httptest.NewRequest(http.MethodPost, URL, body) + req.Header.Set(echo.HeaderContentType, writer.FormDataContentType()) + + return req + } + + recorder = httptest.NewRecorder() + mod.srv.ServeHTTP(recorder, multipartRequest("/forms/foo")) + + if recorder.Code != http.StatusOK { + t.Errorf("expected %d status code but got %d", http.StatusOK, recorder.Code) + } + + recorder = httptest.NewRecorder() + mod.srv.ServeHTTP(recorder, multipartRequest("/forms/bar")) + + if recorder.Code != http.StatusInternalServerError { + t.Errorf("expected %d status code but got %d", http.StatusInternalServerError, recorder.Code) + } + + err = mod.srv.Shutdown(context.TODO()) + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestAPI_StartupMessage(t *testing.T) { + mod := API{ + port: 3000, + } + + actual := mod.StartupMessage() + expect := "server listening on port 3000" + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestAPI_Stop(t *testing.T) { + mod := API{ + port: 3000, + multipartFormDataRoutes: []MultipartFormDataRoute{ + { + Path: "/foo", + Handler: func(_ *Context) error { return nil }, + }, + }, + logger: zap.NewNop(), + } + + err := mod.Start() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + err = mod.Stop(context.TODO()) + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestAPI_GraceDuration(t *testing.T) { + for i, tc := range []struct { + mod API + expect time.Duration + }{ + { + mod: API{ + readTimeout: time.Duration(1) * time.Second, + processTimeout: time.Duration(1) * time.Second, + writeTimeout: time.Duration(1) * time.Second, + disableWebhook: true, + }, + expect: time.Duration(3) * time.Second, + }, + { + mod: API{ + readTimeout: time.Duration(1) * time.Second, + processTimeout: time.Duration(1) * time.Second, + writeTimeout: time.Duration(1) * time.Second, + webhookMaxRetry: 5, + webhookRetryMaxWait: time.Duration(5) * time.Second, + }, + expect: time.Duration(28) * time.Second, + }, + } { + actual := tc.mod.GraceDuration() + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*ProtoModule)(nil) + _ gotenberg.Validator = (*ProtoValidator)(nil) + _ gotenberg.Module = (*ProtoValidator)(nil) + _ MultipartFormDataRouter = (*ProtoMultipartFormDataRouter)(nil) + _ gotenberg.Module = (*ProtoMultipartFormDataRouter)(nil) + _ gotenberg.Validator = (*ProtoMultipartFormDataRouter)(nil) + _ MiddlewareProvider = (*ProtoMiddlewareProvider)(nil) + _ gotenberg.Module = (*ProtoMiddlewareProvider)(nil) + _ gotenberg.Validator = (*ProtoMiddlewareProvider)(nil) + _ HealthChecker = (*ProtoHealthChecker)(nil) + _ gotenberg.Module = (*ProtoHealthChecker)(nil) + _ gotenberg.Validator = (*ProtoHealthChecker)(nil) + _ gotenberg.LoggerProvider = (*ProtoLoggerProvider)(nil) + _ gotenberg.Module = (*ProtoLoggerProvider)(nil) +) diff --git a/pkg/modules/api/context.go b/pkg/modules/api/context.go new file mode 100644 index 00000000..88fb79c3 --- /dev/null +++ b/pkg/modules/api/context.go @@ -0,0 +1,319 @@ +package api + +import ( + "compress/flate" + "context" + "errors" + "fmt" + "io" + "mime/multipart" + "net/http" + "os" + "path/filepath" + "strings" + "time" + "unicode" + + "github.com/google/uuid" + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/labstack/echo/v4" + "github.com/mholt/archiver/v3" + "go.uber.org/zap" + "golang.org/x/text/runes" + "golang.org/x/text/transform" + "golang.org/x/text/unicode/norm" +) + +var ( + // ErrContextAlreadyClosed happens when the context has been canceled. + ErrContextAlreadyClosed = errors.New("context already closed") + + // ErrOutOfBoundsOutputPath happens when an output path is not within + // context's working directory. It enforces having all the files in the + // same directory. + ErrOutOfBoundsOutputPath = errors.New("output path is not within context's working directory") +) + +// Context is the request context for a "multipart/form-data" requests. +type Context struct { + dirPath string + values map[string][]string + files map[string]string + + outputPaths []string + + cancelled bool + logger *zap.Logger + echoCtx echo.Context + context.Context +} + +// newContext returns a Context by parsing a "multipart/form-data" request. +func newContext(echoCtx echo.Context, logger *zap.Logger, timeout time.Duration) (*Context, context.CancelFunc, error) { + processCtx, processCancel := context.WithTimeout(context.Background(), timeout) + + ctx := &Context{ + outputPaths: make([]string, 0), + cancelled: false, + logger: logger, + echoCtx: echoCtx, + Context: processCtx, + } + + // A custom cancel function which removes the context's working directory + // when called. + cancel := func() context.CancelFunc { + return func() { + if ctx.cancelled { + return + } + + processCancel() + + if ctx.dirPath == "" { + return + } + + err := os.RemoveAll(ctx.dirPath) + if err != nil { + ctx.logger.Error(fmt.Sprintf("remove context's working directory: %s", err)) + + return + } + + ctx.logger.Debug(fmt.Sprintf("'%s' removed", ctx.dirPath)) + ctx.cancelled = true + } + }() + + form, err := echoCtx.MultipartForm() + if err != nil { + + if errors.Is(err, http.ErrNotMultipart) { + return nil, cancel, WrapError( + fmt.Errorf("get multipart form: %w", err), + NewSentinelHTTPError(http.StatusUnsupportedMediaType, "Invalid 'Content-Type' header value: want 'multipart/form-data'"), + ) + } + + if errors.Is(err, http.ErrMissingBoundary) { + return nil, cancel, WrapError( + fmt.Errorf("get multipart form: %w", err), + NewSentinelHTTPError(http.StatusUnsupportedMediaType, "Invalid 'Content-Type' header value: no boundary"), + ) + } + + if strings.Contains(err.Error(), io.EOF.Error()) { + return nil, cancel, WrapError( + fmt.Errorf("get multipart form: %w", err), + NewSentinelHTTPError(http.StatusBadRequest, "Malformed body: it does not match the 'Content-Type' header boundaries"), + ) + } + + return nil, cancel, fmt.Errorf("get multipart form: %w", err) + } + + dirPath, err := gotenberg.MkdirAll() + if err != nil { + return nil, cancel, fmt.Errorf("create working directory: %w", err) + } + + ctx.dirPath = dirPath + ctx.values = form.Value + ctx.files = make(map[string]string) + + copyToDisk := func(fh *multipart.FileHeader) error { + // Avoid directory traversal and normalize filename. + // See https://github.com/gotenberg/gotenberg/issues/104. + // See https://github.com/gotenberg/gotenberg/issues/228. + t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) + + filename, _, err := transform.String(t, strings.ToLower(filepath.Base(fh.Filename))) + if err != nil { + return fmt.Errorf("transform filename: %w", err) + } + + in, err := fh.Open() + if err != nil { + return fmt.Errorf("open multipart file: %w", err) + } + + defer func() { + err := in.Close() + if err != nil { + logger.Error(fmt.Sprintf("close file header: %s", err)) + } + }() + + path := fmt.Sprintf("%s/%s", ctx.dirPath, filename) + + out, err := os.Create(path) + if err != nil { + return fmt.Errorf("create local file: %w", err) + } + + defer func() { + err := out.Close() + if err != nil { + logger.Error(fmt.Sprintf("close local file: %s", err)) + } + }() + + _, err = io.Copy(out, in) + if err != nil { + return fmt.Errorf("copy multipart file to local file: %w", err) + } + + ctx.files[filename] = path + + return nil + } + + for _, files := range form.File { + for _, fh := range files { + err = copyToDisk(fh) + + if err != nil { + return ctx, cancel, fmt.Errorf("copy to disk: %w", err) + } + } + } + + ctx.Log().Debug(fmt.Sprintf("form data values: %+v", ctx.values)) + ctx.Log().Debug(fmt.Sprintf("form data files: %+v", ctx.files)) + + return ctx, cancel, err +} + +// Request returns the http.Request. +func (ctx Context) Request() *http.Request { + return ctx.echoCtx.Request() +} + +// FormData return a FormData. +func (ctx Context) FormData() *FormData { + return &FormData{ + values: ctx.values, + files: ctx.files, + errors: nil, + } +} + +// GeneratePath generates a path within the context's working directory. It +// does not create a file. +func (ctx Context) GeneratePath(extension string) string { + return fmt.Sprintf("%s/%s%s", ctx.dirPath, uuid.New(), extension) +} + +// AddOutputPaths adds the given paths. Those paths will be used later to build +// the output file. +func (ctx *Context) AddOutputPaths(paths ...string) error { + if ctx.cancelled { + return ErrContextAlreadyClosed + } + + for _, path := range paths { + if !strings.HasPrefix(path, ctx.dirPath) { + return ErrOutOfBoundsOutputPath + } + + ctx.outputPaths = append(ctx.outputPaths, path) + } + + return nil +} + +// Log returns the context zap.Logger. +func (ctx Context) Log() *zap.Logger { + return ctx.logger +} + +// buildOutputFile builds the output file according to the output paths +// registered in the context. If many output paths, an archive is created. +func (ctx Context) buildOutputFile() (string, error) { + if ctx.cancelled { + return "", ErrContextAlreadyClosed + } + + if len(ctx.outputPaths) == 0 { + return "", errors.New("no output path") + } + + if len(ctx.outputPaths) == 1 { + ctx.logger.Debug(fmt.Sprintf("only one output file '%s', skip archive creation", ctx.outputPaths[0])) + + return ctx.outputPaths[0], nil + } + + z := archiver.Zip{ + CompressionLevel: flate.DefaultCompression, + MkdirAll: true, + SelectiveCompression: true, + ContinueOnError: false, + OverwriteExisting: false, + ImplicitTopLevelFolder: false, + } + + archivePath := ctx.GeneratePath(".zip") + + err := z.Archive(ctx.outputPaths, archivePath) + if err != nil { + return "", fmt.Errorf("archive output files: %w", err) + } + + ctx.logger.Debug(fmt.Sprintf("archive '%s' created", archivePath)) + + return archivePath, nil +} + +// MockContext is a helper for tests. +// +// ctx := &api.MockContext{Context: &api.Context{}} +type MockContext struct { + *Context +} + +// SetDirPath sets the context's working directory path. +// +// ctx := &api.MockContext{Context: &api.Context{}} +// ctx.SetDirPath("/foo") +func (ctx *MockContext) SetDirPath(path string) { + ctx.dirPath = path +} + +// SetValues sets the values. +// +// ctx := &api.MockContext{Context: &api.Context{}} +// ctx.SetValues(map[string][]string{ +// "url": { +// "foo", +// }, +// }) +func (ctx *MockContext) SetValues(values map[string][]string) { + ctx.values = values +} + +// SetFiles sets the files. +// +// ctx := &api.MockContext{Context: &api.Context{}} +// ctx.SetFiles(map[string]string{ +// "foo": "/foo", +// }) +func (ctx *MockContext) SetFiles(files map[string]string) { + ctx.files = files +} + +// SetCancelled sets if the context is cancelled or not. +// +// ctx := &api.MockContext{Context: &api.Context{}} +// ctx.SetCancelled(true) +func (ctx *MockContext) SetCancelled(cancelled bool) { + ctx.cancelled = cancelled +} + +// OutputPaths returns the registered output paths. +// ctx := &api.MockContext{Context: &api.Context{}} +// outputPaths := ctx.OutputPaths() +func (ctx MockContext) OutputPaths() []string { + return ctx.outputPaths +} diff --git a/pkg/modules/api/context_test.go b/pkg/modules/api/context_test.go new file mode 100644 index 00000000..3f872790 --- /dev/null +++ b/pkg/modules/api/context_test.go @@ -0,0 +1,373 @@ +package api + +import ( + "bytes" + "errors" + "mime/multipart" + "net/http" + "net/http/httptest" + "os" + "reflect" + "strings" + "testing" + "time" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/labstack/echo/v4" + "go.uber.org/zap" +) + +func TestNewContext(t *testing.T) { + for i, tc := range []struct { + request *http.Request + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + }{ + { + request: httptest.NewRequest(http.MethodPost, "/", nil), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusUnsupportedMediaType, + }, + { + request: func() *http.Request { + req := httptest.NewRequest(http.MethodPost, "/", nil) + req.Header.Set(echo.HeaderContentType, echo.MIMEMultipartForm) + + return req + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusUnsupportedMediaType, + }, + { + request: func() *http.Request { + body := &bytes.Buffer{} + + writer := multipart.NewWriter(body) + + defer func() { + err := writer.Close() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + }() + + err := writer.WriteField("foo", "foo") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + req := httptest.NewRequest(http.MethodPost, "/", nil) + req.Header.Set(echo.HeaderContentType, writer.FormDataContentType()) + + return req + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: func() *http.Request { + body := &bytes.Buffer{} + + writer := multipart.NewWriter(body) + + defer func() { + err := writer.Close() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + }() + + err := writer.WriteField("foo", "foo") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + part, err := writer.CreateFormFile("foo.txt", "foo.txt") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + _, err = part.Write([]byte("foo")) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + req := httptest.NewRequest(http.MethodPost, "/", body) + req.Header.Set(echo.HeaderContentType, writer.FormDataContentType()) + + return req + }(), + }, + } { + handler := func(c echo.Context) error { + _, cancel, err := newContext(c, zap.NewNop(), time.Duration(10)*time.Second) + defer cancel() + // Context already cancelled. + defer cancel() + + if err != nil { + return err + } + + return nil + } + + recorder := httptest.NewRecorder() + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(tc.request, recorder) + err := handler(c) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + } +} + +func TestContext_Request(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "/", nil) + recorder := httptest.NewRecorder() + c := echo.New().NewContext(request, recorder) + + ctx := Context{ + echoCtx: c, + } + + if !reflect.DeepEqual(ctx.Request(), c.Request()) { + t.Errorf("expected %v but got %v", ctx.Request(), c.Request()) + } +} + +func TestContext_FormData(t *testing.T) { + ctx := Context{ + values: map[string][]string{ + "foo": {"foo"}, + }, + files: map[string]string{ + "foo.txt": "/foo.txt", + }, + } + + actual := ctx.FormData() + expect := &FormData{ + values: ctx.values, + files: ctx.files, + } + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %+v but got %+v", expect, actual) + } +} + +func TestContext_GeneratePath(t *testing.T) { + ctx := Context{ + dirPath: "/foo", + } + + path := ctx.GeneratePath(".pdf") + + if !strings.HasPrefix(path, ctx.dirPath) { + t.Errorf("expected '%s' to start with '%s'", path, ctx.dirPath) + } +} + +func TestContext_AddOutputPaths(t *testing.T) { + for i, tc := range []struct { + ctx *Context + path string + expectCount int + expectErr bool + }{ + { + ctx: &Context{cancelled: true}, + expectErr: true, + }, + { + ctx: &Context{dirPath: "/foo"}, + path: "/bar/foo.txt", + expectErr: true, + }, + { + ctx: &Context{dirPath: "/foo"}, + path: "/foo/foo.txt", + expectCount: 1, + }, + } { + err := tc.ctx.AddOutputPaths(tc.path) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + if len(tc.ctx.outputPaths) != tc.expectCount { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectCount, len(tc.ctx.outputPaths)) + } + } +} + +func TestContext_Log(t *testing.T) { + expect := zap.NewNop() + ctx := Context{logger: expect} + actual := ctx.Log() + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %v but got %v", expect, actual) + } +} + +func TestContext_buildOutputFile(t *testing.T) { + for i, tc := range []struct { + ctx *Context + expectErr bool + }{ + { + ctx: &Context{cancelled: true}, + expectErr: true, + }, + { + ctx: &Context{}, + expectErr: true, + }, + { + ctx: &Context{outputPaths: []string{"foo.txt"}}, + }, + { + ctx: &Context{outputPaths: []string{"foo.txt", "foo.pdf"}}, + expectErr: true, + }, + { + ctx: &Context{ + outputPaths: []string{ + "/tests/test/testdata/api/sample1.txt", + "/tests/test/testdata/api/sample1.txt", + }, + }, + }, + } { + dirPath, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("%d: expected no erro but got: %v", i, err) + } + + tc.ctx.dirPath = dirPath + tc.ctx.logger = zap.NewNop() + + _, err = tc.ctx.buildOutputFile() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + err = os.RemoveAll(dirPath) + if err != nil { + t.Fatalf("%d: expected no erro but got: %v", i, err) + } + } +} + +func TestMockContext_SetDirPath(t *testing.T) { + mock := &MockContext{&Context{}} + mock.SetDirPath("/foo") + + actual := mock.dirPath + expect := "/foo" + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestMockContext_SetValues(t *testing.T) { + mock := &MockContext{&Context{}} + mock.SetValues(map[string][]string{ + "foo": {"foo"}, + }) + + actual := mock.values + expect := map[string][]string{ + "foo": {"foo"}, + } + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %+v but got: %+v", expect, actual) + } +} + +func TestMockContext_SetFiles(t *testing.T) { + mock := &MockContext{&Context{}} + mock.SetFiles(map[string]string{ + "foo": "/foo", + }) + + actual := mock.files + expect := map[string]string{ + "foo": "/foo", + } + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %+v but got: %+v", expect, actual) + } +} + +func TestMockContext_SetCancelled(t *testing.T) { + mock := &MockContext{&Context{}} + mock.SetCancelled(true) + + actual := mock.cancelled + + if !actual { + t.Errorf("expected %t but got %t", true, actual) + } +} + +func TestMockContext_OutputPaths(t *testing.T) { + mock := MockContext{ + &Context{ + outputPaths: []string{"/foo"}, + }, + } + + actual := mock.OutputPaths() + expect := []string{"/foo"} + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %+v but got: %+v", expect, actual) + } +} diff --git a/pkg/modules/api/doc.go b/pkg/modules/api/doc.go new file mode 100644 index 00000000..3c255a45 --- /dev/null +++ b/pkg/modules/api/doc.go @@ -0,0 +1,3 @@ +// Package api provides a module which is an HTTP server. Other modules may +// add multipart/form-data routes, middlewares, and health checks. +package api diff --git a/pkg/modules/api/errors.go b/pkg/modules/api/errors.go new file mode 100644 index 00000000..cd080480 --- /dev/null +++ b/pkg/modules/api/errors.go @@ -0,0 +1,77 @@ +package api + +// Credits: https://www.joeshaw.org/error-handling-in-go-http-applications. + +// HTTPError is an interface allowing to retrieve the HTTP details of an error. +type HTTPError interface { + HTTPError() (int, string) +} + +// SentinelHTTPError is the HTTP sidekick of an error. +type SentinelHTTPError struct { + status int + message string +} + +// NewSentinelHTTPError creates a SentinelHTTPError. The message will be sent +// as the response's body if returned from an handler, so make sure to not leak +// sensible information. +func NewSentinelHTTPError(status int, message string) SentinelHTTPError { + return SentinelHTTPError{ + status: status, + message: message, + } +} + +// Error returns the message. +func (err SentinelHTTPError) Error() string { + return err.message +} + +// HTTPError returns the status and message. +func (err SentinelHTTPError) HTTPError() (int, string) { + return err.status, err.message +} + +// sentinelWrappedError contains both the error which will logged and the +// sidekick SentinelHTTPError. +type sentinelWrappedError struct { + error + sentinel SentinelHTTPError +} + +func (w sentinelWrappedError) Is(err error) bool { + return w.sentinel == err +} + +func (w sentinelWrappedError) HTTPError() (int, string) { + return w.sentinel.HTTPError() +} + +// WrapError wraps the given error with a SentinelHTTPError. The wrapped error +// will be displayed in a log, while the SentinelHTTPError will be sent in the +// response. +// +// return api.WrapError( +// // This first error will be logged. +// fmt.Errorf("my action: %w", err), +// // The HTTP error will be sent as a response. +// api.NewSentinelHTTPError( +// http.StatusForbidden, +// "Hey, you did something wrong!" +// ), +// ) +func WrapError(err error, sentinel SentinelHTTPError) error { + return sentinelWrappedError{ + error: err, + sentinel: sentinel, + } +} + +// Interface guards. +var ( + _ error = (*SentinelHTTPError)(nil) + _ HTTPError = (*SentinelHTTPError)(nil) + _ error = (*sentinelWrappedError)(nil) + _ HTTPError = (*sentinelWrappedError)(nil) +) diff --git a/pkg/modules/api/errors_test.go b/pkg/modules/api/errors_test.go new file mode 100644 index 00000000..9e0eca24 --- /dev/null +++ b/pkg/modules/api/errors_test.go @@ -0,0 +1,108 @@ +package api + +import ( + "errors" + "net/http" + "reflect" + "testing" +) + +func TestNewSentinelHTTPError(t *testing.T) { + actual := NewSentinelHTTPError(http.StatusInternalServerError, "foo") + expect := SentinelHTTPError{ + status: http.StatusInternalServerError, + message: "foo", + } + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %v but got %v", expect, actual) + } +} + +func TestSentinelHTTPError_Error(t *testing.T) { + err := SentinelHTTPError{ + message: "foo", + } + + actual := err.Error() + expect := "foo" + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestSentinelHTTPError_HTTPError(t *testing.T) { + actualStatus, actualMessage := SentinelHTTPError{ + status: http.StatusInternalServerError, + message: "foo", + }.HTTPError() + + expectStatus := http.StatusInternalServerError + expectMessage := "foo" + + if actualStatus != expectStatus { + t.Errorf("expected %d but got %d", expectStatus, actualStatus) + } + + if actualMessage != expectMessage { + t.Errorf("expected '%s' but got '%s'", expectMessage, actualMessage) + } +} + +func TestSentinelWrappedError_Is(t *testing.T) { + errSentinel := SentinelHTTPError{} + + err := sentinelWrappedError{ + error: errors.New("foo"), + sentinel: errSentinel, + } + + if !err.Is(errSentinel) { + t.Error("expected true") + } +} + +func TestSentinelWrappedError_HTTPError(t *testing.T) { + expectStatus, expectMessage := SentinelHTTPError{ + status: http.StatusInternalServerError, + message: "foo", + }.HTTPError() + + actualStatus, actualMessage := sentinelWrappedError{ + error: errors.New("foo"), + sentinel: SentinelHTTPError{ + status: http.StatusInternalServerError, + message: "foo", + }, + }.HTTPError() + + if actualStatus != expectStatus { + t.Errorf("expected %d but got %d", expectStatus, actualStatus) + } + + if actualMessage != expectMessage { + t.Errorf("expected '%s' but got '%s'", expectMessage, actualMessage) + } +} + +func TestWrapError(t *testing.T) { + errFoo := errors.New("foo") + + expect := sentinelWrappedError{ + error: errFoo, + sentinel: SentinelHTTPError{ + status: http.StatusInternalServerError, + message: "foo", + }, + } + + actual := WrapError(errFoo, SentinelHTTPError{ + status: http.StatusInternalServerError, + message: "foo", + }) + + if !reflect.DeepEqual(actual, expect) { + t.Errorf("expected %v but got %v", expect, actual) + } +} diff --git a/pkg/modules/api/formdata.go b/pkg/modules/api/formdata.go new file mode 100644 index 00000000..c4260a36 --- /dev/null +++ b/pkg/modules/api/formdata.go @@ -0,0 +1,439 @@ +package api + +import ( + "fmt" + "io/ioutil" + "net/http" + "path/filepath" + "sort" + "strconv" + "strings" + "time" + + "go.uber.org/multierr" +) + +// FormData is a helper for validating and hydrating values from a +// "multipart/form-data" request. +// +// form := ctx.FormData() +type FormData struct { + values map[string][]string + files map[string]string + errors error +} + +// Validate returns nil or an error related to the FormData values, with a +// SentinelHTTPError (status code 400, errors' details as message) wrapped +// inside. +// +// var foo string +// +// err := ctx.FormData(). +// MandatoryString("foo", &foo, "bar"). +// Validate() +func (form FormData) Validate() error { + if form.errors == nil { + return nil + } + + return WrapError( + form.errors, + NewSentinelHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid form data: %s", form.errors)), + ) +} + +// String binds a form data value to a string variable. +// +// var foo string +// +// ctx.FormData().String("foo", &foo, "bar") +func (form *FormData) String(key string, target *string, defaultValue string) *FormData { + return form.mustValue(key, target, defaultValue) +} + +// MandatoryString binds a form data value to a string variable. It populates +// an error if the value is empty or the "key" does not exist. +// +// var foo string +// +// ctx.FormData().MandatoryString("foo", &foo) +func (form *FormData) MandatoryString(key string, target *string) *FormData { + return form.mustMandatoryValue(key, target) +} + +// Bool binds a form data value to a bool variable. It populates an error if +// the value is not bool. +// +// var foo bool +// +// ctx.FormData().Bool("foo", &foo, true) +func (form *FormData) Bool(key string, target *bool, defaultValue bool) *FormData { + return form.mustValue(key, target, defaultValue) +} + +// MandatoryBool binds a form data value to a bool variable. It populates an +// error if the value is not bool, is empty, or the "key" does not exist. +// +// var foo bool +// +// ctx.FormData().MandatoryBool("foo", &foo) +func (form *FormData) MandatoryBool(key string, target *bool) *FormData { + return form.mustMandatoryValue(key, target) +} + +// Int binds a form data value to an int variable. It populates an error if the +// value is not int. +// +// var foo int +// +// ctx.FormData().Int("foo", &foo, 2) +func (form *FormData) Int(key string, target *int, defaultValue int) *FormData { + return form.mustValue(key, target, defaultValue) +} + +// MandatoryInt binds a form data value to an int variable. It populates an +// error if the value is not int, is empty, or the "key" does not exist. +// +// var foo int +// +// ctx.FormData().MandatoryInt("foo", &foo) +func (form *FormData) MandatoryInt(key string, target *int) *FormData { + return form.mustMandatoryValue(key, target) +} + +// Float64 binds a form data value to a float64 variable. It populates an error +// if the value is not float64. +// +// var foo float64 +// +// ctx.FormData().Float64("foo", &foo, 2.0) +func (form *FormData) Float64(key string, target *float64, defaultValue float64) *FormData { + return form.mustValue(key, target, defaultValue) +} + +// MandatoryFloat64 binds a form data value to a float64 variable. It populates +// an error if the is not float64, is empty, or the "key" does not exist. +// +// var foo float64 +// +// ctx.FormData().MandatoryFloat64("foo", &foo) +func (form *FormData) MandatoryFloat64(key string, target *float64) *FormData { + return form.mustMandatoryValue(key, target) +} + +// Duration binds a form data value to a time.Duration variable. It populates +// an error if the form data value is not time.Duration. +// +// var foo time.Duration +// +// ctx.FormData().Duration("foo", &foo, time.Duration(2) * time.Second) +func (form *FormData) Duration(key string, target *time.Duration, defaultValue time.Duration) *FormData { + return form.mustValue(key, target, defaultValue) +} + +// MandatoryDuration binds a form data value to a time.Duration variable. It +// populates an error if the value is not time.Duration, is empty, or the "key" +// does not exist. +// +// var foo time.Duration +// +// ctx.FormData().MandatoryDuration("foo", &foo) +func (form *FormData) MandatoryDuration(key string, target *time.Duration) *FormData { + return form.mustMandatoryValue(key, target) +} + +// Custom helps to define a custom binding function for a form data value. +// +// var foo map[string]string +// +// ctx.FormData().Custom("foo", func(value string) error { +// if value == "" { +// foo = "bar" +// +// return nil +// } +// +// err := json.Unmarshal([]byte(value), &foo) +// if err != nil { +// return fmt.Errorf("unmarshal foo: %w", err) +// } +// +// return nil +// }) +func (form *FormData) Custom(key string, assign func(value string) error) *FormData { + var value string + form.mustValue(key, &value, "") + + err := assign(value) + if err != nil { + form.append( + fmt.Errorf("form value '%s' is invalid (got '%s', resulting to %w)", key, value, err), + ) + } + + return form +} + +// MandatoryCustom helps to define a custom binding function for a form data +// value. It populates an error if the value is empty or the "key" does not +// exist. +// +// var foo map[string]string +// +// ctx.FormData().MandatoryCustom("foo", func(value string) error { +// err := json.Unmarshal([]byte(value), &foo) +// if err != nil { +// return fmt.Errorf("unmarshal foo: %w", err) +// } +// +// return nil +// }) +func (form *FormData) MandatoryCustom(key string, assign func(value string) error) *FormData { + var value string + form.mustMandatoryValue(key, &value) + + if value == "" { + return form + } + + err := assign(value) + if err != nil { + form.append( + fmt.Errorf("form value '%s' is invalid (got '%s', resulting to %w)", key, value, err), + ) + } + + return form +} + +// Path binds the absolute path of a form data file to a string variable. +// +// var path string +// +// ctx.FormData().Path("foo.txt", &path) +func (form *FormData) Path(filename string, target *string) *FormData { + return form.path(filename, target) +} + +// MandatoryPath binds the absolute path ofa form data file to a string +// variable. It populates an error if the file does not exist. +// +// var path string +// +// ctx.FormData().MandatoryPath("foo.txt", &path) +func (form *FormData) MandatoryPath(filename string, target *string) *FormData { + return form.mandatoryPath(filename, target) +} + +// Content binds the content of a form data file to a string variable. +// +// var content string +// +// ctx.FormData().Content("foo.txt", &content, "bar") +func (form *FormData) Content(filename string, target *string, defaultValue string) *FormData { + var path string + form.path(filename, &path) + + if path == "" { + *target = defaultValue + + return form + } + + return form.readFile(path, filename, target) +} + +// MandatoryContent binds the content of a form data file to a string variable. +// It populates an error if the file does not exist. +// +// var content string +// +// ctx.FormData().MandatoryContent("foo.txt", &content) +func (form *FormData) MandatoryContent(filename string, target *string) *FormData { + var path string + form.mandatoryPath(filename, &path) + + if path == "" { + return form + } + + return form.readFile(path, filename, target) +} + +// Paths binds the absolute paths of form data files, according to a list of +// file extensions, to a string slice variable. +// +// var paths []string +// +// ctx.FormData().Paths([]string{".txt"}, &paths) +func (form *FormData) Paths(extensions []string, target *[]string) *FormData { + return form.paths(extensions, target) +} + +// MandatoryPaths binds the absolute paths of form data files, according to a +// list of file extensions, to a string slice variable. It populates an error +// if there is no file for given file extensions. +// +// var paths []string +// +// ctx.FormData().MandatoryPaths([]string{".txt"}, &paths) +func (form *FormData) MandatoryPaths(extensions []string, target *[]string) *FormData { + form.paths(extensions, target) + + if len(*target) > 0 { + return form + } + + form.append( + fmt.Errorf("no form file found for extensions: %v", extensions), + ) + + return form +} + +// paths binds the absolute paths of form data files, according to a list of +// file extensions, to a string slice variable. +func (form *FormData) paths(extensions []string, target *[]string) *FormData { + for filename, path := range form.files { + for _, ext := range extensions { + // See https://github.com/gotenberg/gotenberg/issues/228. + if strings.ToLower(filepath.Ext(filename)) == ext { + *target = append(*target, path) + } + } + } + + // See https://github.com/gotenberg/gotenberg/issues/139. + sort.Strings(*target) + + return form +} + +// append adds an error to the list of errors. +func (form *FormData) append(err error) { + form.errors = multierr.Append(form.errors, err) +} + +// mustValue binds the target interface with a form data value. If the value is +// empty or the "key" does not exist, it binds the default value. Currently, +// only the string, bool, int, float64 and time.Duration types are bindable. +func (form *FormData) mustValue(key string, target interface{}, defaultValue interface{}) *FormData { + val, ok := form.values[key] + + if !ok || val[0] == "" { + switch t := (target).(type) { + case *string: + *t = defaultValue.(string) + case *bool: + *t = defaultValue.(bool) + case *int: + *t = defaultValue.(int) + case *float64: + *t = defaultValue.(float64) + case *time.Duration: + *t = defaultValue.(time.Duration) + default: + panic("target type not supported") + } + + return form + } + + return form.mustAssign(key, val[0], target) +} + +// mustMandatoryValue binds the target interface with a form data value. It +// populates an error if the value is empty or the "key" does not exist. +// Currently, only the string, bool, int, float64 and time.Duration types are +// bindable. +func (form *FormData) mustMandatoryValue(key string, target interface{}) *FormData { + val, ok := form.values[key] + + if !ok || val[0] == "" { + form.append( + fmt.Errorf("form value '%s' is required", key), + ) + + return form + } + + form.mustAssign(key, val[0], target) + + return form +} + +// mustAssign parses the string value and tries to convert it to the target +// interface real type. Currently, only the string, bool, int, float64 and +// time.Duration types are bindable. +func (form *FormData) mustAssign(key, value string, target interface{}) *FormData { + var err error + + switch t := (target).(type) { + case *string: + *t = value + case *bool: + *t, err = strconv.ParseBool(value) + case *int: + *t, err = strconv.Atoi(value) + case *float64: + *t, err = strconv.ParseFloat(value, 64) + case *time.Duration: + *t, err = time.ParseDuration(value) + default: + panic("target type not supported") + } + + if err != nil { + form.append( + fmt.Errorf("form value '%s' is invalid (got '%s', resulting to %w)", key, value, err), + ) + } + + return form +} + +// path binds the absolute path of a form data file to a string variable. +func (form *FormData) path(filename string, target *string) *FormData { + for name, path := range form.files { + if name == filename { + *target = path + return form + } + } + + return form +} + +// mandatoryPath binds the absolute path of a form data file to a string +// variable. It populates an error if the file does not exist. +func (form *FormData) mandatoryPath(filename string, target *string) *FormData { + form.path(filename, target) + + if *target != "" { + return form + } + + form.append( + fmt.Errorf("form file '%s' is required", filename), + ) + + return form +} + +// readFile binds the content of a file to a string variable. It populates an +// error if it fails to read the file content. +func (form *FormData) readFile(path, filename string, target *string) *FormData { + b, err := ioutil.ReadFile(path) + if err != nil { + form.append( + fmt.Errorf("form file '%s' is invalid (%w)", filename, err), + ) + + return form + } + + *target = string(b) + + return form +} diff --git a/pkg/modules/api/formdata_test.go b/pkg/modules/api/formdata_test.go new file mode 100644 index 00000000..f16a4e5d --- /dev/null +++ b/pkg/modules/api/formdata_test.go @@ -0,0 +1,1111 @@ +package api + +import ( + "encoding/json" + "errors" + "reflect" + "testing" + "time" +) + +func TestFormData_Validate(t *testing.T) { + for i, tc := range []struct { + form FormData + expectErr bool + }{ + { + form: FormData{ + errors: errors.New("foo"), + }, + expectErr: true, + }, + { + form: FormData{ + errors: nil, + }, + }, + } { + err := tc.form.Validate() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestFormData_String(t *testing.T) { + for i, tc := range []struct { + form *FormData + defaultValue string + expect string + }{ + { + form: &FormData{}, + }, + { + form: &FormData{}, + defaultValue: "foo", + expect: "foo", + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expect: "foo", + }, + } { + var actual string + + tc.form.String("foo", &actual, tc.defaultValue) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryString(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect string + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expect: "foo", + }, + } { + var actual string + + tc.form.MandatoryString("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Bool(t *testing.T) { + for i, tc := range []struct { + form *FormData + defaultValue bool + expect bool + expectErr bool + }{ + { + form: &FormData{}, + }, + { + form: &FormData{}, + defaultValue: true, + expect: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "true", + }, + }, + }, + expect: true, + }, + } { + var actual bool + + tc.form.Bool("foo", &actual, tc.defaultValue) + + if actual != tc.expect { + t.Errorf("test %d: expected %t but got %t", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryBool(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect bool + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "true", + }, + }, + }, + expect: true, + }, + } { + var actual bool + + tc.form.MandatoryBool("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected %t but got %t", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Int(t *testing.T) { + for i, tc := range []struct { + form *FormData + defaultValue int + expect int + expectErr bool + }{ + { + form: &FormData{}, + }, + { + form: &FormData{}, + defaultValue: 2, + expect: 2, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "3", + }, + }, + }, + expect: 3, + }, + } { + var actual int + + tc.form.Int("foo", &actual, tc.defaultValue) + + if actual != tc.expect { + t.Errorf("test %d: expected %d but got %d", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryInt(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect int + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "2", + }, + }, + }, + expect: 2, + }, + } { + var actual int + + tc.form.MandatoryInt("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected %d but got %d", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Float64(t *testing.T) { + for i, tc := range []struct { + form *FormData + defaultValue float64 + expect float64 + expectErr bool + }{ + { + form: &FormData{}, + }, + { + form: &FormData{}, + defaultValue: 2.5, + expect: 2.5, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "3.5", + }, + }, + }, + expect: 3.5, + }, + } { + var actual float64 + + tc.form.Float64("foo", &actual, tc.defaultValue) + + if actual != tc.expect { + t.Errorf("test %d: expected %f but got %f", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryFloat64(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect float64 + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "2.5", + }, + }, + }, + expect: 2.5, + }, + } { + var actual float64 + + tc.form.MandatoryFloat64("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected %f but got %f", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Duration(t *testing.T) { + for i, tc := range []struct { + form *FormData + defaultValue time.Duration + expect time.Duration + expectErr bool + }{ + { + form: &FormData{}, + }, + { + form: &FormData{}, + defaultValue: time.Duration(1) * time.Second, + expect: time.Duration(1) * time.Second, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "1s", + }, + }, + }, + expect: time.Duration(1) * time.Second, + }, + } { + var actual time.Duration + + tc.form.Duration("foo", &actual, tc.defaultValue) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryDuration(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect time.Duration + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "1s", + }, + }, + }, + expect: time.Duration(1) * time.Second, + }, + } { + var actual time.Duration + + tc.form.MandatoryDuration("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Custom(t *testing.T) { + for i, tc := range []struct { + form *FormData + defaultValue map[string]string + expect map[string]string + expectErr bool + }{ + { + form: &FormData{}, + }, + { + form: &FormData{}, + defaultValue: map[string]string{"foo": "foo"}, + expect: map[string]string{"foo": "foo"}, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + `{ "foo": "foo" }`, + }, + }, + }, + expect: map[string]string{"foo": "foo"}, + }, + } { + var actual map[string]string + + tc.form.Custom("foo", func(value string) error { + if value == "" { + actual = tc.defaultValue + + return nil + } + + err := json.Unmarshal([]byte(value), &actual) + if err != nil { + return err + } + + return nil + }) + + if !reflect.DeepEqual(actual, tc.expect) { + t.Errorf("test %d: expected %+v but got: %+v", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryCustom(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect map[string]string + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + "foo", + }, + }, + }, + expectErr: true, + }, + { + form: &FormData{ + values: map[string][]string{ + "foo": { + `{ "foo": "foo" }`, + }, + }, + }, + expect: map[string]string{"foo": "foo"}, + }, + } { + var actual map[string]string + + tc.form.MandatoryCustom("foo", func(value string) error { + err := json.Unmarshal([]byte(value), &actual) + if err != nil { + return err + } + + return nil + }) + + if !reflect.DeepEqual(actual, tc.expect) { + t.Errorf("test %d: expected %+v but got: %+v", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Path(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect string + }{ + { + form: &FormData{}, + }, + { + form: &FormData{ + files: map[string]string{ + "bar": "/bar", + }, + }, + }, + { + form: &FormData{ + files: map[string]string{ + "foo": "/foo", + }, + }, + expect: "/foo", + }, + } { + var actual string + + tc.form.Path("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryPath(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect string + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "bar": "/bar", + }, + }, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "foo": "/foo", + }, + }, + expect: "/foo", + }, + } { + var actual string + + tc.form.MandatoryPath("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Content(t *testing.T) { + for i, tc := range []struct { + form *FormData + defaultValue string + expect string + expectErr bool + }{ + { + form: &FormData{}, + }, + { + form: &FormData{ + files: map[string]string{ + "bar": "/bar", + }, + }, + }, + { + form: &FormData{ + files: map[string]string{ + "bar": "/bar", + }, + }, + defaultValue: "foo", + expect: "foo", + }, + { + form: &FormData{ + files: map[string]string{ + "foo": "/foo", + }, + }, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "foo": "/tests/test/testdata/api/sample1.txt", + }, + }, + expect: "foo", + }, + } { + var actual string + + tc.form.Content("foo", &actual, tc.defaultValue) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryContent(t *testing.T) { + for i, tc := range []struct { + form *FormData + expect string + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "bar": "/bar", + }, + }, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "foo": "/foo", + }, + }, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "foo": "/tests/test/testdata/api/sample1.txt", + }, + }, + expect: "foo", + }, + } { + var actual string + + tc.form.MandatoryContent("foo", &actual) + + if actual != tc.expect { + t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_Paths(t *testing.T) { + for i, tc := range []struct { + form *FormData + extensions []string + expect []string + expectCount int + }{ + { + form: &FormData{}, + }, + { + form: &FormData{ + files: map[string]string{ + "foo.zip": "/foo.zip", + "foo.pdf": "/foo.pdf", + }, + }, + extensions: []string{".txt"}, + }, + { + form: &FormData{ + files: map[string]string{ + "foo.zip": "/foo.zip", + "b.pdf": "/b.pdf", + "a.pdf": "/a.pdf", + }, + }, + extensions: []string{".pdf"}, + expect: []string{ + "/a.pdf", + "/b.pdf", + }, + expectCount: 2, + }, + } { + var actual []string + + tc.form.Paths(tc.extensions, &actual) + + if !reflect.DeepEqual(actual, tc.expect) { + t.Errorf("test %d: expected %v but got: %v", i, tc.expect, actual) + } + + if len(actual) != tc.expectCount { + t.Errorf("test %d: expected %d files but got %d", i, tc.expectCount, len(actual)) + } + + if tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_MandatoryPaths(t *testing.T) { + for i, tc := range []struct { + form *FormData + extensions []string + expect []string + expectCount int + expectErr bool + }{ + { + form: &FormData{}, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "foo.zip": "/foo.zip", + "foo.pdf": "/foo.pdf", + }, + }, + extensions: []string{".txt"}, + expectErr: true, + }, + { + form: &FormData{ + files: map[string]string{ + "foo.zip": "/foo.zip", + "b.pdf": "/b.pdf", + "a.pdf": "/a.pdf", + }, + }, + extensions: []string{".pdf"}, + expect: []string{ + "/a.pdf", + "/b.pdf", + }, + expectCount: 2, + }, + } { + var actual []string + + tc.form.MandatoryPaths(tc.extensions, &actual) + + if !reflect.DeepEqual(actual, tc.expect) { + t.Errorf("test %d: expected %v but got: %v", i, tc.expect, actual) + } + + if len(actual) != tc.expectCount { + t.Errorf("test %d: expected %d files but got %d", i, tc.expectCount, len(actual)) + } + + if tc.expectErr && tc.form.errors == nil { + t.Errorf("test %d: expected error but got: %v", i, tc.form.errors) + } + + if !tc.expectErr && tc.form.errors != nil { + t.Errorf("test %d: expected no error but got: %v", i, tc.form.errors) + } + } +} + +func TestFormData_append(t *testing.T) { + form := &FormData{} + form.append(errors.New("foo")) + + if form.errors == nil { + t.Errorf("expected error but got: %v", form.errors) + } +} + +func TestFormData_mustValue(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Error("expected panic but got none") + } + }() + + form := &FormData{} + defaultValue := []string{"foo"} + + var target []string + form.mustValue("foo", &target, defaultValue) +} + +func TestFormData_mustAssign(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Error("expected panic but got none") + } + }() + + form := &FormData{} + + var target []string + form.mustAssign("foo", "foo", &target) +} diff --git a/pkg/modules/api/middlewares.go b/pkg/modules/api/middlewares.go new file mode 100644 index 00000000..5a0e67b1 --- /dev/null +++ b/pkg/modules/api/middlewares.go @@ -0,0 +1,576 @@ +package api + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "time" + + "github.com/google/uuid" + "github.com/hashicorp/go-retryablehttp" + "github.com/labstack/echo/v4" + "go.uber.org/zap" +) + +// httpErrorHandler is the centralized HTTP error handler. It parses the error, +// returns either a response as "text/plain; charset=UTF-8" or, if a webhook +// client exists in the echo.Context, sends a request to the webhook error URL +// with a JSON body containing the trace, the status and the error message. +func httpErrorHandler(traceHeader string) echo.HTTPErrorHandler { + return func(err error, c echo.Context) { + parseError := func(err error) (int, string) { + echoErr, ok := err.(*echo.HTTPError) + if ok { + return echoErr.Code, http.StatusText(echoErr.Code) + } + + if errors.Is(err, context.DeadlineExceeded) { + return http.StatusServiceUnavailable, http.StatusText(http.StatusServiceUnavailable) + } + + var httpErr HTTPError + if errors.As(err, &httpErr) { + return httpErr.HTTPError() + } + + // Default 500 status code. + return http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError) + } + + status, message := parseError(err) + + logger := c.Get("logger").(*zap.Logger) + clientOrNil := c.Get("webhookClient") + + // No webhook client, meaning we can send the error as a response. + if clientOrNil == nil { + c.Response().Header().Add(echo.HeaderContentType, echo.MIMETextPlainCharsetUTF8) + + err = c.String(status, message) + + if err != nil { + logger.Error(fmt.Sprintf("send error response: %s", err.Error())) + } + + return + } + + // We have to send the error to the webhook. + client := clientOrNil.(*webhookClient) + + body := struct { + Status int `json:"status"` + Message string `json:"message"` + }{ + Status: status, + Message: message, + } + + b, err := json.Marshal(body) + if err != nil { + logger.Error(fmt.Sprintf("marshal JSON: %s", err.Error())) + + return + } + + headers := map[string]string{ + echo.HeaderContentType: echo.MIMEApplicationJSONCharsetUTF8, + traceHeader: c.Get("trace").(string), + } + + err = client.send(bytes.NewReader(b), headers, true) + if err != nil { + logger.Error(fmt.Sprintf("send error response to webhook: %s", err.Error())) + } + } +} + +// latencyMiddleware sets the start time in the echo.Context under "startTime". +// Its value will be used later to calculate a request latency. +// +// startTime := c.Get("startTime").(time.Time) +func latencyMiddleware() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + // First piece for calculating the latency. + startTime := time.Now() + c.Set("startTime", startTime) + + // Call the next middleware in the chain. + return next(c) + } + } +} + +// rootPathMiddleware sets the root path in the echo.Context under "rootPath". +// Its value may be used to skip a middleware execution based on a request +// URI. +// +// rootPath := c.Get("rootPath").(string) +// healthURI := fmt.Sprintf("%shealth", rootPath) +// +// // Skip the middleware if health check URI. +// if c.Request().RequestURI == healthURI { +// // Call the next middleware in the chain. +// return next(c) +// } +func rootPathMiddleware(rootPath string) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + c.Set("rootPath", rootPath) + + // Call the next middleware in the chain. + return next(c) + } + } +} + +// traceMiddleware sets the request identifier in the echo.Context under +// "trace". Its value is either retrieved from the trace header or generated if +// the header is not present / its value is empty. +// +// trace := c.Get("trace").(string) +func traceMiddleware(header string) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + // Get or create the request identifier. + trace := c.Request().Header.Get(header) + + if trace == "" { + trace = uuid.New().String() + } + + c.Set("trace", trace) + c.Response().Header().Add(header, trace) + + // Call the next middleware in the chain. + return next(c) + } + } +} + +// loggerMiddleware sets the logger in the echo.Context under "logger" and logs +// a request result (but does not log a webhook call result, which is the job +// of the webhookClient). +// +// logger := c.Get("logger").(*zap.Logger) +func loggerMiddleware(logger *zap.Logger, skipHealthRouteLogging bool) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + startTime := c.Get("startTime").(time.Time) + trace := c.Get("trace").(string) + + // Create the request logger and add it to our locals. + reqLogger := logger.With(zap.String("trace", trace)) + c.Set("logger", reqLogger) + + // Call the next middleware in the chain. + err := next(c) + if err != nil { + c.Error(err) + } + + if skipHealthRouteLogging { + rootPath := c.Get("rootPath").(string) + healthURI := fmt.Sprintf("%shealth", rootPath) + + if c.Request().RequestURI == healthURI { + return nil + } + } + + // Last piece for calculating the latency. + finishTime := time.Now() + + // Now, let's log! + fields := make([]zap.Field, 12) + fields[0] = zap.String("remote_ip", c.RealIP()) + fields[1] = zap.String("host", c.Request().Host) + fields[2] = zap.String("uri", c.Request().RequestURI) + fields[3] = zap.String("method", c.Request().Method) + fields[4] = zap.String("path", func() string { + path := c.Request().URL.Path + + if path == "" { + path = "/" + } + + return path + }()) + fields[5] = zap.String("referer", c.Request().Referer()) + fields[6] = zap.String("user_agent", c.Request().UserAgent()) + fields[7] = zap.Int("status", c.Response().Status) + fields[8] = zap.Int64("latency", int64(finishTime.Sub(startTime))) + fields[9] = zap.String("latency_human", finishTime.Sub(startTime).String()) + fields[10] = zap.Int64("bytes_in", c.Request().ContentLength) + fields[11] = zap.Int64("bytes_out", c.Response().Size) + + if err != nil { + reqLogger.Error(err.Error(), fields...) + } else { + reqLogger.Info("request handled", fields...) + } + + return nil + } + } +} + +type contextMiddlewareConfig struct { + traceHeader string + timeout struct { + process time.Duration + write time.Duration + } + webhook struct { + allowList *regexp.Regexp + denyList *regexp.Regexp + errorAllowList *regexp.Regexp + errorDenyList *regexp.Regexp + maxRetry int + retryMinWait time.Duration + retryMaxWait time.Duration + disable bool + } +} + +// contextMiddleware handles the result of a "multipart/form-data" request. If +// a webhook URL is present in the headers, exit early and process the result +// in a goroutine. +func contextMiddleware(cfg contextMiddlewareConfig) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + webhookURL := c.Request().Header.Get("Gotenberg-Webhook-Url") + logger := c.Get("logger").(*zap.Logger).With(zap.Bool("webhook", webhookURL != "")) + + // We create a context with a timeout so that underlying processes are + // able to stop early and handle correctly a timeout scenario. + ctx, cancel, err := newContext(c, logger, cfg.timeout.process) + if err != nil { + cancel() + + return fmt.Errorf("create request context: %w", err) + } + c.Set("context", ctx) + + // Helper function for retrieving/creating the output filename. + outputFilename := func(outputPath string) string { + filename := c.Request().Header.Get("Gotenberg-Output-Filename") + + if filename == "" { + return filepath.Base(outputPath) + } + + return fmt.Sprintf("%s%s", filename, filepath.Ext(outputPath)) + } + + if webhookURL == "" { + defer cancel() + + // No webhook URL, call the next middleware in the chain. + err := next(c) + + if err != nil { + return err + } + + // No error, let's build the output file. + outputPath, err := ctx.buildOutputFile() + if err != nil { + return fmt.Errorf("build output file: %w", err) + } + + // Send the output file. + err = c.Attachment(outputPath, outputFilename(outputPath)) + if err != nil { + return fmt.Errorf("send response: %w", err) + } + + return nil + } + + // Ok, we got a webhook URL. + + if cfg.webhook.disable { + // The client requested the webhook feature, but it has been + // disabled. Let's tell the client about that. + cancel() + + return WrapError( + errors.New("webhook feature requested but it is disabled"), + NewSentinelHTTPError(http.StatusForbidden, "Invalid 'Gotenberg-Webhook-Url' header: feature is disabled"), + ) + } + + // Do we have a webhook error URL in case of... error? + webhookErrorURL := c.Request().Header.Get("Gotenberg-Webhook-Error-Url") + + if webhookErrorURL == "" { + cancel() + + return WrapError( + errors.New("empty webhook error URL"), + NewSentinelHTTPError(http.StatusBadRequest, "Invalid 'Gotenberg-Webhook-Error-Url' header: empty value or header not provided"), + ) + } + + // Let's check if the webhook URLs are acceptable according to our + // allowed/denied lists. + filter := func(URL, header string, allowList, denyList *regexp.Regexp) error { + if !allowList.MatchString(URL) { + return WrapError( + fmt.Errorf("'%s' does not match the expression from the allowed list", URL), + NewSentinelHTTPError( + http.StatusForbidden, + fmt.Sprintf("Invalid '%s' header value: '%s' does not match the authorized URLs", header, URL), + ), + ) + } + + if denyList.String() != "" && denyList.MatchString(URL) { + return WrapError( + fmt.Errorf("'%s' matches the expression from the denied list", URL), + NewSentinelHTTPError( + http.StatusForbidden, + fmt.Sprintf("Invalid '%s' header value: '%s' does not match the authorized URLs", header, URL), + ), + ) + } + + return nil + } + + err = filter(webhookURL, "Gotenberg-Webhook-Url", cfg.webhook.allowList, cfg.webhook.denyList) + if err != nil { + cancel() + + return fmt.Errorf("filter webhook URL: %w", err) + } + + err = filter(webhookErrorURL, "Gotenberg-Webhook-Error-Url", cfg.webhook.errorAllowList, cfg.webhook.errorDenyList) + if err != nil { + cancel() + + return fmt.Errorf("filter webhook error URL: %w", err) + } + + // Let's check the HTTP methods for calling the webhook URLs. + methodFromHeader := func(header string) (string, error) { + method := c.Request().Header.Get(header) + + if method == "" { + return http.MethodPost, nil + } + + method = strings.ToUpper(method) + + switch method { + case http.MethodPost: + return method, nil + case http.MethodPatch: + return method, nil + case http.MethodPut: + return method, nil + } + + return "", WrapError( + fmt.Errorf("webhook method '%s' is not '%s', '%s' or '%s'", method, http.MethodPost, http.MethodPatch, http.MethodPut), + NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("Invalid '%s' header value: expected '%s', '%s' or '%s', but got '%s'", header, http.MethodPost, http.MethodPatch, http.MethodPut, method), + ), + ) + } + + webhookMethod, err := methodFromHeader("Gotenberg-Webhook-Method") + if err != nil { + cancel() + + return fmt.Errorf("get method to use for webhook: %w", err) + } + + webhookErrorMethod, err := methodFromHeader("Gotenberg-Webhook-Error-Method") + if err != nil { + cancel() + + return fmt.Errorf("get method to use for webhook error: %w", err) + } + + // What about extra HTTP headers? + var extraHTTPHeaders map[string]string + + extraHTTPHeadersJSON := c.Request().Header.Get("Gotenberg-Webhook-Extra-Http-Headers") + if extraHTTPHeadersJSON != "" { + err = json.Unmarshal([]byte(extraHTTPHeadersJSON), &extraHTTPHeaders) + if err != nil { + cancel() + + return WrapError( + fmt.Errorf("unmarshal webhook extra HTTP headers: %w", err), + NewSentinelHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid 'Gotenberg-Webhook-Extra-Http-Headers' header value: %s", err.Error())), + ) + } + } + + client := &webhookClient{ + url: webhookURL, + method: webhookMethod, + errorURL: webhookErrorURL, + errorMethod: webhookErrorMethod, + extraHTTPHeaders: extraHTTPHeaders, + startTime: c.Get("startTime").(time.Time), + + client: &retryablehttp.Client{ + HTTPClient: &http.Client{ + Timeout: cfg.timeout.write, + }, + RetryMax: cfg.webhook.maxRetry, + RetryWaitMin: cfg.webhook.retryMinWait, + RetryWaitMax: cfg.webhook.retryMaxWait, + Logger: leveledLogger{ + logger: logger, + }, + CheckRetry: retryablehttp.DefaultRetryPolicy, + Backoff: retryablehttp.DefaultBackoff, + }, + logger: logger, + } + + c.Set("webhookClient", client) + + // As a webhook URL has been given, we handle the request in a + // goroutine and return immediately. + go func() { + defer cancel() + + // Call the next middleware in the chain. + err := next(c) + + if err != nil { + // The process failed for whatever reason. Let's send the + // details to the webhook. + ctx.Log().Error(err.Error()) + c.Error(err) + + return + } + + // No error, let's get build the output file. + outputPath, err := ctx.buildOutputFile() + if err != nil { + ctx.Log().Error(fmt.Sprintf("build output file: %s", err)) + c.Error(err) + + return + } + + outputFile, err := os.Open(outputPath) + if err != nil { + ctx.Log().Error(fmt.Sprintf("open output file: %s", err)) + c.Error(err) + + return + } + + defer func() { + err := outputFile.Close() + if err != nil { + ctx.Log().Error(fmt.Sprintf("close output file: %s", err)) + } + }() + + fileHeader := make([]byte, 512) + _, err = outputFile.Read(fileHeader) + if err != nil { + ctx.Log().Error(fmt.Sprintf("read header of output file: %s", err)) + c.Error(err) + + return + } + + fileStat, err := outputFile.Stat() + if err != nil { + ctx.Log().Error(fmt.Sprintf("get stat from output file: %s", err)) + c.Error(err) + + return + } + + _, err = outputFile.Seek(0, 0) + if err != nil { + ctx.Log().Error(fmt.Sprintf("reset output file reader: %s", err)) + c.Error(err) + + return + } + + headers := map[string]string{ + echo.HeaderContentDisposition: fmt.Sprintf("attachement; filename=%q", outputFilename(outputPath)), + echo.HeaderContentType: http.DetectContentType(fileHeader), + echo.HeaderContentLength: strconv.FormatInt(fileStat.Size(), 10), + cfg.traceHeader: c.Get("trace").(string), + } + + // Send the output file to the webhook. + err = client.send(bufio.NewReader(outputFile), headers, false) + if err != nil { + ctx.Log().Error(fmt.Sprintf("send output file to webhook: %s", err)) + c.Error(err) + } + }() + + return c.NoContent(http.StatusNoContent) + } + } +} + +// timeoutMiddleware manages hard timeout scenarios, i.e., when a route handler +// fails to timeout as expected. +func timeoutMiddleware(hardTimeout time.Duration) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + logger := c.Get("logger").(*zap.Logger) + + // Define a hard timeout if the route handler fails to timeout as + // expected. + hardTimeoutCtx, hardTimeoutCancel := context.WithTimeout( + context.Background(), + hardTimeout, + ) + defer hardTimeoutCancel() + + errChan := make(chan error, 1) + + go func() { + // In case of hard timeout, a panic may occur. + // This deferred function allows us to recover from such scenarios. + defer func() { + if r := recover(); r != nil { + logger.Debug(fmt.Sprintf("recovering from a panic (possible cause being a hard timeout): %s", r)) + } + }() + + // Call the next middleware in the chain. + errChan <- next(c) + }() + + select { + case err := <-errChan: + return err + case <-hardTimeoutCtx.Done(): + logger.Debug("hard timeout as the route handler did not timeout as expected") + + return fmt.Errorf("hard timeout: %w", hardTimeoutCtx.Err()) + } + } + } +} diff --git a/pkg/modules/api/middlewares_test.go b/pkg/modules/api/middlewares_test.go new file mode 100644 index 00000000..fc61def7 --- /dev/null +++ b/pkg/modules/api/middlewares_test.go @@ -0,0 +1,1033 @@ +package api + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "math/rand" + "mime/multipart" + "net/http" + "net/http/httptest" + "regexp" + "strings" + "testing" + "time" + + "github.com/hashicorp/go-retryablehttp" + "github.com/labstack/echo/v4" + "go.uber.org/zap" +) + +func TestHttpErrorHandler(t *testing.T) { + for i, tc := range []struct { + err error + webhookClient *webhookClient + expectStatus int + expectMessage string + }{ + { + err: echo.ErrInternalServerError, + expectStatus: http.StatusInternalServerError, + expectMessage: http.StatusText(http.StatusInternalServerError), + }, + { + err: context.DeadlineExceeded, + expectStatus: http.StatusServiceUnavailable, + expectMessage: http.StatusText(http.StatusServiceUnavailable), + }, + { + err: WrapError( + errors.New("foo"), + NewSentinelHTTPError(http.StatusBadRequest, "foo"), + ), + expectStatus: http.StatusBadRequest, + expectMessage: "foo", + }, + { + err: echo.ErrInternalServerError, + webhookClient: &webhookClient{ + errorURL: "http://localhost:%d/", + errorMethod: http.MethodPost, + client: retryablehttp.NewClient(), + logger: zap.NewNop(), + }, + expectStatus: http.StatusInternalServerError, + expectMessage: http.StatusText(http.StatusInternalServerError), + }, + { + err: echo.ErrInternalServerError, + webhookClient: &webhookClient{ + errorURL: "non-existent", + errorMethod: http.MethodPost, + client: func() *retryablehttp.Client { + client := retryablehttp.NewClient() + client.RetryMax = 0 + + return client + }(), + logger: zap.NewNop(), + }, + }, + } { + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/foo", nil) + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(request, recorder) + c.Set("logger", zap.NewNop()) + c.Set("trace", "foo") + + if tc.webhookClient != nil { + c.Set("webhookClient", tc.webhookClient) + } + + if tc.webhookClient == nil { + handler := httpErrorHandler("Gotenberg-Trace") + handler(tc.err, c) + + contentType := recorder.Header().Get(echo.HeaderContentType) + if contentType != echo.MIMETextPlainCharsetUTF8 { + t.Errorf("test %d: expected %s '%s' but got '%s'", i, echo.HeaderContentType, echo.MIMETextPlainCharsetUTF8, contentType) + } + + // Note: we cannot test the trace header in the response here, as it is set in the trace middleware. + + if recorder.Code != tc.expectStatus { + t.Errorf("test %d: expected HTTP status code %d but got %d", i, tc.expectStatus, recorder.Code) + } + + if recorder.Body.String() != tc.expectMessage { + t.Errorf("test %d: expected message '%s' but got '%s'", i, tc.expectMessage, recorder.Body.String()) + } + + continue + } + + func() { + rand.Seed(time.Now().UnixNano()) + webhookPort := rand.Intn(65535-1+1) + 1 + + tc.webhookClient.errorURL = fmt.Sprintf(tc.webhookClient.errorURL, webhookPort) + + c.Set("webhookClient", tc.webhookClient) + + webhook := echo.New() + webhook.HideBanner = true + webhook.HidePort = true + + webhook.POST( + "/", + func() echo.HandlerFunc { + return func(c echo.Context) error { + contentType := c.Request().Header.Get(echo.HeaderContentType) + if contentType != echo.MIMEApplicationJSONCharsetUTF8 { + t.Errorf("test %d: expected %s '%s' but got '%s'", i, echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8, contentType) + } + + trace := c.Request().Header.Get("Gotenberg-Trace") + if trace != "foo" { + t.Errorf("test %d: expected %s '%s' but got '%s'", i, "Gotenberg-Trace", "foo", trace) + } + + body, err := ioutil.ReadAll(c.Request().Body) + if err != nil { + t.Fatalf("test %d: expected not error but got: %v", i, err) + } + + result := struct { + Status int `json:"status"` + Message string `json:"message"` + }{} + + err = json.Unmarshal(body, &result) + if err != nil { + t.Fatalf("test %d: expected not error but got: %v", i, err) + } + + if result.Status != tc.expectStatus { + t.Errorf("test %d: expected status %d from JSON but got %d", i, tc.expectStatus, result.Status) + } + + if result.Message != tc.expectMessage { + t.Errorf("test %d: expected message '%s' from JSON but got '%s'", i, tc.expectMessage, result.Message) + } + + return nil + } + }(), + ) + + go func(server *echo.Echo, port, i int) { + err := webhook.Start(fmt.Sprintf(":%d", port)) + if !errors.Is(err, http.ErrServerClosed) { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }(webhook, webhookPort, i) + + defer func() { + err := webhook.Shutdown(context.TODO()) + if err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + + handler := httpErrorHandler("Gotenberg-Trace") + handler(tc.err, c) + }() + } +} + +func TestLatencyMiddleware(t *testing.T) { + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/foo", nil) + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(request, recorder) + + err := latencyMiddleware()( + func(c echo.Context) error { + return nil + }, + )(c) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + startTime := c.Get("startTime").(time.Time) + now := time.Now() + + if now.Before(startTime) { + t.Errorf("expected start time %s to be < %s", startTime, now) + } +} + +func TestRootPathMiddleware(t *testing.T) { + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/foo", nil) + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(request, recorder) + + err := rootPathMiddleware("foo")( + func(c echo.Context) error { + return nil + }, + )(c) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + rootPath := c.Get("rootPath").(string) + + if rootPath != "foo" { + t.Errorf("expected '%s' but got '%s", "foo", rootPath) + } +} + +func TestTraceMiddleware(t *testing.T) { + for i, tc := range []struct { + trace string + }{ + { + trace: "foo", + }, + { + trace: "", + }, + } { + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/foo", nil) + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(request, recorder) + + if tc.trace != "" { + c.Request().Header.Set("Gotenberg-Trace", tc.trace) + } + + err := traceMiddleware("Gotenberg-Trace")( + func(c echo.Context) error { + return nil + }, + )(c) + + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + + trace := c.Get("trace").(string) + + if trace == "" { + t.Errorf("test %d: expected non empty trace in context", i) + } + + if tc.trace != "" && trace != tc.trace { + t.Errorf("test %d: expected context trace '%s' but got '%s'", i, tc.trace, trace) + } + + if tc.trace == "" && trace == tc.trace { + t.Errorf("test %d: expected context trace different from '%s' but got '%s'", i, tc.trace, trace) + } + + responseTrace := recorder.Header().Get("Gotenberg-Trace") + + if tc.trace != "" && responseTrace != tc.trace { + t.Errorf("test %d: expected header trace '%s' but got '%s'", i, tc.trace, responseTrace) + } + + if tc.trace == "" && responseTrace == tc.trace { + t.Errorf("test %d: expected header trace different from '%s' but got '%s'", i, tc.trace, responseTrace) + } + } +} + +func TestLoggerMiddleware(t *testing.T) { + for i, tc := range []struct { + request *http.Request + next echo.HandlerFunc + skipHealthRouteLogging bool + }{ + { + request: httptest.NewRequest(http.MethodGet, "/", nil), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return errors.New("foo") + } + }(), + }, + { + request: httptest.NewRequest(http.MethodGet, "/health", nil), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return nil + } + }(), + skipHealthRouteLogging: true, + }, + { + request: httptest.NewRequest(http.MethodGet, "/health", nil), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return nil + } + }(), + }, + } { + recorder := httptest.NewRecorder() + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(tc.request, recorder) + c.Set("startTime", time.Now()) + c.Set("trace", "foo") + c.Set("rootPath", "/") + + err := loggerMiddleware(zap.NewNop(), tc.skipHealthRouteLogging)(tc.next)(c) + + if err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestContextMiddlewareWithoutWebhook(t *testing.T) { + buildMultipartFormDataRequest := func() *http.Request { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + defer func() { + err := writer.Close() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + }() + + err := writer.WriteField("foo", "foo") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + req := httptest.NewRequest(http.MethodPost, "/", body) + req.Header.Set(echo.HeaderContentType, writer.FormDataContentType()) + + return req + } + + for i, tc := range []struct { + request *http.Request + next echo.HandlerFunc + expectErr bool + expectContentType string + expectFilename string + }{ + { + request: httptest.NewRequest(http.MethodGet, "/", nil), + expectErr: true, + }, + { + request: buildMultipartFormDataRequest(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return errors.New("foo") + } + }(), + expectErr: true, + }, + { + request: buildMultipartFormDataRequest(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return nil + } + }(), + expectErr: true, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Output-Filename", "foo") + + return req + }(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + ctx := c.Get("context").(*Context) + ctx.outputPaths = []string{ + "/tests/test/testdata/api/sample2.pdf", + } + + return nil + } + }(), + expectContentType: "application/pdf", + expectFilename: "foo.pdf", + }, + { + request: buildMultipartFormDataRequest(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + ctx := c.Get("context").(*Context) + ctx.outputPaths = []string{ + "/tests/test/testdata/api/sample1.txt", + "/tests/test/testdata/api/sample2.pdf", + } + + return nil + } + }(), + expectContentType: "application/zip", + }, + } { + recorder := httptest.NewRecorder() + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(tc.request, recorder) + c.Set("logger", zap.NewNop()) + c.Set("trace", "foo") + c.Set("startTime", time.Now()) + + cfg := contextMiddlewareConfig{ + timeout: struct { + process time.Duration + write time.Duration + }{ + process: time.Duration(10) * time.Second, + }, + } + + err := contextMiddleware(cfg)(tc.next)(c) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + if err != nil { + continue + } + + if recorder.Code != http.StatusOK { + t.Errorf("test %d: expected HTTP status code %d but got %d", i, http.StatusOK, recorder.Code) + } + + contentType := recorder.Header().Get(echo.HeaderContentType) + if contentType != tc.expectContentType { + t.Errorf("test %d: expected %s '%s' but got '%s'", i, echo.HeaderContentType, tc.expectContentType, contentType) + } + + contentDisposition := recorder.Header().Get(echo.HeaderContentDisposition) + if !strings.Contains(contentDisposition, tc.expectFilename) { + t.Errorf("test %d: expected %s '%s' to contain '%s'", i, echo.HeaderContentDisposition, contentDisposition, tc.expectFilename) + } + } +} + +func TestContextMiddlewareWithWebhook(t *testing.T) { + buildMultipartFormDataRequest := func() *http.Request { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + defer func() { + err := writer.Close() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + }() + + err := writer.WriteField("foo", "foo") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + req := httptest.NewRequest(http.MethodPost, "/", body) + req.Header.Set(echo.HeaderContentType, writer.FormDataContentType()) + + return req + } + + buildContextMiddlewareConfig := func() contextMiddlewareConfig { + return contextMiddlewareConfig{ + traceHeader: "Gotenberg-Trace", + timeout: struct { + process time.Duration + write time.Duration + }{ + process: time.Duration(10) * time.Second, + write: time.Duration(10) * time.Second, + }, + webhook: struct { + allowList *regexp.Regexp + denyList *regexp.Regexp + errorAllowList *regexp.Regexp + errorDenyList *regexp.Regexp + maxRetry int + retryMinWait time.Duration + retryMaxWait time.Duration + disable bool + }{ + allowList: regexp.MustCompile(""), + denyList: regexp.MustCompile(""), + errorAllowList: regexp.MustCompile(""), + errorDenyList: regexp.MustCompile(""), + }, + } + } + + for i, tc := range []struct { + request *http.Request + cfg contextMiddlewareConfig + next echo.HandlerFunc + autoWebhookURLs bool + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectWebhookContentType string + expectWebhookMethod string + expectWebhookExtraHTTPHeaders map[string]string + expectWebhookFilename string + }{ + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + + return req + }(), + cfg: func() contextMiddlewareConfig { + cfg := buildContextMiddlewareConfig() + cfg.webhook.disable = true + + return cfg + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusForbidden, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + + return req + }(), + cfg: buildContextMiddlewareConfig(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + + return req + }(), + cfg: func() contextMiddlewareConfig { + cfg := buildContextMiddlewareConfig() + cfg.webhook.allowList = regexp.MustCompile("bar") + + return cfg + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusForbidden, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + + return req + }(), + cfg: func() contextMiddlewareConfig { + cfg := buildContextMiddlewareConfig() + cfg.webhook.denyList = regexp.MustCompile("foo") + + return cfg + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusForbidden, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + + return req + }(), + cfg: func() contextMiddlewareConfig { + cfg := buildContextMiddlewareConfig() + cfg.webhook.errorAllowList = regexp.MustCompile("foo") + + return cfg + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusForbidden, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + + return req + }(), + cfg: func() contextMiddlewareConfig { + cfg := buildContextMiddlewareConfig() + cfg.webhook.errorDenyList = regexp.MustCompile("bar") + + return cfg + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusForbidden, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Method", http.MethodGet) + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + + return req + }(), + cfg: buildContextMiddlewareConfig(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + req.Header.Set("Gotenberg-Webhook-Error-Method", http.MethodGet) + + return req + }(), + cfg: buildContextMiddlewareConfig(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Method", http.MethodPost) + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + req.Header.Set("Gotenberg-Webhook-Error-Method", http.MethodGet) + + return req + }(), + cfg: buildContextMiddlewareConfig(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Method", http.MethodPatch) + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + req.Header.Set("Gotenberg-Webhook-Error-Method", http.MethodGet) + + return req + }(), + cfg: buildContextMiddlewareConfig(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Method", http.MethodPut) + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + req.Header.Set("Gotenberg-Webhook-Error-Method", http.MethodGet) + + return req + }(), + cfg: buildContextMiddlewareConfig(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Webhook-Url", "foo") + req.Header.Set("Gotenberg-Webhook-Error-Url", "bar") + req.Header.Set("Gotenberg-Webhook-Extra-Http-Headers", "foo") + + return req + }(), + cfg: buildContextMiddlewareConfig(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + request: buildMultipartFormDataRequest(), + cfg: buildContextMiddlewareConfig(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return errors.New("foo") + } + }(), + autoWebhookURLs: true, + expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8, + expectWebhookMethod: http.MethodPost, + }, + { + request: buildMultipartFormDataRequest(), + cfg: buildContextMiddlewareConfig(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return nil + } + }(), + autoWebhookURLs: true, + expectWebhookContentType: echo.MIMEApplicationJSONCharsetUTF8, + expectWebhookMethod: http.MethodPost, + }, + { + request: func() *http.Request { + req := buildMultipartFormDataRequest() + req.Header.Set("Gotenberg-Output-Filename", "foo") + req.Header.Set("Gotenberg-Webhook-Extra-Http-Headers", `{ "foo": "bar" }`) + + return req + }(), + cfg: buildContextMiddlewareConfig(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + ctx := c.Get("context").(*Context) + ctx.outputPaths = []string{ + "/tests/test/testdata/api/sample2.pdf", + } + + return nil + } + }(), + autoWebhookURLs: true, + expectWebhookContentType: "application/pdf", + expectWebhookMethod: http.MethodPost, + expectWebhookFilename: "foo", + expectWebhookExtraHTTPHeaders: map[string]string{"foo": "bar"}, + }, + { + request: buildMultipartFormDataRequest(), + cfg: buildContextMiddlewareConfig(), + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + ctx := c.Get("context").(*Context) + ctx.outputPaths = []string{ + "/tests/test/testdata/api/sample1.txt", + "/tests/test/testdata/api/sample2.pdf", + } + + return nil + } + }(), + autoWebhookURLs: true, + expectWebhookContentType: "application/zip", + expectWebhookMethod: http.MethodPost, + }, + } { + func() { + recorder := httptest.NewRecorder() + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + srv.HTTPErrorHandler = httpErrorHandler(tc.cfg.traceHeader) + + c := srv.NewContext(tc.request, recorder) + c.Set("logger", zap.NewNop()) + c.Set("trace", "foo") + c.Set("startTime", time.Now()) + + webhook := echo.New() + webhook.HideBanner = true + webhook.HidePort = true + + rand.Seed(time.Now().UnixNano()) + webhookPort := rand.Intn(65535-1+1) + 1 + + if tc.autoWebhookURLs { + c.Request().Header.Set("Gotenberg-Webhook-Url", fmt.Sprintf("http://localhost:%d/", webhookPort)) + c.Request().Header.Set("Gotenberg-Webhook-Error-Url", fmt.Sprintf("http://localhost:%d/", webhookPort)) + } + + errChan := make(chan error, 1) + + webhook.POST( + "/", + func() echo.HandlerFunc { + return func(c echo.Context) error { + contentType := c.Request().Header.Get(echo.HeaderContentType) + if contentType != tc.expectWebhookContentType { + t.Errorf("test %d: expected %s '%s' but got '%s'", i, echo.HeaderContentType, tc.expectWebhookContentType, contentType) + } + + trace := c.Request().Header.Get(tc.cfg.traceHeader) + if trace != "foo" { + t.Errorf("test %d: expected %s '%s' but got '%s'", i, "Gotenberg-Trace", "foo", trace) + } + + method := c.Request().Method + if method != tc.expectWebhookMethod { + t.Errorf("test %d: expected HTTP method '%s' but got '%s'", i, tc.expectWebhookMethod, method) + } + + for key, expect := range tc.expectWebhookExtraHTTPHeaders { + actual := c.Request().Header.Get(key) + + if actual != expect { + t.Errorf("test %d: expected %s '%s' but got '%s'", i, key, expect, actual) + } + } + + if tc.expectWebhookContentType == echo.MIMEApplicationJSONCharsetUTF8 { + errChan <- nil + return nil + } + + contentLength := c.Request().Header.Get(echo.HeaderContentLength) + if contentLength == "" { + t.Errorf("test %d: expected non empty %s", i, echo.HeaderContentLength) + } + + contentDisposition := c.Request().Header.Get(echo.HeaderContentDisposition) + if !strings.Contains(contentDisposition, tc.expectWebhookFilename) { + t.Errorf("test %d: expected %s '%s' to contain '%s'", i, echo.HeaderContentDisposition, contentDisposition, tc.expectWebhookFilename) + } + + body, err := ioutil.ReadAll(c.Request().Body) + if err != nil { + errChan <- err + return nil + } + + if body == nil || len(body) == 0 { + t.Errorf("test %d: expected non nil body", i) + } + + errChan <- nil + return nil + } + }(), + ) + + go func(server *echo.Echo, port, i int) { + err := server.Start(fmt.Sprintf(":%d", webhookPort)) + if !errors.Is(err, http.ErrServerClosed) { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }(webhook, webhookPort, i) + + defer func() { + err := webhook.Shutdown(context.TODO()) + if err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + + err := contextMiddleware(tc.cfg)(tc.next)(c) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if err != nil { + return + } + + if recorder.Code != http.StatusNoContent { + t.Errorf("test %d: expected HTTP status code %d but got %d", i, http.StatusNoContent, recorder.Code) + } + + err = <-errChan + if err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + } +} + +func TestTimeoutMiddleware(t *testing.T) { + for i, tc := range []struct { + next echo.HandlerFunc + timeout time.Duration + expectErr bool + expectHardTimeout bool + }{ + { + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return nil + } + }(), + timeout: time.Duration(100) * time.Millisecond, + }, + { + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + panic("foo") + } + }(), + timeout: time.Duration(100) * time.Millisecond, + expectErr: true, + expectHardTimeout: true, + }, + { + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + return errors.New("foo") + } + }(), + timeout: time.Duration(100) * time.Millisecond, + expectErr: true, + }, + { + next: func() echo.HandlerFunc { + return func(c echo.Context) error { + time.Sleep(time.Duration(200) * time.Millisecond) + + return nil + } + }(), + timeout: time.Duration(100) * time.Millisecond, + expectErr: true, + expectHardTimeout: true, + }, + } { + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/foo", nil) + + srv := echo.New() + srv.HideBanner = true + srv.HidePort = true + + c := srv.NewContext(request, recorder) + c.Set("logger", zap.NewNop()) + + err := timeoutMiddleware(tc.timeout)(tc.next)(c) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var isHardTimeout bool + if err != nil { + isHardTimeout = strings.Contains(err.Error(), "hard timeout") + } + + if tc.expectHardTimeout && !isHardTimeout { + t.Errorf("test %d: expected hard timeout error but got: %v", i, err) + } + + if !tc.expectHardTimeout && isHardTimeout { + t.Errorf("test %d: expected no hard timeout error but got one: %v", i, err) + } + } +} diff --git a/pkg/modules/api/webhook.go b/pkg/modules/api/webhook.go new file mode 100644 index 00000000..f186b21a --- /dev/null +++ b/pkg/modules/api/webhook.go @@ -0,0 +1,139 @@ +package api + +import ( + "fmt" + "io" + "strconv" + "time" + + "github.com/hashicorp/go-retryablehttp" + "github.com/labstack/echo/v4" + "go.uber.org/zap" +) + +// webhookClient gathers all the data required to send a request to a webhook. +type webhookClient struct { + url string + method string + errorURL string + errorMethod string + extraHTTPHeaders map[string]string + startTime time.Time + + client *retryablehttp.Client + logger *zap.Logger +} + +// send call the webhook either to send the success response or the error response. +func (webhook webhookClient) send(body io.Reader, headers map[string]string, erroed bool) error { + URL := webhook.url + if erroed { + URL = webhook.errorURL + } + + method := webhook.method + if erroed { + method = webhook.errorMethod + } + + req, err := retryablehttp.NewRequest(method, URL, body) + if err != nil { + return fmt.Errorf("create '%s' request to '%s': %w", method, URL, err) + } + + req.Header.Set("User-Agent", "Gotenberg") + + // Extra HTTP headers are the custom headers from the user. + for key, value := range webhook.extraHTTPHeaders { + req.Header.Set(key, value) + } + + // Middleware caller's headers > extra HTTP headers from the user. + + contentLength, ok := headers[echo.HeaderContentLength] + if ok { + // Golang "http" package should automatically calculate the size of the + // body. But, when using a buffered file reader, it does not work. + // Worse, the "Content-Length" header is also removed. Therefore, in + // order to keep this valuable information, we have to trust the caller + // by reading the value of the "Content-Length" entry and set it as the + // content length of the request. It's kinda sub-optimal, but hey, at + // least it works. + + bodySize, err := strconv.ParseInt(contentLength, 10, 64) + + if err != nil { + return fmt.Errorf("parse content length entry: %w", err) + } + + req.ContentLength = bodySize + } + + for key, value := range headers { + req.Header.Set(key, value) + } + + resp, err := webhook.client.Do(req) + if err != nil { + return fmt.Errorf("send '%s' request to '%s': %w", method, URL, err) + } + + defer func() { + err := resp.Body.Close() + if err != nil { + webhook.logger.Error(fmt.Sprintf("close response body from '%s': %s", URL, err)) + } + }() + + // Last piece for calculating the latency. + finishTime := time.Now() + + // Now let's log! + fields := make([]zap.Field, 5) + fields[0] = zap.String("webhook_url", URL) + fields[1] = zap.String("method", method) + fields[2] = zap.Int64("latency", int64(finishTime.Sub(webhook.startTime))) + fields[3] = zap.String("latency_human", finishTime.Sub(webhook.startTime).String()) + fields[4] = zap.Int64("bytes_out", req.ContentLength) + + if erroed { + webhook.logger.Warn("request to webhook with error details handled", fields...) + + return nil + } + + webhook.logger.Info("request to webhook handled", fields...) + + return nil +} + +// leveledLogger is wrapper around a zap.Logger which is used by the +// retryablehttp.Client. +type leveledLogger struct { + logger *zap.Logger +} + +// Error logs a message at error level using the wrapped zap.Logger. +func (leveled leveledLogger) Error(msg string, keysAndValues ...interface{}) { + leveled.logger.Error(fmt.Sprintf("%s: %+v", msg, keysAndValues)) +} + +// Warn logs a message at warning level using the wrapped zap.Logger. +func (leveled leveledLogger) Warn(msg string, keysAndValues ...interface{}) { + leveled.logger.Warn(fmt.Sprintf("%s: %+v", msg, keysAndValues)) +} + +// Info logs a message at info level using the wrapped zap.Logger. +func (leveled leveledLogger) Info(msg string, keysAndValues ...interface{}) { + leveled.logger.Info(fmt.Sprintf("%s: %+v", msg, keysAndValues)) +} + +// Debug logs a message at debug level using the wrapped zap.Logger. +func (leveled leveledLogger) Debug(msg string, keysAndValues ...interface{}) { + leveled.logger.Debug(fmt.Sprintf("%s: %+v", msg, keysAndValues)) +} + +// Interface guards. +var ( + _ retryablehttp.LeveledLogger = (*leveledLogger)(nil) +) diff --git a/pkg/modules/api/webhook_test.go b/pkg/modules/api/webhook_test.go new file mode 100644 index 00000000..5c72df3c --- /dev/null +++ b/pkg/modules/api/webhook_test.go @@ -0,0 +1,23 @@ +package api + +import ( + "testing" + + "go.uber.org/zap" +) + +func TestLeveledLogger_Error(t *testing.T) { + leveledLogger{logger: zap.NewNop()}.Error("foo") +} + +func TestLeveledLogger_Warn(t *testing.T) { + leveledLogger{logger: zap.NewNop()}.Warn("foo") +} + +func TestLeveledLogger_Info(t *testing.T) { + leveledLogger{logger: zap.NewNop()}.Info("foo") +} + +func TestLeveledLogger_Debug(t *testing.T) { + leveledLogger{logger: zap.NewNop()}.Debug("foo") +} diff --git a/pkg/modules/chromium/chromium.go b/pkg/modules/chromium/chromium.go new file mode 100644 index 00000000..6b54d789 --- /dev/null +++ b/pkg/modules/chromium/chromium.go @@ -0,0 +1,484 @@ +package chromium + +import ( + "context" + "errors" + "fmt" + "io/ioutil" + "os" + "regexp" + "strings" + "time" + + "github.com/chromedp/cdproto/fetch" + "github.com/chromedp/cdproto/network" + "github.com/chromedp/cdproto/page" + "github.com/chromedp/chromedp" + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + flag "github.com/spf13/pflag" + "go.uber.org/zap" +) + +func init() { + gotenberg.MustRegisterModule(Chromium{}) +} + +var ( + // ErrURLNotAuthorized happens if a URL is not acceptable according to the + // allowed/denied lists. + ErrURLNotAuthorized = errors.New("URL not authorized") + + // ErrInvalidPrinterSettings happens if the Options have one or more + // aberrant values. + ErrInvalidPrinterSettings = errors.New("invalid printer settings") + + // ErrPageRangesSyntaxError happens if the Options have an invalid page + // ranges. + ErrPageRangesSyntaxError = errors.New("page ranges syntax error") + + // ErrRpccMessageTooLarge happens when the messages received by + // ChromeDevTools are larger than 100 MB. + ErrRpccMessageTooLarge = errors.New("rpcc message too large") +) + +// Chromium is a module which provides both an API and routes for converting +// HTML document to PDF. +type Chromium struct { + binPath string + engine gotenberg.PDFEngine + userAgent string + incognito bool + ignoreCertificateErrors bool + allowList *regexp.Regexp + denyList *regexp.Regexp + disableRoutes bool +} + +// Options are the available options for converting HTML document to PDF. +type Options struct { + // WaitDelay is the duration to wait when loading an HTML document before + // converting it to PDF. + // Optional. + WaitDelay time.Duration + + // WaitWindowStatus is the window.status value to wait for before + // converting an HTML document to PDF. + // Optional. + WaitWindowStatus string + + // ExtraHTTPHeaders are the HTTP headers to send by Chromium while loading + // the HTML document. + // Optional. + ExtraHTTPHeaders map[string]string + + // Landscape sets the paper orientation. + // Optional. + Landscape bool + + // PrintBackground prints the background graphics. + // Optional. + PrintBackground bool + + // Scale is the scale of the page rendering. + // Optional. + Scale float64 + + // PaperWidth is the paper width, in inches. + // Optional. + PaperWidth float64 + + // PaperHeight is the paper height, in inches. + // Optional. + PaperHeight float64 + + // MarginTop is the top margin, in inches. + // Optional. + MarginTop float64 + + // MarginBottom is the bottom margin, in inches. + // Optional. + MarginBottom float64 + + // MarginLeft is the left margin, in inches. + // Optional. + MarginLeft float64 + + // MarginRight is the right margin, in inches. + // Optional. + MarginRight float64 + + // Page ranges to print, e.g., '1-5, 8, 11-13'. Empty means all pages. + // Optional. + PageRanges string + + // HeaderTemplate is the HTML template of the header. It should be valid + // HTML markup with following classes used to inject printing values into + // them: + // - date: formatted print date + // - title: document title + // - url: document location + // - pageNumber: current page number + // - totalPages: total pages in the document + // For example, would generate span containing + // the title. + // Optional. + HeaderTemplate string + + // FooterTemplate is the HTML template of the footer. It should use the + // same format as the HeaderTemplate. + // Optional. + FooterTemplate string + + // PreferCSSPageSize defines whether to prefer page size as defined by CSS. + // If false, the content will be scaled to fit the paper size. + // Optional. + PreferCSSPageSize bool +} + +// DefaultOptions returns the default values for Options. +func DefaultOptions() Options { + return Options{ + WaitDelay: 0, + WaitWindowStatus: "", + ExtraHTTPHeaders: nil, + Landscape: false, + PrintBackground: false, + Scale: 1.0, + PaperWidth: 8.5, + PaperHeight: 11, + MarginTop: 0.39, + MarginBottom: 0.39, + MarginLeft: 0.39, + MarginRight: 0.39, + PageRanges: "", + HeaderTemplate: "", + FooterTemplate: "", + PreferCSSPageSize: false, + } +} + +// API helps to interact with Chromium for converting HTML documents to PDF. +type API interface { + PDF(ctx context.Context, logger *zap.Logger, URL, outputPath string, options Options) error +} + +// Provider is a module interface which exposes a method for creating an API +// for other modules. +// +// func (m *YourModule) Provision(ctx *gotenberg.Context) error { +// provider, _ := ctx.Module(new(chromium.Provider)) +// chromium, _ := provider.(chromium.Provider).Chromium() +// } +type Provider interface { + Chromium() (API, error) +} + +// Descriptor returns a Chromium's module descriptor. +func (mod Chromium) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "chromium", + FlagSet: func() *flag.FlagSet { + fs := flag.NewFlagSet("chromium", flag.ExitOnError) + fs.String("chromium-user-agent", "", "Override the default User-Agent header") + fs.Bool("chromium-incognito", false, "Start Chromium with incognito mode") + fs.Bool("chromium-ignore-certificate-errors", false, "Ignore the certificate errors") + fs.String("chromium-allow-list", "", "Set the allowed URLs for Chromium using a regular expression") + fs.String("chromium-deny-list", "^file:///[^tmp].*", "Set the denied URLs for Chromium using a regular expression") + fs.Bool("chromium-disable-routes", false, "Disable the routes") + + return fs + }(), + New: func() gotenberg.Module { return new(Chromium) }, + } +} + +// Provision sets the module properties. +func (mod *Chromium) Provision(ctx *gotenberg.Context) error { + flags := ctx.ParsedFlags() + mod.ignoreCertificateErrors = flags.MustBool("chromium-ignore-certificate-errors") + mod.allowList = flags.MustRegexp("chromium-allow-list") + mod.denyList = flags.MustRegexp("chromium-deny-list") + mod.disableRoutes = flags.MustBool("chromium-disable-routes") + + binPath, ok := os.LookupEnv("CHROMIUM_BIN_PATH") + if !ok { + return errors.New("CHROMIUM_BIN_PATH environment variable is not set") + } + + mod.binPath = binPath + + provider, err := ctx.Module(new(gotenberg.PDFEngineProvider)) + if err != nil { + return fmt.Errorf("get PDF engine provider: %w", err) + } + + engine, err := provider.(gotenberg.PDFEngineProvider).PDFEngine() + if err != nil { + return fmt.Errorf("get PDF engine: %w", err) + } + + mod.engine = engine + + return nil +} + +// Validate validates the module properties. +func (mod Chromium) Validate() error { + _, err := os.Stat(mod.binPath) + if os.IsNotExist(err) { + return fmt.Errorf("chromium binary path does not exist: %w", err) + } + + return nil +} + +// Chromium returns an API for interacting with Chromium for converting HTML +// documents to PDF. +func (mod Chromium) Chromium() (API, error) { + return mod, nil +} + +// Routes returns the API routes. +func (mod Chromium) Routes() ([]api.MultipartFormDataRoute, error) { + if mod.disableRoutes { + return nil, nil + } + + return []api.MultipartFormDataRoute{ + convertURLRoute(mod, mod.engine), + convertHTMLRoute(mod, mod.engine), + convertMarkdownRoute(mod, mod.engine), + }, nil +} + +// PDF converts a URL to PDF. It creates a dedicated Chromium instance. +// Substantial calls to this method may increase CPU and memory usage +// drastically. In such a scenario, the given context may also be done before +// the end of the conversion. +func (mod Chromium) PDF(ctx context.Context, logger *zap.Logger, URL, outputPath string, options Options) error { + userProfileDirPath := gotenberg.NewDirPath() + + args := append(chromedp.DefaultExecAllocatorOptions[:], + chromedp.ExecPath(mod.binPath), + chromedp.NoSandbox, + // See: + // https://github.com/puppeteer/puppeteer/issues/661 + // https://github.com/puppeteer/puppeteer/issues/2410 + chromedp.Flag("font-render-hinting", "none"), + chromedp.UserDataDir(userProfileDirPath), + ) + + if mod.userAgent != "" { + args = append(args, chromedp.UserAgent(mod.userAgent)) + } + + if mod.incognito { + args = append(args, chromedp.Flag("incognito", mod.incognito)) + } + + if mod.ignoreCertificateErrors { + args = append(args, chromedp.IgnoreCertErrors) + } + + allocatorCtx, cancel := chromedp.NewExecAllocator(ctx, args...) + defer cancel() + + taskCtx, cancel := chromedp.NewContext(allocatorCtx) + defer cancel() + + // We validate the "main" URL against our allow / deny lists. + if !mod.allowList.MatchString(URL) { + return fmt.Errorf("'%s' does not match the expression from the allowed list: %w", URL, ErrURLNotAuthorized) + } + + if mod.denyList.String() != "" && mod.denyList.MatchString(URL) { + return fmt.Errorf("'%s' matches the expression from the denied list: %w", URL, ErrURLNotAuthorized) + } + + printToPDF := func(URL string, options Options, result *[]byte) chromedp.Tasks { + // We validate the underlying requests against our allow / deny lists. + // If a request does not pass the validation, we make it fail. + listenForEventRequestPaused(taskCtx, logger, mod.allowList, mod.denyList) + + return chromedp.Tasks{ + network.Enable(), + fetch.Enable(), + chromedp.ActionFunc(func(ctx context.Context) error { + if len(options.ExtraHTTPHeaders) == 0 { + logger.Debug("no extra HTTP headers") + + return nil + } + + logger.Debug(fmt.Sprintf("extra HTTP headers: %+v", options.ExtraHTTPHeaders)) + + headers := make(network.Headers, len(options.ExtraHTTPHeaders)) + for key, value := range options.ExtraHTTPHeaders { + headers[key] = value + } + + err := network.SetExtraHTTPHeaders(headers).Do(ctx) + if err == nil { + return nil + } + + return fmt.Errorf("set extra HTTP headers: %w", err) + }), + chromedp.ActionFunc(func(ctx context.Context) error { + logger.Debug(fmt.Sprintf("navigate to '%s'", URL)) + + _, _, _, err := page.Navigate(URL).Do(ctx) + if err != nil { + return fmt.Errorf("navigate to '%s': %w", URL, err) + } + + err = runBatch( + ctx, + waitForEventDomContentEventFired(ctx, logger), + waitForEventLoadEventFired(ctx, logger), + waitForEventNetworkIdle(ctx, logger), + waitForEventLoadingFinished(ctx, logger), + ) + + if err == nil { + return nil + } + + return fmt.Errorf("wait for events: %w", err) + }), + chromedp.ActionFunc(func(ctx context.Context) error { + if options.WaitDelay > 0 { + // We wait for a given amount of time so that JavaScript + // scripts have a chance to finish before printing the page + // to PDF. + logger.Debug(fmt.Sprintf("wait '%s' before print", options.WaitDelay)) + + select { + case <-ctx.Done(): + return fmt.Errorf("wait delay: %w", ctx.Err()) + case <-time.After(options.WaitDelay): + return nil + } + } + + return nil + }), + chromedp.ActionFunc(func(ctx context.Context) error { + if options.WaitWindowStatus == "" { + return nil + } + + // We wait until the evaluation of + // "window.status === options.WaitWindowStatus" is true or + // until the context is done. + logger.Debug(fmt.Sprintf("wait for window.status === '%s' before print", options.WaitWindowStatus)) + + ticker := time.NewTicker(time.Duration(100) * time.Millisecond) + + for { + select { + case <-ctx.Done(): + ticker.Stop() + + return fmt.Errorf("wait for window.status === '%s': %w", options.WaitWindowStatus, ctx.Err()) + case <-ticker.C: + var ok bool + + evaluate := chromedp.Evaluate(fmt.Sprintf("window.status === '%s'", options.WaitWindowStatus), &ok) + err := evaluate.Do(ctx) + + if err != nil { + return fmt.Errorf("evaluate: %w", err) + } + + if ok { + ticker.Stop() + + return nil + } + + continue + } + } + }), + chromedp.ActionFunc(func(ctx context.Context) error { + printToPDF := page.PrintToPDF(). + WithLandscape(options.Landscape). + WithPrintBackground(options.PrintBackground). + WithScale(options.Scale). + WithPaperWidth(options.PaperWidth). + WithPaperHeight(options.PaperHeight). + WithMarginTop(options.MarginTop). + WithMarginBottom(options.MarginBottom). + WithMarginLeft(options.MarginLeft). + WithMarginRight(options.MarginRight). + WithIgnoreInvalidPageRanges(false). + WithPageRanges(options.PageRanges). + WithDisplayHeaderFooter(true). + WithHeaderTemplate(options.HeaderTemplate). + WithFooterTemplate(options.FooterTemplate). + WithPreferCSSPageSize(options.PreferCSSPageSize) + + logger.Debug(fmt.Sprintf("print to PDF with: %+v", printToPDF)) + + data, _, err := printToPDF.Do(ctx) + if err != nil { + return fmt.Errorf("print to PDF: %w", err) + } + + *result = data + + return nil + }), + } + } + + var buffer []byte + err := chromedp.Run(taskCtx, printToPDF(URL, options, &buffer)) + + // Always remove the user profile directory created by Chromium. + go func() { + logger.Debug(fmt.Sprintf("remove user profile directory '%s'", userProfileDirPath)) + + err := os.RemoveAll(userProfileDirPath) + if err != nil { + logger.Error(fmt.Sprintf("remove user profile directory: %s", err)) + } + }() + + if err != nil { + errMessage := err.Error() + + if strings.Contains(errMessage, "Show invalid printer settings error (-32000)") { + return ErrInvalidPrinterSettings + } + + if strings.Contains(errMessage, "Page range syntax error") { + return ErrPageRangesSyntaxError + } + + if strings.Contains(errMessage, "rpcc: message too large") { + return ErrRpccMessageTooLarge + } + + return fmt.Errorf("chromium PDF: %w", err) + } + + err = ioutil.WriteFile(outputPath, buffer, 0600) + if err != nil { + return fmt.Errorf("write result to output path: %w", err) + } + + return nil +} + +// Interface guards. +var ( + _ gotenberg.Module = (*Chromium)(nil) + _ gotenberg.Provisioner = (*Chromium)(nil) + _ gotenberg.Validator = (*Chromium)(nil) + _ api.MultipartFormDataRouter = (*Chromium)(nil) + _ API = (*Chromium)(nil) + _ Provider = (*Chromium)(nil) +) diff --git a/pkg/modules/chromium/chromium_test.go b/pkg/modules/chromium/chromium_test.go new file mode 100644 index 00000000..8c1e374d --- /dev/null +++ b/pkg/modules/chromium/chromium_test.go @@ -0,0 +1,373 @@ +package chromium + +import ( + "context" + "errors" + "io/ioutil" + "os" + "reflect" + "regexp" + "testing" + "time" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +type ProtoModule struct { + descriptor func() gotenberg.ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() gotenberg.ModuleDescriptor { + return mod.descriptor() +} + +type ProtoAPI struct { + pdf func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error +} + +func (mod ProtoAPI) PDF(ctx context.Context, logger *zap.Logger, URL, outputPath string, options Options) error { + return mod.pdf(ctx, logger, URL, outputPath, options) +} + +type ProtoPDFEngineProvider struct { + ProtoModule + pdfEngine func() (gotenberg.PDFEngine, error) +} + +func (mod ProtoPDFEngineProvider) PDFEngine() (gotenberg.PDFEngine, error) { + return mod.pdfEngine() +} + +type ProtoPDFEngine struct { + merge func(_ context.Context, _ *zap.Logger, _ []string, _ string) error + convert func(_ context.Context, _ *zap.Logger, _, _, _ string) error +} + +func (mod ProtoPDFEngine) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error { + return mod.merge(ctx, logger, inputPaths, outputPath) +} + +func (mod ProtoPDFEngine) Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error { + return mod.convert(ctx, logger, format, inputPath, outputPath) +} + +func TestDefaultOptions(t *testing.T) { + actual := DefaultOptions() + notExpect := Options{} + + if reflect.DeepEqual(actual, notExpect) { + t.Errorf("expected %v and got identical %v", actual, notExpect) + } +} + +func TestChromium_Descriptor(t *testing.T) { + descriptor := Chromium{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(Chromium)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestChromium_Provision(t *testing.T) { + for i, tc := range []struct { + ctx *gotenberg.Context + expectErr bool + }{ + { + ctx: func() *gotenberg.Context { + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(Chromium).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{}, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoPDFEngineProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod }} + } + mod.pdfEngine = func() (gotenberg.PDFEngine, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(Chromium).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoPDFEngineProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod }} + } + mod.pdfEngine = func() (gotenberg.PDFEngine, error) { + return struct{ ProtoPDFEngine }{}, nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(Chromium).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + }, + } { + mod := new(Chromium) + err := mod.Provision(tc.ctx) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestChromium_Validate(t *testing.T) { + for i, tc := range []struct { + binPath string + expectErr bool + }{ + { + expectErr: true, + }, + { + binPath: "/foo", + expectErr: true, + }, + { + binPath: os.Getenv("CHROMIUM_BIN_PATH"), + }, + } { + mod := new(Chromium) + mod.binPath = tc.binPath + err := mod.Validate() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestChromium_Chromium(t *testing.T) { + mod := new(Chromium) + + _, err := mod.Chromium() + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestChromium_Routes(t *testing.T) { + for i, tc := range []struct { + expectRoutes int + disableRoutes bool + }{ + { + expectRoutes: 3, + }, + { + disableRoutes: true, + }, + } { + mod := new(Chromium) + mod.disableRoutes = tc.disableRoutes + + routes, err := mod.Routes() + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + + if tc.expectRoutes != len(routes) { + t.Errorf("test %d: expected %d routes but got %d", i, tc.expectRoutes, len(routes)) + } + } +} + +func TestChromium_PDF(t *testing.T) { + for i, tc := range []struct { + timeout time.Duration + cancel context.CancelFunc + URL string + options Options + userAgent string + incognito bool + ignoreCertificateErrors bool + allowList *regexp.Regexp + denyList *regexp.Regexp + expectErr bool + }{ + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + allowList: regexp.MustCompile("file:///tmp/*"), + expectErr: true, + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + denyList: regexp.MustCompile("file:///tests/*"), + expectErr: true, + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + options: Options{ + ExtraHTTPHeaders: map[string]string{ + "foo": "bar", + }, + }, + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + options: Options{ + WaitDelay: time.Duration(1) * time.Nanosecond, + }, + }, + { + timeout: time.Duration(3) * time.Second, + URL: "file:///tests/test/testdata/chromium/html/sample2/index.html", + options: Options{ + WaitWindowStatus: "foo", + }, + expectErr: true, + }, + { + timeout: time.Duration(3) * time.Second, + URL: "file:///tests/test/testdata/chromium/html/sample2/index.html", + options: Options{ + WaitWindowStatus: "ready", + }, + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + options: Options{ + MarginBottom: 100, + }, + expectErr: true, + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + options: Options{ + PageRanges: "foo", + }, + expectErr: true, + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + userAgent: "foo", + incognito: true, + ignoreCertificateErrors: true, + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample1/index.html", + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample3/index.html", + allowList: regexp.MustCompile("file:///tests/*"), + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample3/index.html", + denyList: regexp.MustCompile("file:///etc/*"), + }, + { + URL: "file:///tests/test/testdata/chromium/html/sample4/index.html", + options: Options{ + HeaderTemplate: func() string { + b, err := ioutil.ReadFile("/tests/test/testdata/chromium/url/sample2/header.html") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return string(b) + }(), + FooterTemplate: func() string { + b, err := ioutil.ReadFile("/tests/test/testdata/chromium/url/sample2/footer.html") + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return string(b) + }(), + }, + }, + } { + func() { + mod := new(Chromium) + mod.binPath = os.Getenv("CHROMIUM_BIN_PATH") + mod.userAgent = tc.userAgent + mod.incognito = tc.incognito + mod.ignoreCertificateErrors = tc.ignoreCertificateErrors + + if tc.allowList == nil { + tc.allowList = regexp.MustCompile("") + } + + if tc.denyList == nil { + tc.denyList = regexp.MustCompile("") + } + + mod.allowList = tc.allowList + mod.denyList = tc.denyList + + outputDir, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + defer func() { + err := os.RemoveAll(outputDir) + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }() + + if tc.timeout == 0 { + err = mod.PDF(context.Background(), zap.NewNop(), tc.URL, outputDir+"/foo.pdf", tc.options) + } else { + ctx, cancel := context.WithTimeout(context.Background(), tc.timeout) + defer cancel() + + err = mod.PDF(ctx, zap.NewNop(), tc.URL, outputDir+"/foo.pdf", tc.options) + } + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*ProtoModule)(nil) + _ API = (*ProtoAPI)(nil) + _ gotenberg.PDFEngineProvider = (*ProtoPDFEngineProvider)(nil) + _ gotenberg.Module = (*ProtoPDFEngineProvider)(nil) + _ gotenberg.PDFEngine = (*ProtoPDFEngine)(nil) +) diff --git a/pkg/modules/chromium/doc.go b/pkg/modules/chromium/doc.go new file mode 100644 index 00000000..0d1dd861 --- /dev/null +++ b/pkg/modules/chromium/doc.go @@ -0,0 +1,4 @@ +// Package chromium provides a module which adds routes for converting HTML +// documents to PDF. Other modules may also retrieve the API provided by this +// module. +package chromium diff --git a/pkg/modules/chromium/events.go b/pkg/modules/chromium/events.go new file mode 100644 index 00000000..510a7820 --- /dev/null +++ b/pkg/modules/chromium/events.go @@ -0,0 +1,170 @@ +package chromium + +import ( + "context" + "fmt" + "regexp" + + "github.com/chromedp/cdproto/cdp" + "github.com/chromedp/cdproto/fetch" + "github.com/chromedp/cdproto/network" + "github.com/chromedp/cdproto/page" + "github.com/chromedp/chromedp" + "go.uber.org/zap" + "golang.org/x/sync/errgroup" +) + +// listenForEventRequestPaused listens for requests to check if they are +// allowed or not. +func listenForEventRequestPaused(ctx context.Context, logger *zap.Logger, allowList *regexp.Regexp, denyList *regexp.Regexp) { + chromedp.ListenTarget(ctx, func(ev interface{}) { + switch e := ev.(type) { + case *fetch.EventRequestPaused: + go func() { + logger.Debug(fmt.Sprintf("event EventRequestPaused fired for '%s'", e.Request.URL)) + allow := true + + if !allowList.MatchString(e.Request.URL) { + logger.Warn(fmt.Sprintf("'%s' does not match the expression from the allowed list", e.Request.URL)) + allow = false + } + + if denyList.String() != "" && denyList.MatchString(e.Request.URL) { + logger.Warn(fmt.Sprintf("'%s' matches the expression from the denied list", e.Request.URL)) + allow = false + } + + cctx := chromedp.FromContext(ctx) + executorCtx := cdp.WithExecutor(ctx, cctx.Target) + + if allow { + req := fetch.ContinueRequest(e.RequestID) + err := req.Do(executorCtx) + + if err != nil { + logger.Error(fmt.Sprintf("continue request: %s", err)) + } + + return + } + + req := fetch.FailRequest(e.RequestID, network.ErrorReasonAccessDenied) + err := req.Do(executorCtx) + + if err != nil { + logger.Error(fmt.Sprintf("fail request: %s", err)) + } + }() + } + }) +} + +// waitForEventDomContentEventFired waits until the event DomContentEventFired +// is fired or the context timeout. +func waitForEventDomContentEventFired(ctx context.Context, logger *zap.Logger) func() error { + return func() error { + ch := make(chan struct{}) + cctx, cancel := context.WithCancel(ctx) + chromedp.ListenTarget(cctx, func(ev interface{}) { + switch ev.(type) { + case *page.EventDomContentEventFired: + cancel() + close(ch) + } + }) + + select { + case <-ch: + logger.Debug("event DomContentEventFired fired") + return nil + case <-ctx.Done(): + return fmt.Errorf("wait for event DomContentEventFired: %w", ctx.Err()) + } + } +} + +// waitForEventLoadEventFired waits until the event LoadEventFired is fired or +// the context timeout. +func waitForEventLoadEventFired(ctx context.Context, logger *zap.Logger) func() error { + return func() error { + ch := make(chan struct{}) + cctx, cancel := context.WithCancel(ctx) + chromedp.ListenTarget(cctx, func(ev interface{}) { + switch ev.(type) { + case *page.EventLoadEventFired: + cancel() + close(ch) + } + }) + + select { + case <-ch: + logger.Debug("event LoadEventFired fired") + return nil + case <-ctx.Done(): + return fmt.Errorf("wait for event LoadEventFired: %w", ctx.Err()) + } + } +} + +// waitForEventNetworkIdle waits until the event networkIdle is fired or the +// context timeout. +func waitForEventNetworkIdle(ctx context.Context, logger *zap.Logger) func() error { + return func() error { + ch := make(chan struct{}) + cctx, cancel := context.WithCancel(ctx) + chromedp.ListenTarget(cctx, func(ev interface{}) { + switch e := ev.(type) { + case *page.EventLifecycleEvent: + if e.Name == "networkIdle" { + cancel() + close(ch) + } + } + }) + + select { + case <-ch: + logger.Debug("event networkIdle fired") + return nil + case <-ctx.Done(): + return fmt.Errorf("wait for event networkIdle: %w", ctx.Err()) + } + } +} + +// waitForEventLoadingFinished waits until the event LoadingFinished is fired +// or the context timeout. +func waitForEventLoadingFinished(ctx context.Context, logger *zap.Logger) func() error { + return func() error { + ch := make(chan struct{}) + cctx, cancel := context.WithCancel(ctx) + chromedp.ListenTarget(cctx, func(ev interface{}) { + switch ev.(type) { + case *network.EventLoadingFinished: + cancel() + close(ch) + } + }) + + select { + case <-ch: + logger.Debug("event LoadingFinished fired") + return nil + case <-ctx.Done(): + return fmt.Errorf("wait for event LoadingFinished: %w", ctx.Err()) + } + } +} + +// runBatch runs all functions simultaneously and waits until all of them are +// completed or an error is encountered. +func runBatch(ctx context.Context, fn ...func() error) error { + eg, _ := errgroup.WithContext(ctx) + + for _, f := range fn { + eg.Go(f) + } + + return eg.Wait() +} diff --git a/pkg/modules/chromium/routes.go b/pkg/modules/chromium/routes.go new file mode 100644 index 00000000..de7f9424 --- /dev/null +++ b/pkg/modules/chromium/routes.go @@ -0,0 +1,340 @@ +package chromium + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "html/template" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + "github.com/microcosm-cc/bluemonday" + "github.com/russross/blackfriday/v2" + "go.uber.org/multierr" +) + +// FormDataChromiumPDFOptions creates Options form the form data. Fallback to +// default value if the considered key is not present. +func FormDataChromiumPDFOptions(ctx *api.Context) (*api.FormData, Options) { + defaultOptions := DefaultOptions() + + var ( + waitDelay time.Duration + waitWindowStatus string + extraHTTPHeaders map[string]string + landscape, printBackground bool + scale, paperWidth, paperHeight float64 + marginTop, marginBottom, marginLeft, marginRight float64 + pageRanges string + headerTemplate, footerTemplate string + preferCSSPageSize bool + ) + + form := ctx.FormData(). + Duration("waitDelay", &waitDelay, defaultOptions.WaitDelay). + String("waitWindowStatus", &waitWindowStatus, defaultOptions.WaitWindowStatus). + Custom("extraHttpHeaders", func(value string) error { + if value == "" { + extraHTTPHeaders = defaultOptions.ExtraHTTPHeaders + + return nil + } + + err := json.Unmarshal([]byte(value), &extraHTTPHeaders) + if err != nil { + return fmt.Errorf("unmarshal extra HTTP headers: %w", err) + } + + return nil + }). + Bool("landscape", &landscape, defaultOptions.Landscape). + Bool("printBackground", &printBackground, defaultOptions.PrintBackground). + Float64("scale", &scale, defaultOptions.Scale). + Float64("paperWidth", &paperWidth, defaultOptions.PaperWidth). + Float64("paperHeight", &paperHeight, defaultOptions.PaperHeight). + Float64("marginTop", &marginTop, defaultOptions.MarginTop). + Float64("marginBottom", &marginBottom, defaultOptions.MarginBottom). + Float64("marginLeft", &marginLeft, defaultOptions.MarginLeft). + Float64("marginRight", &marginRight, defaultOptions.MarginRight). + String("nativePageRanges", &pageRanges, defaultOptions.PageRanges). + Content("header.html", &headerTemplate, defaultOptions.HeaderTemplate). + Content("footer.html", &footerTemplate, defaultOptions.FooterTemplate). + Bool("preferCssPageSize", &preferCSSPageSize, defaultOptions.PreferCSSPageSize) + + options := Options{ + WaitDelay: waitDelay, + WaitWindowStatus: waitWindowStatus, + ExtraHTTPHeaders: extraHTTPHeaders, + Landscape: landscape, + PrintBackground: printBackground, + Scale: scale, + PaperWidth: paperWidth, + PaperHeight: paperHeight, + MarginTop: marginTop, + MarginBottom: marginBottom, + MarginLeft: marginLeft, + MarginRight: marginRight, + PageRanges: pageRanges, + HeaderTemplate: headerTemplate, + FooterTemplate: footerTemplate, + PreferCSSPageSize: preferCSSPageSize, + } + + return form, options +} + +// convertURLRoute returns an api.MultipartFormDataRoute route which can +// convert a URL to PDF. +func convertURLRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartFormDataRoute { + return api.MultipartFormDataRoute{ + Path: "/chromium/convert/url", + Handler: func(ctx *api.Context) error { + form, options := FormDataChromiumPDFOptions(ctx) + + var ( + URL string + PDFformat string + ) + + err := form. + MandatoryString("url", &URL). + String("pdfFormat", &PDFformat, ""). + Validate() + + if err != nil { + return fmt.Errorf("validate form data: %w", err) + } + + err = convertURL(ctx, chromium, engine, URL, PDFformat, options) + if err != nil { + return fmt.Errorf("convert URL to PDF: %w", err) + } + + return nil + }, + } +} + +// convertHTMLRoute returns an api.MultipartFormDataRoute route which can +// convert an HTML file to PDF. +func convertHTMLRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartFormDataRoute { + return api.MultipartFormDataRoute{ + Path: "/chromium/convert/html", + Handler: func(ctx *api.Context) error { + form, options := FormDataChromiumPDFOptions(ctx) + + var ( + inputPath string + PDFformat string + ) + + err := form. + MandatoryPath("index.html", &inputPath). + String("pdfFormat", &PDFformat, ""). + Validate() + + if err != nil { + return fmt.Errorf("validate form data: %w", err) + } + + URL := fmt.Sprintf("file://%s", inputPath) + + err = convertURL(ctx, chromium, engine, URL, PDFformat, options) + if err != nil { + return fmt.Errorf("convert HTML to PDF: %w", err) + } + + return nil + }, + } +} + +// convertMarkdownRoute returns an api.MultipartFormDataRoute route which can +// convert markdown files to PDF. +func convertMarkdownRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartFormDataRoute { + return api.MultipartFormDataRoute{ + Path: "/chromium/convert/markdown", + Handler: func(ctx *api.Context) error { + form, options := FormDataChromiumPDFOptions(ctx) + + var ( + inputPath string + markdownPaths []string + PDFformat string + ) + + err := form. + MandatoryPath("index.html", &inputPath). + MandatoryPaths([]string{".md"}, &markdownPaths). + String("pdfFormat", &PDFformat, ""). + Validate() + + if err != nil { + return fmt.Errorf("validate form data: %w", err) + } + + // We have to convert each markdown file referenced in the HTML + // file to... HTML. Thanks to the "html/template" package, we are + // able to provide the "toHTML" function which the user may call + // directly inside the HTML file. + + var markdownFilesNotFoundErr error + + tmpl, err := template. + New(filepath.Base(inputPath)). + Funcs(template.FuncMap{ + "toHTML": func(filename string) (template.HTML, error) { + var path string + + for _, markdownPath := range markdownPaths { + markdownFilename := filepath.Base(markdownPath) + + if filename == markdownFilename { + path = markdownPath + break + } + } + + if path == "" { + markdownFilesNotFoundErr = multierr.Append( + markdownFilesNotFoundErr, + fmt.Errorf("'%s'", filename), + ) + + return "", nil + } + + b, err := ioutil.ReadFile(path) + if err != nil { + return "", fmt.Errorf("read markdown file '%s': %w", filename, err) + } + + unsafe := blackfriday.Run(b) + sanitized := bluemonday.UGCPolicy().SanitizeBytes(unsafe) + + // #nosec + return template.HTML(sanitized), nil + }, + }).ParseFiles(inputPath) + + if err != nil { + return fmt.Errorf("parse template file: %w", err) + } + + var buffer bytes.Buffer + + err = tmpl.Execute(&buffer, &struct{}{}) + if err != nil { + return fmt.Errorf("execute template: %w", err) + } + + if markdownFilesNotFoundErr != nil { + return api.WrapError( + fmt.Errorf("markdown files not found: %w", markdownFilesNotFoundErr), + api.NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("Markdown file(s) not found: %s", markdownFilesNotFoundErr), + ), + ) + } + + inputPath = ctx.GeneratePath(".html") + + err = os.WriteFile(inputPath, buffer.Bytes(), 0600) + if err != nil { + return fmt.Errorf("write template result: %w", err) + } + + URL := fmt.Sprintf("file://%s", inputPath) + + err = convertURL(ctx, chromium, engine, URL, PDFformat, options) + if err != nil { + return fmt.Errorf("convert markdown to PDF: %w", err) + } + + return nil + }, + } +} + +// convertURL is a stub which is called by the other methods of this file. +func convertURL(ctx *api.Context, chromium API, engine gotenberg.PDFEngine, URL, PDFformat string, options Options) error { + outputPath := ctx.GeneratePath(".pdf") + + err := chromium.PDF(ctx, ctx.Log(), URL, outputPath, options) + if err != nil { + + if errors.Is(err, ErrURLNotAuthorized) { + return api.WrapError( + fmt.Errorf("convert to PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusForbidden, + fmt.Sprintf("'%s' does not match the authorized URLs", URL), + ), + ) + } + + if errors.Is(err, ErrInvalidPrinterSettings) { + return api.WrapError( + fmt.Errorf("convert to PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusBadRequest, + "Chromium does not handle the provided settings; please check for aberrant form values", + ), + ) + } + + if errors.Is(err, ErrPageRangesSyntaxError) { + return api.WrapError( + fmt.Errorf("convert to PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("Chromium does not handle the page ranges '%s' (nativePageRanges)", options.PageRanges), + ), + ) + } + + return fmt.Errorf("convert to PDF: %w", err) + } + + // So far so good, the URL has been converted to PDF. + // Now, let's check if the client want to convert this result PDF + // to a specific PDF format. + + if PDFformat != "" { + convertInputPath := outputPath + convertOutputPath := ctx.GeneratePath(".pdf") + + err = engine.Convert(ctx, ctx.Log(), PDFformat, convertInputPath, convertOutputPath) + + if err != nil { + if errors.Is(err, gotenberg.ErrPDFFormatNotAvailable) { + return api.WrapError( + fmt.Errorf("convert PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("At least one PDF engine does not handle the PDF format '%s' (pdfFormat), while other have failed to convert for other reasons", PDFformat), + ), + ) + } + + return fmt.Errorf("convert PDF: %w", err) + } + + // Important: the output path is now the converted file. + outputPath = convertOutputPath + } + + err = ctx.AddOutputPaths(outputPath) + if err != nil { + return fmt.Errorf("add output path: %w", err) + } + + return nil +} diff --git a/pkg/modules/chromium/routes_test.go b/pkg/modules/chromium/routes_test.go new file mode 100644 index 00000000..d351b18d --- /dev/null +++ b/pkg/modules/chromium/routes_test.go @@ -0,0 +1,676 @@ +package chromium + +import ( + "context" + "errors" + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "net/http" + "os" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + "go.uber.org/zap" +) + +func TestFormDataChromiumPDFOptions(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + options Options + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + options: DefaultOptions(), + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetValues(map[string][]string{ + "extraHttpHeaders": { + "foo", + }, + }) + + return ctx + }(), + options: DefaultOptions(), + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetValues(map[string][]string{ + "extraHttpHeaders": { + `{"foo":"bar"}`, + }, + }) + + return ctx + }(), + options: func() Options { + options := DefaultOptions() + options.ExtraHTTPHeaders = map[string]string{ + "foo": "bar", + } + + return options + }(), + }, + } { + _, actual := FormDataChromiumPDFOptions(tc.ctx.Context) + + if !reflect.DeepEqual(actual, tc.options) { + t.Errorf("test %d: expected %v but got: %v", i, tc.options, actual) + } + } +} + +func TestConvertURLHandler(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + api API + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectOutputPathsCount int + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetValues(map[string][]string{ + "url": { + "", + }, + }) + + return ctx + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetValues(map[string][]string{ + "url": { + "foo", + }, + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return errors.New("foo") + } + + return chromiumAPI + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetValues(map[string][]string{ + "url": { + "foo", + }, + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + expectOutputPathsCount: 1, + }, + } { + err := convertURLRoute(tc.api, nil).Handler(tc.ctx.Context) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr api.HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectOutputPathsCount, len(tc.ctx.OutputPaths())) + } + } +} + +func TestConvertHTMLHandler(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + api API + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectOutputPathsCount int + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "foo.html": "/foo/foo.html", + }) + + return ctx + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "index.html": "/foo/foo.html", + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return errors.New("foo") + } + + return chromiumAPI + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "index.html": "/foo/foo.html", + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + expectOutputPathsCount: 1, + }, + } { + err := convertHTMLRoute(tc.api, nil).Handler(tc.ctx.Context) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr api.HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectOutputPathsCount, len(tc.ctx.OutputPaths())) + } + } +} + +func TestConvertMarkdownHandler(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + api API + outputDir string + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectOutputPathsCount int + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "foo.html": "/foo/foo.html", + }) + + return ctx + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "index.html": "/foo/foo.html", + }) + + return ctx + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "index.html": "/foo/foo.html", + "markdown.md": "/foo/markdown.md", + }) + + return ctx + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "index.html": "/tests/test/testdata/chromium/markdown/sample2/index.html", + "markdown1.md": "/foo/markdown1.md", + }) + + return ctx + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "index.html": "/tests/test/testdata/chromium/markdown/sample1/index.html", + "markdown1.md": "/foo/markdown1.md", + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return errors.New("foo") + } + + return chromiumAPI + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetFiles(map[string]string{ + "index.html": "/tests/test/testdata/chromium/markdown/sample1/index.html", + "markdown1.md": "/tests/test/testdata/chromium/markdown/sample1/markdown1.md", + "markdown2.md": "/tests/test/testdata/chromium/markdown/sample1/markdown2.md", + "markdown3.md": "/tests/test/testdata/chromium/markdown/sample1/markdown3.md", + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return errors.New("foo") + } + + return chromiumAPI + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetDirPath("/tmp/foo") + ctx.SetFiles(map[string]string{ + "index.html": "/tests/test/testdata/chromium/markdown/sample1/index.html", + "markdown1.md": "/tests/test/testdata/chromium/markdown/sample1/markdown1.md", + "markdown2.md": "/tests/test/testdata/chromium/markdown/sample1/markdown2.md", + "markdown3.md": "/tests/test/testdata/chromium/markdown/sample1/markdown3.md", + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return errors.New("foo") + } + + return chromiumAPI + }(), + outputDir: "/tmp/foo", + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetDirPath("/tmp/foo") + ctx.SetFiles(map[string]string{ + "index.html": "/tests/test/testdata/chromium/markdown/sample1/index.html", + "markdown1.md": "/tests/test/testdata/chromium/markdown/sample1/markdown1.md", + "markdown2.md": "/tests/test/testdata/chromium/markdown/sample1/markdown2.md", + "markdown3.md": "/tests/test/testdata/chromium/markdown/sample1/markdown3.md", + }) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + outputDir: "/tmp/foo", + expectOutputPathsCount: 1, + }, + } { + func() { + if tc.outputDir != "" { + err := os.MkdirAll(tc.outputDir, 0755) + + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + defer func() { + err := os.RemoveAll(tc.outputDir) + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }() + } + + err := convertMarkdownRoute(tc.api, nil).Handler(tc.ctx.Context) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr api.HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectOutputPathsCount, len(tc.ctx.OutputPaths())) + } + }() + } +} + +func TestConvertURL(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + api API + engine gotenberg.PDFEngine + PDFformat string + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectOutputPathsCount int + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return ErrURLNotAuthorized + } + + return chromiumAPI + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusForbidden, + }, + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return ErrInvalidPrinterSettings + } + + return chromiumAPI + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return ErrPageRangesSyntaxError + } + + return chromiumAPI + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return errors.New("foo") + } + + return chromiumAPI + }(), + expectErr: true, + }, + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return gotenberg.ErrPDFFormatNotAvailable + }, + } + }(), + PDFformat: "foo", + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + } + }(), + PDFformat: "foo", + expectErr: true, + }, + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + PDFformat: "foo", + expectOutputPathsCount: 1, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetCancelled(true) + + return ctx + }(), + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + expectErr: true, + }, + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() API { + chromiumAPI := struct{ ProtoAPI }{} + chromiumAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ Options) error { + return nil + } + + return chromiumAPI + }(), + expectOutputPathsCount: 1, + }, + } { + err := convertURL(tc.ctx.Context, tc.api, tc.engine, "", tc.PDFformat, DefaultOptions()) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr api.HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectOutputPathsCount, len(tc.ctx.OutputPaths())) + } + } +} diff --git a/pkg/modules/gc/doc.go b/pkg/modules/gc/doc.go new file mode 100644 index 00000000..cc923b9e --- /dev/null +++ b/pkg/modules/gc/doc.go @@ -0,0 +1,3 @@ +// Package gc provides a module for removing files and directories that have +// expired. +package gc diff --git a/pkg/modules/gc/gc.go b/pkg/modules/gc/gc.go new file mode 100644 index 00000000..f3f37e86 --- /dev/null +++ b/pkg/modules/gc/gc.go @@ -0,0 +1,235 @@ +package gc + +import ( + "context" + "errors" + "fmt" + "os" + "os/signal" + "path/filepath" + "strings" + "sync" + "time" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +func init() { + gotenberg.MustRegisterModule(GarbageCollector{}) +} + +// GarbageCollector is a module for removing files and directories that have +// expired. It allows us to make sure that the application does not leak files +// or directories when running. +type GarbageCollector struct { + rootPath string + graceDuration time.Duration + excludeSubstr []string + + ticker *time.Ticker + done chan bool + + logger *zap.Logger +} + +// GarbageCollectorGraceDurationModifier is a module interface which allows to +// update the expiration time of files and directories parsed by the garbage +// collector. For instance, if the grace duration is 30s, the garbage collector +// will remove paths that have a modification time older than 30s. If there are +// many GarbageCollectorGraceDurationModifier, only the longest grace duration +// is selected. +type GarbageCollectorGraceDurationModifier interface { + GraceDuration() time.Duration +} + +// GarbageCollectorExcludeSubstrModifier is a module interface which adds the +// given substrings to the exclude list of the garbage collector. If a path +// contains one of those substrings, the garbage collector ignores it. +type GarbageCollectorExcludeSubstrModifier interface { + ExcludeSubstr() []string +} + +// Descriptor returns a GarbageCollector's module descriptor. +func (gc GarbageCollector) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "gc", + New: func() gotenberg.Module { return new(GarbageCollector) }, + } +} + +// Provision sets the module properties. +func (gc *GarbageCollector) Provision(ctx *gotenberg.Context) error { + gc.rootPath = gotenberg.TmpPath() + + graceDurationModifiers, err := ctx.Modules(new(GarbageCollectorGraceDurationModifier)) + if err != nil { + return fmt.Errorf("get grace duration modifiers: %w", err) + } + + for _, graceDurationModifier := range graceDurationModifiers { + modifier := graceDurationModifier.(GarbageCollectorGraceDurationModifier) + + if gc.graceDuration < modifier.GraceDuration() { + gc.graceDuration = modifier.GraceDuration() + } + } + + excludeSubstrModifiers, err := ctx.Modules(new(GarbageCollectorExcludeSubstrModifier)) + if err != nil { + return fmt.Errorf("get exclude substr modifiers: %w", err) + } + + gc.excludeSubstr = strings.Split(os.Getenv("GC_EXCLUDE_SUBSTR"), ",") + + for _, excludeSubstrModifier := range excludeSubstrModifiers { + modifier := excludeSubstrModifier.(GarbageCollectorExcludeSubstrModifier) + + gc.excludeSubstr = append(gc.excludeSubstr, modifier.ExcludeSubstr()...) + } + + loggerProvider, err := ctx.Module(new(gotenberg.LoggerProvider)) + if err != nil { + return fmt.Errorf("get logger provider: %w", err) + } + + logger, err := loggerProvider.(gotenberg.LoggerProvider).Logger(gc) + if err != nil { + return fmt.Errorf("get logger: %w", err) + } + + gc.logger = logger + + return nil +} + +// Start starts the garbage collector. +func (gc *GarbageCollector) Start() error { + gc.ticker = time.NewTicker(gc.graceDuration + time.Duration(1)*time.Second) + gc.done = make(chan bool, 1) + + go func() { + for { + func() { + gcMu.RLock() + defer gcMu.RUnlock() + + select { + case <-gc.done: + return + case <-gc.ticker.C: + gc.collect(false) + } + }() + } + }() + + return nil +} + +// collect parses the root path of the garbage collector and removes files or +// directories that have expired. It ignores the expiration date if the "force" +// argument is set to true. +func (gc GarbageCollector) collect(force bool) { + expirationTime := time.Now().Add(-gc.graceDuration) + + // To make sure that the next Walk method stays on + // the root level of the considered path, we have to + // return a filepath.SkipDir error if the current path + // is a directory. + skipDirOrNil := func(info os.FileInfo) error { + if info.IsDir() { + return filepath.SkipDir + } + + return nil + } + + removePath := func(path string) { + err := os.RemoveAll(path) + if err != nil { + gc.logger.Error(fmt.Sprintf("remove '%s': %s", path, err)) + } + + gc.logger.Debug(fmt.Sprintf("'%s' removed", path)) + } + + err := filepath.Walk(gc.rootPath, func(path string, info os.FileInfo, pathErr error) error { + if pathErr != nil { + // For whatever reasons, the Walk method failed + // to process the current path. + return pathErr + } + + if path == gc.rootPath { + return nil + } + + for _, substr := range gc.excludeSubstr { + if strings.Contains(info.Name(), substr) { + return skipDirOrNil(info) + } + } + + if force { + removePath(path) + + return skipDirOrNil(info) + } + + if info.ModTime().Before(expirationTime) { + removePath(path) + } + + return skipDirOrNil(info) + }) + + if err != nil { + gc.logger.Error(err.Error()) + } +} + +// StartupMessage returns an empty string. +func (gc GarbageCollector) StartupMessage() string { + return "" +} + +// Stop stops the garbage collector. +func (gc *GarbageCollector) Stop(ctx context.Context) error { + _, ok := ctx.Deadline() + if !ok { + return errors.New("no context dead line") + } + + // Block until the context is done so that other module may gracefully stop + // before we do a shutdown cleanup. We skip this step if we receive a + // SIGINT in the meantime. + gc.logger.Debug("wait for the end of grace duration") + + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt) + + select { + case <-quit: + return nil + case <-ctx.Done(): + break + } + + gc.ticker.Stop() + gc.done <- true + + gc.logger.Debug("shutdown cleanup...") + gc.collect(true) + + return nil +} + +var gcMu sync.RWMutex + +// Interface guards. +var ( + _ gotenberg.Module = (*GarbageCollector)(nil) + _ gotenberg.Provisioner = (*GarbageCollector)(nil) + _ gotenberg.App = (*GarbageCollector)(nil) +) diff --git a/pkg/modules/gc/gc_test.go b/pkg/modules/gc/gc_test.go new file mode 100644 index 00000000..adcba889 --- /dev/null +++ b/pkg/modules/gc/gc_test.go @@ -0,0 +1,468 @@ +package gc + +import ( + "context" + "errors" + "os" + "reflect" + "strings" + "testing" + "time" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +type ProtoModule struct { + descriptor func() gotenberg.ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() gotenberg.ModuleDescriptor { + return mod.descriptor() +} + +type ProtoValidator struct { + ProtoModule + validate func() error +} + +func (mod ProtoValidator) Validate() error { + return mod.validate() +} + +type ProtoGarbageCollectorGraceDurationModifier struct { + ProtoValidator + graceDuration func() time.Duration +} + +func (mod ProtoGarbageCollectorGraceDurationModifier) GraceDuration() time.Duration { + return mod.graceDuration() +} + +type ProtoGarbageCollectorExcludeSubstrModifier struct { + ProtoValidator + excludeSubstr func() []string +} + +func (mod ProtoGarbageCollectorExcludeSubstrModifier) ExcludeSubstr() []string { + return mod.excludeSubstr() +} + +type ProtoLoggerProvider struct { + ProtoModule + logger func(mod gotenberg.Module) (*zap.Logger, error) +} + +func (factory ProtoLoggerProvider) Logger(mod gotenberg.Module) (*zap.Logger, error) { + return factory.logger(mod) +} + +func TestGarbageCollector_Descriptor(t *testing.T) { + descriptor := GarbageCollector{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(GarbageCollector)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestGarbageCollector_Provision(t *testing.T) { + for i, tc := range []struct { + ctx *gotenberg.Context + expectGraceDuration time.Duration + expectExcludeSubstr []string + expectErr bool + }{ + { + ctx: func() *gotenberg.Context { + mod := struct { + ProtoGarbageCollectorGraceDurationModifier + }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { return errors.New("foo") } + + return gotenberg.NewContext(gotenberg.ParsedFlags{}, []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct { + ProtoGarbageCollectorExcludeSubstrModifier + }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.validate = func() error { return errors.New("foo") } + + return gotenberg.NewContext(gotenberg.ParsedFlags{}, []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }) + }(), + expectErr: true, + }, + { + ctx: gotenberg.NewContext(gotenberg.ParsedFlags{}, make([]gotenberg.ModuleDescriptor, 0)), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct { + ProtoLoggerProvider + }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.logger = func(mod gotenberg.Module) (*zap.Logger, error) { return nil, errors.New("foo") } + + return gotenberg.NewContext(gotenberg.ParsedFlags{}, []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct { + ProtoLoggerProvider + }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.logger = func(mod gotenberg.Module) (*zap.Logger, error) { return zap.NewNop(), nil } + + return gotenberg.NewContext(gotenberg.ParsedFlags{}, []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }) + }(), + }, + { + ctx: func() *gotenberg.Context { + mod1 := struct { + ProtoGarbageCollectorGraceDurationModifier + }{} + mod1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod1 }} + } + mod1.graceDuration = func() time.Duration { return time.Duration(10) * time.Second } + mod1.validate = func() error { return nil } + + mod2 := struct { + ProtoGarbageCollectorGraceDurationModifier + }{} + mod2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod2 }} + } + mod2.graceDuration = func() time.Duration { return time.Duration(20) * time.Second } + mod2.validate = func() error { return nil } + + mod3 := struct { + ProtoLoggerProvider + }{} + mod3.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "baz", New: func() gotenberg.Module { return mod3 }} + } + mod3.logger = func(mod gotenberg.Module) (*zap.Logger, error) { return zap.NewNop(), nil } + + return gotenberg.NewContext(gotenberg.ParsedFlags{}, []gotenberg.ModuleDescriptor{ + mod1.Descriptor(), + mod2.Descriptor(), + mod3.Descriptor(), + }) + }(), + expectGraceDuration: time.Duration(20) * time.Second, + }, + { + ctx: func() *gotenberg.Context { + mod1 := struct { + ProtoGarbageCollectorExcludeSubstrModifier + }{} + mod1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod1 }} + } + mod1.excludeSubstr = func() []string { return []string{"foo"} } + mod1.validate = func() error { return nil } + + mod2 := struct { + ProtoGarbageCollectorExcludeSubstrModifier + }{} + mod2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod2 }} + } + mod2.excludeSubstr = func() []string { return []string{"bar"} } + mod2.validate = func() error { return nil } + + mod3 := struct { + ProtoLoggerProvider + }{} + mod3.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "baz", New: func() gotenberg.Module { return mod3 }} + } + mod3.logger = func(mod gotenberg.Module) (*zap.Logger, error) { return zap.NewNop(), nil } + + return gotenberg.NewContext(gotenberg.ParsedFlags{}, []gotenberg.ModuleDescriptor{ + mod1.Descriptor(), + mod2.Descriptor(), + mod3.Descriptor(), + }) + }(), + expectExcludeSubstr: func() []string { + expect := strings.Split(os.Getenv("GC_EXCLUDE_SUBSTR"), ",") + return append(expect, "foo", "bar") + }(), + }, + } { + mod := new(GarbageCollector) + err := mod.Provision(tc.ctx) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + if tc.expectGraceDuration != 0 && tc.expectGraceDuration != mod.graceDuration { + t.Errorf("test %d: expected grace duration of '%s' but got '%s'", i, tc.expectGraceDuration, mod.graceDuration) + } + + if tc.expectExcludeSubstr != nil && !reflect.DeepEqual(tc.expectExcludeSubstr, mod.excludeSubstr) { + t.Errorf("test %d: expected exclude substr '%s' but got '%s'", i, tc.expectExcludeSubstr, mod.excludeSubstr) + } + } +} + +func TestGarbageCollector_Start(t *testing.T) { + mod := new(GarbageCollector) + mod.logger = zap.NewNop() + + path, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + mod.rootPath = path + + err = mod.Start() + if err != nil { + t.Errorf("expected no error but got: %v", err) + } + + time.Sleep(time.Duration(2) * time.Second) + mod.ticker.Stop() + mod.done <- true +} + +func TestGarbageCollector_collect(t *testing.T) { + for i, tc := range []struct { + gc *GarbageCollector + expectNotExists []string + expectExists []string + force bool + }{ + { + gc: func() *GarbageCollector { + mod := new(GarbageCollector) + mod.logger = zap.NewNop() + + path, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + mod.rootPath = path + + err = os.WriteFile(path+"/foo", []byte{1}, 0755) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + mod.excludeSubstr = []string{ + "foo", + } + + return mod + }(), + expectExists: []string{ + "/foo", + }, + }, + { + gc: func() *GarbageCollector { + mod := new(GarbageCollector) + mod.logger = zap.NewNop() + + path, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + mod.rootPath = path + + err = os.WriteFile(path+"/foo", []byte{1}, 0755) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + err = os.MkdirAll(path+"/bar", 0755) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return mod + }(), + expectNotExists: []string{ + "/foo", + "/bar", + }, + force: true, + }, + { + gc: func() *GarbageCollector { + mod := new(GarbageCollector) + mod.logger = zap.NewNop() + mod.graceDuration = time.Duration(10) * time.Second + + path, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + mod.rootPath = path + + err = os.WriteFile(path+"/foo", []byte{1}, 0755) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + newTime := time.Now().Add(-time.Duration(20) * time.Second) + err = os.Chtimes(path+"/foo", newTime, newTime) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + err = os.WriteFile(path+"/bar", []byte{1}, 0755) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + newTime = time.Now().Add(time.Duration(10) * time.Second) + err = os.Chtimes(path+"/bar", newTime, newTime) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return mod + }(), + expectNotExists: []string{ + "/foo", + }, + expectExists: []string{ + "/bar", + }, + }, + } { + tc.gc.collect(tc.force) + + for _, name := range tc.expectNotExists { + path := tc.gc.rootPath + name + _, err := os.Stat(path) + if !os.IsNotExist(err) { + t.Errorf("test %d: expected '%s' not to exist but got: %v", i, path, err) + } + } + + for _, name := range tc.expectExists { + path := tc.gc.rootPath + name + _, err := os.Stat(path) + if os.IsNotExist(err) { + t.Errorf("test %d: expected '%s' to exist but got: %v", i, path, err) + } + } + + err := os.RemoveAll(tc.gc.rootPath) + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestGarbageCollector_StartupMessage(t *testing.T) { + actual := new(GarbageCollector).StartupMessage() + expect := "" + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestGarbageCollector_Stop(t *testing.T) { + for i, tc := range []struct { + timeout time.Duration + expectErr bool + }{ + { + expectErr: true, + }, + { + timeout: time.Duration(1) * time.Nanosecond, + }, + } { + func() { + mod := new(GarbageCollector) + mod.logger = zap.NewNop() + + path, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + + mod.rootPath = path + + err = mod.Start() + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + + if tc.timeout == 0 { + err = mod.Stop(context.TODO()) + } else { + ctx, cancel := context.WithTimeout(context.Background(), tc.timeout) + defer cancel() + + err = mod.Stop(ctx) + } + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*ProtoModule)(nil) + _ gotenberg.Validator = (*ProtoValidator)(nil) + _ GarbageCollectorGraceDurationModifier = (*ProtoGarbageCollectorGraceDurationModifier)(nil) + _ gotenberg.Module = (*ProtoGarbageCollectorGraceDurationModifier)(nil) + _ gotenberg.Validator = (*ProtoGarbageCollectorGraceDurationModifier)(nil) + _ GarbageCollectorExcludeSubstrModifier = (*ProtoGarbageCollectorExcludeSubstrModifier)(nil) + _ gotenberg.Module = (*ProtoGarbageCollectorExcludeSubstrModifier)(nil) + _ gotenberg.Validator = (*ProtoGarbageCollectorExcludeSubstrModifier)(nil) + _ gotenberg.LoggerProvider = (*ProtoLoggerProvider)(nil) + _ gotenberg.Module = (*ProtoLoggerProvider)(nil) +) diff --git a/pkg/modules/libreoffice/doc.go b/pkg/modules/libreoffice/doc.go new file mode 100644 index 00000000..763f6c96 --- /dev/null +++ b/pkg/modules/libreoffice/doc.go @@ -0,0 +1,3 @@ +// Package libreoffice provides a module which adds a route for converting +// document to PDF with LibreOffice. +package libreoffice diff --git a/pkg/modules/libreoffice/libreoffice.go b/pkg/modules/libreoffice/libreoffice.go new file mode 100644 index 00000000..462c3182 --- /dev/null +++ b/pkg/modules/libreoffice/libreoffice.go @@ -0,0 +1,86 @@ +package libreoffice + +import ( + "fmt" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/unoconv" + flag "github.com/spf13/pflag" +) + +func init() { + gotenberg.MustRegisterModule(LibreOffice{}) +} + +// LibreOffice is a module which provides a route for converting documents to +// PDF with LibreOffice. +type LibreOffice struct { + unoconv unoconv.API + engine gotenberg.PDFEngine + disableRoutes bool +} + +// Descriptor returns a LibreOffice's module descriptor. +func (LibreOffice) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "libreoffice", + FlagSet: func() *flag.FlagSet { + fs := flag.NewFlagSet("libreoffice", flag.ExitOnError) + fs.Bool("libreoffice-disable-routes", false, "Disable the routes") + + return fs + }(), + New: func() gotenberg.Module { return new(LibreOffice) }, + } +} + +// Provision sets the module properties. +func (mod *LibreOffice) Provision(ctx *gotenberg.Context) error { + flags := ctx.ParsedFlags() + mod.disableRoutes = flags.MustBool("libreoffice-disable-routes") + + provider, err := ctx.Module(new(unoconv.Provider)) + if err != nil { + return fmt.Errorf("get unoconv provider: %w", err) + } + + uno, err := provider.(unoconv.Provider).Unoconv() + if err != nil { + return fmt.Errorf("get unoconv API: %w", err) + } + + mod.unoconv = uno + + provider, err = ctx.Module(new(gotenberg.PDFEngineProvider)) + if err != nil { + return fmt.Errorf("get PDF engine provider: %w", err) + } + + engine, err := provider.(gotenberg.PDFEngineProvider).PDFEngine() + if err != nil { + return fmt.Errorf("get PDF engine: %w", err) + } + + mod.engine = engine + + return nil +} + +// Routes returns the API routes. +func (mod LibreOffice) Routes() ([]api.MultipartFormDataRoute, error) { + if mod.disableRoutes { + return nil, nil + } + + return []api.MultipartFormDataRoute{ + convertRoute(mod.unoconv, mod.engine), + }, nil +} + +// Interface guards. +var ( + _ gotenberg.Module = (*LibreOffice)(nil) + _ gotenberg.Provisioner = (*LibreOffice)(nil) + _ api.MultipartFormDataRouter = (*LibreOffice)(nil) +) diff --git a/pkg/modules/libreoffice/libreoffice_test.go b/pkg/modules/libreoffice/libreoffice_test.go new file mode 100644 index 00000000..6d1d5875 --- /dev/null +++ b/pkg/modules/libreoffice/libreoffice_test.go @@ -0,0 +1,250 @@ +package libreoffice + +import ( + "context" + "errors" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/unoconv" + "go.uber.org/zap" +) + +type ProtoModule struct { + descriptor func() gotenberg.ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() gotenberg.ModuleDescriptor { + return mod.descriptor() +} + +type ProtoUnoconvProvider struct { + ProtoModule + unoconv func() (unoconv.API, error) +} + +func (mod ProtoUnoconvProvider) Unoconv() (unoconv.API, error) { + return mod.unoconv() +} + +type ProtoUnoconvAPI struct { + pdf func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error + extensions func() []string +} + +func (mod ProtoUnoconvAPI) PDF(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options unoconv.Options) error { + return mod.pdf(ctx, logger, inputPath, outputPath, options) +} + +func (mod ProtoUnoconvAPI) Extensions() []string { + return mod.extensions() +} + +type ProtoPDFEngineProvider struct { + ProtoModule + pdfEngine func() (gotenberg.PDFEngine, error) +} + +func (mod ProtoPDFEngineProvider) PDFEngine() (gotenberg.PDFEngine, error) { + return mod.pdfEngine() +} + +type ProtoPDFEngine struct { + merge func(_ context.Context, _ *zap.Logger, _ []string, _ string) error + convert func(_ context.Context, _ *zap.Logger, _, _, _ string) error +} + +func (mod ProtoPDFEngine) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error { + return mod.merge(ctx, logger, inputPaths, outputPath) +} + +func (mod ProtoPDFEngine) Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error { + return mod.convert(ctx, logger, format, inputPath, outputPath) +} + +func TestLibreOffice_Descriptor(t *testing.T) { + descriptor := LibreOffice{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(LibreOffice)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestLibreOffice_Provision(t *testing.T) { + for i, tc := range []struct { + ctx *gotenberg.Context + expectErr bool + }{ + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoModule }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(LibreOffice).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoUnoconvProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.unoconv = func() (unoconv.API, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(LibreOffice).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoUnoconvProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.unoconv = func() (unoconv.API, error) { + return struct{ ProtoUnoconvAPI }{}, nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(LibreOffice).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod1 := struct{ ProtoUnoconvProvider }{} + mod1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod1 }} + } + mod1.unoconv = func() (unoconv.API, error) { + return struct{ ProtoUnoconvAPI }{}, nil + } + + mod2 := struct{ ProtoPDFEngineProvider }{} + mod2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod2 }} + } + mod2.pdfEngine = func() (gotenberg.PDFEngine, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(LibreOffice).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod1.Descriptor(), + mod2.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod1 := struct{ ProtoUnoconvProvider }{} + mod1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod1 }} + } + mod1.unoconv = func() (unoconv.API, error) { + return struct{ ProtoUnoconvAPI }{}, nil + } + + mod2 := struct{ ProtoPDFEngineProvider }{} + mod2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod2 }} + } + mod2.pdfEngine = func() (gotenberg.PDFEngine, error) { + return struct{ ProtoPDFEngine }{}, nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(LibreOffice).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + mod1.Descriptor(), + mod2.Descriptor(), + }, + ) + }(), + }, + } { + mod := new(LibreOffice) + err := mod.Provision(tc.ctx) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestLibreOffice_Routes(t *testing.T) { + for i, tc := range []struct { + expectRoutes int + disableRoutes bool + }{ + { + expectRoutes: 1, + }, + { + disableRoutes: true, + }, + } { + mod := new(LibreOffice) + mod.disableRoutes = tc.disableRoutes + + routes, err := mod.Routes() + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + + if tc.expectRoutes != len(routes) { + t.Errorf("test %d: expected %d routes but got %d", i, tc.expectRoutes, len(routes)) + } + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*ProtoModule)(nil) + _ unoconv.Provider = (*ProtoUnoconvProvider)(nil) + _ gotenberg.Module = (*ProtoUnoconvProvider)(nil) + _ unoconv.API = (*ProtoUnoconvAPI)(nil) + _ gotenberg.PDFEngineProvider = (*ProtoPDFEngineProvider)(nil) + _ gotenberg.Module = (*ProtoPDFEngineProvider)(nil) + _ gotenberg.PDFEngine = (*ProtoPDFEngine)(nil) +) diff --git a/pkg/modules/libreoffice/pdfengine/doc.go b/pkg/modules/libreoffice/pdfengine/doc.go new file mode 100644 index 00000000..56c906c0 --- /dev/null +++ b/pkg/modules/libreoffice/pdfengine/doc.go @@ -0,0 +1,3 @@ +// Package pdfengine provides a module which abstracts the CLI tool unoconv and +// implements the gotenberg.PDFEngine interface. +package pdfengine diff --git a/pkg/modules/libreoffice/pdfengine/pdfengine.go b/pkg/modules/libreoffice/pdfengine/pdfengine.go new file mode 100644 index 00000000..c2bf62a5 --- /dev/null +++ b/pkg/modules/libreoffice/pdfengine/pdfengine.go @@ -0,0 +1,76 @@ +package pdfengine + +import ( + "context" + "fmt" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/unoconv" + "go.uber.org/zap" +) + +func init() { + gotenberg.MustRegisterModule(UnoconvPDFEngine{}) +} + +// UnoconvPDFEngine abstracts the CLI tool unoconv and implements the +// gotenberg.PDFEngine interface. +type UnoconvPDFEngine struct { + unoconv unoconv.API +} + +// Descriptor returns a UnoconvPDFEngine's module descriptor. +func (engine UnoconvPDFEngine) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "unoconv-pdfengine", + New: func() gotenberg.Module { return new(UnoconvPDFEngine) }, + } +} + +// Provision sets the module properties. +func (engine *UnoconvPDFEngine) Provision(ctx *gotenberg.Context) error { + provider, err := ctx.Module(new(unoconv.Provider)) + if err != nil { + return fmt.Errorf("get unoconv provider: %w", err) + } + + uno, err := provider.(unoconv.Provider).Unoconv() + if err != nil { + return fmt.Errorf("get unoconv API: %w", err) + } + + engine.unoconv = uno + + return nil +} + +// Merge is not available for this PDF engine. +func (engine UnoconvPDFEngine) Merge(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return fmt.Errorf("merge PDFs with unoconv: %w", gotenberg.ErrPDFEngineMethodNotAvailable) +} + +// Convert converts the given PDF to a specific PDF format. Currently, only the +// PDF/A-1 format is available. If another PDF format is requested, it returns +// a gotenberg.ErrPDFFormatNotAvailable error. +func (engine UnoconvPDFEngine) Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error { + if format != gotenberg.FormatPDFA1a { + return fmt.Errorf("convert PDF to '%s' with unoconv: %w", format, gotenberg.ErrPDFFormatNotAvailable) + } + + err := engine.unoconv.PDF(ctx, logger, inputPath, outputPath, unoconv.Options{ + PDFArchive: true, + }) + + if err == nil { + return nil + } + + return fmt.Errorf("convert PDF to '%s' with unoconv: %w", format, err) +} + +// Interface guards. +var ( + _ gotenberg.Module = (*UnoconvPDFEngine)(nil) + _ gotenberg.Provisioner = (*UnoconvPDFEngine)(nil) + _ gotenberg.PDFEngine = (*UnoconvPDFEngine)(nil) +) diff --git a/pkg/modules/libreoffice/pdfengine/pdfengine_test.go b/pkg/modules/libreoffice/pdfengine/pdfengine_test.go new file mode 100644 index 00000000..fb2787f3 --- /dev/null +++ b/pkg/modules/libreoffice/pdfengine/pdfengine_test.go @@ -0,0 +1,197 @@ +package pdfengine + +import ( + "context" + "errors" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/unoconv" + flag "github.com/spf13/pflag" + "go.uber.org/zap" +) + +type ProtoModule struct { + descriptor func() gotenberg.ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() gotenberg.ModuleDescriptor { + return mod.descriptor() +} + +type ProtoUnoconvProvider struct { + ProtoModule + unoconv func() (unoconv.API, error) +} + +func (mod ProtoUnoconvProvider) Unoconv() (unoconv.API, error) { + return mod.unoconv() +} + +type ProtoUnoconvAPI struct { + pdf func(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options unoconv.Options) error +} + +func (mod ProtoUnoconvAPI) PDF(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options unoconv.Options) error { + return mod.pdf(ctx, logger, inputPath, outputPath, options) +} + +func (mod ProtoUnoconvAPI) Extensions() []string { + return nil +} + +func TestUnoconvPDFEngine_Descriptor(t *testing.T) { + descriptor := UnoconvPDFEngine{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(UnoconvPDFEngine)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestUnoconvPDFEngine_Provision(t *testing.T) { + for i, tc := range []struct { + ctx *gotenberg.Context + expectErr bool + }{ + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoModule }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: flag.NewFlagSet("foo", flag.ExitOnError), + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoUnoconvProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.unoconv = func() (unoconv.API, error) { + return nil, errors.New("foo") + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: flag.NewFlagSet("foo", flag.ExitOnError), + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + mod := struct{ ProtoUnoconvProvider }{} + mod.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return mod }} + } + mod.unoconv = func() (unoconv.API, error) { + return struct{ ProtoUnoconvAPI }{}, nil + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: flag.NewFlagSet("foo", flag.ExitOnError), + }, + []gotenberg.ModuleDescriptor{ + mod.Descriptor(), + }, + ) + }(), + }, + } { + mod := new(UnoconvPDFEngine) + err := mod.Provision(tc.ctx) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestUnoconvPDFEngine_Merge(t *testing.T) { + mod := new(UnoconvPDFEngine) + err := mod.Merge(context.TODO(), zap.NewNop(), nil, "") + + if !errors.Is(err, gotenberg.ErrPDFEngineMethodNotAvailable) { + t.Errorf("expected error %v, but got: %v", gotenberg.ErrPDFEngineMethodNotAvailable, err) + } +} + +func TestUnoconvPDFEngine_Convert(t *testing.T) { + for i, tc := range []struct { + api unoconv.API + format string + expectErr bool + }{ + { + format: "", + expectErr: true, + }, + { + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, __ string, _ unoconv.Options) error { + return errors.New("foo") + } + + return unoconvAPI + }(), + format: gotenberg.FormatPDFA1a, + expectErr: true, + }, + { + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, __ string, _ unoconv.Options) error { + return nil + } + + return unoconvAPI + }(), + format: gotenberg.FormatPDFA1a, + }, + } { + mod := new(UnoconvPDFEngine) + mod.unoconv = tc.api + + err := mod.Convert(context.TODO(), zap.NewNop(), tc.format, "", "") + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*ProtoModule)(nil) + _ unoconv.Provider = (*ProtoUnoconvProvider)(nil) + _ gotenberg.Module = (*ProtoUnoconvProvider)(nil) + _ unoconv.API = (*ProtoUnoconvAPI)(nil) +) diff --git a/pkg/modules/libreoffice/routes.go b/pkg/modules/libreoffice/routes.go new file mode 100644 index 00000000..a54f6d9f --- /dev/null +++ b/pkg/modules/libreoffice/routes.go @@ -0,0 +1,177 @@ +package libreoffice + +import ( + "errors" + "fmt" + "net/http" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/unoconv" +) + +// convertRoute returns an api.MultipartFormDataRoute which can convert +// LibreOffice documents to PDF. +func convertRoute(uno unoconv.API, engine gotenberg.PDFEngine) api.MultipartFormDataRoute { + return api.MultipartFormDataRoute{ + Path: "/libreoffice/convert", + Handler: func(ctx *api.Context) error { + // Let's get the data from the form and validate them. + var ( + inputPaths []string + landscape bool + nativePageRanges string + nativePDFA1aFormat bool + PDFformat string + merge bool + ) + + err := ctx.FormData(). + MandatoryPaths(uno.Extensions(), &inputPaths). + Bool("landscape", &landscape, false). + String("nativePageRanges", &nativePageRanges, ""). + Bool("nativePdfA1aFormat", &nativePDFA1aFormat, false). + String("pdfFormat", &PDFformat, ""). + Bool("merge", &merge, false). + Validate() + + if err != nil { + return fmt.Errorf("validate form data: %w", err) + } + + if nativePDFA1aFormat && PDFformat != "" { + return api.WrapError( + errors.New("got both 'pdfFormat' and 'nativePdfA1aFormat' form values"), + api.NewSentinelHTTPError(http.StatusBadRequest, "Both 'pdfFormat' and 'nativePdfA1aFormat' form values are provided"), + ) + } + + // Alright, let's convert each document to PDF. + + outputPaths := make([]string, len(inputPaths)) + + for i, inputPath := range inputPaths { + outputPaths[i] = ctx.GeneratePath(".pdf") + + options := unoconv.Options{ + Landscape: landscape, + PageRanges: nativePageRanges, + PDFArchive: nativePDFA1aFormat, + } + + err = uno.PDF(ctx, ctx.Log(), inputPath, outputPaths[i], options) + + if err != nil { + if errors.Is(err, unoconv.ErrMalformedPageRanges) { + return api.WrapError( + fmt.Errorf("convert to PDF: %w", err), + api.NewSentinelHTTPError(http.StatusBadRequest, fmt.Sprintf("Malformed page ranges '%s' (nativePageRanges)", options.PageRanges)), + ) + } + + return fmt.Errorf("convert to PDF: %w", err) + } + } + + // So far so good, let's check if we have to merge the PDFs. Quick + // win: if there is only one PDF, skip this step. + + if len(outputPaths) > 1 && merge { + outputPath := ctx.GeneratePath(".pdf") + + err = engine.Merge(ctx, ctx.Log(), outputPaths, outputPath) + if err != nil { + return fmt.Errorf("merge PDFs: %w", err) + } + + // Now, let's check if the client want to convert this result + // PDF to a specific PDF format. + + // Note: nativePdfA1aFormat has not been specified if we reach + // this part of the code. Indeed, the handler returns early on + // an error if both nativePdfA1aFormat and pdfFormat are + // present. + + if PDFformat != "" { + convertInputPath := outputPath + convertOutputPath := ctx.GeneratePath(".pdf") + + err = engine.Convert(ctx, ctx.Log(), PDFformat, convertInputPath, convertOutputPath) + + if err != nil { + if errors.Is(err, gotenberg.ErrPDFFormatNotAvailable) { + return api.WrapError( + fmt.Errorf("convert PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("At least one PDF engine does not handle the PDF format '%s' (pdfFormat), while other have failed to convert for other reasons", PDFformat), + ), + ) + } + + return fmt.Errorf("convert PDF: %w", err) + } + + // Important: the output path is now the converted file. + outputPath = convertOutputPath + } + + // Last but not least, add the output path to the context so that + // the API is able to send it as a response to the client. + + err = ctx.AddOutputPaths(outputPath) + if err != nil { + return fmt.Errorf("add output path: %w", err) + } + + return nil + } + + // Ok, we don't have to merge the PDFs. Let's check if the client + // want to convert each PDF to a specific PDF format. + + // Note: nativePdfA1aFormat has not been specified if we reach this + // part of the code. Indeed, the handler returns early on an error + // if both nativePdfA1aFormat and pdfFormat are present. + + if PDFformat != "" { + convertOutputPaths := make([]string, len(outputPaths)) + + for i, outputPath := range outputPaths { + convertInputPath := outputPath + convertOutputPaths[i] = ctx.GeneratePath(".pdf") + + err = engine.Convert(ctx, ctx.Log(), PDFformat, convertInputPath, convertOutputPaths[i]) + + if err != nil { + if errors.Is(err, gotenberg.ErrPDFFormatNotAvailable) { + return api.WrapError( + fmt.Errorf("convert PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("At least one PDF engine does not handle the PDF format '%s' (pdfFormat), while other have failed to convert for other reasons", PDFformat), + ), + ) + } + + return fmt.Errorf("convert PDF: %w", err) + } + + } + + // Important: the output paths are now the converted files. + outputPaths = convertOutputPaths + } + + // Last but not least, add the output paths to the context so that + // the API is able to send them as a response to the client. + + err = ctx.AddOutputPaths(outputPaths...) + if err != nil { + return fmt.Errorf("add output paths: %w", err) + } + + return nil + }, + } +} diff --git a/pkg/modules/libreoffice/routes_test.go b/pkg/modules/libreoffice/routes_test.go new file mode 100644 index 00000000..4cd9c0d6 --- /dev/null +++ b/pkg/modules/libreoffice/routes_test.go @@ -0,0 +1,541 @@ +package libreoffice + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/unoconv" + "go.uber.org/zap" +) + +func TestConvertHandler(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + api unoconv.API + engine gotenberg.PDFEngine + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectOutputPathsCount int + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.extensions = func() []string { + return []string{ + ".foo", + } + } + + return unoconvAPI + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + }) + ctx.SetValues(map[string][]string{ + "nativePdfA1aFormat": { + "true", + }, + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return unoconv.ErrMalformedPageRanges + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return errors.New("foo") + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "merge": { + "true", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return errors.New("foo") + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "merge": { + "true", + }, + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return gotenberg.ErrPDFFormatNotAvailable + }, + } + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "merge": { + "true", + }, + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetCancelled(true) + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "merge": { + "true", + }, + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "merge": { + "true", + }, + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectOutputPathsCount: 1, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return gotenberg.ErrPDFFormatNotAvailable + }, + } + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetCancelled(true) + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.docx": "/foo/foo.docx", + "bar.docx": "/foo/bar.docx", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + api: func() unoconv.API { + unoconvAPI := struct{ ProtoUnoconvAPI }{} + unoconvAPI.pdf = func(_ context.Context, _ *zap.Logger, _, _ string, _ unoconv.Options) error { + return nil + } + unoconvAPI.extensions = func() []string { + return []string{ + ".docx", + } + } + + return unoconvAPI + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectOutputPathsCount: 2, + }, + } { + err := convertRoute(tc.api, tc.engine).Handler(tc.ctx.Context) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr api.HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectOutputPathsCount, len(tc.ctx.OutputPaths())) + } + } +} diff --git a/pkg/modules/libreoffice/unoconv/doc.go b/pkg/modules/libreoffice/unoconv/doc.go new file mode 100644 index 00000000..b495a98c --- /dev/null +++ b/pkg/modules/libreoffice/unoconv/doc.go @@ -0,0 +1,2 @@ +// Package unoconv provides a module which abstracts the CLI tool unoconv. +package unoconv diff --git a/pkg/modules/libreoffice/unoconv/unoconv.go b/pkg/modules/libreoffice/unoconv/unoconv.go new file mode 100644 index 00000000..9019d282 --- /dev/null +++ b/pkg/modules/libreoffice/unoconv/unoconv.go @@ -0,0 +1,287 @@ +package unoconv + +import ( + "context" + "errors" + "fmt" + "net" + "os" + "strconv" + "strings" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +func init() { + gotenberg.MustRegisterModule(Unoconv{}) +} + +// ErrMalformedPageRanges happens if the page ranges option cannot be +// interpreted by LibreOffice. +var ErrMalformedPageRanges = errors.New("page ranges are malformed") + +// Unoconv is a module which provides an API to interact with unoconv. +type Unoconv struct { + binPath string +} + +// Options gathers available options when converting a document to PDF. +type Options struct { + // Landscape allows to change the orientation of the resulting PDF. + // Optional. + Landscape bool + + // PageRanges allows to select the pages to convert. + // TODO: should prefer a method form PDFEngine. + // Optional. + PageRanges string + + // PDFArchive allows to convert the resulting PDF to PDF/A-1a. + // In a module, prefer the Convert method from the gotenberg.PDFEngine + // interface. + // Optional. + PDFArchive bool +} + +// API is an abstraction on top of unoconv. +// +// See https://github.com/unoconv/unoconv. +type API interface { + PDF(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options Options) error + Extensions() []string +} + +// Provider is a module interface which exposes a method for creating an API +// for other modules. +// +// func (m *YourModule) Provision(ctx *gotenberg.Context) error { +// provider, _ := ctx.Module(new(unoconv.Provider)) +// uno, _ := provider.(unoconv.Provider).Unoconv() +// } +type Provider interface { + Unoconv() (API, error) +} + +// Descriptor returns a Unoconv's module descriptor. +func (Unoconv) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "unoconv", + New: func() gotenberg.Module { return new(Unoconv) }, + } +} + +// Provision sets the module properties. It returns an error if the environment +// variable UNOCONV_BIN_PATH is not set. +func (mod *Unoconv) Provision(_ *gotenberg.Context) error { + binPath, ok := os.LookupEnv("UNOCONV_BIN_PATH") + if !ok { + return errors.New("UNOCONV_BIN_PATH environment variable is not set") + } + + mod.binPath = binPath + + return nil +} + +// Validate validates the module properties. +func (mod Unoconv) Validate() error { + _, err := os.Stat(mod.binPath) + if os.IsNotExist(err) { + return fmt.Errorf("unoconv binary path does not exist: %w", err) + } + + return nil +} + +// Unoconv returns an API for interacting with unoconv. +func (mod Unoconv) Unoconv() (API, error) { + return mod, nil +} + +// PDF converts a document to PDF. It creates a dedicated LibreOffice instance +// thanks to a custom user profile directory and a free port. Substantial calls +// to this method may increase CPU and memory usage drastically. In such a +// scenario, the given context may also be done before the end of the +// conversion. +func (mod Unoconv) PDF(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options Options) error { + port, err := func() (int, error) { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return 0, fmt.Errorf("listen on the local network address: %w", err) + } + defer func() { + err := listener.Close() + if err != nil { + logger.Error(fmt.Sprintf("close listener: %s", err.Error())) + } + }() + + addr := listener.Addr().String() + + _, portStr, err := net.SplitHostPort(addr) + if err != nil { + return 0, fmt.Errorf("get free port from host: %w", err) + } + + return strconv.Atoi(portStr) + }() + + if err != nil { + return fmt.Errorf("get free port: %w", err) + } + + userProfileDirPath := gotenberg.NewDirPath() + + args := []string{ + "--user-profile", + fmt.Sprintf("//%s", userProfileDirPath), + "--port", + fmt.Sprintf("%d", port), + "--format", + "pdf", + } + + if options.Landscape { + args = append(args, "--printer", "PaperOrientation=landscape") + } + + if options.PageRanges != "" { + args = append(args, "--export", fmt.Sprintf("PageRange=%s", options.PageRanges)) + } + + if options.PDFArchive { + args = append(args, "--export", "SelectPdfVersion=1") + } + + args = append(args, "--output", outputPath, inputPath) + + cmd, err := gotenberg.CommandContext(ctx, logger, mod.binPath, args...) + if err != nil { + return fmt.Errorf("create unoconv command: %w", err) + } + + logger.Debug(fmt.Sprintf("print to PDF with: %+v", options)) + + err = cmd.Exec() + + // Always remove the user profile directory created by LibreOffice. + // See https://github.com/gotenberg/gotenberg/issues/192. + go func() { + logger.Debug(fmt.Sprintf("remove user profile directory '%s'", userProfileDirPath)) + + err := os.RemoveAll(userProfileDirPath) + if err != nil { + logger.Error(fmt.Sprintf("remove user profile directory: %s", err)) + } + }() + + if err == nil { + return nil + } + + // Unoconv/LibreOffice errors are not explicit. + // That's why we have to make an educated guess according to the exit code + // and given inputs. + + if strings.Contains(err.Error(), "exit status 5") && options.PageRanges != "" { + return ErrMalformedPageRanges + } + + // Possible errors: + // 1. Unoconv/LibreOffice failed for some reason. + // 2. Context done. + // + // On the second scenario, LibreOffice might not had time to remove some of + // its temporary files, as it has been killed without warning. The garbage + // collector will delete them for us (if the module is loaded). + return fmt.Errorf("unoconv PDF: %w", err) +} + +// Extensions returns the file extensions available with unoconv. +func (mod Unoconv) Extensions() []string { + return []string{ + ".bib", + ".doc", + ".xml", + ".docx", + ".fodt", + ".html", + ".ltx", + ".txt", + ".odt", + ".ott", + ".pdb", + ".pdf", + ".psw", + ".rtf", + ".sdw", + ".stw", + ".sxw", + ".uot", + ".vor", + ".wps", + ".epub", + ".png", + ".bmp", + ".emf", + ".eps", + ".fodg", + ".gif", + ".jpg", + ".met", + ".odd", + ".otg", + ".pbm", + ".pct", + ".pgm", + ".ppm", + ".ras", + ".std", + ".svg", + ".svm", + ".swf", + ".sxd", + ".sxw", + ".tiff", + ".xhtml", + ".xpm", + ".fodp", + ".potm", + ".pot", + ".pptx", + ".pps", + ".ppt", + ".pwp", + ".sda", + ".sdd", + ".sti", + ".sxi", + ".uop", + ".wmf", + ".csv", + ".dbf", + ".dif", + ".fods", + ".ods", + ".ots", + ".pxl", + ".sdc", + ".slk", + ".stc", + ".sxc", + ".uos", + ".xls", + ".xlt", + ".xlsx", + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*Unoconv)(nil) + _ gotenberg.Provisioner = (*Unoconv)(nil) + _ gotenberg.Validator = (*Unoconv)(nil) + _ API = (*Unoconv)(nil) + _ Provider = (*Unoconv)(nil) +) diff --git a/pkg/modules/libreoffice/unoconv/unoconv_test.go b/pkg/modules/libreoffice/unoconv/unoconv_test.go new file mode 100644 index 00000000..449d380c --- /dev/null +++ b/pkg/modules/libreoffice/unoconv/unoconv_test.go @@ -0,0 +1,154 @@ +package unoconv + +import ( + "context" + "os" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +func TestUnoconv_Descriptor(t *testing.T) { + descriptor := Unoconv{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(Unoconv)) + + if actual != expect { + t.Errorf("expected '%'s' but got '%s'", expect, actual) + } +} + +func TestUnoconv_Provision(t *testing.T) { + mod := new(Unoconv) + ctx := gotenberg.NewContext(gotenberg.ParsedFlags{}, nil) + + err := mod.Provision(ctx) + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestUnoconv_Validate(t *testing.T) { + for i, tc := range []struct { + binPath string + expectErr bool + }{ + { + expectErr: true, + }, + { + binPath: "/foo", + expectErr: true, + }, + { + binPath: os.Getenv("UNOCONV_BIN_PATH"), + }, + } { + mod := new(Unoconv) + mod.binPath = tc.binPath + err := mod.Validate() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestUnoconv_Unoconv(t *testing.T) { + mod := new(Unoconv) + + _, err := mod.Unoconv() + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestUnoconv_PDF(t *testing.T) { + for i, tc := range []struct { + ctx context.Context + inputPath string + options Options + expectErr bool + }{ + { + expectErr: true, + }, + { + ctx: context.Background(), + inputPath: "/tests/test/testdata/libreoffice/sample1.docx", + options: Options{ + Landscape: true, + PageRanges: "1-2", + PDFArchive: true, + }, + }, + { + ctx: context.Background(), + inputPath: "/tests/test/testdata/libreoffice/sample1.docx", + options: Options{ + PageRanges: "foo", + }, + expectErr: true, + }, + { + ctx: func() context.Context { + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + return ctx + }(), + inputPath: "/tests/test/testdata/libreoffice/sample1.docx", + expectErr: true, + }, + } { + func() { + mod := new(Unoconv) + + err := mod.Provision(nil) + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + outputDir, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + defer func() { + err := os.RemoveAll(outputDir) + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }() + + err = mod.PDF(tc.ctx, zap.NewNop(), tc.inputPath, outputDir+"/foo.pdf", tc.options) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + } +} + +func TestUnoconv_Extensions(t *testing.T) { + mod := new(Unoconv) + extensions := mod.Extensions() + + actual := len(extensions) + expect := 73 + + if actual != expect { + t.Errorf("expected %d extentions but got %d", expect, actual) + } +} diff --git a/pkg/modules/logging/doc.go b/pkg/modules/logging/doc.go new file mode 100644 index 00000000..cb735310 --- /dev/null +++ b/pkg/modules/logging/doc.go @@ -0,0 +1,3 @@ +// Package logging provides a module which creates a zap.Logger for other +// modules. +package logging diff --git a/pkg/modules/logging/logging.go b/pkg/modules/logging/logging.go new file mode 100644 index 00000000..6f8ef456 --- /dev/null +++ b/pkg/modules/logging/logging.go @@ -0,0 +1,169 @@ +package logging + +import ( + "fmt" + "os" + "time" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + flag "github.com/spf13/pflag" + "go.uber.org/multierr" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "golang.org/x/term" +) + +func init() { + gotenberg.MustRegisterModule(Logging{}) +} + +const ( + errorLoggingLevel = "error" + warnLoggingLevel = "warn" + infoLoggingLevel = "info" + debugLoggingLevel = "debug" +) + +const ( + autoLoggingFormat = "auto" + jsonLoggingFormat = "json" + textLoggingFormat = "text" +) + +// Logging is a module which implements the gotenberg.LoggerProvider interface. +type Logging struct { + level string + format string +} + +// Descriptor returns a Logging's module descriptor. +func (Logging) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "logging", + FlagSet: func() *flag.FlagSet { + fs := flag.NewFlagSet("logging", flag.ExitOnError) + fs.String("log-level", infoLoggingLevel, fmt.Sprintf("Set the log level - %s, %s, %s, or %s", errorLoggingLevel, warnLoggingLevel, infoLoggingLevel, debugLoggingLevel)) + fs.String("log-format", autoLoggingFormat, fmt.Sprintf("Set log format - %s, %s, or %s", autoLoggingFormat, jsonLoggingFormat, textLoggingFormat)) + + return fs + }(), + New: func() gotenberg.Module { return new(Logging) }, + } +} + +// Provision sets the log level and format. +func (log *Logging) Provision(ctx *gotenberg.Context) error { + flags := ctx.ParsedFlags() + + log.level = flags.MustString("log-level") + log.format = flags.MustString("log-format") + + return nil +} + +// Validate validates the log level and format. +func (log Logging) Validate() error { + var err error + + switch log.level { + case errorLoggingLevel, warnLoggingLevel, infoLoggingLevel, debugLoggingLevel: + break + default: + err = multierr.Append( + err, + fmt.Errorf("log level must be either %s, %s, %s or %s", errorLoggingLevel, warnLoggingLevel, infoLoggingLevel, debugLoggingLevel), + ) + } + + switch log.format { + case autoLoggingFormat, jsonLoggingFormat, textLoggingFormat: + break + default: + err = multierr.Append( + err, + fmt.Errorf("log format must be either %s, %s or %s", autoLoggingFormat, jsonLoggingFormat, textLoggingFormat), + ) + } + + return err +} + +// Logger returns a zap.Logger. +func (log Logging) Logger(mod gotenberg.Module) (*zap.Logger, error) { + if logger == nil { + lvl, err := newLogLevel(log.level) + if err != nil { + return nil, fmt.Errorf("get log level: %w", err) + } + + encoder, err := newLogEncoder(log.format) + if err != nil { + return nil, fmt.Errorf("get log encoder: %w", err) + } + + core := zapcore.NewCore(encoder, os.Stderr, lvl) + logger = zap.New(core) + + // nolint + defer logger.Sync() + } + + return logger.Named(mod.Descriptor().ID), nil +} + +func newLogLevel(level string) (zapcore.Level, error) { + switch level { + case errorLoggingLevel: + return zap.ErrorLevel, nil + case warnLoggingLevel: + return zap.WarnLevel, nil + case infoLoggingLevel: + return zap.InfoLevel, nil + case debugLoggingLevel: + return zap.DebugLevel, nil + default: + return -2, fmt.Errorf("%s is not a recognized log level", level) + } +} + +func newLogEncoder(format string) (zapcore.Encoder, error) { + isTerminal := term.IsTerminal(int(os.Stdout.Fd())) + encCfg := zap.NewProductionEncoderConfig() + + if isTerminal { + // If interactive terminal, make output more human-readable by default. + // Credits: https://github.com/caddyserver/caddy/blob/v2.1.1/logging.go#L671. + encCfg.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.UTC().Format("2006/01/02 15:04:05.000")) + } + + if format == textLoggingFormat || format == autoLoggingFormat { + encCfg.EncodeLevel = zapcore.CapitalColorLevelEncoder + } + } + + if format == autoLoggingFormat && isTerminal { + format = textLoggingFormat + } else if format == autoLoggingFormat { + format = jsonLoggingFormat + } + + switch format { + case textLoggingFormat: + return zapcore.NewConsoleEncoder(encCfg), nil + case jsonLoggingFormat: + return zapcore.NewJSONEncoder(encCfg), nil + default: + return nil, fmt.Errorf("%s is not a recognized log format", format) + } +} + +var logger *zap.Logger = nil + +// Interface guards. +var ( + _ gotenberg.Module = (*Logging)(nil) + _ gotenberg.Provisioner = (*Logging)(nil) + _ gotenberg.Validator = (*Logging)(nil) + _ gotenberg.LoggerProvider = (*Logging)(nil) +) diff --git a/pkg/modules/logging/logging_test.go b/pkg/modules/logging/logging_test.go new file mode 100644 index 00000000..3212b770 --- /dev/null +++ b/pkg/modules/logging/logging_test.go @@ -0,0 +1,199 @@ +package logging + +import ( + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap/zapcore" +) + +type ProtoModule struct { + descriptor func() gotenberg.ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() gotenberg.ModuleDescriptor { + return mod.descriptor() +} + +func TestLogging_Descriptor(t *testing.T) { + descriptor := Logging{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(Logging)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestLogging_Provision(t *testing.T) { + logging := new(Logging) + fs := logging.Descriptor().FlagSet + + err := fs.Parse([]string{""}) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + ctx := gotenberg.NewContext(gotenberg.ParsedFlags{FlagSet: fs}, nil) + + err = logging.Provision(ctx) + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestLogging_Validate(t *testing.T) { + for i, tc := range []struct { + level, format string + expectErr bool + }{ + { + level: "foo", + expectErr: true, + }, + { + level: debugLoggingLevel, + format: "foo", + expectErr: true, + }, + { + level: debugLoggingLevel, + format: autoLoggingFormat, + }, + } { + mod := new(Logging) + mod.level = tc.level + mod.format = tc.format + + err := mod.Validate() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestLogging_Logger(t *testing.T) { + for i, tc := range []struct { + level, format string + expectErr bool + }{ + { + level: "foo", + expectErr: true, + }, + { + level: debugLoggingLevel, + format: "foo", + expectErr: true, + }, + { + level: debugLoggingLevel, + format: autoLoggingFormat, + }, + } { + mod := new(Logging) + mod.level = tc.level + mod.format = tc.format + + _, err := mod.Logger(ProtoModule{ + descriptor: func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: nil} + }, + }) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestNewLogLevel(t *testing.T) { + for i, tc := range []struct { + level string + expectZapLevel zapcore.Level + expectErr bool + }{ + { + level: errorLoggingLevel, + expectZapLevel: zapcore.ErrorLevel, + }, + { + level: warnLoggingLevel, + expectZapLevel: zapcore.WarnLevel, + }, + { + level: infoLoggingLevel, + expectZapLevel: zapcore.InfoLevel, + }, + { + level: debugLoggingLevel, + expectZapLevel: zapcore.DebugLevel, + }, + { + level: "foo", + expectZapLevel: -2, + expectErr: true, + }, + } { + actual, err := newLogLevel(tc.level) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + if tc.expectZapLevel != actual { + t.Errorf("test %d: expected %d level but got %d", i, tc.expectZapLevel, actual) + } + } +} + +func TestNewLogEncoder(t *testing.T) { + for i, tc := range []struct { + format string + expectErr bool + }{ + { + format: autoLoggingFormat, + }, + { + format: textLoggingFormat, + }, + { + format: jsonLoggingFormat, + }, + { + format: "foo", + expectErr: true, + }, + } { + _, err := newLogEncoder(tc.format) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*ProtoModule)(nil) +) diff --git a/pkg/modules/pdfcpu/doc.go b/pkg/modules/pdfcpu/doc.go new file mode 100644 index 00000000..1d7b0058 --- /dev/null +++ b/pkg/modules/pdfcpu/doc.go @@ -0,0 +1,4 @@ +// Package pdfcpu provides a module which wraps the +// https://github.com/pdfcpu/pdfcpu library and implements the +// gotenberg.PDFEngine interface. +package pdfcpu diff --git a/pkg/modules/pdfcpu/pdfcpu.go b/pkg/modules/pdfcpu/pdfcpu.go new file mode 100644 index 00000000..4ab4d86c --- /dev/null +++ b/pkg/modules/pdfcpu/pdfcpu.go @@ -0,0 +1,62 @@ +package pdfcpu + +import ( + "context" + "fmt" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + pdfcpuAPI "github.com/pdfcpu/pdfcpu/pkg/api" + pdfcpuLog "github.com/pdfcpu/pdfcpu/pkg/log" + pdfcpuConfig "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" + "go.uber.org/zap" +) + +func init() { + gotenberg.MustRegisterModule(PDFcpu{}) +} + +// PDFcpu is a module which wraps the https://github.com/pdfcpu/pdfcpu library +// and implements the gotenberg.PDFEngine interface. +type PDFcpu struct { + conf *pdfcpuConfig.Configuration +} + +// Descriptor returns a PDFcpu's module descriptor. +func (engine PDFcpu) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "pdfcpu", + New: func() gotenberg.Module { return new(PDFcpu) }, + } +} + +// Provision sets the engine properties. +func (engine *PDFcpu) Provision(_ *gotenberg.Context) error { + pdfcpuConfig.ConfigPath = "disable" + pdfcpuLog.DisableLoggers() + + engine.conf = pdfcpuConfig.NewDefaultConfiguration() + + return nil +} + +// Merge merges the given PDFs into a unique PDF. +func (engine PDFcpu) Merge(_ context.Context, _ *zap.Logger, inputPaths []string, outputPath string) error { + err := pdfcpuAPI.MergeCreateFile(inputPaths, outputPath, engine.conf) + if err == nil { + return nil + } + + return fmt.Errorf("merge PDFs with PDFcpu: %w", err) +} + +// Convert is not available for this PDF engine. +func (engine PDFcpu) Convert(_ context.Context, _ *zap.Logger, format, _, _ string) error { + return fmt.Errorf("convert PDF to '%s' with PDFcpu: %w", format, gotenberg.ErrPDFEngineMethodNotAvailable) +} + +// Interface guards. +var ( + _ gotenberg.Module = (*PDFcpu)(nil) + _ gotenberg.Provisioner = (*PDFcpu)(nil) + _ gotenberg.PDFEngine = (*PDFcpu)(nil) +) diff --git a/pkg/modules/pdfcpu/pdfcpu_test.go b/pkg/modules/pdfcpu/pdfcpu_test.go new file mode 100644 index 00000000..924eac55 --- /dev/null +++ b/pkg/modules/pdfcpu/pdfcpu_test.go @@ -0,0 +1,98 @@ +package pdfcpu + +import ( + "context" + "errors" + "os" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +func TestPDFcpu_Descriptor(t *testing.T) { + descriptor := PDFcpu{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(PDFcpu)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestPDFcpu_Provision(t *testing.T) { + mod := new(PDFcpu) + ctx := gotenberg.NewContext(gotenberg.ParsedFlags{}, nil) + + err := mod.Provision(ctx) + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestPDFcpu_Merge(t *testing.T) { + for i, tc := range []struct { + inputPaths []string + expectErr bool + }{ + { + inputPaths: []string{ + "/tests/test/testdata/pdfengines/sample1.pdf", + }, + }, + { + inputPaths: []string{ + "/tests/test/testdata/pdfengines/sample1.pdf", + "/tests/test/testdata/pdfengines/sample2.pdf", + }, + }, + { + inputPaths: []string{ + "foo", + }, + expectErr: true, + }, + } { + func() { + mod := new(PDFcpu) + + err := mod.Provision(nil) + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + outputDir, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + defer func() { + err := os.RemoveAll(outputDir) + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }() + + err = mod.Merge(nil, nil, tc.inputPaths, outputDir+"/foo.pdf") + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + } +} + +func TestPDFcpu_Convert(t *testing.T) { + mod := new(PDFcpu) + err := mod.Convert(context.TODO(), zap.NewNop(), "", "", "") + + if !errors.Is(err, gotenberg.ErrPDFEngineMethodNotAvailable) { + t.Errorf("expected error %v, but got: %v", gotenberg.ErrPDFEngineMethodNotAvailable, err) + } +} diff --git a/pkg/modules/pdfengines/doc.go b/pkg/modules/pdfengines/doc.go new file mode 100644 index 00000000..667344d4 --- /dev/null +++ b/pkg/modules/pdfengines/doc.go @@ -0,0 +1,3 @@ +// Package pdfengines provides a module which gathers modules that implements +// the gotenberg.PDFEngine interface. +package pdfengines diff --git a/pkg/modules/pdfengines/multi.go b/pkg/modules/pdfengines/multi.go new file mode 100644 index 00000000..7e163c82 --- /dev/null +++ b/pkg/modules/pdfengines/multi.go @@ -0,0 +1,81 @@ +package pdfengines + +import ( + "context" + "fmt" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/multierr" + "go.uber.org/zap" +) + +// multiPDFEngines implements the gotenberg.PDFEngine interface and gathers one +// or more gotenberg.PDFEngine. It provides a sort of fallback mechanism: if an +// engine's method returns an error, it calls the same method from another +// engine. +type multiPDFEngines struct { + engines []gotenberg.PDFEngine +} + +// newMultiPDFEngines returns a multiPDFEngines. Arguments' order determines the +// order of the engines called. +func newMultiPDFEngines(engines ...gotenberg.PDFEngine) *multiPDFEngines { + return &multiPDFEngines{ + engines: engines, + } +} + +// Merge tries to merge the given PDFs into a unique PDF thanks to its +// children. If the context is done, it stops and returns an error. +func (multi multiPDFEngines) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error { + var err error + errChan := make(chan error, 1) + + for _, engine := range multi.engines { + go func(engine gotenberg.PDFEngine) { + errChan <- engine.Merge(ctx, logger, inputPaths, outputPath) + }(engine) + + select { + case mergeErr := <-errChan: + errored := multierr.AppendInto(&err, mergeErr) + if !errored { + return nil + } + case <-ctx.Done(): + return ctx.Err() + } + } + + return fmt.Errorf("merge PDFs with multi PDF engines: %w", err) +} + +// Convert converts the given PDF to a specific PDF format. thanks to its +// children. If the context is done, it stops and returns an error. +func (multi multiPDFEngines) Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error { + var err error + errChan := make(chan error, 1) + + for _, engine := range multi.engines { + go func(engine gotenberg.PDFEngine) { + errChan <- engine.Convert(ctx, logger, format, inputPath, outputPath) + }(engine) + + select { + case mergeErr := <-errChan: + errored := multierr.AppendInto(&err, mergeErr) + if !errored { + return nil + } + case <-ctx.Done(): + return ctx.Err() + } + } + + return fmt.Errorf("convert PDF to '%s' with multi PDF engines: %w", format, err) +} + +// Interface guards. +var ( + _ gotenberg.PDFEngine = (*multiPDFEngines)(nil) +) diff --git a/pkg/modules/pdfengines/multi_test.go b/pkg/modules/pdfengines/multi_test.go new file mode 100644 index 00000000..7401903b --- /dev/null +++ b/pkg/modules/pdfengines/multi_test.go @@ -0,0 +1,215 @@ +package pdfengines + +import ( + "context" + "errors" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +func TestNewMultiPDFEngines(t *testing.T) { + engine1 := &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + + engine2 := &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return errors.New("foo") + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + } + + multi := newMultiPDFEngines(engine1, engine2) + + if len(multi.engines) != 2 { + t.Fatalf("expected %d engines but got %d", 2, len(multi.engines)) + } + + if !reflect.DeepEqual(engine1, multi.engines[0]) { + t.Errorf("expected %v, but got: %v", engine1, multi.engines[0]) + } + + if !reflect.DeepEqual(engine2, multi.engines[1]) { + t.Errorf("expected %v, but got: %v", engine2, multi.engines[1]) + } +} + +func TestMultiPDFEngines_Merge(t *testing.T) { + for i, tc := range []struct { + ctx context.Context + engines []gotenberg.PDFEngine + expectErr bool + }{ + { + ctx: context.TODO(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + }, + } + }(), + }, + { + ctx: context.TODO(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return errors.New("foo") + }, + }, + ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + }, + } + }(), + }, + { + ctx: context.TODO(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return errors.New("foo") + }, + }, + ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return errors.New("bar") + }, + }, + } + }(), + expectErr: true, + }, + { + ctx: func() context.Context { + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + return ctx + }(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + }, + } + }(), + expectErr: true, + }, + } { + multi := newMultiPDFEngines(tc.engines...) + err := multi.Merge(tc.ctx, nil, nil, "") + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestMultiPDFEngines_Convert(t *testing.T) { + for i, tc := range []struct { + ctx context.Context + engines []gotenberg.PDFEngine + expectErr bool + }{ + { + ctx: context.TODO(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + }, + } + }(), + }, + { + ctx: context.TODO(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + }, + ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + }, + } + }(), + }, + { + ctx: context.TODO(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + }, + ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("bar") + }, + }, + } + }(), + expectErr: true, + }, + { + ctx: func() context.Context { + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + return ctx + }(), + engines: func() []gotenberg.PDFEngine { + return []gotenberg.PDFEngine{ + ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + }, + } + }(), + expectErr: true, + }, + } { + multi := newMultiPDFEngines(tc.engines...) + err := multi.Convert(tc.ctx, nil, "", "", "") + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} diff --git a/pkg/modules/pdfengines/pdfengines.go b/pkg/modules/pdfengines/pdfengines.go new file mode 100644 index 00000000..c7161287 --- /dev/null +++ b/pkg/modules/pdfengines/pdfengines.go @@ -0,0 +1,160 @@ +package pdfengines + +import ( + "errors" + "fmt" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + flag "github.com/spf13/pflag" +) + +func init() { + gotenberg.MustRegisterModule(PDFEngines{}) +} + +// PDFEngines is a module which gathers available gotenberg.PDFEngine modules. +// The available gotenberg.PDFEngine modules can be either all +// gotenberg.PDFEngine modules or the modules selected by the user thanks to +// the "engines" flag. +// +// PDFEngines wraps the gotenberg.PDFEngine modules in an internal struct which +// also implements gotenberg.PDFEngine. This struct provides a sort of fallback +// mechanism: if an engine's method returns an error, it calls the same method +// from another engine. +// +// This module implements the gotenberg.PDFEngineProvider interface. +type PDFEngines struct { + names []string + engines []gotenberg.PDFEngine + disableRoutes bool +} + +// Descriptor returns a PDFEngines' module descriptor. +func (PDFEngines) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "pdfengines", + FlagSet: func() *flag.FlagSet { + fs := flag.NewFlagSet("pdfengines", flag.ExitOnError) + fs.StringSlice("pdfengines-engines", make([]string, 0), "Set the PDF engines - all by default") + fs.Bool("pdfengines-disable-routes", false, "Disable the routes") + + return fs + }(), + New: func() gotenberg.Module { return new(PDFEngines) }, + } +} + +// Provision gets either all gotenberg.PDFEngine modules or the modules +// selected by the user thanks to the "engines" flag. +func (mod *PDFEngines) Provision(ctx *gotenberg.Context) error { + flags := ctx.ParsedFlags() + names := flags.MustStringSlice("pdfengines-engines") + mod.disableRoutes = flags.MustBool("pdfengines-disable-routes") + + engines, err := ctx.Modules(new(gotenberg.PDFEngine)) + if err != nil { + return fmt.Errorf("get PDF engines: %w", err) + } + + mod.engines = make([]gotenberg.PDFEngine, len(engines)) + + for i, engine := range engines { + mod.engines[i] = engine.(gotenberg.PDFEngine) + } + + if len(names) > 0 { + // Selection from user. + mod.names = names + + return nil + } + + // No selection from user, use all PDF engines available. + mod.names = make([]string, len(mod.engines)) + + for i, engine := range mod.engines { + mod.names[i] = engine.(gotenberg.Module).Descriptor().ID + } + + return nil +} + +// Validate validates there is at least one gotenberg.PDFEngine module +// available. It also validates that selected gotenberg.PDFEngine modules +// actually exist. +func (mod PDFEngines) Validate() error { + if len(mod.engines) == 0 { + return errors.New("no PDF engine") + } + + availableEngines := make([]string, len(mod.engines)) + + for i, engine := range mod.engines { + availableEngines[i] = engine.(gotenberg.Module).Descriptor().ID + } + + nonExistingEngines := make([]string, 0) + + for _, name := range mod.names { + engineExists := false + + for _, engine := range mod.engines { + if name == engine.(gotenberg.Module).Descriptor().ID { + engineExists = true + break + } + } + + if !engineExists { + nonExistingEngines = append(nonExistingEngines, name) + } + } + + if len(nonExistingEngines) == 0 { + return nil + } + + return fmt.Errorf("non-existing PDF engine(s): %s - available PDF engine(s): %s", nonExistingEngines, availableEngines) +} + +// PDFEngine returns a gotenberg.PDFEngine. +func (mod PDFEngines) PDFEngine() (gotenberg.PDFEngine, error) { + engines := make([]gotenberg.PDFEngine, len(mod.engines)) + + i := 0 + for _, engine := range mod.engines { + engines[i] = engine + i++ + } + + return newMultiPDFEngines(engines...), nil +} + +// Routes returns the API routes. +func (mod PDFEngines) Routes() ([]api.MultipartFormDataRoute, error) { + if mod.disableRoutes { + return nil, nil + } + + engine, err := mod.PDFEngine() + if err != nil { + // Should not happen, unless our provider implementation + // changes in the future. + return nil, fmt.Errorf("get pdf engine: %w", err) + } + + return []api.MultipartFormDataRoute{ + mergeRoute(engine), + convertRoute(engine), + }, nil +} + +// Interface guards. +var ( + _ gotenberg.Module = (*PDFEngines)(nil) + _ gotenberg.Provisioner = (*PDFEngines)(nil) + _ gotenberg.Validator = (*PDFEngines)(nil) + _ gotenberg.PDFEngineProvider = (*PDFEngines)(nil) + _ api.MultipartFormDataRouter = (*PDFEngines)(nil) +) diff --git a/pkg/modules/pdfengines/pdfengines_test.go b/pkg/modules/pdfengines/pdfengines_test.go new file mode 100644 index 00000000..8ca3b712 --- /dev/null +++ b/pkg/modules/pdfengines/pdfengines_test.go @@ -0,0 +1,304 @@ +package pdfengines + +import ( + "context" + "errors" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +type ProtoModule struct { + descriptor func() gotenberg.ModuleDescriptor +} + +func (mod ProtoModule) Descriptor() gotenberg.ModuleDescriptor { + return mod.descriptor() +} + +type ProtoValidator struct { + ProtoModule + validate func() error +} + +func (mod ProtoValidator) Validate() error { + return mod.validate() +} + +type ProtoPDFEngine struct { + ProtoValidator + merge func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error + convert func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error +} + +func (mod ProtoPDFEngine) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error { + return mod.merge(ctx, logger, inputPaths, outputPath) +} + +func (mod ProtoPDFEngine) Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error { + return mod.convert(ctx, logger, format, inputPath, outputPath) +} + +func TestPDFEngine_Descriptor(t *testing.T) { + descriptor := PDFEngines{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(PDFEngines)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestPDFEngine_Provision(t *testing.T) { + for i, tc := range []struct { + ctx *gotenberg.Context + expectNames []string + expectEnginesCount int + expectErr bool + }{ + { + ctx: func() *gotenberg.Context { + engine := struct{ ProtoPDFEngine }{} + engine.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return engine }} + } + engine.validate = func() error { return errors.New("foo") } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(PDFEngines).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + engine.Descriptor(), + }, + ) + }(), + expectErr: true, + }, + { + ctx: func() *gotenberg.Context { + engine := struct{ ProtoPDFEngine }{} + engine.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return engine }} + } + engine.validate = func() error { return nil } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: new(PDFEngines).Descriptor().FlagSet, + }, + []gotenberg.ModuleDescriptor{ + engine.Descriptor(), + }, + ) + }(), + expectNames: []string{"foo"}, + expectEnginesCount: 1, + }, + { + ctx: func() *gotenberg.Context { + engine1 := struct{ ProtoPDFEngine }{} + engine1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "a", New: func() gotenberg.Module { return engine1 }} + } + engine1.validate = func() error { return nil } + + engine2 := struct{ ProtoPDFEngine }{} + engine2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "b", New: func() gotenberg.Module { return engine2 }} + } + engine2.validate = func() error { return nil } + + fs := new(PDFEngines).Descriptor().FlagSet + err := fs.Parse([]string{"--pdfengines-engines=b", "--pdfengines-engines=a"}) + + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: fs, + }, + []gotenberg.ModuleDescriptor{ + engine1.Descriptor(), + engine2.Descriptor(), + }, + ) + }(), + expectNames: []string{"b", "a"}, + expectEnginesCount: 2, + }, + { + ctx: func() *gotenberg.Context { + engine1 := struct{ ProtoPDFEngine }{} + engine1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "a", New: func() gotenberg.Module { return engine1 }} + } + engine1.validate = func() error { return nil } + + engine2 := struct{ ProtoPDFEngine }{} + engine2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "b", New: func() gotenberg.Module { return engine2 }} + } + engine2.validate = func() error { return nil } + + fs := new(PDFEngines).Descriptor().FlagSet + err := fs.Parse([]string{"--pdfengines-engines=b"}) + + if err != nil { + t.Fatalf("expected error but got: %v", err) + } + + return gotenberg.NewContext( + gotenberg.ParsedFlags{ + FlagSet: fs, + }, + []gotenberg.ModuleDescriptor{ + engine1.Descriptor(), + engine2.Descriptor(), + }, + ) + }(), + expectNames: []string{"b"}, + expectEnginesCount: 2, + }, + } { + mod := new(PDFEngines) + err := mod.Provision(tc.ctx) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + if len(tc.expectNames) != len(mod.names) { + t.Errorf("test %d: expected %d names but got %d", i, len(tc.expectNames), len(mod.names)) + } + + if tc.expectEnginesCount != len(mod.engines) { + t.Errorf("test %d: expected %d engines but got %d", i, tc.expectEnginesCount, len(mod.engines)) + } + + for index, name := range mod.names { + if name != tc.expectNames[index] { + t.Errorf("test %d: expected name at index %d to be %s, but got: %s", i, index, name, tc.expectNames[index]) + } + } + } +} + +func TestPDFEngine_Validate(t *testing.T) { + for i, tc := range []struct { + names []string + engines []gotenberg.PDFEngine + expectErr bool + }{ + { + expectErr: true, + }, + { + names: []string{"foo"}, + engines: func() []gotenberg.PDFEngine { + engine := struct{ ProtoPDFEngine }{} + engine.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return engine }} + } + + return []gotenberg.PDFEngine{ + engine, + } + }(), + }, + { + names: []string{"foo", "bar", "baz"}, + engines: func() []gotenberg.PDFEngine { + engine1 := struct{ ProtoPDFEngine }{} + engine1.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return engine1 }} + } + + engine2 := struct{ ProtoPDFEngine }{} + engine2.descriptor = func() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ID: "baz", New: func() gotenberg.Module { return engine2 }} + } + + return []gotenberg.PDFEngine{ + engine1, + engine2, + } + }(), + expectErr: true, + }, + } { + mod := new(PDFEngines) + mod.names = tc.names + mod.engines = tc.engines + err := mod.Validate() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestPDFEngine_PDFEngine(t *testing.T) { + mod := new(PDFEngines) + mod.engines = []gotenberg.PDFEngine{ + struct{ ProtoPDFEngine }{}, + } + + _, err := mod.PDFEngine() + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestPDFEngine_Routes(t *testing.T) { + for i, tc := range []struct { + expectRoutes int + disableRoutes bool + }{ + { + expectRoutes: 2, + }, + { + disableRoutes: true, + }, + } { + mod := new(PDFEngines) + mod.engines = []gotenberg.PDFEngine{ + struct{ ProtoPDFEngine }{}, + } + mod.disableRoutes = tc.disableRoutes + + routes, err := mod.Routes() + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + + if tc.expectRoutes != len(routes) { + t.Errorf("test %d: expected %d routes but got %d", i, tc.expectRoutes, len(routes)) + } + } +} + +// Interface guards. +var ( + _ gotenberg.Module = (*ProtoModule)(nil) + _ gotenberg.Validator = (*ProtoValidator)(nil) + _ gotenberg.Module = (*ProtoValidator)(nil) + _ gotenberg.PDFEngine = (*ProtoPDFEngine)(nil) + _ gotenberg.Module = (*ProtoPDFEngine)(nil) + _ gotenberg.Validator = (*ProtoPDFEngine)(nil) +) diff --git a/pkg/modules/pdfengines/routes.go b/pkg/modules/pdfengines/routes.go new file mode 100644 index 00000000..721dba9d --- /dev/null +++ b/pkg/modules/pdfengines/routes.go @@ -0,0 +1,138 @@ +package pdfengines + +import ( + "errors" + "fmt" + "net/http" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" +) + +// mergeRoute returns an api.MultipartFormDataRoute which can merge PDFs. +func mergeRoute(engine gotenberg.PDFEngine) api.MultipartFormDataRoute { + return api.MultipartFormDataRoute{ + Path: "/pdfengines/merge", + Handler: func(ctx *api.Context) error { + // Let's get the data from the form and validate them. + var ( + inputPaths []string + PDFformat string + ) + + err := ctx.FormData(). + MandatoryPaths([]string{".pdf"}, &inputPaths). + String("pdfFormat", &PDFformat, ""). + Validate() + + if err != nil { + return fmt.Errorf("validate form data: %w", err) + } + + // Alright, let's merge the PDFs. + + outputPath := ctx.GeneratePath(".pdf") + + err = engine.Merge(ctx, ctx.Log(), inputPaths, outputPath) + if err != nil { + return fmt.Errorf("merge PDFs: %w", err) + } + + // So far so good, the PDFs are merged into one unique PDF. + // Now, let's check if the client want to convert this result PDF + // to a specific PDF format. + + if PDFformat != "" { + convertInputPath := outputPath + convertOutputPath := ctx.GeneratePath(".pdf") + + err = engine.Convert(ctx, ctx.Log(), PDFformat, convertInputPath, convertOutputPath) + + if err != nil { + if errors.Is(err, gotenberg.ErrPDFFormatNotAvailable) { + return api.WrapError( + fmt.Errorf("convert PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("At least one PDF engine does not handle the PDF format '%s' (pdfFormat), while other have failed to convert for other reasons", PDFformat), + ), + ) + } + + return fmt.Errorf("convert PDF: %w", err) + } + + // Important: the output path is now the converted file. + outputPath = convertOutputPath + } + + // Last but not least, add the output path to the context so that + // the API is able to send it as a response to the client. + + err = ctx.AddOutputPaths(outputPath) + if err != nil { + return fmt.Errorf("add output path: %w", err) + } + + return nil + }, + } +} + +// convertRoute returns an api.MultipartFormDataRoute which can convert a PDF +// to a specific PDF format. +func convertRoute(engine gotenberg.PDFEngine) api.MultipartFormDataRoute { + return api.MultipartFormDataRoute{ + Path: "/pdfengines/convert", + Handler: func(ctx *api.Context) error { + // Let's get the data from the form and validate them. + var ( + inputPaths []string + PDFformat string + ) + + err := ctx.FormData(). + MandatoryPaths([]string{".pdf"}, &inputPaths). + MandatoryString("pdfFormat", &PDFformat). + Validate() + + if err != nil { + return fmt.Errorf("validate form data: %w", err) + } + + // Alright, let's merge the PDFs. + + outputPaths := make([]string, len(inputPaths)) + + for i, inputPath := range inputPaths { + outputPaths[i] = ctx.GeneratePath(".pdf") + + err = engine.Convert(ctx, ctx.Log(), PDFformat, inputPath, outputPaths[i]) + + if err != nil { + if errors.Is(err, gotenberg.ErrPDFFormatNotAvailable) { + return api.WrapError( + fmt.Errorf("convert PDF: %w", err), + api.NewSentinelHTTPError( + http.StatusBadRequest, + fmt.Sprintf("At least one PDF engine does not handle the PDF format '%s' (pdfFormat), while other have failed to convert for other reasons", PDFformat), + ), + ) + } + + return fmt.Errorf("convert PDF: %w", err) + } + } + + // Last but not least, add the output paths to the context so that + // the API is able to send them as a response to the client. + + err = ctx.AddOutputPaths(outputPaths...) + if err != nil { + return fmt.Errorf("add output paths: %w", err) + } + + return nil + }, + } +} diff --git a/pkg/modules/pdfengines/routes_test.go b/pkg/modules/pdfengines/routes_test.go new file mode 100644 index 00000000..47a86b05 --- /dev/null +++ b/pkg/modules/pdfengines/routes_test.go @@ -0,0 +1,392 @@ +package pdfengines + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + "go.uber.org/zap" +) + +func TestMergeHandler(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + engine gotenberg.PDFEngine + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectOutputPathsCount int + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return errors.New("foo") + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return gotenberg.ErrPDFFormatNotAvailable + }, + } + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetCancelled(true) + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectOutputPathsCount: 1, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + merge: func(_ context.Context, _ *zap.Logger, _ []string, _ string) error { + return nil + }, + } + }(), + expectOutputPathsCount: 1, + }, + } { + err := mergeRoute(tc.engine).Handler(tc.ctx.Context) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr api.HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectOutputPathsCount, len(tc.ctx.OutputPaths())) + } + } +} + +func TestConvertHandler(t *testing.T) { + for i, tc := range []struct { + ctx *api.MockContext + engine gotenberg.PDFEngine + expectErr bool + expectHTTPErr bool + expectHTTPStatus int + expectOutputPathsCount int + }{ + { + ctx: &api.MockContext{Context: &api.Context{}}, + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return gotenberg.ErrPDFFormatNotAvailable + }, + } + }(), + expectErr: true, + expectHTTPErr: true, + expectHTTPStatus: http.StatusBadRequest, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return errors.New("foo") + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetCancelled(true) + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectErr: true, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectOutputPathsCount: 1, + }, + { + ctx: func() *api.MockContext { + ctx := &api.MockContext{Context: &api.Context{}} + + ctx.SetFiles(map[string]string{ + "foo.pdf": "/foo/foo.pdf", + "bar.pdf": "/foo/bar.pdf", + }) + ctx.SetValues(map[string][]string{ + "pdfFormat": { + "foo", + }, + }) + + return ctx + }(), + engine: func() gotenberg.PDFEngine { + return &ProtoPDFEngine{ + convert: func(_ context.Context, _ *zap.Logger, _, _, _ string) error { + return nil + }, + } + }(), + expectOutputPathsCount: 2, + }, + } { + err := convertRoute(tc.engine).Handler(tc.ctx.Context) + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + + var httpErr api.HTTPError + isHTTPErr := errors.As(err, &httpErr) + + if tc.expectHTTPErr && !isHTTPErr { + t.Errorf("test %d: expected HTTP error but got: %v", i, err) + } + + if !tc.expectHTTPErr && isHTTPErr { + t.Errorf("test %d: expected no HTTP error but got one: %v", i, httpErr) + } + + if err != nil && tc.expectHTTPErr && isHTTPErr { + status, _ := httpErr.HTTPError() + if status != tc.expectHTTPStatus { + t.Errorf("test %d: expected %d HTTP status code but got %d", i, tc.expectHTTPStatus, status) + } + } + + if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) { + t.Errorf("test %d: expected %d output paths but got %d", i, tc.expectOutputPathsCount, len(tc.ctx.OutputPaths())) + } + } +} diff --git a/pkg/modules/pdftk/doc.go b/pkg/modules/pdftk/doc.go new file mode 100644 index 00000000..759540dd --- /dev/null +++ b/pkg/modules/pdftk/doc.go @@ -0,0 +1,3 @@ +// Package pdftk provides a module which abstracts the CLI tool PDFtk and +// implements the gotenberg.PDFEngine interface. +package pdftk diff --git a/pkg/modules/pdftk/pdftk.go b/pkg/modules/pdftk/pdftk.go new file mode 100644 index 00000000..f7026db8 --- /dev/null +++ b/pkg/modules/pdftk/pdftk.go @@ -0,0 +1,84 @@ +package pdftk + +import ( + "context" + "errors" + "fmt" + "os" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +func init() { + gotenberg.MustRegisterModule(PDFtk{}) +} + +// PDFtk abstracts the CLI tool PDFtk and implements the gotenberg.PDFEngine +// interface. +type PDFtk struct { + binPath string +} + +// Descriptor returns a PDFtk's module descriptor. +func (engine PDFtk) Descriptor() gotenberg.ModuleDescriptor { + return gotenberg.ModuleDescriptor{ + ID: "pdftk", + New: func() gotenberg.Module { return new(PDFtk) }, + } +} + +// Provision sets the modules properties. It returns an error if the +// environment variable PDFTK_BIN_PATH is not set. +func (engine *PDFtk) Provision(_ *gotenberg.Context) error { + binPath, ok := os.LookupEnv("PDFTK_BIN_PATH") + if !ok { + return errors.New("PDFTK_BIN_PATH environment variable is not set") + } + + engine.binPath = binPath + + return nil +} + +// Validate validates the module properties. +func (engine PDFtk) Validate() error { + _, err := os.Stat(engine.binPath) + if os.IsNotExist(err) { + return fmt.Errorf("PDFtk binary path does not exist: %w", err) + } + + return nil +} + +// Merge merges the given PDFs into a unique PDF. +func (engine PDFtk) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error { + var args []string + args = append(args, inputPaths...) + args = append(args, "cat", "output", outputPath) + + cmd, err := gotenberg.CommandContext(ctx, logger, engine.binPath, args...) + if err != nil { + return fmt.Errorf("create command: %w", err) + } + + err = cmd.Exec() + if err == nil { + return nil + } + + return fmt.Errorf("merge PDFs with PDFtk: %w", err) +} + +// Convert is not available for this PDF engine. +func (engine PDFtk) Convert(_ context.Context, _ *zap.Logger, format, _, _ string) error { + return fmt.Errorf("convert PDF to '%s' with PDFtk: %w", format, gotenberg.ErrPDFEngineMethodNotAvailable) +} + +// Interface guards. +var ( + _ gotenberg.Module = (*PDFtk)(nil) + _ gotenberg.Provisioner = (*PDFtk)(nil) + _ gotenberg.Validator = (*PDFtk)(nil) + _ gotenberg.PDFEngine = (*PDFtk)(nil) +) diff --git a/pkg/modules/pdftk/pdftk_test.go b/pkg/modules/pdftk/pdftk_test.go new file mode 100644 index 00000000..4d05552c --- /dev/null +++ b/pkg/modules/pdftk/pdftk_test.go @@ -0,0 +1,136 @@ +package pdftk + +import ( + "context" + "errors" + "os" + "reflect" + "testing" + + "github.com/gotenberg/gotenberg/v7/pkg/gotenberg" + "go.uber.org/zap" +) + +func TestPDFtk_Descriptor(t *testing.T) { + descriptor := PDFtk{}.Descriptor() + + actual := reflect.TypeOf(descriptor.New()) + expect := reflect.TypeOf(new(PDFtk)) + + if actual != expect { + t.Errorf("expected '%s' but got '%s'", expect, actual) + } +} + +func TestPDFtk_Provision(t *testing.T) { + mod := new(PDFtk) + ctx := gotenberg.NewContext(gotenberg.ParsedFlags{}, nil) + + err := mod.Provision(ctx) + if err != nil { + t.Errorf("expected no error but got: %v", err) + } +} + +func TestPDFtk_Validate(t *testing.T) { + for i, tc := range []struct { + binPath string + expectErr bool + }{ + { + expectErr: true, + }, + { + binPath: "/foo", + expectErr: true, + }, + { + binPath: os.Getenv("PDFTK_BIN_PATH"), + }, + } { + mod := new(PDFtk) + mod.binPath = tc.binPath + err := mod.Validate() + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + } +} + +func TestPDFtk_Merge(t *testing.T) { + for i, tc := range []struct { + ctx context.Context + inputPaths []string + expectErr bool + }{ + { + ctx: context.TODO(), + inputPaths: []string{ + "/tests/test/testdata/pdfengines/sample1.pdf", + }, + }, + { + ctx: context.TODO(), + inputPaths: []string{ + "/tests/test/testdata/pdfengines/sample1.pdf", + "/tests/test/testdata/pdfengines/sample2.pdf", + }, + }, + { + ctx: nil, + expectErr: true, + }, + { + ctx: context.TODO(), + inputPaths: []string{ + "foo", + }, + expectErr: true, + }, + } { + func() { + mod := new(PDFtk) + + err := mod.Provision(nil) + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + outputDir, err := gotenberg.MkdirAll() + if err != nil { + t.Fatalf("test %d: expected error but got: %v", i, err) + } + + defer func() { + err := os.RemoveAll(outputDir) + if err != nil { + t.Fatalf("test %d: expected no error but got: %v", i, err) + } + }() + + err = mod.Merge(tc.ctx, zap.NewNop(), tc.inputPaths, outputDir+"/foo.pdf") + + if tc.expectErr && err == nil { + t.Errorf("test %d: expected error but got: %v", i, err) + } + + if !tc.expectErr && err != nil { + t.Errorf("test %d: expected no error but got: %v", i, err) + } + }() + } +} + +func TestPDFtk_Convert(t *testing.T) { + mod := new(PDFtk) + err := mod.Convert(context.TODO(), zap.NewNop(), "", "", "") + + if !errors.Is(err, gotenberg.ErrPDFEngineMethodNotAvailable) { + t.Errorf("expected error %v, but got: %v", gotenberg.ErrPDFEngineMethodNotAvailable, err) + } +} diff --git a/pkg/standard/doc.go b/pkg/standard/doc.go new file mode 100644 index 00000000..46d336a0 --- /dev/null +++ b/pkg/standard/doc.go @@ -0,0 +1,2 @@ +// Package standard imports the application's default modules. +package standard diff --git a/pkg/standard/imports.go b/pkg/standard/imports.go new file mode 100644 index 00000000..6084407a --- /dev/null +++ b/pkg/standard/imports.go @@ -0,0 +1,11 @@ +package standard + +import ( + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/api" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/chromium" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/gc" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/libreoffice/unoconv" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/logging" + _ "github.com/gotenberg/gotenberg/v7/pkg/modules/pdfengines" +) diff --git a/scripts/publish.sh b/scripts/publish.sh deleted file mode 100755 index f6d2c87d..00000000 --- a/scripts/publish.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -set -e - -GOLANG_VERSION="$1" -TINI_VERSION="$2" -DOCKER_REGISTRY="$3" -VERSION="$4" -DOCKER_USER="$5" -DOCKER_PASSWORD="$6" - -docker login -u "$DOCKER_USER" -p "$DOCKER_PASSWORD" - -VERSION="${VERSION//v}" -SEMVER=( ${VERSION//./ } ) -VERSION_LENGTH=${#SEMVER[@]} - -if [ $VERSION_LENGTH -ne 3 ]; then - echo "$VERSION is not semver." - exit 1 -fi - -docker build \ - --build-arg VERSION=${VERSION} \ - --build-arg TINI_VERSION=${TINI_VERSION} \ - -t ${DOCKER_REGISTRY}/gotenberg:latest \ - -t ${DOCKER_REGISTRY}/gotenberg:${SEMVER[0]} \ - -t ${DOCKER_REGISTRY}/gotenberg:${SEMVER[0]}.${SEMVER[1]} \ - -t ${DOCKER_REGISTRY}/gotenberg:${SEMVER[0]}.${SEMVER[1]}.${SEMVER[2]} \ - -f build/package/Dockerfile . - -docker push "${DOCKER_REGISTRY}/gotenberg:latest" -docker push "${DOCKER_REGISTRY}/gotenberg:${SEMVER[0]}" -docker push "${DOCKER_REGISTRY}/gotenberg:${SEMVER[0]}.${SEMVER[1]}" -docker push "${DOCKER_REGISTRY}/gotenberg:${SEMVER[0]}.${SEMVER[1]}.${SEMVER[2]}" \ No newline at end of file diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 00000000..d7a612ca --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +set -e + +GOLANG_VERSION="$1" +GOTENBERG_VERSION="$2" +GOTENBERG_USER_GID="$3" +GOTENBERG_USER_UID="$4" +PDFTK_VERSION="$5" +DOCKER_REGISTRY="$6" + +GOTENBERG_VERSION="${GOTENBERG_VERSION//v}" +SEMVER=( ${GOTENBERG_VERSION//./ } ) +VERSION_LENGTH=${#SEMVER[@]} + +if [ $VERSION_LENGTH -ne 3 ]; then + echo "$VERSION is not semver." + exit 1 +fi + +docker buildx build \ + --build-arg GOLANG_VERSION="$GOLANG_VERSION" \ + --build-arg GOTENBERG_VERSION="$GOTENBERG_VERSION" \ + --build-arg GOTENBERG_USER_GID="$GOTENBERG_USER_GID" \ + --build-arg GOTENBERG_USER_UID="$GOTENBERG_USER_UID" \ + --build-arg PDFTK_VERSION="$PDFTK_VERSION" \ + --platform linux/amd64 \ + --platform linux/arm64 \ + -t "$DOCKER_REGISTRY/gotenberg:latest" \ + -t "$DOCKER_REGISTRY/gotenberg:${SEMVER[0]}" \ + -t "$DOCKER_REGISTRY/gotenberg:${SEMVER[0]}.${SEMVER[1]}" \ + -t "$DOCKER_REGISTRY/gotenberg:${SEMVER[0]}.${SEMVER[1]}.${SEMVER[2]}" \ + --push \ + -f build/Dockerfile . + +# Cloud Run variant. +docker buildx build \ + --build-arg DOCKER_REGISTRY="$DOCKER_REGISTRY" \ + --build-arg GOTENBERG_VERSION="$GOTENBERG_VERSION" \ + --platform linux/amd64 \ + --platform linux/arm64 \ + -t "$DOCKER_REGISTRY/gotenberg:latest-cloudrun" \ + -t "$DOCKER_REGISTRY/gotenberg:${SEMVER[0]}-cloudrun" \ + -t "$DOCKER_REGISTRY/gotenberg:${SEMVER[0]}.${SEMVER[1]}-cloudrun" \ + -t "$DOCKER_REGISTRY/gotenberg:${SEMVER[0]}.${SEMVER[1]}.${SEMVER[2]}-cloudrun" \ + --push \ + -f build/Dockerfile.cloudrun . \ No newline at end of file diff --git a/scripts/tests.sh b/scripts/tests.sh deleted file mode 100755 index 814d50f0..00000000 --- a/scripts/tests.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e - -DOCKER_REGISTRY="$1" -CODE_COVERAGE="$2" - -touch "$PWD/coverage.txt" -chmod 777 "$PWD/coverage.txt" -docker build -t "$DOCKER_REGISTRY/gotenberg:tests" -f build/tests/Dockerfile . - -if [ "$CODE_COVERAGE" = "1" ]; then - docker run --rm -e "CODE_COVERAGE=$CODE_COVERAGE" -v "$PWD/coverage.txt:/gotenberg/tests/coverage.txt" "$DOCKER_REGISTRY/gotenberg:tests" -else - docker run --rm -e "CODE_COVERAGE=$CODE_COVERAGE" "$DOCKER_REGISTRY/gotenberg:tests" -fi \ No newline at end of file diff --git a/test/Dockerfile b/test/Dockerfile new file mode 100644 index 00000000..9762ac94 --- /dev/null +++ b/test/Dockerfile @@ -0,0 +1,45 @@ +ARG GOLANG_VERSION +ARG DOCKER_REGISTRY +ARG GOTENBERG_VERSION +ARG GOLANGCI_LINT_VERSION + +FROM golang:$GOLANG_VERSION-stretch as golang + +# We're extending the Gotenberg's Docker image because our code relies on external +# dependencies like Google Chrome, LibreOffice, etc. +FROM $DOCKER_REGISTRY/gotenberg:$GOTENBERG_VERSION + +USER root + +COPY --from=golang /usr/local/go /usr/local/go +COPY ./test/docker-entrypoint.sh /usr/bin/docker-entrypoint.sh +COPY ./test/golint.sh /usr/bin/golint +COPY ./test/gotest.sh /usr/bin/gotest +COPY ./test/gotodos.sh /usr/bin/gotodos + +ENV GOPATH /go +ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH +ENV CGO_ENABLED 1 + +RUN apt-get update -qq &&\ + apt-get install -y -qq --no-install-recommends \ + sudo \ + # gcc for cgo. + g++ \ + gcc \ + libc6-dev \ + make \ + pkg-config &&\ + rm -rf /var/lib/apt/lists/* &&\ + mkdir -p "$GOPATH/src" "$GOPATH/bin" &&\ + chmod -R 777 "$GOPATH" &&\ + adduser gotenberg sudo &&\ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers &&\ + # We cannot use $PATH in the next command (print $PATH instead of the environment variable value). + sed -i 's#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/go/bin:/usr/local/go/bin#g' /etc/sudoers &&\ + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin $GOLANGCI_LINT_VERSION + +# Pristine working directory. +WORKDIR /tests + +ENTRYPOINT [ "docker-entrypoint.sh" ] \ No newline at end of file diff --git a/test/cmd/chrome.go b/test/cmd/chrome.go deleted file mode 100644 index 82234f3e..00000000 --- a/test/cmd/chrome.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "github.com/thecodingmachine/gotenberg/internal/pkg/chrome" - "github.com/thecodingmachine/gotenberg/internal/pkg/conf" - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -func main() { - const op string = "main" - config, err := conf.FromEnv() - systemLogger := xlog.New(config.LogLevel(), "system") - if err != nil { - systemLogger.FatalOp(op, err) - } - // start Google Chrome headless. - if err := chrome.Start(systemLogger, config.GoogleChromeIgnoreCertificateErrors()); err != nil { - systemLogger.FatalOp(op, err) - } -} diff --git a/test/context.go b/test/context.go deleted file mode 100644 index 537ae5f2..00000000 --- a/test/context.go +++ /dev/null @@ -1,29 +0,0 @@ -package test - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/labstack/echo/v4" -) - -// DummyEchoContext creates a -// echo.Context without anything. -func DummyEchoContext() echo.Context { - e := echo.New() - req := httptest.NewRequest(http.MethodGet, "/", nil) - rec := httptest.NewRecorder() - return e.NewContext(req, rec) -} - -// EchoContextMultipart creates a -// echo.Context with form files. -func EchoContextMultipart(t *testing.T) echo.Context { - e := echo.New() - body, contentType := MergeMultipartForm(t, nil) - req := httptest.NewRequest(http.MethodPost, "/", body) - req.Header.Set(echo.HeaderContentType, contentType) - rec := httptest.NewRecorder() - return e.NewContext(req, rec) -} diff --git a/test/doc.go b/test/doc.go deleted file mode 100644 index edc5a4d1..00000000 --- a/test/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package test contains useful -// functions used across tests. -package test diff --git a/test/docker-entrypoint.sh b/test/docker-entrypoint.sh new file mode 100755 index 00000000..413e24e2 --- /dev/null +++ b/test/docker-entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# This entrypoint allows us to set the UID and GID of the host user so that +# our testing environment does not override files permissions from the host. +# Credits: https://github.com/thecodingmachine/docker-images-php. + +set +e +mkdir testing_file_system_rights.foo +chmod 700 testing_file_system_rights.foo +su gotenberg -c "touch testing_file_system_rights.foo/foo > /dev/null 2>&1" +HAS_CONSISTENT_RIGHTS=$? + +if [[ "$HAS_CONSISTENT_RIGHTS" != "0" ]]; then + # If not specified, the DOCKER_USER is the owner of the current working directory (heuristic!). + DOCKER_USER=`ls -dl $(pwd) | cut -d " " -f 3` +else + # macOs or Windows. + # Note: in most cases, we don't care about the rights (they are not respected). + FILE_OWNER=`ls -dl testing_file_system_rights.foo/foo | cut -d " " -f 3` + if [[ "$FILE_OWNER" == "root" ]]; then + # If root, we are likely on a Windows host. + # All files will belong to root, but it does not matter as everybody can write/delete + # those (0777 access rights). + DOCKER_USER=gotenberg + else + # In case of a NFS mount (common on macOS), the created files will belong to the NFS user. + DOCKER_USER=$FILE_OWNER + fi +fi + +rm -rf testing_file_system_rights.foo +set -e +unset HAS_CONSISTENT_RIGHTS + +# Note: DOCKER_USER is either a username (if the user exists in the container), +# otherwise a user ID (a user from the host). + +# DOCKER_USER is an ID. +if [[ "$DOCKER_USER" =~ ^[0-9]+$ ]] ; then + # Let's change the gotenberg user's ID in order to match this free ID. + usermod -u $DOCKER_USER -G sudo gotenberg + DOCKER_USER=gotenberg +fi + +DOCKER_USER_ID=`id -ur $DOCKER_USER` + +# Fix access rights to stdout and stderr. +set +e +chown $DOCKER_USER /proc/self/fd/{1,2} +set -e + +# Install modules. +set -x +go mod download +go mod tidy +set +x + +# Run the command with the correct user. +exec "sudo" "-E" "-H" "-u" "#$DOCKER_USER_ID" "$@" \ No newline at end of file diff --git a/test/golint.sh b/test/golint.sh new file mode 100755 index 00000000..107c7018 --- /dev/null +++ b/test/golint.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -x + +golangci-lint run \ No newline at end of file diff --git a/test/gotest.sh b/test/gotest.sh new file mode 100755 index 00000000..d9c2de80 --- /dev/null +++ b/test/gotest.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -x + +go test -race -covermode=atomic -coverprofile=/tests/coverage.txt ./... +go tool cover -html=coverage.txt -o /tests/coverage.html \ No newline at end of file diff --git a/test/gotodos.sh b/test/gotodos.sh new file mode 100755 index 00000000..c6201369 --- /dev/null +++ b/test/gotodos.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -x + +golangci-lint run \ + --no-config \ + --disable-all \ + --enable godox \ No newline at end of file diff --git a/test/http.go b/test/http.go deleted file mode 100644 index 187ba58c..00000000 --- a/test/http.go +++ /dev/null @@ -1,17 +0,0 @@ -package test - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" -) - -// AssertStatusCode checks if the given request -// returns the expected status code. -func AssertStatusCode(t *testing.T, expectedStatusCode int, srv http.Handler, req *http.Request) { - rec := httptest.NewRecorder() - srv.ServeHTTP(rec, req) - assert.Equal(t, expectedStatusCode, rec.Code) -} diff --git a/test/multipartform.go b/test/multipartform.go deleted file mode 100644 index 00e8e552..00000000 --- a/test/multipartform.go +++ /dev/null @@ -1,90 +0,0 @@ -package test - -import ( - "bytes" - "io" - "mime/multipart" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" -) - -/* -MergeMultipartForm returns the body -for a multipart/form-data request with all -files under "testdata/pdf" folder. -*/ -func MergeMultipartForm(t *testing.T, formValues map[string]string) (*bytes.Buffer, string) { - fpaths := MergeFpaths(t) - return multipartForm(t, "pdf", formValues, fpaths) -} - -/* -HTMLMultipartForm returns the body -for a multipart/form-data request with all -files under "testdata/html" folder. -*/ -func HTMLMultipartForm(t *testing.T, formValues map[string]string) (*bytes.Buffer, string) { - fpaths := HTMLFpaths(t) - return multipartForm(t, "html", formValues, fpaths) -} - -/* -URLMultipartForm returns the body -for a multipart/form-data request with all -files under "testdata/url" folder. -*/ -func URLMultipartForm(t *testing.T, formValues map[string]string) (*bytes.Buffer, string) { - fpaths := URLFpaths(t) - return multipartForm(t, "url", formValues, fpaths) -} - -/* -MarkdownMultipartForm returns the body -for a multipart/form-data request with all -files under "testdata/markdown" folder. -*/ -func MarkdownMultipartForm(t *testing.T, formValues map[string]string) (*bytes.Buffer, string) { - fpaths := MarkdownFpaths(t) - return multipartForm(t, "markdown", formValues, fpaths) -} - -/* -OfficeMultipartForm returns the body -for a multipart/form-data request with all -files under "testdata/office" folder. -*/ -func OfficeMultipartForm(t *testing.T, formValues map[string]string) (*bytes.Buffer, string) { - fpaths := OfficeFpaths(t) - return multipartForm(t, "office", formValues, fpaths) -} - -func multipartForm( - t *testing.T, - kind string, - formValues map[string]string, - formFilePaths []string, -) (*bytes.Buffer, string) { - body := &bytes.Buffer{} - writer := multipart.NewWriter(body) - defer writer.Close() - for _, fpath := range formFilePaths { - file, err := os.Open(fpath) - require.Nil(t, err) - part, err := writer.CreateFormFile("foo", filepath.Base(fpath)) - require.Nil(t, err) - _, err = io.Copy(part, file) - require.Nil(t, err) - } - if kind == "url" { - err := writer.WriteField("remoteURL", "https://google.com") - require.Nil(t, err) - } - for k, v := range formValues { - err := writer.WriteField(k, v) - require.Nil(t, err) - } - return body, writer.FormDataContentType() -} diff --git a/test/testdata.go b/test/testdata.go deleted file mode 100644 index fc72472b..00000000 --- a/test/testdata.go +++ /dev/null @@ -1,88 +0,0 @@ -package test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "github.com/thecodingmachine/gotenberg/internal/pkg/xrand" -) - -/* -testdataDirectoryPath should be -the absolute of the testdata INSIDE -the Docker image. -*/ -const testdataDirectoryPath string = "/gotenberg/tests/test/testdata" - -// GenerateDestination simply generates -// a path for a resulting PDF file. -func GenerateDestination() string { - return fmt.Sprintf("/tmp/%s.pdf", xrand.Get()) -} - -// MergeFpaths return the paths of all -// files under "testdata/pdf" folder. -func MergeFpaths(t *testing.T) []string { - return []string{ - fpath(t, "pdf", "gotenberg.pdf"), - fpath(t, "pdf", "gotenberg_bis.pdf"), - } -} - -// HTMLFpaths return the paths of all -// files under "testdata/html" folder. -func HTMLFpaths(t *testing.T) []string { - return []string{ - fpath(t, "html", "index.html"), - fpath(t, "html", "header.html"), - fpath(t, "html", "footer.html"), - fpath(t, "html", "style.css"), - fpath(t, "html", "img.gif"), - fpath(t, "html", "font.woff"), - } -} - -// URLFpaths return the paths of all -// files under "testdata/url" folder. -func URLFpaths(t *testing.T) []string { - return []string{ - fpath(t, "url", "header.html"), - fpath(t, "url", "footer.html"), - } -} - -// MarkdownFpaths return the paths of all -// files under "testdata/markdown" folder. -func MarkdownFpaths(t *testing.T) []string { - return []string{ - fpath(t, "markdown", "index.html"), - fpath(t, "markdown", "header.html"), - fpath(t, "markdown", "footer.html"), - fpath(t, "markdown", "style.css"), - fpath(t, "markdown", "img.gif"), - fpath(t, "markdown", "font.woff"), - fpath(t, "markdown", "paragraph1.md"), - fpath(t, "markdown", "paragraph2.md"), - fpath(t, "markdown", "paragraph3.md"), - } -} - -// OfficeFpaths return the paths of all -// files under "testdata/office" folder. -func OfficeFpaths(t *testing.T) []string { - return []string{ - fpath(t, "office", "document.docx"), - fpath(t, "office", "document.rtf"), - fpath(t, "office", "document.txt"), - fpath(t, "office", "document_with_special_éà.txt"), - } -} - -func fpath(t *testing.T, kind, filename string) string { - require.NotEmpty(t, kind) - require.NotEmpty(t, filename) - fpath := fmt.Sprintf("%s/%s/%s", testdataDirectoryPath, kind, filename) - require.FileExists(t, fpath) - return fpath -} diff --git a/test/testdata/api/sample1.txt b/test/testdata/api/sample1.txt new file mode 100644 index 00000000..19102815 --- /dev/null +++ b/test/testdata/api/sample1.txt @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/test/testdata/pdf/gotenberg.pdf b/test/testdata/api/sample2.pdf similarity index 100% rename from test/testdata/pdf/gotenberg.pdf rename to test/testdata/api/sample2.pdf diff --git a/test/testdata/html/font.woff b/test/testdata/chromium/html/sample1/font.woff old mode 100755 new mode 100644 similarity index 100% rename from test/testdata/html/font.woff rename to test/testdata/chromium/html/sample1/font.woff diff --git a/test/testdata/chromium/html/sample1/footer.html b/test/testdata/chromium/html/sample1/footer.html new file mode 100644 index 00000000..71749d08 --- /dev/null +++ b/test/testdata/chromium/html/sample1/footer.html @@ -0,0 +1,15 @@ + + + + + +

+ of +

+ + \ No newline at end of file diff --git a/test/testdata/chromium/html/sample1/header.html b/test/testdata/chromium/html/sample1/header.html new file mode 100644 index 00000000..00ab687b --- /dev/null +++ b/test/testdata/chromium/html/sample1/header.html @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/test/testdata/html/img.gif b/test/testdata/chromium/html/sample1/img.gif similarity index 100% rename from test/testdata/html/img.gif rename to test/testdata/chromium/html/sample1/img.gif diff --git a/test/testdata/chromium/html/sample1/index.html b/test/testdata/chromium/html/sample1/index.html new file mode 100644 index 00000000..8c9bbd51 --- /dev/null +++ b/test/testdata/chromium/html/sample1/index.html @@ -0,0 +1,38 @@ + + + + + + + Gutenberg + + +
+
+

Gutenberg

+ +
+ +
+

It is a press, certainly, but a press from which shall flow in inexhaustible streams...Through it, God will spread His Word. A spring of truth shall flow from it: like a new star it shall scatter the darkness of ignorance, and cause a light heretofore unknown to shine amongst men.

+ +
+
+ +
+

This paragraph use the default font

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

This paragraph use a Google font

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

This paragraph use a local font

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+ +
+

This image is loaded from a URL

+ +
+ + \ No newline at end of file diff --git a/test/testdata/html/style.css b/test/testdata/chromium/html/sample1/style.css similarity index 100% rename from test/testdata/html/style.css rename to test/testdata/chromium/html/sample1/style.css diff --git a/test/testdata/chromium/html/sample2/index.html b/test/testdata/chromium/html/sample2/index.html new file mode 100644 index 00000000..a1dd5fd6 --- /dev/null +++ b/test/testdata/chromium/html/sample2/index.html @@ -0,0 +1,28 @@ + + + + + Gutenberg + + + +

+ No window.status +

+ + + + \ No newline at end of file diff --git a/test/testdata/chromium/html/sample3/index.html b/test/testdata/chromium/html/sample3/index.html new file mode 100644 index 00000000..9be80e2b --- /dev/null +++ b/test/testdata/chromium/html/sample3/index.html @@ -0,0 +1,10 @@ + + + + + Gutenberg + + + + + \ No newline at end of file diff --git a/test/testdata/chromium/html/sample4/index.html b/test/testdata/chromium/html/sample4/index.html new file mode 100644 index 00000000..60e1f403 --- /dev/null +++ b/test/testdata/chromium/html/sample4/index.html @@ -0,0 +1,10 @@ + + + + + Gutenberg + + +

Hello, world!

+ + \ No newline at end of file diff --git a/test/testdata/markdown/font.woff b/test/testdata/chromium/markdown/sample1/font.woff old mode 100755 new mode 100644 similarity index 100% rename from test/testdata/markdown/font.woff rename to test/testdata/chromium/markdown/sample1/font.woff diff --git a/test/testdata/chromium/markdown/sample1/footer.html b/test/testdata/chromium/markdown/sample1/footer.html new file mode 100644 index 00000000..22bae5d2 --- /dev/null +++ b/test/testdata/chromium/markdown/sample1/footer.html @@ -0,0 +1,15 @@ + + + + + +

+ of +

+ + \ No newline at end of file diff --git a/test/testdata/chromium/markdown/sample1/header.html b/test/testdata/chromium/markdown/sample1/header.html new file mode 100644 index 00000000..00ab687b --- /dev/null +++ b/test/testdata/chromium/markdown/sample1/header.html @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/test/testdata/markdown/img.gif b/test/testdata/chromium/markdown/sample1/img.gif similarity index 100% rename from test/testdata/markdown/img.gif rename to test/testdata/chromium/markdown/sample1/img.gif diff --git a/test/testdata/markdown/index.html b/test/testdata/chromium/markdown/sample1/index.html similarity index 60% rename from test/testdata/markdown/index.html rename to test/testdata/chromium/markdown/sample1/index.html index ddeccdbf..1fe783cf 100644 --- a/test/testdata/markdown/index.html +++ b/test/testdata/chromium/markdown/sample1/index.html @@ -1,34 +1,34 @@ - + Gutenberg - - -
-
+ + +
+

Gutenberg

-
+
-
+

It is a press, certainly, but a press from which shall flow in inexhaustible streams...Through it, God will spread His Word. A spring of truth shall flow from it: like a new star it shall scatter the darkness of ignorance, and cause a light heretofore unknown to shine amongst men.

-
+
+
+ +
+ {{ toHTML "markdown1.md" }} + +
+ {{ toHTML "markdown2.md" }}
-
- {{ toHTML .DirPath "paragraph1.md" }} - -
- {{ toHTML .DirPath "paragraph2.md" }} -
- -
- {{ toHTML .DirPath "paragraph3.md" }} -
+
+ {{ toHTML "markdown3.md" }}
- +
+ \ No newline at end of file diff --git a/test/testdata/markdown/paragraph1.md b/test/testdata/chromium/markdown/sample1/markdown1.md similarity index 84% rename from test/testdata/markdown/paragraph1.md rename to test/testdata/chromium/markdown/sample1/markdown1.md index f30e2d73..14c83035 100644 --- a/test/testdata/markdown/paragraph1.md +++ b/test/testdata/chromium/markdown/sample1/markdown1.md @@ -1,3 +1,3 @@ -## This paragraph use the default font and has been generated from a markdown file +## This paragraph uses the default font and has been generated from a markdown file Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file diff --git a/test/testdata/office/document_with_special_éà.txt b/test/testdata/chromium/markdown/sample1/markdown2.md similarity index 84% rename from test/testdata/office/document_with_special_éà.txt rename to test/testdata/chromium/markdown/sample1/markdown2.md index 16eab9d7..d8dd4f23 100644 --- a/test/testdata/office/document_with_special_éà.txt +++ b/test/testdata/chromium/markdown/sample1/markdown2.md @@ -1,3 +1,3 @@ -Gutenberg +## This paragraph uses a Google font and has been generated from a markdown file Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file diff --git a/test/testdata/markdown/paragraph2.md b/test/testdata/chromium/markdown/sample1/markdown3.md similarity index 87% rename from test/testdata/markdown/paragraph2.md rename to test/testdata/chromium/markdown/sample1/markdown3.md index 0a02537f..c0aac6f3 100644 --- a/test/testdata/markdown/paragraph2.md +++ b/test/testdata/chromium/markdown/sample1/markdown3.md @@ -1,3 +1,3 @@ -## This paragraph use a Google font and has been generated from a markdown file +## This paragraph uses a local font and has been generated from a markdown file Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file diff --git a/test/testdata/markdown/style.css b/test/testdata/chromium/markdown/sample1/style.css similarity index 100% rename from test/testdata/markdown/style.css rename to test/testdata/chromium/markdown/sample1/style.css diff --git a/test/testdata/chromium/markdown/sample2/index.html b/test/testdata/chromium/markdown/sample2/index.html new file mode 100644 index 00000000..f36ca65f --- /dev/null +++ b/test/testdata/chromium/markdown/sample2/index.html @@ -0,0 +1,23 @@ + + + + + Gutenberg + + +
+
+

Gutenberg

+
+ +
+

It is a press, certainly, but a press from which shall flow in inexhaustible streams...Through it, God will spread His Word. A spring of truth shall flow from it: like a new star it shall scatter the darkness of ignorance, and cause a light heretofore unknown to shine amongst men.

+ +
+
+ +
+ {{ toHTML "markdown.md" }} +
+ + \ No newline at end of file diff --git a/test/testdata/chromium/url/sample1/footer.html b/test/testdata/chromium/url/sample1/footer.html new file mode 100644 index 00000000..22bae5d2 --- /dev/null +++ b/test/testdata/chromium/url/sample1/footer.html @@ -0,0 +1,15 @@ + + + + + +

+ of +

+ + \ No newline at end of file diff --git a/test/testdata/chromium/url/sample1/header.html b/test/testdata/chromium/url/sample1/header.html new file mode 100644 index 00000000..00ab687b --- /dev/null +++ b/test/testdata/chromium/url/sample1/header.html @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/test/testdata/chromium/url/sample2/footer.html b/test/testdata/chromium/url/sample2/footer.html new file mode 100644 index 00000000..d5e55914 --- /dev/null +++ b/test/testdata/chromium/url/sample2/footer.html @@ -0,0 +1,8206 @@ + + + + + +

+ 9254835974458887629672873635789957411886024698554157393849494864228024962939550688297074527198420261051675205999609689838587412 + 7948702662533481896767559573369920938242346354580061545409242090168773727371802699309443935396635866263937828773324526334321892 + 7929250312741837331511829643632683169694074912332726993582394725302853411901337696207186358524323117172520907433878952968176465 + 9486937364148093931718552300016332142708943190856638524388888569011747617956915519539025796115901484762122047712200094207683584 + 0703675740855407318047361595661595146837376373951978537785605481083388906490085533348547865459237835407372374738389274773789264 + 3524314516560200536698529022539598732463389124803873184044464663165630452635665559603483233341839268186056673186867104904449866 + 3388466377320953222057779182433549144340237502432464295061371141084500222833875925546082542869030852833895137466510262849050187 + 2359980877010447170873386178573828860442255448874794721230413368694441497441338856684036949118353204002591974711928301953002372 + 6372613557152801003023836434406997863096739346637849381675791163293956729985652182807911615231198696051411047800847064484769940 + 4555399892730282159333189930818248844009737851281434494736943722577947684829017806688345340403991974811107725657399196027995602 + 3976607710681047393460981746843991626375149576917517874980586155555711990727221948467045177979554215577477183785345135535682148 + 8981224019853812859833307577420310576654838103212699667682513798088777109119729024038590682109547975734687407898816774007038892 + 9017123764104410282402525387418186790830943654104676998756681754083664849203556615995024922746652778319099999725942494552746687 + 4602993085345245279681119328539229356959910969065035141679707233267342542524482900839390718291823532073464112692162110160887576 + 8646564120617234541914353449310981315044240998894442066188871011899825887695202156119273906958004776559173081177243291448706570 + 4866033151494706872899672197703352421058356661105030485577210664650513250767511742264039882291373723618030276740280451621184372 + 9438899492601727676139376045138079061355198567322008270344297244790265795845160675322685239683610065522225253070076549915962270 + 8389935622999431104891971065250599273560270041530059453015141663393829191008304620453278274234791447194116642959854046669653221 + 4390066870930359126190473237338490788280116222078414392005864878004044572924012489353108185972058375678318527434060575546457283 + 0571024164252835918003185534087097269093594036226831977994875139354124615791501602629221816855731144878875700135493432353006251 + 5927821910139360288795697248742701824779517711136895716699422565064551330393130338804982871980774254446227613970394730940420871 + 3742377272014443550088749485134437400845098911378170974616143540710504172620523980130687874417124218036934374655684373965565750 + 1478423915766121994159683752043056020433068572256778826939436280481378432842397489866548450027752963017529841096517341127140258 + 8566764493817154363962092792522076892737665735147823735202597353071978920287229637466345140359899735477359400126088124931881468 + 8940255760337363163978793913265843793885760290540433771518954295210648595347128727773745692808704267887587662204824695198843990 + 0899757006576147578169404543275069681042994730814241204020586377450354179962282687398746645565905502250948590090052580759060254 + 6486974981051360582508378437652320531515639324364424491392656403886587101611394285202791775180181840494403192370521504242888310 + 0832863857962097233772304981176182241414796661234070317886749751979535621508014316193777356696545211120669034308685700669047575 + 1601920560631092775469657814901382577801938745924198963515833985856042317888652481510158158143597978988591350058772254540887509 + 2132235148831014717469033542114409228818750252221985002159849994061876844567039235968616101425307518401162305005282076459564485 + 3749005491254116003221964938075605607977980187695543266859111481060871108661145469674590183816636520815523589998805144183387552 + 3454557776795930937812464849331806246436437524220402821725671887519345824588678830784061509096255092713692879753496348543679698 + 6604711892156464428503873379368266697844691398807542828869396127474509499861163107833096454590997165019449027223124752455672795 + 1464056065563451406292025100441586772081609300298880665395988771146415490692648836974652685280576941091682396423173897267646839 + 0355383165630525414486907132932207574564820206814521900700480593494653392345246480522618317569197186894847097184780188176595384 + 2234714652935409724403164799544553996270776652429105659472464101488105672623286713328942045106946821859926624587221567145826782 + 0309935578008890373154226142294034025862773115052182464935233315361839771441799453095926400038395389556682588458216003237653863 + 1061156071932484650516913321439215405043703716040614962270232640142284681169472791577978618224769535957766957086206741391709970 + 7647351716205014294072195135184469100518783539374945598848168573993875333505334011212625117442647232720744618603822330582078365 + 6190042304849971211815384939288709598033150233044255711655989057889996862762413082297341687788607689416591830790638752880761817 + 3350993967482666602170935703513835999165561197161777938477157925978429670778105685120890113130859239045083522459241247368307415 + 5460081669964922086720150722963115784946235169601550836667474277946931369187925788894576312382075479577915204545165252523196796 + 9483728931707116749644793319165741326903913011722074179317419072713429472369240811255731316334667969479890293999075667048649131 + 3479265891282260862086967904220845208360231245372151218473448305464967324382299780822943482467600298687513476936031155077963601 + 5358607166888753271639287331221882667306965170073890751994864930247242443182503197751744519602399141153643026523167858853130538 + 7454234112327473005509721991333469328638161495819890863131852055720398755713433050343878076412540696773945682790587599473898772 + 1829500286670935139918198012253669665196719074234685642111242009658467409729732638466770339415767564217863874440642300491597266 + 5585497029761221358413402963546931530898077983556347511671398790492531247609197801647309393017719703556474420667077635431137035 + 8446511749461154540070308470454488783535318141900958816289412388611370858697615498746416636102261400237788596935028958347787028 + 3125589335242227429164632721324285385335478344437654660712476162463759322956724441170491898597020350367163787012219584863841888 + 6802337989299969519242898184367047999251583706804577726542893830886334416591927545136810611568115854449708934129157129519681281 + 4502536799805954583144549032621959969753071050956941684132891200046324576389173182566153807220810192479638581311891427849367417 + 6325541021938064574977797529368876421571303611445571554655335842928934553745122110842178236045825160364424732178843094315127909 + 7416551206319999579172591987511489686313571898121634456963111089610744020435972487389528243640299599133169203384400119064268257 + 5942558924368052900576494867848083529988242331335385049200017447913990221665638834941940132033114280719741451021709322013495656 + 3034267296680277379429583962288582457402893052674209528241394670330734634693333770067544918231098413897817493181756172191761769 + 4462568735945386723562623780129364617626340957792264088426814103842409805756856047587770203362285297182877719759239486173167134 + 8181657858983878076788365457679611406051878073922935400724071002626732091440173091689286855430601190105542880854867957669944342 + 1682764258327911438109776589215105175058720345720016147450773913501679216877023673201387960875767306750352156509386560915532694 + 4168453046768399507263930483191895109159119018724369742162771101927944398681984030667327651300421681200981291741743361136642792 + 5961214949092908589726506803431211408890378633711553535211419472586275853572210445315467622414789208830684013971300686277675328 + 9269710543143964341467182430089608998710751826481978504336310277969086698368677287182389959721242273938854619109417313330166529 + 8486459999966843090378171773263091325696386996545517566407679424699279968298703891528397394384066258625248890398189881141241156 + 1449849546688513154852662654151484110306993368687380709636409815697889872688403677017676988174939843342948688833489247136945501 + 3026821425662283243215241228426396875362999466310497066906176240972976192127107346129568606866349374029240104708104443230866441 + 4888599832610923002904596161762304764008702325429097763470366526898011656507069583771589908698710318907474941536590688671464002 + 2187786798670885931014137550230451723811271617853032443909991254363190383287294838940424051082728434647528986018234698035977262 + 4010150476565439429491060857277549534561616385054516756344772776300804281913985317098584407945908254666687113999982299034911916 + 9543106789274635042741853569705907409683466986445551664737067041728196021666244823741197574167419992584104093228192902092720801 + 1102588771206288521669854794170734776396759389699841902844928003578465247527168100807066013305698109312645455547945036883046986 + 3363256734764708042924448420459037705906529627671525144633382899415555101340497992824046104327698365969273385304329013580634534 + 5814024400502542484138080303093675479908925878015957334513036393579080542663814740530799226052633254072603206379019404756963615 + 8568459878266889844587337958272179244147420281407959235700418194754222652142770182396574372220705526302797889629403089542338729 + 8226364273353855713782831639652716359809735693921459950536413341806490125092787610897542413754704628839004798504470781343226879 + 9564108089806303912196187245286576464060313163695650258929860024346682416259472890719900060340274063102211811727469052257146328 + 0723807096388817245239864356681843226170736144832701238842559718295427226555369395998370081796589238415142792914737246512392617 + 4241424816471283201248965000004171003042756134627995493041482479770591013182623840449510466593158465328399081296605282376713554 + 9973513220590332519460381924338347505856779256581376567327469745338170108702340101128824216183825500136464452346025348049667485 + 8383897971629124447860057453350337067099519586684049058435585462779736095630666963739484221218567448740285624710665297561214099 + 9964116268591382706460872763874878534297946361217165257274977145088020502651470013064060961213429959898581048432243027406481577 + 4824315082578790346775943088343852549806522479147355182415674805204204673847884219703487656256651056490611337757236524094938348 + 7062382447597254598729362880233858271292436951748099256624309342834053225940366427538355199347489811241328865453894894705029296 + 9735693411211619628088603452483215272175364970550497151583596541206523461527332458408984429879086514102509879665768932131692226 + 6961688387629152540756216546017259642317857065168508958573052496210655276891659756089714383999813015316305245290357709870563638 + 3863034723721495784723589237391107262786771026496285596990386769945707595340965195448259401890929565886615037974745228156868323 + 3287577904832967842610714371567414265151412481754216777139400930821306278453396427971928947503983582862250196984342590738386627 + 1791128295449101351282899590128118669109794265058849951756999066974826947872800232214872176234126177766951584517353226892319930 + 8805052099840613606036822579273082344123139982418321238213526119536401574939527633217151490658267375799590895845553195225375174 + 1355928510541796297379079857922955866076933929404227257481153317061720856509437585235189609477388103725696248255380889259925943 + 1402201875930840177564779603131963190398447445546273482826943610197406605496467698637182093544726028048446184407465904504733488 + 1834037129267281181848805100644706716446934703366578946950288560270548606368029542736413168537166947783032181537827321728818305 + 2399588088866368871684803227983829485917501647912319399696731866908470118289600881964063135888922021379521028829404789266368968 + 5637489977535077950426899162426475829892339881113388204978816994197921201698140466319573566765752657389499556451516488232245559 + 6112692169213605381302831305889438504096793315962284966459192757358537426473374519814657784899843476819443537896967951107338491 + 7895505461382759098793722523795396339534176000429147383719128841803883949006205025948100090981495836498310874463726230844486437 + 9522042614500829901321795525603265978871144309432521198633117362072879318547949126425751870262081563243482328537146079314556599 + 5093542621599279420676140514142072884094585996707002095359240117940447064308608734332029368110977503867431654445743620282821742 + 2074818355004815481495949283111185240895061522427508730372487670815127557063465146879286952537668866636765956480834805349247418 + 0982616183770170277896101663961256388046096956303414645662042291995673037815635718874781061367093483701372208717092453548930045 + 3197990341408426456860501773717322183556963874016603497159407408857792270849795326742052795163483613191779561704529979153717213 + 0442381165605136382176204027769856937910886725474913822447353042136166362618403395513606165988761350028767809916274534709139581 + 1546533500647539778292217072989397950692244341857345231008319214990106951110301762058019968223873956867021450221558460837271796 + 1089583682950702039719953402978240768135379617758154644301927987331573523265837746123630494418924793748993674977892210713791382 + 2010498095473532597719948269554932451554991652103201520706494302534512806373772862577948592827967992187111665796229241795272327 + 4495947525239030494005205359163320911969546009892986032715554824732415447400580445227801191434206229755544175085033640445463730 + 5799343664533857261737308836915890943267341995945607000250119768647338018370977116150224513412795224930773162810128318361091070 + 2845165641335198012087900200223115487995666447653144922411381435396653532150893427712002942030941647409112450887593516206623257 + 5995936189970345951128332927675055555031225056766626864377451946716279426300206796784320339236602175243416848009874418064376734 + 2751388225971927284674719275737386426623723915170272496656834116124167598744380632642578314683658323664087930294748983479134152 + 4463890675024338744201454760164930410895360686852249316115526602608580347281230566360947860956394767605509297995646286805155429 + 3902535272296902694906404269870261097232828009262961508419387381919670436136425912908116240583462930917866834873246313946702767 + 0171550221706917129701789274673785241823132172160837286626181116666263103300493781986590027327174868610919833041462749008446670 + 1233446436949798212579086729206735034953949556045481891487880919889748751337486349345808929953562851746791383784762700811827813 + 3273320169223863915019571833988285591541029709234409949795661766708317004888223115613777281294607726043777706813741640111212754 + 2476840221289778122524588163601454015024966289209119530584971298419043747426874336591254749329149388984462650479516131162264547 + 8321322112340265706034027413610131445579234122444443539849216325832257070066442940612976748450142222873158683339615189385385401 + 2845301295555610107931163495080379964949955895954082606347174241430747973616106979000794362756653542557197433894470866065773098 + 7002289110540946230118386265586199860767183813803128176222583812066464632835592487506968002253203796340562076570806978606547027 + 0518614265711371822209002835579969441398099868205035333550662371029236766960492501859441092496004547436756442048667962205035734 + 4662742623053069471722274771033535333247780680117662494001501801076484609461801093095512629224389725470873708072969419161134986 + 8879423231727024904174405990021786946862967043559824446453539979244586561718968470449066018656109597862462444251052806647222165 + 2462868109247823087920350263249330583062507248433983310105749602411182363633125913535849740456631462938827755069526554867046297 + 0556317986368239387236732047607114173950737209007825151623731055762898522619516377121452352573813859619423710420648830645140602 + 0693502619716624171936460417629499350461603844160041861287075322351538559343745415528939056080652464222483749575581089457335292 + 4766904028429523888256867990946783862212788485169555738269492360138212802976905819698072914952002888319407814152289904290372830 + 3063149485419553279766015944554584134585112055860455417890621924246024514671960271622075351843821409825893454426591239346175825 + 4138071925467858356596514010874840756148724225545969356853427243328235466057330927837715365449101436095007553412409485033663473 + 1718208277388066697955637942282188804022877425156297722332673824998500535568426990569492133060260476735245935911435663031104540 + 7259896781146483425619092546253937377799155709431757305830799439617510543866635784180461435471514956432054478723110546701399601 + 4212208190748800869765878332993087846354727233690197986460622890272309218632979045510485708917467310543076772888886969650697402 + 5830555875156620379814707898244277917838097196097913596741388644704517369937389656755811401456911697429799824431768975340394565 + 5218384019129708961023696421751573471619498755822698446106554346210228582416782419196987283985815988033363104751364948821321736 + 1511408675805990625863697514171112598891753956197059919478438005392395089087719396999097527167894172833319566356364163919692543 + 6760864061185222844062388472607262118669410742190580800609818458141651702885176634837319000673951554557807668749868767849900633 + 4624693982782044541974663953840367719217355838087352148000020445830027606519679992919499646684217452676557562945022247829061975 + 2885293059896283301736153794239325555898371313303885556968069349802848506212069388120502744705750493536808390340479824477084109 + 4742565846910523167821445663540712005957374896244507720218360942226085109738527921622092099772083368812073433747682045449511884 + 6164131243427554092783794384838205105688550227514505179310025715143470000166045228305059905780171994193190773288044579516190413 + 6196746209214286300600159852801523856096528659384736317041341206058064233216653841144231397934288134905891354902685060365011048 + 5888543435289034798476752259935453803961756168693460157400272434328483248778988626059542292033153708506682448981834226044225475 + 3520105979519175798851693163134966793094384503981145911295918784323346445102768597120762535638265452619900970085082259502423098 + 6023108133594199401032707688284772080067633191011227704160888217224741219472651134131857620995953537078628999627600457859691029 + 7135355737374006279317910328897677569526320656280275576870747086734764513800879537763010892690268998504415888806085447064856828 + 7067645951048993310751362481424429404370974532580270127897680271443323793244595619510531091473812713032955994538657114149409819 + 4429631547566328842887647552139562050329710358137821590185444827892759275367380722401524911377817064992340751082835810723755618 + 7949457580263990600187866192739809055130641391600646169338376355962933757309772135951086682561238922534649604316450790162767470 + 6778696718174528127426896010544648198065903564137512038147927254912585276060875391066341248912566730098691603844487954144583289 + 9567988530970013733492869819764508889770837509952069384446637448211216157716267753953316429209184585653933599673133926099458608 + 3413492966631743395005504952764856687552734825362970605800032693220033767913422924066513158712050177343306017113090503548595910 + 6782760373416377101401788671756172877579108677684185994928623883970442286211028728581037425407354811624955553337741266271223038 + 4228769569080076083693265874897262718489495320015615486943453828550003614854151710616339504422293141400194809493593482338761720 + 1275749976017493214306625272092330580872354604747422498275624636561377503079831465248194508227879655351358840776762816388383155 + 4044611547062276323077587550347056464054608166550263311750875441257836393920920323092209759398994038142599127607649577377981910 + 4521255521824521693676238300467676986666555950395922139641083951517880343036286546664953201729241686129223651162600610883998263 + 4053431348518058012397818472045875672812077824208246071436792077005700411785602017912645840401853632467140385402691379589989961 + 5296228207351306866595027867237475870719440724477597041700391443928732836085081541635185416372585087892465757549359102233343361 + 5753047891155830333399279611743974102446066339908340811693445790222472707295688908858729491663915472040238337620182908302697924 + 1508699849153464593476010736879669905272623521348097908417836104685217230447793112158735284635375208948973376371517941685224649 + 0333224377446486130711894052961084313686306998844675785828086842465862992758130724435712277355911443550657464532883107599718794 + 6835605634916383199967953082993703931572871914916373072477880100548805151438790628235173925034028725412169450381473208146789756 + 5647596797800233744008641095874820885871714922036190240494729749620603436690380840330661337877272707920476284213555812599419547 + 5513261332211064956118510684223202485323331553849116007081552356506786559518794150443263231676076605407451231256028775857402194 + 0513233346964413426058663133294017428893643801135629939987380889256710071523164000264715556002787400893978524476668487881682249 + 2238557041006601823583800792379249859430190860772025645499651325329407777431099926158122243379494002959281894688702064542524790 + 5329597914788889055993063859757359411515855405549076867209561054324585069797183524577493085961561532791013967475565456058906425 + 1727267651465421481105710991587303136944086691165624660300683125601416772368166283177444892976868345022274558919475820725390404 + 9723590243421203442884921434798664645968065479222983928276913077586527562214486087189922112591555037425227530771384194025142882 + 2491150360749458092334991769156796313818947278756674701926505201943095015129003490350920079450451251986198697962197375931585963 + 3288323311745586996701741630221983319300390047571862205264349777484027201608059718085154305903308263735198400749807369566973087 + 1513669962911297058622557295345513797998471626294474435337069062590410594233688469673875484253912558586263976338954760252676149 + 5698941909248281308488717883921117273305117757034931046904729563167368375307728972002962702645828488935279252804415118514787991 + 4226862654077359109954473957002792990601772994320272543965433892756039129932073592057677191275583708907760929447157089919000104 + 5013015202975115790118348806423060224599193301855272198220793587287609415484559416236588999749109103840932649489845113026318936 + 0096212754630289886604076288072412229982106747320501739034720205607227829189554712104511341545586461792092663001971581276075105 + 1400830012525551115910295470153382076377587383792342868236429581401216573706230071139732339253271088253819425521718399148426972 + 8130329129443141149308342972871751834898890054061408002066328617017958243761248655943163660366018684672224076482931610024551435 + 1612470444029502611969134698674683976299405806211129021898957209691274647456212891723004609478869086828079731180673443147282673 + 2207763612557030174078525394691981763423880246207823469307642881721011975478949627177448531469379452033830830547116487954748579 + 8943550014526152971159374128630625318393391528677655228099671641521821415999666028671716937719971706453115362098995997004338463 + 6633791090761145650463177053061879817237525424207069349153087084514135819202898699531517360951263097509259970351913296855368085 + 3253556229437227815840782322932038842610282009077575504105765620857277275220518640524545781112378703944765595787111117088536490 + 3612778048987899240807648365404713381232983899393777316948941796158037305227415310986733359795685540845368139757679718651388721 + 0329656082303032301035960655149116897998069813522388783445067885544697734848160954106786926689147778838221235161040983098545023 + 4949145925422482842946072091038603570358418034882170359973918018079551251028978485799644769497234033416966830413282850538365544 + 9688715528548523732988559882524759509039740049260246259447423254924760566724656561201075170029641287177630144231062011355479091 + 9326655743860681005816798142139776662356020296561383131825601205038606699757827396575776760705487871722516625005501108342115046 + 4862493770761711413231246894538240278199950440029797832691068222332648670966923316771267216815856555063431665762362373752681261 + 7759348913324715341816977430054410931106803880118579894939051307627827449748451051704548335839341424354678283555009009093334643 + 5035504534504599464259968803145065603468459325562475588547886212145426779673200191888479107787688352706387961887120658923163596 + 7064143605981003619608323632499268464142806140873807593464533126484595249138527994250140164063377300752448939069709418760740581 + 3405460804222472492156715297971710492718005664789725902179902462523655008185987881883912400930038752420707768027434069222517179 + 6201754337957471374021641947490208688904315801118730053700597398632018696041671232277781587402859428981324544384470959282694488 + 6581501955752939978682011949909110724289175482558070539947143137365139752819830357605189104362596510417675677952395485738392629 + 5415386438105335984223237131949793153812658394744575126207919072784736846230789712179591745207901814607314375532066326818332653 + 3916132472388884065768704630042622537625667251509691545801542090771247404318802955070620862627476301969800427094218570764969521 + 4673296443835065767694158631727161041961301871016507435883528289555722603890069782368970629525870136617529702747543702356107980 + 3969736866659860369283152300636814307559050510391015595957669034065148689817184431746719346979216411505522453887905503375134993 + 2033209673996359127998948182294581452192221728807476998740417776019537129643269360367751767407520936424856588589036363660084548 + 8920359577043563701436228560312778025314413146903691717334802285060730546542075837699964573276987471415144914980259764316759773 + 3627657012409360919929372833162804983136382545072275729679633045374976939117136265913209976809144657411039862524163682772934353 + 7062667690768603813766580397495981633020198031283191319322060508875443418955017187814158494951274114076243932640382433951906100 + 7089164714588749807180199878456232640504233132283953906601030144605887922753172274055475279148519962245834295034899100856266109 + 6314588522281633268271129575999011547246790816567972537919142521521537511380072338334215014034228037819143744053883142669885047 + 1533466041592069230562893355289214460798489775583299853132986367560533284715718053651634282346811547110422080041794519104713892 + 4512970626101824923414591998781160477443695022763348614143799819070327746195782058463430126505518264262282025424239196981682678 + 0616389983515682792619586855106396642118585620436668809283536133165065564894495800101984339481469054418070569566522216534870046 + 3480404934288007401354060197932800798509063792079011642804930003377191431422069063134440047889535881274567178940747418743011151 + 6923077833597121569133964233884887129884707102983051918568192593065049229148460460606709813558966649828440283419826988551789494 + 7928629618912970441223379654942167876674509009329326197500704752789973531185610595644942798244043453568923441723724834770288101 + 5686916225325175369639383018669733714398867749909229151589872339897763998251848983094518391124033198227341074940345064217565274 + 6976813108342658294069521014494920511978448452850030848500379855545152314960261910035283177013574685072898109220517966532820914 + 1235440485859974578507661524414185881273494203471328032423655298610228309217218895796957468358842309363210353318874365415441005 + 4775757215064448647761305923181381380005564211124254441169985896444461359377488533806177746993363765363744834471832298666899659 + 6549502546484198000053617666533373457701974326516846596770901748191355355442117405686714513545060992856554971022392931918431672 + 7550521620433789157641377352042796699563142807992890238677899811145361588800069593324309664156547033893582449253982866608790396 + 8335832703903786234598337454771069254394148676210696718885661839587950139009136903487221685179093872236368600881697661914186761 + 6081423646547430855633909798819189360248786532594620983774708429259122445948885539867620755942089483824811916664871291112367965 + 6763010129734054857751250818823088329080234337202140258490696882947562857997890963039131549439624749888135285626495741851799125 + 3823814359862336359300824370629334246257087407174522366323576913384874982113357872199582879993086251942490130349296563220714459 + 5201936494493880745125428463676510521663426683417020693977788479860674628237207703884747094987717754212968764024565059007572287 + 5656800692578264688131164439239627529022443380780216659445516384845610830241501827976377913518196568744298647947111534785980646 + 1465035810576162949068709350012676100595272189178329025511241633720229686245517256992739629981296918245960598907587127807526613 + 3498649092457065189914681277177637039326561250640746889454833842625621406771442705555721525931725554548176228818511280348712812 + 1526903631217370487596090586369687092431736602852047414002552907015226570166585529226164536775440508494117144839832365340311216 + 7172800070700446830268660237981558246985408200103623671258540515214258800554645764441093416997150958224932045592907480540349584 + 8145891984169127686107656905169532154735243264685794264058843466267191409417280492627793038318403119617408184518297221316412215 + 3733585102819835157576236492205872180664881259553134950516961350305063296415930019908542524245430548400901559537444244647471710 + 8919107817519795022023748231546623121376187758240479239499900553296636944913506176758776881811178925344276782657634277574411018 + 0087408240115194690559689367771085179492160150159772172117583670772068640711181227707347785373406551286722418977845204918371862 + 4087671496873156369239006050995430210075877655341012369255927938969111714405072240508066221092434986016434496634246773638497705 + 3997764933956408083465951727938645280914517402927065500370134817839436837421504452664821784855528363909858322652715776945384928 + 6358034140171396799781808478643680937510756584505346662094931360684566558016245219693809041873394197337373027746374913052226841 + 3523525169184690915788330052438367441556380178099903982632705234888141866441214930597392851790874812046196446764134474357280196 + 7912390044622498326943727559828557263667260605437809865126129166669886288145038860031004268429510310452514645934110806061259377 + 8350389661397820495902304825219183306686077590455378114318515252557794852940943308375379300282537760761994418165168215848774199 + 4335948571309322083199073879107610257555821153883090762370374143145191005083410872058977433580493717339726072170334542991808382 + 0741068478360850873822704930167309345230781173492590875420659162725013692793497218747184011101436665668426379299561926131540226 + 9684119382210299933488533355753954403421331470099036025961973755235128720357457186896140454721156015369426494838464841418224574 + 2606550410151415944627360045368428365343042196701567415760981599314167562524281114850783881875311867997694821988388783550617647 + 3906118902121264712371873625367711895188485445955724568729752600563482629569914020509331709891753567605376276818895453947988485 + 1946035303735634882855442231649687139100528774921727985325887697840697252312164193587116219630593036960739462878472488751794288 + 7553042934057050700594030020764349497635594011506182646429625749401961796662698874719407015328877341348471848266936805626731614 + 3965083773308342246671432838925759649742042738645731254867213711401607696364783002153346490446057228458139827872431818981641456 + 6290917282609648173484002432007182859707772380995362779354118181323028872604689080381882966273198128487451758287389558544864092 + 5135412345654409193398015818933242323380089276961210614666090376540312839620184116491698184580875294639581135409937430385452967 + 7814752714924949029739912516676992468879575093818117912716084850528773868618697654019734174399226706840162753982136880421595798 + 8344230549785765490790122830425599688553302815508985004520791080241214227127540251939234623642895839337504147995870998311297157 + 1312261536153577576475501063559792340822581967430971162124952202625290357772475691141555237352878643256411801046597748593662978 + 5420113078044378326245454890074054926337548530109656935414953837202844128511917486560998089330806876653700112974245139455110655 + 1446316293204894461498438056975498718142802987046646526458433588790266320884188848067627056955062757523352642280099730639892974 + 8768410207973700878297712434460869178087366365740643368423050061014329802628323539796504787700469737820946806556379851425348409 + 6903484946126406722104799612810275531016737884354336960835748710713062889887930835389522081146458095107803234373499389860789149 + 6113798456809198989364723468291582407592480139088852307707256783165897446795918270682937158869421622443360894104220836046672216 + 1297180429334742843324101908319081257574325368096788573404226330238491288173549545719251363488582787945804486932260991191153289 + 6310060489009039954463983763054135671085760401926391779699811819750329003225671390731075907159344886944959170333579705985011394 + 8928332308562582665591113793712076278529561597438667031252620919756801258278599576959931680328088876910755153375346545987026059 + 6122799394738485298698282219069449469308864175448069521079405422190290510333027132055402559422290946776150886848955390869348557 + 3298127120443406100122108547957183131539174057790900079286455780159808161628252012286085211125545510059619150351442374519647873 + 7895547723969636832110890595697353438517639756208042458909186966958825057542753856885651750056062715953653156961335641588198051 + 7242277604059435612451710438360700839539630420328128639238629662384680381167202360792624305492770524378775130253064094350170239 + 6328910744252096963453975544360333319092492567496656064841933375445672717827688660311871137666274201081402086421470543791139037 + 1263075806974163649200998435369614522606717804984408053096263479824896274273438278637073802016955266073407127338686266295417138 + 3380472791463934939167548524939273036820154830243043930199471181363843017057589926197441097934643398001941245455025305275718778 + 6053039097745341259474392045998222000183392630902077243215225896980913571132934688432219430448989534298905581203790323081204451 + 9398618592749592673582297312578194153271726432191886003886455601016177152460729663034185278967994135744387261240974218700552874 + 5660578626067455796320901716488860867842597868415619043285914590213707161427735661103212503097888685177044222466862770614738888 + 7523554669658437443860955048187147707950298396691077287510802686031319997279006079308577219459278947413769480723164988814047848 + 7728230896579900984081254526628677638403672817908586482917564357430378814260695955826428360637353362697491648099319657648279806 + 1471506063396451021205086178083016198973053283515072407397794280863574093292850961361893442271480652011908263493969049518154719 + 1271663389268841465526530211516124798508874084299647641127612963439336172485890973748223056840291177210000865573662838724859865 + 1558003045612329244947071838328209194658672648215862136590055290358556159847830215232765640226279624286079243381635121169856392 + 5235686772055013347630127336838697764880220575101940207293906989459723943700375632099865606791689918944793971999840022845627855 + 3362608893556970872086765317357229622168187942063554148251194799624231946317410456787560024770536041305554794440402555379048363 + 5400711312343982155393978124014413441498824140561950458826861214386401267011236483424009049988004220217832202185519723172983734 + 4739966966771226209909624912450025675969022747113454805529677743180928548967947375791545038561055048316262023987945828187738406 + 8806383430961455857801815047901978280522034447065757458634887588704123408758546678452281010485610787173222519794754395918755668 + 1313032694820263690081002684124072214508820793025272277314613304407858220279657882431787747545642867929558977205831435007980692 + 3821423807029286765485523471547535800355065560255771366935624333716101960889324812432465967939307158664437101875808531730514686 + 0552828401027435473969844207309352000803571913860014776373394805498998489404828887974801011916107676224063398083299850490285852 + 3252785594630414326772320135663653623232974740345887923006984684749440127689169558676316478796812920656203083787608388272541143 + 0886829100701462879464273672433682081314775699581471366939184918943997271841997863805609882688632845996559926289731733309941773 + 1588621110929737275611330049699746179538000510503020090443485760166202124848757232989323035029655555830280894064603577880623924 + 9460393092105077041540924186306320293949908924617136654677663794806814239207321566509608838781326729111423409256038330560254768 + 2457234134203393682333223194421969884096521962196051357781698196280191186003044231263105047089066125824374037625184294564841726 + 1139020355104202113948476242624526315291276395095210708873598278111336130644448701938653730158050834519082575031500159059606323 + 5508845274116902540996666349891489554638610844733883825695366107090243640688502082955261760220172087743405531646494097110373564 + 6139164128879727447485151113660365410811051772254913947601863445614936478465117644061091010800284725353254306320280311126282508 + 3691867968556520735423213939515627425003649240791159831598564334907098275550400308993911728901273767070664323401959466199812550 + 4385285527314360012494827503644449196670340936661875727271329351754418864846693134514944138823292825239723190822861243721969511 + 3358507325257641984977160116136111658256532073729689685425144586604492783647635836225848095839938544002404873700622644589011676 + 0802250613087293781581129847507424374630865942136402236774163044580066760450481644654868348223850714885941401523519942001370346 + 4033651642172702525694267019009943272304377112789600524789052835595443304754361088227651039992096267114223436584457492049115625 + 1008702122009370555007456522799161340685826326521804374437361823776598365128302875870953921955751574077453333491368066562183540 + 8297016982983877478208126579509560908805708870139177751490524014204560610778740303237644832086788493774257972604784310184677682 + 6595999611158451837934955382339066842486744152636969464066220937412139592293869816659174158028425151865523439443968468476337116 + 8189453034430471397425280708179774110697730501130625090567026833440338110187758034977661201862518966699911402128869207946665922 + 2967301009332385012982602845125958037212145265901920840751275900004234804254302792404413397360100212415586648851954797337031843 + 4621309795646253111797549932297844132545282162620476457572874699573469126157531277320612819758228011208417228396419529928921453 + 8015689409373876308149147646698419734053674168732622753328286778805854267784590171527922720365829353861437404497654095122385810 + 3928532819894452405285805315911246752486216644456327155370715615309647716023031992277092232949890587556921144870096925641170977 + 8706990895052933118940892301863446619427769704201470123344557113277628075518257745853511560735206426541219526593186205677069195 + 9323565048038756996967463636608859147371871703253988562924960678047445864387523330892542610569708364248757858563962167618047606 + 7400110024724615888960177029937719273668926142229826804752461957263527604940620456908940268767529855383328656980509173310228171 + 2961079316835291946492496420673777366632570317335815018560521820389694972648667220189874230520964455139599084822803458488491752 + 2053325276467463411017022059798270225751157375504499399426618848961341529109405849259510473132610506746820731096435354555540869 + 8022085653261752864363248353443911714595466837953116893617432029480864961559617145874891482509931363773686667586008577729590619 + 9511531059462330034969446429670396910393858411286019648142180898913734931062268324002479006487407711948954747504728441451817299 + 2402899664016344765585783952968436864461868976736500943447165022135283244224710415767003722013469693233516880183011359108783628 + 3912070384615994999455640965424049848090544713337811655011624123059617272139004908000480810430015004300019350285545631530421459 + 7040129421344930471792157420616841533490962354840490248534268666426427664847776443733801972606800005209711387678959754783758169 + 4514744752921544867887197341433819468485319076219844212297689345457872671062595496333380534044033301910072934964202067332750929 + 7744301249953061021059801665718252827169031698368805857673827901657376462120738712603816558346872095129968009454819539063410887 + 6694959951385441493938996005094705323326365638007625755937236084671116883434472854253964886004560210329640317017985931432992507 + 9830755088107356428137960573336610521897465624860840691251416368635190221352342520096074021567053917840102300469951496094532646 + 0386151915867137989482068036180096232759486104299898530934407665433761886348452364475713105652919177827149093478062390353337982 + 5026237611119968967543921268886408485214827943839163757065518470886816959612437396882015040264309844556286249899479340530273455 + 3790585606726228419436731177762295480034329918020969162076958086843994331135466429174339242003665276457867681590462499745066166 + 2010072822988771442333707800353630624045735130580706054631404185963369356383377732515576219388977808173711224814572042638811746 + 7799862036041836103498954213010085023304912197271099528776247085017591855736447939941510010043072233516636490128682332435837718 + 5444031310957599380550217779540801553000957068137470959947071825380695799288846148959315246034349773291226461068837384267657314 + 2720831922046271298345192916201975278989464655822747470522487119845175483171802764985807888092086888555468865508558747670561030 + 5037268239030155207644532217893862758398321608270496665238719184860604497280537678204406616537105359104541182047680859111844623 + 4406453518829809819978030558459040108565356220631255519247977687593573153889331324518157228436273334635625807524985686484922311 + 7999885151695902136577261421847256015439589971601084977870060297320803728853045230722764838994142711659330991658042253610623719 + 7149325976325848648664235796296763337498794913699316628172271388813068172391895353748736320858783488531575015143960860926515250 + 9988100123929774124197265328008141820710758495752123486181540545695574140507942678614702580850949656109084164982037643220132234 + 0375655311441060929515636645306301671876166021260474227545267428349070029167644989380583812184485451805574601129180998157634256 + 2128590561140195400524100610776393812855470570049174388092975612532917892277799041074366790055894057834557983976227857050864930 + 3547444389508771568810075527864526064121655767293193457033048336615284399475478737509966968763107403398079684015244980874035979 + 8519927849602061794266560801914694036469483013102023144973737181284943231700919734522079332185384045910178109811932848109276138 + 3567893790780435626536700059643971391023938979188277544418757492427060624484762199641583855650960393640504524655219454811384399 + 1735108417168233650163860054247929680595797171838825452321119827231787146560622246912322232224942016739093046379276365165998295 + 2756695873865903361436041234030623662053438358924238813701743016813195378135003338279782291211315013357508842537428877943825850 + 6550701509812921278785065189524058197762485207459987155095767921276575821627138362297358879947692406013849533700244092475658064 + 1746417294003960060064872265575781963057635907396407260460748957479942537372418296161245217676807862873866767635894044939661427 + 2752800199195253529712854754798642118106991591404644917342058968657791030752834046050164301961614256798982226629143783613672100 + 0156432932446788502003627727688728508740309980174215347673828299641766130526832968939502574943042109833631744090112189289099293 + 3949539215662926707735521667894130134427486982796357220482855624651559957655963754443694394481228836760254413314867991125537370 + 0833694740794893624914563726494064663925162779653035815936273173351045298468454290966312347207985664544908635066940292067018215 + 0068104260838913669470167249521001975928318786418160510709377212045134485178004263296128628173776672447600907854928188803969244 + 5213186606414124173974080816812650470078589656434215381413340547874523982782714789910645183938314140377172417321651847315127943 + 3831079213870153648590263375611549325132489817138611364392701108960231363751036773655982850004119077364131468986709426279928740 + 0816735516514168218608953096598217254388061619583961807831532937684267549690578384517226873045647249368898189499267589557763196 + 7614683199694761607567513771357320522896560891215582525317620218466204798420014498841517198000714225395529432437408592988810647 + 6493791813371800888731383040408467219612486147146096499615909931691397312978653723829961950808111958324158561777510444489457609 + 4673680562966535580522867179325650694242060572148395328716350087210015917993916484085808071728589768362522840828065262726854285 + 9484597285206848463033004828740831651691831183702931423669671299973340807479819361399029066256705512283915649297270684923293120 + 1714285317558703325551063623439102862882087552524008272992080310001454376923262343097189280399813634553559119888320098054640112 + 6878492562141548781762151287184309582512789444294394903670308453724775992147414690794148922865626436020007876554089383158780819 + 9151911784071444893456939300122542765400868095022473582458690303654492910301968711120089416900205538880607052645783814509878005 + 1882377638793327163743947324933816937365677683669086577608915703348630259888777501270806753764247220631643679580537815123548411 + 6272056421434812628524453496821198676269890972424881983781819205395093370536909259477553372703891212584194254740307122112225533 + 9681870026283102041075727337579428100736459914910652574617863758549452931286799490040297351890738617979595875678774646214173033 + 4185695124550535533485860637896723654154834853472854068710912474987668413470803105179616610921355620666097149488574561869489797 + 3333789216162396397679204330436931257560768258425513267401621836728579265694014546537584859527037491359360764924746663506919770 + 2081504393567373511045831331064517139188352171030907247345004840816407938277996907076471099879274974679268216987024065310558333 + 4237450865130692858281322184224268516039222037739605355087614033374925113958908332718451900205100215886486089988991485524969556 + 7929075290163499129098877300162688469599528046726233844196457006510599251899484746828484574667591829570772351512078305736672654 + 9048657921163013454470683806356852138380411128268107788272256300715016144618475970710912738205043728268553865691241054834233600 + 7029431095139361764456603528202380622931434502522594214209499225882330762428652317267948702623321489577844016464692915246359712 + 1105356646640216883904536505154508223476242075189032231521222657818953039915135319911079058876034135094530224254031516149971890 + 9040945596327638323723931073336767619159273652642403035784821558395849500879059623038153539774239738033911626241510146918039749 + 5283073188137753905883236902928531799079492225443087557262624838420087547899455213109577396225125545248301841891417389453351792 + 7168518951278682051937542342148124215459196543677153007216757499379420036959725544058917170458823956258437616459586004329579552 + 5203183504391078070063471026373757432195663011756522268894506479810617330340549685777010011742133881536309636471645529762659089 + 4854999787239813251707701121392165868052289429676407362096901868531485589830231940346048063593475645736706551014468995600111842 + 4955763538748975069385515923948951672972674499411759026560381765340448515748581186486358853253830173480680063909301824002408127 + 9640228631714593257928903905827590703526290377038235443447387587380382054598578561742893844220053769466029427853174638397427339 + 7206862882358947361070854137919196014699723353543071743024301192848154276186984110546320724917862537765542130378492262094573104 + 9132037902884622149627426018038745128067438979528182768862440252858820253995972446342211888009471423051493159698724414795710825 + 4044729478097558603438562691316366082632115863305337165834502683246949426265600257894877978230675496217762990369003197560692400 + 1914819988622085254720645203900712417397542695171367605811941681178792903669629925720096971822910923986744641852805301639652708 + 2489879698662595408916009150319958484334649360641536805110449468835050783501013718256899380316883895243102069697127104742796718 + 4988423693542042725154817443015091705766869067613353141088272355694386531680806067437655514967029170154529196712934789617792274 + 9999952996574987268331116423939940247569869095269736111023291772144901858552922926558494336795934151397996022792048113880115874 + 1453279672186008281192597269984891593458554070326190463606379023362133764652707672957322700161490484448540753367821464532839504 + 8011800610118047251507565848810514239096971840458570325653839372359200258329325658866372171001058138732560340444368314621028592 + 8193050742913890615185212677939019076499475354863399017606329114085259623153218920828787136128272822531407941969673998134066236 + 6165032662878134088891598296730315347615307351518186514382605872591152954913301540364688295560996800081490449469152762525841628 + 6574519924837827479315694440706135165231391744110344384147108151733208482344899812368417803491072197299164648305134049390042783 + 4020778253016163495293946067531529520938183648436344477015365877950549136205835548741134429268197026979922853216037833912140076 + 2560367110629307999607135522026567041549325633921424597293236948045008668100091755427842685667533245402093886980655601060106544 + 8546203408136109675436916166218885966337393842202215612854795887800951672240495314500504099192631873269330473780375743830861472 + 9788815056490265802740571039729926738317636325182129335295512619052159101153870121975439793577984106855088335077085584239297075 + 0607830196004382404188902942190311303589870612777737359147435465863424442529799140567063628056860095478745600686399779891523221 + 6451811221617351847394635729026502559474989696391694472537910902735717543356566711060840045900392940941333171363021277998101010 + 5131780001821762931334985227662541898093578808808129086254438607279239181340438600040947973426848418990057822839591824881359023 + 1781431927220093804299065870243095263893435123368341056371775420733487563878765425465471958566683414339834418118022714155686281 + 7855784526694976383147640552245153733193000678558101047345867400675345449097722230036412101539440443445801673442840764573276547 + 7277064664195765848534013590019916383557749169375559963951776576181466602296914352536749809247940247872302329782226925806468043 + 7192135649991318277247808266477765244997880386860464765070023950465490749600254005312168230797058556941811885358619067264540155 + 7745942254017380214048240376624237449522972214173349323588251697136718540827110673334670762835744617609275818957162829921297194 + 9308025524075793350930587214905796399488049433256186463627589329393236892726854692113712455277309297788479077266643487682416715 + 0884436213404481146144542589017779230742715119840784000653264872459751590076369675379177572780987987657953814990135600852985178 + 3730124530298931373240431341115710398974380360265132276809345755075936226833617497570877144367390338090832665519341170114016004 + 4487614165841966483390809601332500844989818602599615930254525814591372642009685306021109318297597415196166334778397096512192919 + 9738135052767202788355804851260065753666213740432424577877433994081030576175406007197406894692674226624886870624390536370450115 + 4972079333970854412711805268652812255100648740561624233549801666164086630826247751458218621070591048081789263645429911196722042 + 6264477153602121971771346665126521727114186506364463613567938860398188315590497953212091430368302124372365408850328299694402187 + 7096923163132078408222622634338258654575603652287595704602066710353019363339205986259588116309830845020074124235604674290929803 + 8620319232582906151287500817533307221837336344013921731345438451489042597967502976685688377786979657248449082964352894633940456 + 2338290774645460787964275902190755185934483199622353782037807590665967507775691698706742149485822727584225845398159573488959138 + 9690411512559467787285374715845943612220011261976368220307963458032917206195128934924351124238497339947198608551639030163894645 + 2522942273087160899325601687017261599086953489151039944965907240532011926664847298253352884442034273091440472287878013270485552 + 1149024375555901235741559582840384810679491209306220816791833779666244374445454015124428345163452944670223052356961455086641846 + 4911582198911887147216938492382715818668300238279079306283822841054803949022104243393368739761683072273825914099989412306146198 + 9386705286204083264591504191247314048641049210231970001783669995174466309042384199881382505454205575494098905658585266777083412 + 6597181522016787958122306510209743227930379650431716531860926286813430719462209935654406493573792531684209677728726902971780496 + 7454713877871827759953186012939103462107245349313356776395316754209733644734837949073664445059496108161795213098031298387675255 + 8608951097824554197185243937211248657800767047324365682759725200979621123783045604563185385990004228189141941283634284151650878 + 5110742662179788336448957887870922104701629467080657819437644833165127617594897707891497065965495615130086622172410875337801320 + 2393400609667414757827986008711153834467770780863121443973568354701559598965757992398836770293536284505657099974035105460765424 + 5696578078800033701889220099620389665546740070731873354278406253021517777757298261519059116566359233204858968015644380662525991 + 0719487243613892918578289524307174160805716406329931625803050285847534463223682481335815436403441752588538391995273084423051287 + 6507583132575286651290896026205391515246827860101127710478694329951379556419208073957900692792049817183622267407642643093594278 + 1377392380718866307096826670910831948575020464783957275980748872622490677834200043136176315679139636646826582155786548373039619 + 6270395893591295820132189201839068186418319333704429754904087462921395570639063307809781688462251183623162844581418406608429879 + 5043135604579355727135840436265306254474995931628655768285052525690960177800386175175072542969753822246288489006113161219380471 + 2468870042718971405890990067722938578347935929978019468025646064389136067817188723296206441343678326386730657242344326326352583 + 4850753963828793552300794217123706294629474328454245842829452531896699931041364932772984481884556840376569123447688057207356583 + 7057042541510451935323810217032483925746383540989928451101483213770975125680075200108338616874937924879361446516778250185550748 + 0832810498555353548220097752070786325088219810053096162098021215047558250904896030368053916311890910240442204298949146112466005 + 6040761853883330139655359121858985041009457655416978338162675746762113717003221699855200571002086517873586911211646864010901906 + 7256461701161490507120388412005575681572262509069280090655692691681966297281536854053796037221572903258227405845942489932658062 + 8784119159896217889610742272823513831023300901198251714365380671379756902059751391678189474782942687418296669663414454093527211 + 1713004342725426977027637006978967397759795215758374886596544583647960566243025979142738914314172995528789806147213520151545065 + 6148932160477331319836946915602714548850688076504811022908366977684207197869071392739615383347277286078886115107459496844571114 + 2443445647690017845788068401719782165485185661849045242867722200580611203950026796072201135775981201642969396670605705878495845 + 1294371619212953132417647548708472622197636506856370676160451382994700324005284453279834375908065277166478082791508699598722770 + 0053575986014268796134989286247216849523870686352637864684792640382519878279886269694672196689841813884729761559800125789968281 + 4079017492141445585825743793710894771763718871198578437956220555470157513268225528361787107561094227364687598864249537846090985 + 3335615421853085612471428388452383268898317706526014807014690533942186796242785098624189594771605450015209158202436565395838528 + 6313851017796457232684831975868577197008285743175695149676285515896251363246115689779921987378115615609824156064808941150859547 + 2765806218554516717364886537785391971358807028025829434420213828068755277959823238847926003687327479957197440099922200245318093 + 0743837871847609090197592779267491068691643664874076633968061486254606691482824855693172784961663018432092989740850414577990750 + 6025684120312451259686658587433694029989987324349789159690905104220972232002229613273265979326232104213906084669828970966380427 + 6946689887211552778830098495751925653354785324514999092963991842666284889259310987400348941690948665027526678850288865496058905 + 6762732711489921976841952967909655635081188142889946182277259409310226741889437458160117435942945024450654816897944448992096154 + 5422044978529069360644478126257492572807446085424868838210351520631277115650603746786970481265582987466949165123354295111201812 + 4211276624640084315612918421177060204230299421803486633824592006573340606615889580523464227765304350439006450951838160825473751 + 1889210243603037535646067281045805960008570285172891727145769267831573879630019508324069996866828486890146852983707941528252170 + 6433944896458400005722683036542919674416232401927258992043251760109983309622060221449241884161395267285324969554809613236559401 + 5926828496890530602862162152396620975722541268836002211191264684743325984168877494942640619948750726132999624105124012640906283 + 8437529190279374121273890161340277025282882572337700420322280964590810755716568643364840307879983400203857287989101011632690781 + 5802276041061620122710926329386353739806320420710281218622737558209391349689462899753335081329268758815057487656715890733084223 + 8915069186666442083922633115688459542249351209368361689010535548757066038294153139851377020698884275592572198938097053313533421 + 3618393873597153740469607428584632822338908997205070091595456519416863149036488990139674096344263132753025929808588767591996177 + 8414765535715090848046152050822658084473018911692025473276058620384118863100457752482347145023516317250246454398495927754913591 + 4409298010504839698734131748484717641239465901635152376312170896985346043211365815426588368753012122770591860188057761705660735 + 5937603186684235090583457539320837412342393238618817530913846014346149555309319385019839106489932216877734882102311404478731716 + 7896182092904946306296521788524236999972318921384942071102716941043024956484573567729385887708261561271188936395359650621440543 + 9381772394748371157597820184835066654518409316544350915121960781236322808659004922335381181699829103134517372303100027463245782 + 2615260350961768130102419692323579521155005867350775325462551282112894826272075572040191002407099324856614539494210810480930402 + 1838597774381264536500359028476517592435681239463143604712064430411599943084702827260512914320943321785685269655653280527187527 + 6303497221483801786682166005068915785511014637493079986822276972242808097676862236960849777047832121671397043713182928176830651 + 4198254431094795957177601291882860974299955452519675630067202852553365287181631847719984611318356336562220811004590160639271651 + 2089050062014249099555113392986787327862396528284354504971691665000330719435672605372528268724943691397193582081997337212460855 + 8717657741330116057938366732697730717547522872552360477855457981234742653137379848417305649320084599648948083741462795882532206 + 9986804236567371664160082803763334644507241277854017370156980387812678877717978239570818728942909512587707736901227099845780710 + 1187012467446764171881903676699687486363209718049359334271085642494010609014855350532206473984262423560106107436149534409159662 + 2848539362765385732985316450544140366071147981646641820740677994697597799634870260463776941968992688323272637389950097251845343 + 2181340059702615616436136969810778034448257219485660110664564303142589278244498041564775661983269433643752893242421364842071587 + 6511475958145031560867412663572535560224504744829799500512261131519166232318015397419472829178929843115481631831351152969869230 + 5907563295429072630722334129008428981723806690819380400545768764609783317272102244876794754684900328466037092277858030276039049 + 6371121545042724094475375695524854871280733127714683231595927748253222937280791764025222016369882957071507439090065827190758754 + 1326490274618829941454831367643360383905788459550667904893538378442057279259437234426288871318674319032806392619399812416955409 + 2775275011488829091588325070565060813564196841900611728756018532857865700574781000487644896468359788252916194701281784442869238 + 5475404321259151425741175250657761031096608313986258427026901467928877964154516924617882931075782136380173762818340243425882456 + 8098506275539721604499982773326806644420333816118778369209316210417120818431663778002427348509174034183157653013145092651819004 + 3184928471078890543345386093573923680647427432807794321314997911033358058808825224490515008557540951525337845495688169454435522 + 2663993815050031607786993170355950506772886776860845172901406916363156294602197804936561148186445731375733299997098917913770308 + 9652206542382536216286608096098963262843138133196068261154952924480494400928138047212132673039123404498669742532274932056703877 + 0803886057269071094490544437295692503919136095718722047240291609927251689451657849380414877514143018375735518559305335464120670 + 0151936480170888759767939879997438315844081206201757776198680712499035405650084830184555439755477818487911581690050566831394218 + 6229367230673286153903588882341483871782570684557378319370079577894075314574849976163949953230620503498800993353619885098682722 + 0775734990307483598683533921005381003594918538823910337693583925400749988570440308274068133400598419503446320537735625031687287 + 2279164484478563946971740937436182665660391281989609876479617857522997660917074445342075564734477309946731477007826609533166522 + 3758123683039815493345731508244661356741376276550143129350958441510802897891765417564525850067802663207435432004216770694226804 + 5619370786333060777254420771287566622455383721762137194440628363338996839313233289419808657699323597544032060605130001017679348 + 1117350732097568268814555936831091979923626150476679569711035279777989299558634893220687598099570940599334574372587146302188862 + 7465078440908857228369280211059007709404158916443923372217270156208307015594931088483508995735817533317081734115339967063512432 + 0277551433478001259984748926007853394677528181409165584238991766092184666080139589261333280556946872045412337141801061054086949 + 0700754560549557192840941960533883683916477333049889110496053434388836650044089728945956844381845980096615663986249384912038818 + 1729833498846421646108320742580046475400334773592611265395391377127688594599285540845684396076777993728243626683212706942573378 + 4323511472129830807288869567946309250674678068275114664508496611904796208234885435751853338278854135085398181237686024172180393 + 1312943548505486065871582599174831836548648084308970713256187466678464307897110260321658188877464727357499093515658589884692245 + 7139584610276191442567513021000360376560327542398104492743671139951823728316211591532169872633220764756742780779371664542606277 + 8013300125828426771757381146217871760111879193645766888697436656318066675243280906292568248974540959337990973627561398675008197 + 5419373124232954726590126551016645137142696380830673731392642951542537238565961064580394978042654467730915963421765890733361548 + 8922925533382884854249653772799918390864697404746308525228860651400300505857310156341812355891928439789989969029099008533806665 + 0128219411137135309941467559688405403979836275303036131774092714874831957845954239946311223981403764141665925425006138193699503 + 4023035360745761142363755560440975222622652382698883967356728120684964102122995320575139970015373461400690787473496703365503109 + 2193654449177213661881030975620088565679413977376323484863510871705861613106991010472484286534395967108522932664799263272973605 + 1651932770511765948726250021128129739307128956256839990590743197977037091662728274789578774568077274689428101918180304889077378 + 5017924617218629587957879829522315523692604428645809008208520226544692314383658761425382226132125228054011492055441635314272210 + 6749666157481037578188762106676697225815856020636806090419991079970372071289788209874954711658011019178097283297120172931963024 + 3867624578607959056494862536265389313506274108084087969185322137028561490827818437756426384470803080867883480797295503488443754 + 0266755732085811371635896735784706558323514361613693558482118358007540674486152236347627273339110326422500120960164943514979392 + 5851591583094022546650594344855608619956936942520965617453776819147723734709318492888126759979035908706037791854416714517089588 + 7488779820804386679237327683610073367094612676999550051056279635818725821831859618176236859057491859294403215135785905001415728 + 3397867405536078184923760377846341551636533657104459673180071634565287960125731400588939475716477977856211995657191117602660471 + 6368419292461966253403926350187375212915416793685707098775001247308325202429711397391995493844090131420300451991006099818565158 + 3171884061798508018743336874067220372374917564318502076615548912819919624484325005878069566693150527749974672352053137075239471 + 6765298415501192506923578604075674679460732604669110708523132941578157177568853063216936080050749029655642031375231708316371762 + 3941656184595817536876952668926168956461631341364895778129612449325569155094729678326528659230305783051788455638170048468709384 + 9344704062107618220092102502671070488066523904860951808964071896990152691743696929206393427492236495869384495623953241985933433 + 2329954473357680885309244441022618801570174231106127708621760839070677029891079166854592191885991850284207932518637882898896696 + 2253197905988134418498970803242763736997197997987724202146481273276883471048373064146605033007993208986500108914474101742235859 + 4471673346443282932636516218151183887721959139730007987788845685281052854907139082610271978365656275535187015151917676999391516 + 1490454357895502187362105850833658593130025904397280081248261243837433753996643256759896119495710470799362993945917928340275859 + 4187480193910225053682324326478852139878506761849860931936128187212907303727615513834095500089467988300420504891523377586019041 + 2552835341088538861109696869815032626256269959324139802181242249722241877212898021098564840649196902417063584333206994390607317 + 1538928060054617317449920025668989345408124114562616395808759769278572186743963855933221653177548947045222630757626854233433755 + 5185848360760696218717214816135397052477034052026614446970415328439572221368707488898468973353428786860987024947961924953899839 + 2985590716831731870038599668250152561736463733069492744631154471689685148003517537536069537952391933185169671069870236035572482 + 0858819385615354860719000425698572982937868475649379251912477519089804489107469755432874178918458772943168929318750385686530082 + 4333886362870957848081259613648289163828064171655224322239708870842553708643760011978783227657321411272976905508646641961780912 + 2833169683733846355069467452629978104797868384861004576520122658047677739451418977045812632716306848990938028931383957425588061 + 6045777379942977654526927417023844498064089452756699867598470436037381168815462649457696613017471951809000988548875034178737874 + 9160331824383077463591927113486291567227954453778702317129507491730495740733772073822607464672707613182092741352901404225499494 + 2171629178354382148962537134449119312001738349076684871759101972177169632459401670960405086152157843086489006781537667287047896 + 5465718260392150704046827088996611582230320415786650066647900151553492798388495126103785840394545507668150495076747239741124643 + 1419544523318047856148530079232229449051190304992694484547233964026124081035121194889038106213961089629592355710172833338936041 + 5735074574334557161220421706612819925561806730824425800383474349667304718298810588448596848386045836391940535442755152772209476 + 4477743831927353467775816826229193246462805293097367869721250682503407993182691455177890744118461259199550137591872314970843570 + 9614009267031215091375702771630372739884751484563943485109876681877458872527820916316860531787616767154557713108421464243252888 + 5725244451595751926785755645396186934606833650722629688279447836080615920686865486122499155337740847620671316549690747377719416 + 9886724243384291436035548475563689452903302006875551792856774087989888845839795026561561511158603968657727537570783565987096483 + 4338269257625836943750609173139824275314999458619895874921046346622761766613817248643045610302260828228899586867769128173831852 + 1927251435241586742325643335703829021262110618516121300640702167056777723519853174450793473043913595814696522118527504244796457 + 3599578411448167894106533981801012494310659214850381649569414007781396645447499689729938374104814729448345077680781325687345087 + 6129529633831819171439689515282408943585760656344118595138870514119273973014358876594274788901442968142994742135926265337385656 + 2522744449484255252321589542733596606602045925005526885282459116039248444399754430448309551058351839870771919853241700908753171 + 8095397674156020153025647112643503525783203561945051043117484225509753196255050991995918313572389826508756030729780202503607157 + 0514732746209410237098921106270758705122238404358107693018072790601247661147289735400790334022315641411924147791473123654604067 + 2183481353624169330708810250088442996270202852800382852132922090252387617856118236197486397057001588957700864557493511482566082 + 0159554686938426672550427425422201760923684567404107605954807954862252513544057244716697622930133085009155635119267747535809775 + 1603870374074406842079458547774759610733574985005768921583657069449807861035511349884403260777475545081121567326386609338253275 + 2866478551802452645398860404273568244013340206033503958336009745540839717584645607628126532817660071722429335530485083943886111 + 4372806755879104949087031501622642625790498233747556727536449464577828956704936323795941826197457122033168971930280473743209480 + 3510521745467987614604622504324811929598409501462197588604391588467606320835512728358214802216357643065451820237801293132895101 + 8869176817884529359989957422435201680723727230870849702923220814297956988224073755455624237386035731957272496882413670632312027 + 4987041709615070926110617696999725204352784063869478762637421619822949085893727644701242995534552198616152209092394050930669848 + 7400973738218421741284556096408600962957422728138542260382229658265717929340410249216494966480842797114656043729408022372140555 + 5357622280419421430680077268491817179160449030679507850055675685514803114136633487732178706581280425610186327901499849008080553 + 2063614935667238312237638365326101007587181929899519898020565403780654677915752203035463564958973934599571280127628650025231204 + 7510339610097271890758575355760181313472729121504677949019841665976993380277166759244310422659174282752504901557558455360101043 + 6704624590746564335785852066839780043541376118703961641315331313655337920280405840841448353766789935381787637277026193365826955 + 5718584531080420228299782199614112550723022759714938401551695221278973774269123526563402857239118115571007974128747966574892058 + 7406616537246908705363274038771943716880888382315653131428051669734785136535017075892856676521312977758275400592055721561155447 + 8191030503034523458658590430731690106155340044400945735308786298326190302983231623869556707507267012762969572969229893222326020 + 2781627756283482808592633115010135954787388098836449433663074354764942592857302479394320001436105974173300167981736974256889069 + 0749889909665269146510382674032370824445149525831032970035921874308716508078712017288693000420564774687445800320014347768102977 + 9500582955080504298493442003839451470653349230762999448413032412395803444854529134420395637374428892260393652466859653474793248 + 5578683404816116099839255848388989533623282136956100112356341602163894219640627502458957004434668830525937659394378712613593339 + 1328818081682559186294868249152029912791110338139114004470380993085670292745974492137182403037306610656137695392960137614180452 + 9752978688889728250401766859342517990190156836045937377483717028864519242478723992053825465496992411244434140736698055778811865 + 5764034558119091657996034001136138512460220698471156208113839665880299241195462026376651406117658603193270831455055313097779290 + 8887190533917978952783942478895262358255953083684956216049958401478271139454139129915935858174062762845986202401574727546757519 + 9965112384492455902741039666831644918325589401840520355227650968749201419553213336728867559952057316374095495633674649247673155 + 6547477349678905420240149432846633096396537735337479158019850832661246628844505249719392841713290257003652108726047676880419068 + 4709595063724483081528398865202332209399887790016225322294096330311019868576291990108551198704968033034014495019187100300731545 + 3677983555491782274707240632393630038558613476413675438434221141668472183743225033730344641440692723378405837243484642959062746 + 5604991163272359834040422515862505640037839519050818603112192411600677144216422234215431187611787844494127075718764452791848799 + 4854476179924301594123281798645361490338402536310431288082224776520403651635476604940174850365038818289755315902382966023203577 + 0810744335357702561567797304986145218660883831691187353402861163846458499952189536879044115452318681728624510324860015033788398 + 3979771283995380891938289539381044182171976827997056764348788204187193621090041996206584024348644400402675325221299998818648561 + 8560553235856018013965529605400965645682933039991913219712272084018424710938107420465401522172404020985846364794336906931979136 + 4463662321945447989909156167276620401617659159053053338198477063314745749076987397606793494767276193523264007206178167936213596 + 6945045570777520341473278974105523918485559285787445842507870137014286454851350178004328369233461521852484045058748849569462881 + 7175394733133381132769602280613000317015438488548919976504824538838731947546613872200764083627777984989422833194236427886436510 + 6841401583932488101726607361270514543381198032082148492961394207816779730163687527133913837138426969504533356370971942113680465 + 7438297763442758000905394998453798098283316097089007654200747461809281986645383560583766595972712154827834692097585224878349332 + 9365726487547590990433290508632050107564671461069290060500347861396555664994103630437491491318643117772003180597703910105848664 + 6611643426610581687045714856705413399193072506247927181637882082436528718891021527134176567154185837899481317325358321239700678 + 1557904502034099580005949862058754523860889792700842593217321816597173581797908357156234792521428404814333336278006477527454771 + 5551300020237036342120897324580866490216118116991149735001002790662102209629270626643498774459628186650438561401066616780089887 + 6490963755355736580386978526346909059361347064280111211229508805478817906115930155049278075845715671257641653870466615953910939 + 5214778972551839841667874021257601195235129654518890488743898996335333591775608284908553206841411120044347642321931257964395096 + 5963500480745033263837415489981452116756935833729630104233601643805643301868453891208377454731826714298746739883158478178624208 + 8078825488224820778954240186836158374373671746556003072588357835036884385547573916766540198508057742745190671930027702184464479 + 7807519854130748159210155879811678899722270728200599689770154189194726372412310007746266228667023082290285051427818296004435318 + 8849779730758648974379073101178990211676693852201291929217145528640734853429497077571161674011066495817276757324157483849716817 + 3827352998411927949530005101476246283441759897176637008058185334546170312583858564041585383266413483217734023667361663656510262 + 4989459887640993845875939547459055523785574975836774839383442442772727790780196274204446558595371067248953971633261788681833422 + 1430260652446882399259326117845029992780579944482914613560754920430392419419801174119306529200876322246749783122971752437529985 + 1073402550916699040362018956704245437401832452382196705545206547444352132288265525961915924743830388330363555452775455714221746 + 1446616034452999060536906307198084433181209978784238878045014349105221877679941993115397416711191417693894301857690745032510836 + 2955390019036983033546377278387952218996955027373523655965784118029086980123579985775681000785897246210289721704232358897262443 + 1116899333926038276430989136011993311064835969966384464160468735201645112827713375177166600414004561963808951457633980244174631 + 3365167597668328545027411315066184915713562624842225290359331084124729347322094220584503855828183282959730835678676639554531692 + 3703132630286521554741077336255711977522731641435705473997030102644612053700886241315456330580773390018414386585814426113751822 + 9217494111509421272989272558690493322060649433443466464859990829891612802636240902558280843106767641519024486333577210250455758 + 1991150751561946927232491146002439007601543254992434751580119323409611022604175456900099304707614992483865118197257172247468485 + 4718289269042762658615396540607439436267108037664826892947523927247548349191063673761417193077849996352799507438421286155035753 + 3670003174685490297784963434080516316824119943018705327982929605778412196093833118187456471893403114829335230172542023511761918 + 3530299462397538994353624879221057016014513591355266971800473995195599575301873296387357918288523036075230002667564181209941862 + 5652465756063919538830640228613516853681348031923008502389424015416629283480087157633179737963541694567718976270634283296698772 + 0628398273786061322495772855081114777882254155541640367813109541283460927308493462443462004237680494256941289350455650052190389 + 6530923425528750248516830645859529161548508001636146477492907827739674571658452569696309864671893300056851989854105052764500328 + 6377838408857911124605696723808145124469491655188029699697020610066790779133275460162800601521823852930699312176096876169139587 + 0939964825101402137367079294180090650010316165686145129739428563266232844352675969324123159076365905057635263730951535508592474 + 1811804823447992196520518580949056544426238843325335935996032408627339563545875884333166832898448807558706376176980463476019811 + 1853671195949445539340843650229575714750539986544526174232405759132358558190475375028485355385394868549681406717987759935904458 + 0905656451763972780540932190579104438556329939472118207647554428546869843074735432587357981463196272333295652269129883611649971 + 8081235587163561191593283995607470950948702816215035438010567011848029435878836700192088876498542980088266248768136664360732349 + 9048395346539903256416069243232533610069691095414640231288922049229368354092313481960519237230458713935632653201847905841902926 + 3586899375981532151071970206889742452371614510846757239619094223086588901204291404135214382914427118575565088049023826713070734 + 2259183814776114935570816268571424671175423119794189492522671432476564901966405647187984087627618260356094922535155595764746633 + 8775939779211866982932257974707044029673787248018990390269181484731175023868082868637570701885688930003111950730117366747034776 + 7292037040878433775921745075599110933471784681597260046655966261287697859339714368407310137037826533774841074326027111292219013 + 0255740507228750627788675142293353045696200562639503837065555027761345191438643278181859657112500994447007605647817675710357329 + 2976075331061106900800437561657304517961915727589721564040507512613786451696450429048216474153539650176719572123959448008900012 + 3408433706045747990792868143612079234278596536479367304972783738238238625919742682436942402201332632706821698633101418726786131 + 8375660756604324838036937822438189146692980841058943655646096987446498055875487503182581651007976496878268593478897138465125407 + 0302161625788138941756180586844882835162635784547013096553214201480525116709804815394793585124634598219195269074280104207728072 + 4667838900407600665351205946634451166183916253892825653381319301710998507256107777186848085957403008238368100522944303632213848 + 0568234978451633682200113830676859774853569376506354250671989943595147694543341125278943952146653132296950198184251693558754266 + 0837997184654618266464229835853893240382511414642926848175904359357425914225875122515607126936089890130506925127703951001817058 + 7698607971927804322206607636649779969047920064098738740542516881736563449825854806194526365935192809082449412467250570813092077 + 7597321887811111154968364298503454292989382990719881362442172931187037500402048057328677657705369081382090672410230632333022578 + 5702691344767100466202486216169170905325756285673048601355109036801723677816257513289352210067825399512675664902709627155754391 + 9534899164623786842509061739505443727104012615679366121874758009252764781464695793453679090140639672566086270483355150124722338 + 3629599380125790239429932208245186801604452556987851483665390481177058173633973798236252529147955843797090679456499291551397899 + 1654839141753372209578242837530384383897899016697607163271741042796206564645006293555562819243718356635356102675076651792712069 + 0330578183767799422174048823749345411130436371482070584047136107077445803065143356378310883097325525812461948426463818958359831 + 0535837083229949247061916351323305805073161284351843348700635104127671026579915150619625693973299904452300157134992421628495782 + 9135533592025422741289488252334208635046166354163256661447685205945401888767478319569656787569357811074256962118550453119004362 + 9301751134736346294356523345255306657038167822211402293117443464784840025659169376501953957672727051530179579688902595680131766 + 2105969846665539329882900056874716520798786759023512793122449365556804018453805656203040461898429839786920406056455733868681013 + 8994359707951012841246179634189829024194191300675090705148350390247850109295388787831386650321294752877084504137894482370739618 + 9241947230769626839032573755018849701961689378840022528468670515360403514925600595045782712624516468191893178057825723173315417 + 0398704518600034083166938112120280977963993296425790225059839016038745051472686938943167918298644018861694001602670324180907739 + 2829253174521666979009820015551029220993105373115142695444414232286946938928961493390386858301002697320226848958500348592987936 + 4933376341875898717948810316592654389756790528913140902980810511129982071300880573916140408222881362220907631175682400695211957 + 2728405831786952505365442116971677026094675638127255014104635321119617454191227198408175192550442007477181962648595382032863011 + 3335513609023390087365324523236604049358730860336918649941016742564809500323096143070248679219333226141951672644858949079743290 + 2564143013685722767288600853878709769356311565059463598251742499173323941411533573854915762183775988798690410191696639340413240 + 0493448733483595346076056156947860868081377709049727106924154044343435604871736849228001533150906569243527614792377672885378205 + 5757247991130415486385859064419869200094851432494013487858837812428585929428086640566084149796652609672519627454844564932256297 + 4669558478660881121021903646645372020041434507907448258764267056511994202274610206718051374682457426295364768694292186976277202 + 1564360996091464350826834839280932166253903015206256531264131271209638480781609315412345487344374301996139188255108960560840234 + 9176534815648639973257109408451729832095062649822000160147163265683826755303899059727567592934572490764864402347275743547218198 + 1866055495605517210298107031806201932208987305284317169767415130763125409722583393741250961695800822861253047933789380082578910 + 7563809612558319699283127796207634523042191451596228205984495682290513031662522019531400901314878626864267750108819514332947951 + 6013217317646435086018804719571761416592333129643806900438788455325630320446510012694647580590342912656641492584092556696246675 + 0844610636935384963725961540456988648961187114742364338486232200258126457044861826644153851981432318719173242496404738484829592 + 3080829363782082227074488901159023270312983944302028828324523976099006110195688729810726298266450333348633619065288392022236229 + 8005690472921247866581261895577036104640057531331680489329654614207889686295106419176764455962025382611644995861348654828098933 + 8502321967575148172006469677676125932579572402208147927471694132908710196626265784804209764246638587086749717612279459712731943 + 8253507041283227562754413288994720899007749153170225893148651683553291625294974124954074490050789574119491844797138467527966227 + 0130509196073119104402816135401821552059355465255575401457469499625193746950815086568670490180348072693785487568778765124602003 + 0665248124119376664057125582265850335568981888916788294854156077917276025925880496268355143677289608433935345978812154208855268 + 8995137970182597573167629723687168196388018417038021858197249313810312106750976993518701591284371821222304917627037046364482239 + 3380163047424234535936046961259910243886634603953810906816744443879125914109276466757734603864050055610106148478096732039481501 + 0050863632424997195774488430947153709833716798293363139764056905080948883372556055175360309201107604690863026027029304809129018 + 3159045522676282622055741762907017038764983291766901157880220174438440331565498671114637842462602216932285417970008975756029800 + 3552237063449291059014349162828946704972597219745549772402644156576458713144836954411568696563098211658803621586740322438123527 + 8553792749167921622407818214329886287689794104816641507269131593430918574387850051670847355476478466155909359159406347347073422 + 4529077230987714405406119382703861571668341576429308147647968381984164008665288474312273798880569173169482210427510225857144151 + 6873466267196323702969428729542596817149488353193513581368049814798979078196465830515246880993440065883452528995023407220294628 + 3423764900702625807926494346022071251875105005653050523263476206366063134157656968651581937910705560688575444683225925304492434 + 2952113637739291573792177591055762311484591345740602655920022962868733639951191003783483933798477891209504511076833970415208477 + 5918285063915228730571970492875778946493408022023485280196322884176264848374770469091671934052402742006902024842930375953314997 + 0188283754328437589051211543538670804314085522712102214064193375644277314824255259794129098802312806481056628400349306174297818 + 7400374465412082001463306963438819366261869661341067811137716763449961651069723995940239925017934226230532596999220744932707685 + 6210672490680638537370704393760193333970297977253365672997212980801329671424210333810500664050546692669173806880821364438329547 + 0441850655848799432631375117017035628999017015487913470494267041654835295714453029034648907258088418618148803149605119491595378 + 0667709470097778550996561398901373747557627918533058120957567808028277879620594852014529739234370013800886373620787541449928329 + 3125515897530266841998191196333295200100578758020333846745697177799969213733901430202219148194889600422499239512275441137216920 + 5650415027342249979224454839045392096843643602822206652387425455763721764312986203030589819856297909492941454232871627676382600 + 9334860923952422719693805188600329744718934283065130982713900165662458916981874159673444880197331666542991521443060535788337790 + 2260464469972488038180467803562022523783671731570132720326212442908194344858555602668263231905684505806559421525279834670049624 + 7792295078720351079690690721334629651981883246931635344717773193932081371713539221551527543695110154112122644215377568071412160 + 9195473483543180179899660415512485164196998646076213127620507751563271324222304453084630241541418631528227182134165081602418516 + 6107199131518105376224811112336028754695240510430182476876463353393744511821873843541677824666782764783493452855094114804483949 + 4681701662176678506643507046144062278379351438997367570137464357422720669913574736380880061893275748247043675527436431955366100 + 7149553832033242764660394022295041894654956152213899886346680985491273200086975419330405272293533518246991447255727068177450390 + 3655198436587622677364860349928319378663047397528676907239140945275682820405657108502041392682979560846597921188888907265931036 + 6476533442276806500783053564071177712515831376234094631885310570178318133342242810813665266902989059805523937906419013727894188 + 5431372487274298724777517697230193875880937677668764659986523658830811826735084723524757461022654674192380627828684371745612348 + 3820846618376083469895407196241963862417850743410179248545973893510278183277393709562656195366243761330452232662018800107769440 + 2069720833072682115347026542393190511365870201586051736004598121210837565385863777323843786272509797134422300430192141780468920 + 0442031082909423594641218252063553777303614020588281829250848330051744891712248697144729676289337492695365177253047051776547762 + 7268639820077382077506959745238922291525171731315329144119549984484846531136030620064784882237444115815092112452964098100945835 + 9872606636855509027099907122315750101939814965155251567403611737103452272009598076995597635176083234788901670535978209531433759 + 1085327638195333244518594079295886331726523118261222009427508754702667381643585015276186491128806622593525832828640622269002176 + 8000558812466886549021793247340135947691306446427709528028498200426365682563584527832696795214569479985794618339152398807896264 + 6187988847312530289136504030984674599402925257102785831329312431749794271223626066515601194350356075536808657593446997124519277 + 8221593778261506773470868068030158332034878924556789236087379527748372902142937754401272228850387450354124993708739623158789162 + 0522225048132576688432285718958345124544338046135042578516691967468794904627442698787375554323557096004260191198734997094093259 + 2462493092358156921232365706546429643442698260566011347797207644508552329524610339812245114706710736520675636593241151933904714 + 8168806409481440220552654041925492552985114821706878419857282323004033916474011864732600044228285384350058041710798941857144196 + 8456183927145192331984325229219292792322346278563254801756089348717336352552507588302857665733398806159165657708323657950532344 + 7959027432654889449179694030583164431534165468437531025326379868797173494533488353046359898220027884040904102921916878818230634 + 1572671474039612214962772842653777925720919829404267236601529791378862012346769450214240286963754895280462160430824808649254296 + 2713235643749557564532205594282964657763877791499599519104896455051738725475670902079776954156280521778944415643098383791627273 + 6105964254598123007279257593697900824845572590247120355844905046052760198392683039070579501029336629655707492386250995234644336 + 2615762358163929247483738668566291188631481608731204506773561888479176007728316484171079619334578564058039995926257045933155309 + 9915284962226636771930258072321745421222389817234966851925987744510291810977458517680205953227386190750476782698954854970577352 + 5673578687374046860672064496277781044455548859373704110716891640260365042726694184132711815871762240294031220477588483951772686 + 8668728817231201425334885333412781573848400038328099971193361147160493544335456580227648349461318031327984792185171580102807503 + 0169567182553246331404084202997183149669206523460201655479386533242862563036582654644409484005992680312894606697548079677284436 + 2408634459821807360135371085559754639951676453609356475891807606645289547821918227592956096670383760258316085039325249167270345 + 0639753426126492725051857242781368140995333223012553263382165242568922620303770347983405643905206504900791961601071942284936427 + 0871588895354801816598052309754202243843057099627863238724184518284044817748295192358320828895054008513930794283973928514112196 + 9798654324310664456635488952439998180995428408476235283937134417681364575355417817510233366035067348678178856527757300827180944 + 0038123007290989063863175985592778519488056333171045377703085872568160778246582018586168915869948568385646644298618780983546355 + 7869384600764512734048062223566504717806018441987433044570169614606144975153300488119826197625737171672582011169222743563965980 + 6977293818241046999651425289984525444775996710580402650890897413638457082477468109575400763448366802872239506128418904706794072 + 5799904603862986594106662322483455329279349540532965537255861860553280872874108710364305979053889159756036410545175996560632213 + 1905113425852351684154357685504469533745516493501062212340862826870385326709406031686063551224557399310052952422838419329227931 + 7546871961833002037605725905779115533289685288706841277287949763530450546184456445185142124516259820881277398739985868903009290 + 5390552777664596373149764240028438950449670876087502765011571015373476441820757391918243018050536384628502031771242890575429423 + 5602898175403670523511959645093602460733826479169195731008780332981500631244059144423791577718260284080812356359230721779826632 + 0282070388225563293057775488479437333861437827295440192975141284220068554470734762243654683900921775316128776798676828649464561 + 7044919729960370651911034098935618095727733916533962937362197410606374931103363062973825850629444853848346339446960413652519614 + 7923852433886365419446901963455158024361204561948757781294971510735411634498000899993250692952771388573089449720039510778006556 + 6448339128502198442312788117252393804187619178631365039260121533649897690132658417974431016238776431953884429473283621621760928 + 4796673454480093007496675559950785558242785307210144883418877108437084521237518409035829359990440607609053004656855467826840969 + 2539967222010309449705096804270772495367746726394308555148839954759386392982542739753442093370829925036983594533194718249508227 + 5349079635800249074525176724894658939051245265345143033311987922668779171808073614407324686649849960572890952798590407394876104 + 8881074380416317599148271017700792806364855765066986663556628051754736630602571628284291106232498605571402693983906331712030753 + 9874937506608818776772074340810498838067037288381814044995123846119534641571274807743575095446827709625774292925956993651483030 + 1351712538266765203986454072646816009684736475838189392745470191271779327758375268068178391759551780428792430541942252314370156 + 8407859484892460620078868667802179357348492180685724246644370230014476781983275135684947107880402240406891839259873980451085903 + 4906163533191850256268583682454988749837419823578079473319346296433799092047235338380155019552271132115175763259341940167374009 + 0058465924482070913500147064727037054124622100326796664614046484792704959337155884709332716325316023891570424872580884952438266 + 2436800291590505288180953642913700972896437288014085488105811040747638787748114199225450616098949678241069300416404785919318926 + 1934599170792002326313718708164205938810092585230289681773510059324899654472028348104884160918328871998687720554532160558923223 + 2833310668093246151983045850009608661418327316614685260920047242208439507520352050936476946684777115573214252016051709311522733 + 5806306154432125296361988853844471579270461201267503074861984238054921903008010783021332277527690547871326604862832931571535476 + 6953887201338700880983597387777946758689636635028887005208234910693065403037992011989492126099118102129494636864406808581750418 + 8449828487903174265578895543349223421139970247142747092518020699819810023484608128979286359504168816826179123882092074937458466 + 8429190917143583035383484835202769619898592015997875633392860989349020465819040052129531463007708159553740489427112502433350259 + 0015541288911157030703391088218525575081861192862772160417721389983310098584001488671913042391958271599517521875772879817883670 + 8715721723667422477987285388090627370795114420296274720333968016528373376502351404697409435351445641183117232448408900877983999 + 8085119600169893659072473239891529571989304915800525658372770589231187553832358134049724486998092398100951195327740893124363904 + 6825971614998820258858203237294363381385260403003703481866209020749805588161211696398124406863222077112906818160524737133236376 + 4791287439396340287050946270382309108183116290058907007033269789030152170762597022242414148156450382489069745048352057183456698 + 7699407910303700018163871163387977417734630895740976320842794125644044206230844211892365927545147294624099819954065586859396532 + 3131672188768311610064467750350104984282723151135474654890501043106825950749943883966630006426594607652504022624213316206819824 + 2381097970942205624530028578508606408894416081148567879895026246182144217645044116693226312513033539646866882479709987958089969 + 8906558060289356651604127285059333055318644242901255378341192868378040612451560944688746385088366187655524363293058496259834503 + 6045783943499511329380195312503328218913377235931966010737751685331040259612353101709972563764048165640905281453608759750462107 + 2697778235378791219808122722229257971170129904297461026446932149333464400232434190909889478146390656698937276924878791295257123 + 2803907707992452534631676946969649948134841465957319668276815925648168701088565169944440306293458637327427324437179025248962792 + 4731713616143649458304003973798123909714421863335575637937266819992047643342146589405067966192841049385855050988705354679370809 + 5372002945727744156997261317197525282324231196500161732336217784763019914950265863384886596392669097800628799874734609235337063 + 0503789478310331174915570738552836640716185310681333898360502850585012405514745303614418697185463616197057663173866523087604838 + 0675037169916204490298120588020089851962810662807481941976840354009840553886735946987601156791667665686995459100468477453975696 + 6834794049663185275577105102245452812771387897018848470724588835525127031721746222497385677737902506111966509521044773531500357 + 5329174285407427305661763207997349560549428910454568831186538339414510256938492615597532037011523362904523476314189986503671291 + 2718934812220309630578226399896956440076865897466517017205703733213982937662658920267819470286608114781834913036578565065677437 + 0292082835411024840424424503720769844545589088751119682651139453690649901159394940442554457210310520610468908232856172200322893 + 2168944494860484191151489757452268440986053558799687398611861491809004454116677153114993411395893222172780575772632409234094898 + 0022046237220608888434835342573839194475118566063006131560443847533169495969846042538404623478526559762435571079702487933385421 + 2451919192203771937523596048769324041291130793137730493766482430142235410357050813575163787479425148259744336129889104511577631 + 4142550759732390528563707063152034344178846568888223418447224601319163578533878251799463243956174732623278426810354689051255154 + 3970640202120158350260730117870456696154229567633606514596475612129033212370234978048801831781364493706668262862093481931515716 + 6561924140099494620364526936808552193114041143469574838371934269300545161105733392695711211423415123016324534422409169998476243 + 2456534483029530345127697481939835893243537886692901492470290039455511175154304300500928667293566968811328935461117311498383274 + 7770989718625939764088550940976599710169478296655836026852130278698487150688281647540447530622442916288092929799874814879443957 + 9848763764198437026743206591847265528425238321090574928951078930719540533808196681934811602035009442951951047723353414154858302 + 5787946077159159168774450433330444862738778849768023490388074911496672265084989382578533753038885946437129868548176233233930301 + 8580017107399342108923739552269357825947129658651850931301283981215557531809779053507136238066452267893979878894161383251981836 + 9913766525707178278575810543038685579648619267169136094328824697618419625108889858389235878109542078438921757522374605654744287 + 4829229647563208502985033637245591132219509835319418276937992741995767258780935271942567981080789563695276467555561800638017448 + 1643138233933525491385701115282638884356620775214978523597941747167932566311974729439511528404991306505854174907409034566035713 + 6143827997778747391148759316186369744390378766441792907186485522361511087226349625577289271875444080879557771349971812896783921 + 8151037464162282243454432112145953184331053916340169687740205103102595400733446898088691425582734935373310066807019088114280263 + 8729904943075565576008704186063345542320788733990798433124383054387825974302546390620173375209936756748717665874520884924479185 + 9888909645307351789982700065033105216388788398262734159940626037880383673919937047828435841493103609687935677331602519191613414 + 8850737384099163846794178899558085730334694261907207404022320796803770107876986360807427894048245601008966306481139963465178636 + 9603978263464022093387313902323305847024620528667574592309994157800256182557220046954796119376040712963053063896476690374286989 + 3405947975994172973640043088019552492100802303545308377567580689104604977659913539104938989315677959717470803854511462658064563 + 3191162645413432233404183050706031855638390349798393321645475424393193065096426473922012746067572812705091078572123464528104522 + 5754070330806062132016998542325199869791387417374085617357171312577717425296247007640670351991232446756043415004205160478899347 + 1725194535387949369475223998736399458938442651506418282232173272224426998356393475616690357433350683532939697909185050724112276 + 1531609961298179460965979011464443408544699180131732903518616680630569852510445519164321486062756903290742218453214665562625462 + 4277461038526097907874522581743597670466704734455633690080575913829222964025366450929288253518473640288917518499198469245997685 + 7420143434734074307744766434941598412413533864920547945213441905542326713457623437002740516606230037868321117285609425877483514 + 5509703411252690324400121230820675240247540075031296148576782911392574907974824839505516956261324207298130826703943230789524466 + 6235427271350178310739006810179034776823843871399578101065895786301705049659021548642844679899589499916930305008178597329009228 + 8708376738514576473422684695199014327164139367786002985515660277291737951903297112627302613852418677997201436504553518932602363 + 9576506417537859055584148204389221076679317163739081159093922729562344633399336320523856409926599959155324451664857304036979342 + 7821519375657055506931717396389844553686714012907465431386872822303418480617283652851337727643122589592938283893016029851450741 + 4046931470136635022512650864971382510668763279223722442081085741561189482186827034926915081819290103926309450155161557982601266 + 4715454308438516658794722092196206636934007267582801367477453071665674490724227142539801920570519231994847446963269786268119916 + 9168041401535492095223153393392138627537574429611826175866774713151956729343684934892542983754029148830727112711391973335239513 + 6515970901191127073416539618442535739664555006336299291335206114647465786032988393861387837528101930282563813184667131516357399 + 6965025115159934457674823672748261872585621777883115554117585206762204650484234255271173958058407125541367807442514328611570278 + 4831064230665616198380860322957982656881003885916660535633639193463684058409926839010861838915803748651536627056017889319571392 + 2850377483892889368048618651662404196455568541580082178826055899571765132140934322132515590245447090853398672580050380575567268 + 3835035801788676880902622563977805200108581423258706942731469718506605351522050771195525463348620059942550507473397926975656075 + 8170641249931936194409801838731827726032358290235160889838261562910412201128942409820711534658779929527668900047257962358847821 + 3914141889006189906618830872826326907793134446571712010041037077410013305523598603376182060668984447359850821728080727595426748 + 0524288363005399115153078597028593878897064055724890623451683531614421839812503951731500983120346087995189240459208148107096125 + 4155453406508028056687037448768955586471685200246991147018630064209861444093780513311415335160348800209398873165630411940689888 + 6507947702834259046810555837139361937816955993601288388902706347465220128545880169696095175041923698015462911423095653174399855 + 3762547022058799188111929405215622052455625552628888943381861262479627747983891009023031983537685246888772136743333720092806316 + 1214549690057757944760791464294073960482795674578197576015074847454616235022841464586043262062684847644609779311315421146732973 + 8541338437296411555067873828147460205050118794445175546707442427376724688646895066999337376018755680130878200128406968859847082 + 9053903102817499105181101245913670467308052365562812081988351351621302283720868904030918069105268441314194378171102376175885834 + 7390879175657202991792721024454048282348887367327525251428650799473344325817058656761335824140200255463527106801978883972849023 + 9114858631082305511415208423205161099795092979957887353079774012813446208145355233313207283275642795951235302177270570702859527 + 9437270466650300884205636449007422609778006468400075137707364599220020468818147412256802671321760977139033664343323597425197602 + 0302618076580610803854795974063518981909366239035024103586093127902225268380234904318024257226627138837362185766291678782029207 + 3947830739969480621126671162942463986987058328256455824368521897685045168203062702288692030759860685197940546125045250168790201 + 0514803654436570370324022741742361761085767189089724981006110323674867393784988265456553747645514420643289677440464150052019123 + 5223236088122199447858422156052424410894574207990368063564291905403412016110145065374098953504598451976662453874666981008325424 + 8373293703798267046749026333095880042002196112554036817370313956674653924174972808775910245525212215059736970917924397257890308 + 2688275927997288192485396746573266295779844438202521819272050705543165472702597009969819708658965256689368204413111379773538064 + 5084094239742086467203807611090720704742678798346329233433650521401666169943202745736920597870661200400002701183019652790391816 + 9022357095836768187469229301323281507939417769215045474272231522798590708421786910823915726035891376298601448255283206715063088 + 7293988737791411397897393109492140546674166871313197493347838700746175919251207836436115320719048184023218823514733017767389387 + 7188783211699643174822974868235729901402276203893157987109644622416046761772620967723823455916506713613144614196470266830456333 + 3793370001173936142455344055973062003252783611956485218268240522116090384604646513391487197827194186399975132117817107687082668 + 3534299426891086746037016872943029880008565862091417500370811850667508670706496943938696062708498042156433801209832903518387378 + 3612904603444715041436728628573199366360323396870491816934924984624193337784171063290043144432026274325167439913901462851257791 + 8301153338470277907154944290430893973748596163892611069628643761048471308522954471189690031882490684526895423581669049412645780 + 9532276724709021001315582137581907800630208033706211952374871095930264465397182584969831143514075753862615083949416688307055905 + 8388236378283440896890187881320950399116639874885181013806820276432717798539692296166413239097562927693580121835296266376329989 + 7227163697631743317865706478603326970676879690725149096075601615664615649563621319796915072035936935656249230727588009066864898 + 4030193127531435008439718127581289588778728561167418433131262502679346011703797827534339742404719888498611315489306325294200918 + 0822596041854995877122241367357937629640300673554434225279391124715516842541288461765835730255187409409295964047110843143360218 + 8020810762143625695211304403500380226297593451193440072241550883222759127723312388393491431821749019440262383840735943032001195 + 8318237479489554100626369597427649553987985282444811016365279010859228891440704149689826185729924642137537603090218575037482996 + 5366847590778547088514990246112762636619967032116058526965593868078207507263589910269699995373744003756645473632293041062685541 + 9610845056170949836472700450287286628803643135098265884778110832410350875689137416100768678349522724998316556986352522714663266 + 1503726130267377258411268772164465860231491482249362263232011498460531343555282835085236658598989040170763967052694908347332552 + 9494811816089738912922010509947751572303760145536902984045309394480942411502821839970060527331347541450194445987076121267053844 + 0578064800062529101700072602908332148334858119123936457716348054959136175842817084891684097218981249238233949488256020176601607 + 8655837084859592004656876506460130727405913211331057771278893395802267144808219629460783237220481671207469404413079770236276202 + 2474357024202046544233057042050406320202093782109005795759352430295741395906001878748884723478079164300747108788119563090468194 + 9729275772864119080887672349769974091030926766697899488139685369926038289554489717497100438993101868557613700320201349470541544 + 9690121476368923069792412981332423045488814436625785624017824621004713254286195984412682695459029135822031307061078889173619865 + 7378777371791906660635984844468930766958298884404755753328140351948727806677530013266236008432182713748064589578467419387451399 + 5958115863312505525587296099572988051567717080297066945899741469832877228284562546192870097158128338501540449059947967484049806 + 1525360297576645372782766370344139731393001666478941675207716176663153356185352097531952067180451056483850877049391450796637643 + 0957180541118429393622724140553758348088782996643755097821436674434023381251140872906157549968145359578492278555879752671991774 + 6216547228847936682579390485586625009476953902113956539812453553726263850745606267922068236416232274799633682965858910518609181 + 9364762411101864870815658017284551581396524871993598349274914322101521556813705161096159781789698091708777511072561306773711005 + 9372502462001712636254133123395734859574314940832644465721405982847453658518168263698099694805090947049141539874161892364044592 + 2081215406680382103751369362572309567943724594570823605875011736925225634106628852644577321897191396835476563249653975626106030 + 4349971249994089684132392481061788229278189139063384564147513903173876133019427848009965641301113400947275878225261721625731279 + 0221661121010559617008273964451895647239826707650461656354872916410348912631911913485548662828141859786059545072528125011374221 + 4423053386826713852263693496635804173362348029571154806846975163821408623542798104298751000786068795017683260714515841078366993 + 8161127671355970070573405532186939626037976009760161070135615665381704277318637283166773287886342633146869956929128780714287331 + 4724406673554759228867043031026142833731777584308969100843251135369865682593955020981079390823701606661557011686336153922127671 + 6320174341401698137531688064847461308245007114188039688579142931690284251799997677320348583442367762054912291140917964811725137 + 8202757825011219494192886746445679726841310275929718330630078072572216660349917135633404881654966136524906313940172149175596901 + 4973259052196790674213907468121479716985489021755170094314094085515986880378978689367545392713051595516162518064260512413271805 + 1589006020451052603264805726624921702203140540281094471735610296632014298925191276086205769087410850492910589262019474771202876 + 5301512438781961299615681939122770744864098845659058825055415852695585895078281739508660406939859772275150311279745599614771126 + 4288153404604175490400855789649207035885124038840820254085618553577028061229192741635233861987354455133991517534727391845052478 + 6258955556704090814031626148938140929500657324155298474719121746871071846048890688770977276676240866370191127535467056926311394 + 9986426460698287989606477786579619338308357811140009068302509875335795457387693847614672598016435455104290716649294340111672025 + 5987575195605597807571132149058303080863960035941811196802177359118666488648716460574884370433012992324776906424681910784438914 + 3212828929093079665577584834614675181147027766122500255332258719353578136517199306847607401381636227698622152320466280962873067 + 4298697726297500762842637031315949284066464528353792900058970168170276550530718742305480231641988165044232612666352048235992340 + 6528595274852601267138855685497658048124785482783676783853867479073934060681129115971059226209525138395957477851256838662435594 + 6333253678417649760854615241319608105505866305579272971991684020242948061790638726814427247631657265086447512599362760504729659 + 0050552281101516551597310571530814588813676939570968218933911952205870242379775297989531959401920856446210979962385790387518282 + 8767289958783485919140054170755933223361121752964753574235200401049015889601531517259131960751322512615901642287582440268512260 + 3451721805339224609531183820195682695971871204396323817335046115539455320833063731322682287797699412707522241064736997253801427 + 9838095438421652946093122030638044112929662006537527680294782737078006325003341225082530500978086841673076833294743067222781678 + 9343880589742192946487883613246357871516859764774916328816004546765194900049207055237803648799342279688804719689248327413730472 + 0721971662815930264205326239766135366858450956630362245585637639859898001993676716328053273905567456704608882800064784850223773 + 0571787432542029050900323916790197508546510517976343882254348928206749045986326975042209032481347983325984442399998495068210198 + 6252008138898607709468342620809002496223471138515742069863151888069692871096460617937300581107228988473399264367167623204729419 + 2797770513682558101443641688720044042871553905410373246365721075390692021825457052959920292945148726156660506042073326859993576 + 9943199450035463537495910614331149365062244685626306093678223057245690588586113869249388996930139917906887631260478153521760102 + 1950460426985566320913113822097771379876492753786278737646554639417059453209917138732302032256017931681335738155323404263671794 + 2838332702415027792861677040542052438018840283865010592299818970494138350530560217854544968425238656792859418734080761867272852 + 6010463746369529626569768506440616846423788144981864845682008740038225629815725166282753185272670640607060429451038753678650440 + 3603428316928538153550803942955541314085414603075220414550257874931378714081625009020301955524753074400211685480928675879412454 + 9843069053870715332522840750526561812419932672015609424516373833579891793837439080150576601064726524016745608185730860593580037 + 4790338120349419657809887950279987231778879709683733319593125286240898651454362025515251496405484678061036071464115462928635106 + 4812436174990135339020055889098969606774850114068102256726271424987296420443648067709292253692100724695627779636510134753572039 + 8737165463831035630144985978697481580718872897801411679391604620458063323095158841009595789901639579062186093555920948550517282 + 6684194497843892923374409974962663409557384721186689597945008117535697913915795350771799536776499659499378233933827449930665824 + 7081582116471192658574426394048422901610749624872891986363877792779389085331435286663561611309448994925468965045010492951543901 + 3680646340800173339218788077063204059241257097481947777145409084202800888856762009180382127277534304230302616826742040805136435 + 8971885064485253090204122142512764196490013452340872579790701372873179615012971724582237981895972101835369658929642000295179467 + 3378697466160221993719637822345980287088027594206423215053076460092623235649859970956549802453476198188280999027211336510921505 + 2652711751748836279015697510746966396333400935969997511167766407036252126460465825405459671454621493581082715193532241502957665 + 0853017906034458377960386056517204258262136080721053029202866891152909200067791240221407899628896204792320935757942824137109755 + 1860549007099165197284140872678756594535459353075535851412365063078974696027557562375802944288504306767016261985686187927040312 + 6976439902255838121317145194266076485068757990450059106045155783172858632535344129113251970702093415466811410640476211193415639 + 0223864295074452283847305560600110714424512989818888930888094361164360320952698546375108408821282297940103191521862113682311023 + 1062349856533324628662077342594233105268417141054370232872638557841382516201012169119621084906023902818960772903834214834404456 + 6774964345965594961633616650657071025352025214474328041017041037485163730502274877992356272868337521422636796698369213270452116 + 3863759791559426852045781221052728648632252466126078672480213084512794723010528131976170544126507023866299598547784848361822975 + 6029193859923289086357438220756059069241393076481467455226491973473927966812070493726378405565631775752820893408930243604143389 + 8322645429369121872596731546622494472770504292226778137537611049076304139170096181584862462563435300455143882748092410271989379 + 5326365807733260201580801629433084263428632745627040818781791453399164548163815232430786017320082301681273560908524949863305250 + 0127708812120756378948747377847983639315742195284498126386446424753766099623540522826797908737477298768890173160498925727449025 + 2938525448223494002554985481215274772014195861665818544594199880542548809977177276693721985173829796357491362226406805154130568 + 8969218337326188250536163628581836759650127208671515917790854163363077352794417610106050375787449708519147175922505361662892084 + 9818570904194161360123724397774706465600642465735373239577049512865171271762814912171304543676985961805640424586977875904966200 + 5504575938770959529220023577243022588499122259144158193746005510614090936240126010183628014128216077152330048541538274583951558 + 1040854914239994126791549056393295346381943572230033663200164558894293446713116407420635913349055999596494259230893231105260703 + 2206196014061006612340848198814409910794456229071521204012047591463330479752534343609457402515951279901699854399989958952429475 + 7726196843265136180636204555752895156585913253117092477574090168474904085406088453119889514918675712220848883891583790692329162 + 2932979781809321279966736276684170473868093894960203921581294390763273096543783962941941740885305313552176422059326344349963187 + 7716303606885535604492911546074803956458411462697046763121884171908019143640932002882802971285171891988638807617682091180833424 + 6415461043036191035529625558425951185907448251833755623616264167570352631169542482639741527208649286390063877760359771911261699 + 2470130258381358062929085215957585938262216089039199788226601264737025509814505817029779107756588940453410080897136093992799084 + 8707632659399021754985431789449236853018112947892026429638184953314257900880019675773825490255337783864219014358786450842397851 + 5533932851049276649253727477601106534672571299541307151668502286973847937896722437084410916259029864044870523541806218077954614 + 7765554877085157744714903505492619912731173476480412564678818534684847115861709661320561820994876787782948571629974821128726525 + 4958648468242228861341995358858962307381366972784922066788447146487993304134477988625345942386711833780639553271598395688961584 + 1195610154724201767373227499183087873970044260009821201260837039944092568903479517438262374212926002997007192595185854104973828 + 1619364472726153539242937799692428699593667255284692675884347709702639988899768923848970457805127213116307471608615036594270036 + 9983245059851562634241554611084024908123182475839572134087792577459483664336562817481606414919540980247553055009390347181343478 + 6678203813070191242843917525205623295811411258351922528980269188922471356248950351834938277372740881478275242174992792567496074 + 4143356634732380642139347869145766266914672583108623737574556686979737703412637109328384991661662700191639112734811399558605096 + 1208518184191671627470570937029456222980556566946874634805220009038965108642318793927711482497435062563764442708954406150308502 + 9023312095876743701169506435873830799968604505754154998579861924311377960500475654542205202570979796896262463835446621504771900 + 1307938351217139321342488304983730107947723886674861520928741265078308049241789485663045316829261201640722069914290181463616514 + 3662774552959414495906707805907185396346911240417542898771207054497319717662592108767592192807181086654802759806348618578837674 + 1314737004679848142363776160351558775692327407524329957179113590512266999745499877585915362625510835561292623778541138597816039 + 0237557760056059081432345998516737302912533244471786164779569231630397999149258259824248258872090314272651220971111732309368883 + 6627477978424025488072609778273019056422203214910145966781125727030515618065001832071393756745595983343475497495207623260839724 + 3342966216908293442342817978848639488604191273604917723840719378411000753792919755939336669416561658839344042868764649850515740 + 4843734023345647692176295441180249482639581287413972097837107583698158034620661397371501344888180961705583629809207419852455696 + 4443380077789857586353070023335893700728665808003439355680624696628418230215872552816714310195766329481088338871468994321119252 + 9699439754749964974015300163681954912050318298048480045612220669380962262620582805353459791375378214164628533298845978013550599 + 5105714350835688155081910384711576767489399113130569825483778697383765314872304014753426304269107388256780976698871683305123430 + 7876749639965180153007689268468639912304158853044482532644498399416286758021429281245070574658924487014301816203665832428101533 + 0785808281226435244861112112960701400035860271883263300268756398080488577467688265527817734331234380039587960227981962626600939 + 3364281430281513574894870100381156896475296131097244720576919647275082387947394192830802845871083057512101147458345259973497437 + 2352548478260815071941762637203003924467368412816659772061510861905396984310747338352315940227937768901334141297190271981978620 + 7421497155149250772882271160825127041610751435166048440557936723442915599683580765855387190581730147042311189334715395286473607 + 9469405090355283185848987802133089556363626275612421572132540664555746805117424373802421917096772214790891162942671883468819382 + 1589417274385691408452755936967864047060787328586473526198572660582234669906554955441129992972950187613542002387015080229290084 + 6570356377915672505761938151404215475617807815543585573009407518371861507851745477702147309937407690084987324419699405440825645 + 0612011361559116532371585728822626979903698606786712794256913394582020905043090461211508518273342883931278463866340432838401156 + 6760882395086214518227285005993629709889190889508417455761844997600135276044719721514847763212602718036483323892756763864051034 + 9188515996754462022639889466629680669832215175040501200558563344456278764716592388326318156786971890684957626542747491478209927 + 8987779229113917038185012511339563267826387201889188999106457112243660191988731669456871109523244231764354533555547239773405699 + 6489667993193399907320056380302219372587627376810666191791189051092938301013845696380002825207303265588504074647639636023424359 + 5972299897263342080767319345606033144822159869746010125714876643532020183420706758750193523599953077555495726481141414611132824 + 5084488926501974380578938135730935789462111699625550813110845128956753975680460172778115855586076226024263960948204752675321380 + 2481196609759725214010722486828189087368975741750919937794099496934509151874334791821893377695611203497436421390537165843568949 + 5731231776297026471145248406339411301301972034255825750883890535679456779763247607668575953175369910078981695492172415999716775 + 4579188403021146726016160128342968838235818738719371073259844121400672340573224465598262036627730489472180977859344538916635018 + 4072803135751982897056486221080699066662076832459383392956264311706786163956015331215770418998634239350534320417157397046765970 + 1201062381226118587752910736476250954770728984407318744902312031409265281863798225473350200683876473994417794886956931818743554 + 4970302735301544243501924330552682090042743013078749961722848840311456198559231934700094783625178641374367971636230883796585194 + 7528520099930871600504738859526542685454459947737830229008160696355714649737859829804718726706633142812661022345510571151124118 + 8421496990755255433515708880870288195255467739826209142506221198099596830401844825962275951060431553735295340571732198670724017 + 8936767354220444343191661460546264683941090169583805460925893859976635128662736335459378982086771782291262296836018682528094985 + 2091822408378038044344571653062122443897076701230437493508375904957950547708046448886825832044918141237713293307448531246301325 + 3809577056439308352524023850120731400555497421961772257434416551729487887916281181723448155709611102047050048200739035199609339 + 3691135325949817192195090067443211343266627775946016712851865749742799362777412328641698096396095788341581675313236780103509391 + 7728571205866997785438131913054881617576104163904406501238204339704104937888486853321561284077020503299289883355914615218277880 + 1111888880906892863133264981628224969781528602979570581183128605546822078255116005933260161155631478832277334536041066268750461 + 0079412603436706091984459336642210703864450821510237108480924013766858888811236465849216492858539373276328300134023520401083981 + 9032711135936968864615808603415924938529404508326233015998723558019026312135753805702013665081865026922455487474085399902382380 + 1925270181168851392094205156290625337733809503843149282248914199479920984244708969137863994130437975788618973591803506088013062 + 5670224338144189138135191184201868809626683864671529567267492650290228767102161777058656146469480714765930525720049680179040530 + 7230690280352425636146176530879993888167423730080287061127174186402752375468464868170738182852209838339454679149339529988407952 + 5792512066685362806154726245973930382853685512688261188341000372263049656702777229779863118583825044769296407053427341340382043 + 9064288699746230367766305172967912478546347888349770026780079432939827599619309710342120385387650986045115258506762134679333064 + 0440596074705090759141142692292577561658123037036520266673482910698027486128518652316613594364723726387332531338654819095216165 + 6586405699035556181676379611570196812319147084489164717015394853295535428378692362698265567241807453037131148384149957093387466 + 9613627657031243653069021006489437859522461371334813124213550061172753326963975967858093098270917873153645156857962187738174651 + 1136920419639517807349446907609250529925657860858085930986434051082566457439789550530915328824048952555143480521491002977432620 + 9723285190605612751574356382595987410097040493290287438645066768564593720132821343589116869402530302205558307160327389977244390 + 9364492329019171456987187525681281472110463501074399197748223709921114091308897093844593961700969890959904837552334397994454560 + 3052838056301761186571362672662664380662089189821373489289767638693120179754848616628936578638481820222476538767896516701765186 + 5650968841999476243265351662185220984505585094177664675790716289996388896832182868460012463094065416068468660526498381293391126 + 9133890615055659775962704691788335028541094043193982847019337250184246131745395473435608325229593796115617156815138186553076713 + 2129458246410892733861841029801352092648607760367150219892460311630359921628868730343711772190656001417014669173768985351029224 + 1665772830534776231474157241609092342166046079774561656411248463883336203142778691223352454530469529359343352214726777533890124 + 8331713345182730719576279806483123633260411891324365421657390996528436543606816818186451009421810586108827795803801756029033502 + 1364037207944391495829014284717167206349222584053304291053816472070825719135329033244226893785498596526306122826589748158594087 + 5166290726387661882217520391175991236803942524737711932725364262567914513184343152964650814367428507369519194246642124353850820 + 0827084375654733169383428093676562471650179031999648254047083978351359301318312364388282400723012984805620892215650029052432539 + 3941456090006715583530315193770635520541951076921761324088412023106545476103418543330517872032796586561611105128147089091776975 + 1738857734263197422168561159954861725900337109733462635773133902960240600973009046170223803445433108730659547191448827977753217 + 2930699447354813297267803165810088809944869393780407968089194813574507757841359950100327174854511476594508709317805723583889020 + 7143123510044372032973820765560757174132206252079849711539375893206623268969901549499791778646394614259993009419795504303081399 + 1805751816651443729216778302694093259724338799262345264750249439983832664270852123252647682716640466581767974713902148881103321 + 8726470726559295990593930464431140413396151555993515614244807290113117258035592083195115356107951148992883803789239385817695980 + 3921614672869622892796645795274584202330027636891305986908354816884938844639467554178364479042973665199423978535726526806853994 + 1879696934764137925030122852767473404168885624623810742903886724883175975872670995314600387454933128918537822599476294544895031 + 6035100939350635436051361083289099777664034736094529995818610825799950536521416106176327389907566363175789821848187634785837579 + 9000534727303607788183270598866205796784604375642000912263136681354291802540390456321071569535579301082240092546052754082125140 + 1036718094258942656960699558474884940333329012199962569808690163604756147670835128428656230386743308384472157735698077816035891 + 6071364091704432824311172611510490775020204802190669441798310247002139209451209194509056421614671635249279135552841468497623698 + 4388935023201010068076632458613446034376062184128689428896319432854524321580911853120662708261911385263651607882193115809188251 + 7169742597495615052582018265793684790742777650121858370707225197495242787747124696863007018741360971574027831332907655096436810 + 0422401456149077117264566129183248282220685815602963735110673297177754943137791219212563311879171990788150209340116758159767140 + 2965862835354985730344339045722772376955873793360410786309094363480176270871774839639924049136780870709007238189898961666868275 + 2861817902533679195525000340605947416733205573982037034681250485524002724047643727596821058644083422061496633576063860945664624 + 2693808963859011255454082437160794171986401169181404558686995397058453911479501396355062702756373669284391335723793677898504528 + 7653550559325583799147678302921854984957213549656349312970370601725315750255349048113259251600824306253788257181726835044331139 + 2669198588461532129599972595504488308041821964826043635029559596161652526633086414778498340817442875389328897830361220046753460 + 2464008866849845585427596306460289186014718930150794200485697147420894155928351507966633760981788686260275637265508592186109230 + 8485080800308772606343366155948976547130610312843499421865489766584635822710314441085925235277117540126323440360094147819765072 + 3284154124684872982729898726330863362356401302174583854830959819131037571458234265917476543549149369136036055331113709805046443 + 6448518117737425864310082406263081225358862769781154236900286043306718901307704827192440877547054996291784365092391305036785917 + 6937932081779624691771675203207782587255392167526245881985222450132700822827458180664476166098376639952639111122762216172733126 + 4351428226863320079499951081487882664115198758192473811033557945313783704183329712942802900894464150489698398293843181571708391 + 4008673285830233165375165239225902635382169451174378889470574573298752951780171507430341658864697744996790183195739971709305547 + 3512291497844318467447674406573948587271898370849211096489030445902905335005315909627516994616160913716819045790842998532630215 + 5522629798725110629827671497041697233370597035945650285606531591280806838835367751631589755667302233305861288279338186531242009 + 4038072792258238775154639697267095650759428219766235775721809805667537846787229698544718121429627243715285966487077144477541907 + 5934583620628679989854657650575271470278836721346368661646073065566282621355114101575479793022577251192819889432201758294108462 + 4480564984351469882094948004921988867959440174254223793056014056869119031094103106976186436427858310194322489736576393894678612 + 6908132113303990201784965196474475898344897609537622286517498106001289334026874927830753197509682053509801560482547631691338408 + 9319954675495203754314132567507992211027517777636008035159464490278748417535817989110579370702464528694578198640300697978306801 + 4761479515872183180982458008106034482409223233605055754850233921649363735633967021409784641062684672780275455212963103609820201 + 2564622328254102204752883685136476152747302286902963024211546476863845751873654900973840371931652957066788857238841473470464835 + 0397866053032166080589875219701391296400993039583315649582052801128849941725263617220137826074241870851980225112051857130648469 + 8173011294494728142605327204039773210726054522101869637370867240485919811250566145341338527471719086407653593120324797075262800 + 9276563059829040598662749592867289249306923572562392127787551507493862417784430100714677869547866344355462003505196714057035937 + 3281114518664069193538073304543737277406653201799960331850340753228936196208065150992985287938425817855366760648223669372651097 + 2101840795886669078503855800666686104431608113029414404488344962534581805317909553125776693807861855300451192405993773968098583 + 6961316934095858314386858284332606626453618369372169846037717301254036577518610498824984225850477019844523165578520651885370736 + 5674574044356298030636615794164061879134353864364329335297710010416084563498871752753647964277918366926080825456181880254954413 + 1539836063070409136278143569348758593204080100329208721008698517483741296128676983168524689365145284941105915339931290444395066 + 5870435438526474510831874542069716476806976094126759545431524918894521691790318139213265279009865120135936482961615836310836321 + 2764563926650270576320235999861005882574146665848294584476765322933617549606955812826398821817999980232276039438569048353472002 + 4681622264311366983045853037646736891614380849223091345272419576321258005567715693518336948951455962926248349277346106557405718 + 8956877856487148384136234859130353374642270367915456930125213227196134161996004529594088595345226945903651779962975528996861250 + 8929969605933523152819203271238663371252277051363612117118809528465712440154903065164514629518743371367297353604095710696093004 + 7157581534746462952501632250334837099070591121491848742704449306300549604064489388204805910975177833999231196480535164260229721 + 0485019965651431731437912577838502867419408108382589212055345268265256532718527981331506279373063176342764821347791812231845829 + 7209745175723014456091749043194092299024100594164185069424964912279120968460389124726898963864775282217153874785467678332297469 + 6065725443439620053836394925815928161931638271242410865193688681337289422879252019985383178533022928491349413174307090957339832 + 4700128875271375466912640968373319232662860319940601106545249660353269122104137983304514576260940899048020820371598690778056227 + 7730285573414592054013879878236163258148114953801223831916249666510471398921760574945529246282567489263612670937049902168944246 + 9130285817898813367964618316152272977147568779205131506356566544347370722993791917334237866531951886887339933938523558239665651 + 6324176517408834364349803908520408107012550850560156082064698531696664057881361151779666150135225685603149038329558618588277296 + 8952307375129199935262885586527056730554419885668513403462367686079193825971303716999017662160537275706617381132201851911575059 + 9097939471326158030329763386527360778246814576714519406324120582675890884898234797792200042538307916074737348191079713801271431 + 3543558395840050080153435933135880595590305720081325097084551423268599148459068228435603649060705649929053840511309887473304515 + 9764838954490408335606543556024437767253488401288444187782685927977837265995938637882104106333802927203512151240662538609957779 + 2886694819124240943375973107339251767858923004989669776842476259662336587537006376705925903350515688363082070599436191295014286 + 4373652465925317661858189411340138062597385913063993168012584788091469995881494867908911062927314918797351706279530078724029778 + 2064997451678388426343449295809472909654204980492286328038224332702407992526584281413262450071832225709127884717383554674100721 + 7539736814358108443787011442956856478411159063433502735600777534624427911961386455371172130290891500709946519469882478498227746 + 6726050228227536316385485897543745820479149980410361188284581130022635250330849613983713225572081803265842903422696226592604564 + 7194667876267325769087238008916325523655281922437602110657822708321617107090571364990182422106391457560890252879023326941272951 + 8084067244599983014933199534424787256031530896533024441147175887371345390886210891424383817784357384520863399170708018540336261 + 6756491974545573085147283999623619067108143004190487704098038956692693217789059190015343978239812814528286370354978428552071154 + 7449780712548692282752907313327411787266027754878897309843460775599392567392973717717866266635813723308899529146352109375925165 + 4589899290541494280337702591008141258629373350544520604291218705671399173981123075630121451176103241759370092474254377359262199 + 6674505740657078583031897307527013973936077370107324719073133704686647880878285508608449940595668407790459295575945823755660650 + 4398342537751131171214988271811959189579782716426212830903406974442463464257365397952526980356187741927953055943122410685033921 + 0094907389935032343867848721405008172219352354700721989014087040463745373039712419507660947640188922848825854691917677041514246 + 1508958586684510982818262867790308592204381251380001158886369026776930843982561684403451614590888186936500388011892045824866501 + 5793657116945434882250299286723935630635472763043771513002492162136250578168782159984593375232995341440779322489270838200480406 + 1528263927376996749090311110890532617677357745138138771708962614857985706783193215918275341078100860497124422089882672715412665 + 8047862045380193284671628316345513578527766132655289631199372572297400350940186548315099505461109159626804827405877434015762079 + 4497649985437114106619275583585240709212568170308750996103273375973255643809512987167799126855604592582070720993954457629607433 + 4115202807426887388976298359856110123402007311986746450130132490988863002251413157990023529650615874660044346489668889392287152 + 6927862701563682169262409452072639909156413247108366389659864970583248090206725794860315733927719571533833830245401473668394282 + 6642155549542044431836970672852504846515539364245490047433571110732970388069323446548403285359639096781185191635964711812010789 + 3758505500262572544806847683378518452890545811878275350915244958015902281380798955282380990829046266914505428380626717794710699 + 8543173740869008063671194651581188030729498726094049008714991031352383511909957936902571701241692397622133551499445586152966454 + 8558201709766887626106558682087493174247508346751479027758498057382070135663052096489680200478789301589881335174285636803583368 + 4021046412548985259286576563116974009718144433360698911802741759233868394233863822972297994024437477811572624976113883122932672 + 5381918891212001167216621281602456221735226414991801854696667000136111863626404844152191631832767778925457352443210000412625595 + 5545489652781686362831418324972755141214447870296324256972282335912548489681306938005662008761939913552064594595349128397481698 + 1089524707879456280414931183450523776892076608328015438392554074880142678157014194242067164456688702421957600153913700978618426 + 8305117650117364060258714900356625435051024551440455926273115470939757929013176898347131589373525848240533670222323888613399302 + 8471548092796793462446437655496090111004563242834114582368336961549825665258690557364306703617109594457055331363141186121145408 + 2838670852038846380823335210551520468349670239701607224866707358833084563155287946007354912983177147283657585469121005219622389 + 5789402261399916318681167359698620197070246205566424633235135391148334480479925501535906551354569207810065959398048065712057919 + 7261986944279592176600370192037825062903228830667505762121478097517284917101606104242575975523312739096999493662697366954853560 + 9155879998783130488358931786153797296783212124287955652349632245457365996542148509944356865191456587886152913113892875578626974 + 9514039241881963923397516312505696923391431643577404694192615351139994947842245479233801981061807552927418310904314043203688694 + 4614887134561403862531573523675942563015366589167507205886559178959551755768826801165790017789960028672209846259757000436195062 + 6712756378314975481834508159845487505561014170818191973740730433116802799842074666829329785272494733308089058087919052323067808 + 4343294134478763284253795500389053885558601278822120237277266312668433120502431917455874080753529426382802888951317455320771924 + 2376278290758786366787499337556544479743289945243171688237218372051181305516529407353834157305915645651032848895215696121925178 + 3277461207520288197080048258823569914990769314412444872094153856107817656040287107340131396038173497845042121242427193089822818 + 0292406985223320173089591545488895576256166382750650552107291481212988120961054843360076945546651513119822979777064017606102333 + 4155585975612603215642148373485509667928447809166188682093526614287990594479841858693261264552895318696996233565563963262273017 + 3435051958110889869116245172555488932493678104217964596210912258968214519860568648927109250277169274770553939366194092044056400 + 5580589234840522431968399852060022338678890148720329696753155804394492049184529967776995091977565256891476404577309506725891693 + 7335500310521157522656023934693183042792687707804385279531540473816692277059506917018062802407212114266734977379325447178574076 + 1771613660964024539818471437377426571013833744798577093945387086328616540439686380471290881092187502982926867793090143460960995 + 2854310614938011180157233734163443946405910506035197343508210254223120818772340019254546366421372519708012585990732220553479817 + 1257049653581939929259306981138171825335308854774522129783756061113569283775667916315356572397505175426434698580681752134340583 + 0335808023777690523056395860773496290527877864032944037336174082899748170635967157534100283308552217210895819668943595660390141 + 0793041940236886441234025927232106929006722186357450970274155143635586525537995503752589941375247670685666954666533793877981889 + 5778831921482018016340449172209749049865029154730502990831586948434948616688177219302113345681124510479338999307531273610240254 + 0006855309162866716967524960032543880915882390415328777432560766307982993890466192334347172872288555702927609941028091228916549 + 7852480060739012387300892561223523799609034777867042713542472004721462831725545348869852796577495340595446292276187383478785958 + 7959977096587753530877434044450370650017598273016702141156049535064683872702373865885204993323178473693440316927580843350832264 + 5711255434828429627433858416873855046302807982520306738509536092504233877047237492422270856933123651986965389822895956478482440 + 6861826464075028721520622101929991628946998804166738863536077306024363695385475918930843524639833318710346078946645157384213109 + 3481268732060383732986016495680958177849607099558634081654518008026716403239770966732475944721762791451888118885285069414233963 + 8027947110287197529845522807009685886470194904262452476975443162530080660974564750582146126181908103247560999247950332233807322 + 7124796294345362297022824568300955114164662928041497399401450052218863148267186902693402640989732333727359655944286809966607247 + 6673207022195790654496166749745020173181219341922393697843282922354805033819231485054350962234180921218558256719281039871046137 + 9465616068877625982160091084356867655695114307535279252535857794074660077470905649500203254845487633889884403918357791957962609 + 5439735864176545493786682348080515776951063552894497267405045766639566000474520462761676673185451169867195127044329565448901474 + 4077128683528317505947720920671307017612997849640361880751590889728513950754717072470243203246494346250198972938371059265537757 + 1744350487793132663117639969909905883135140378094636348689423577493817809958662291757247314354678873465246383300244542531431911 + 4940086036767442787655065360411221974038277063722727918083568388107313711402640446340277014461054034344740215045925518041320283 + 6681118829208967331321877862087707476476072276521025702668676229506021840555589912885589031283416146794110309804988142636941186 + 2405582757418961820523544833021078187732693088350227346014916968640935524755515218365262141583526578487828351593275991676198367 + 2826944841325179084380122395615301242526065149184196022148551459509194360014728846066978997793718470140240650758184827065285092 + 2993193263125920746329597500608467852384071869621346018318097029329594882972558366328973665134862355812606060309541457130668022 + 4276324020092753413044519728088179483413580580809338027992824022071273342649903541028827269643668077697566268171224024282173079 + 3298668219738409681902878367215423318085688425654045440812819269643490157963034537370434474347979142141704582114328144364074548 + 3331207723416487218945222041751113899922244456772815194220564328760009807415143846017951460454941724943113249362066483407691380 + 6952116171208702291147492954583173797003314720166450613568401114973391179929136073418264108322111138297086137222772204563421106 + 7600975435069311874768177860666996344740802287521757586619300995824931951698677022696322801985871429773970218124919477206966901 + 3780912628061324155929062282119787356103921261553217430966183645130255649596951891774470507549609157651291460007364039518971745 + 3378164561008341242097804088752883493567850412617992500593780122329644848355808639540910546811625908951376798420135130564695711 + 1010690664052506424047390590878204998037797666671722315517689809912733797153349697357764209138638827429140983606619452818262145 + 9300376547277559089699722018353829113301128665766029981150643108015654465357713345760938255089553063389045170395343438086345129 + 5388574617722177598048137212627225252667251794017646238607267836072085293351506292982031628145496634572585511875570432312724337 + 2949102931084425964911707872142235444671368657598878661624977383342922503912907622387561510392479663939836372865380891249214191 + 4125450850629924708967370485579795410196136664949644795471576226816969360966521409006096786481214505471016659590219454123795063 + 1052876846080196429866636468392224678653280363636952881423630013978399548705549755495939234226751546533383899311389616571394812 + 4742555980388054447437326569075723750771475897619661025765632486508214470920970384046022812610698865095434736181621465694089157 + 8053089116717921661140443537567547341019450706571788438437303262785839761518407332728972316994708287799676864196511854612689905 + 9729609228443111962917503361177873795233721041675657438816948255161968110343038443890530223545306466481706693430767571885086143 + 5688308264781028505036247702821583514666470671292172916350280224873269657299593653174145005772915708578064978186214186153683267 + 2204744465132776025498386899741825318473763441099667987231878067919021578886769657107832299974638025812458213339029056421384587 + 2941505567992035598339903647769230684834003209355669548196807243023989038563917277881744820709582631259852618961087166384306292 + 8258024223124059927265905619693379087206675705618331236606891852566067360854244728445479329673501981619440816785961582356678690 + 6012067901366243313604096658402361049393912691496270752442176761357212025454418262374116671287518874273805796136109140975751742 + 1773101052368269774971707329316287503544657412042811119480548137588711677240886794469483314479010931714923252443537409707971115 + 6673163431438354320152064250744844641052080216051967752388682876816416999627859168211126178210239748498710723469312339914116142 + 5806996877521195102255361656866436538966669931939141317697197556942791721788110932577145668299881351690980272915197702021298156 + 3837290410389303517128116353347856259353484969554892124616182205192313287433755106122400179494690010200326668121477882253979202 + 4517266820218197081941589722796747209204288657893693887244618207431797169277035145695561271253339157663193312460041285285239201 + 9619778362364427885644889878069243475033064627573715740274290928496163757241181156603865800841856421952950186816149922823346976 + 2573799739461267334017539893388809186322465134575561495883735717608135099991766507451755547789018617434096932254961072365198882 + 5105319049917763260343536285268328841500875349287045804710455434303605043562842410645690374572514107603618866501621709959657187 + 7151556358315357415841531703618215410583915203575998268810030381640117079961254114904804786046065507943854733690644791284850608 + 8204760879007736798651157366669090166543821998311590636584404376075249452086719646757979910467231964531015916233682304625227803 + 7147573127581292166990486442215222962358403851938571275150035153036061725108691622876773795056511233146161151053768550862751540 + 6784559304983902886590174698622574195988266824149602039534916660889368814614010342767085921580402597291566274193343471685906410 + 7880113249001482900851888199979393787162065292926067710104923584703156779327643300580458887132435255065678627456912854660490039 + 1350749751135031413626228320025567623412283741939627729115634082906593503710519533248918652855496972010878915554543211009367225 + 0004322455171197190670578109680045148889288778920452116958832375230435697820421502377733900228528866659062527967209953101213734 + 2911494504322931801753348544419729543749078880072226980969166346711819931480214331433779640233877327672317049984114641749562870 + 2396528513460618041259531318301991286281693049268735199694175803321673323893916691134629842475605991446026813330356086230228330 + 8981164060702124227875449453939249569083280933393885800497807219622718057632147355043854391102180378987437281964171835261740700 + 4207084959173122310540889440071390175078165835125695056930143838697501277302913507401666310496334451392319525169760616015349520 + 1210081234448921940981378280200458404260945592669718748037205896059223823726981351910671794263375996276697272684781727338912271 + 0029168415827572351727213122061796310780992187543596747141643738703113178475108090159020344233281790182332311601803329178285993 + 3777296404075934053174216751857062118469565443797038517380817156541529651488369770373411767683949249420334108704951789531604654 + 0677478972172417855596910438873967997191564526032435944553932413671467038312980120163881839182106666575810117448701361229089668 + 2906070251543291085920125260549397785656115356661440571177943054793731483489419102892567240649669779614310761600563474068066656 + 8852394653036692892038076417261650066148179764783605637155006560905389777668215992491194523484007340075319390767759607804494192 + 5467138831557823428775541689197797741887498255851810682591799669249141593216801183262480761866825456541084229589715596536290776 + 7751352765591319462216158866914539056239902442050723154683435064019845231969816008347645334022334350198037412040594819924724593 + 3021915992015948439763471750840891829476672656242373621059864369709314486194930162083489346397306741461969474457136306652660884 + 3810149798323432950565012468358334053474435740399651150333513841619654716521117976746459459286758520929133377210685994781661011 + 4783431510440557379639204082385220913253340902177656244399207972984745234341006126872839573292250089207868222847639289722379753 + 7370438575710728204326451494061012215276912157251877502908542289047363288154325283991522374002173371912625950441590135539908011 + 3066350412780717315157416276543477507139338679594873856557881443518665559120844101586947952288770461228629756299270909156776058 + 0225437513080408599402290104732039265518603222598728765215485627157659513804399230415740373980117223389491501554877516067224969 + 6906447098674865317783282853291741419024882827886344308680586123738306172623618313185104401579759220967002703474556768483264969 + 7905688354362418737693115373990150326675244455866285863285017259126406290824772728738190085605025791061658351412473817132182003 + 0647939692176384124068167344966453433916156302209336971942526032217331539621915101096729732974008611758025821638418841239335586 + 8207612011209373495228760846993905535758093646702045474203894639020884032055233069612162464709714659219943117947340234145019206 + 6685510574753704984128082407027684573335104766797904438216667655851315902097650094638260466258758906563426639941626773728838182 + 2859725751851113943873234212381842264933438665075493160334098268584252964692288511136721035397358821669241681360772178239556283 + 5410817225831141636647896001039576920297438613631278187702231335198482845481821124632157811564428311298381077638390915142518664 + 5603082383902365441423743060726658870177085955695406252400018823076710944733837738608757044351867174051742821082475300834328708 + 8478410686281696423470828758415498795393164508886616098722313596122431017415306773664281061410625509783895380848928242909573156 + 1195618788186485122683528679683670597289650244657656876407897279500115335276331331011520690820997358881740005917663903217514124 + 1469313024861648921401247135353735958071127626605430535836717325791385228578496115248025350543355198105506645012545576867598396 + 4272483837056013890177205566878534986867897273483516131338967706119399325076036529394304714161849476343886942682280685872295940 + 6971223873405564611431588388181753597862284579604627783908270991876509853907693857394999066866716324481756490631331601939564088 + 8692753456851589867469578350330459046916706027508903379244973723114291207510039578602992677933126396343784500936297228340222600 + 3596764762533798756045077959160866048043299983905049607435425529900440769757414376919342785743646389458775443875643589233861301 + 9939277922617044929198368291152778217422406940588205287822196961674791811253436361915620783243520085430696637802610907731339802 + 9987990017965498772438500667174890865212624587022291536612477503056361052627799082687991851074848222861818981269823302761583997 + 8147838382210431535807715103935094271794068054691587562868334683152631170314268604516246803968415953907592500669227061338962852 + 5229815249263579089803694020966160885001383014770540554119854860763174611534378849807683267399405523325826175066050422465261245 + 3718808810539902175097435162693814660278935973946526145133557384972950132995651178561319774914749271123710684959722970432994100 + 9959643168956842935132972702456973644474462349184166563719137832114600377784944150813295076399096859538689536653676932352320454 + 3562313742471254053603374767998733448940422800590796399248016870732131873285978468485675936836421845482343165519443520207502472 + 6212070810123317420939860915076451492474105989853395883410582273920108061505858814970010182505273303507369510379631126623445635 + 0255217936242316574157324758578917396184805700986741727460755136645033816635143639164644674079087020280816581372010788765004026 + 8089847944137656769780273194285160566134507215012061013579883469551314461311271302478380193931275275686279445049118291696625976 + 5717365181365376852569097535965171977412985242766246364289767242179344339616335652390309582781287529277190209039953388689399517 + 7041440160561255381091312862643936475613988744385378977312543669992877553324112750381702041222192086102659343479767405018249915 + 2110051683946677346707980171411807954606467103478530131043035978033107947826868347943468663705645386376022529329242653151632937 + 3379574154524802337331393517730441276946707038997138141465007355281465799683250899916025487713716291942082244114027843952458642 + 5030312724644064165890328712593254449923448331621966613833157539215136234997090424298061395610381815885285290455631522924868317 + 4994969373293084869354149476773798201740005462072247291096910619119410509333790774262072570461057954016819195195682237016634823 + 4014617100181465701775054953697719420102573860376968588430229723536957418028396409863878695628364581200214130204435051219695552 + 9995923662150908682939564279380158287700441111607726222291472481672861788611478655050339588555615320984584521234687823576281254 + 7451463346941792082220143976579354392136627715379752529027471716966012381538802459409604897867012386933986500209811720725405141 + 5447700282385988297313347229401494009078606483625633850809103068410968238448493407439403040224936061985927544263475630989480459 + 1276956495071860259959641422731621493130581830343261790000300846232499293476144299954615667025912420799180581171607386310558493 + 5072567626180671481702538305209899197776259094898315797269647260887831166441294066368414302707370453117631015362578331461379694 + 1152681127657219064376008724117880126055071670561685874051473152694654802783634954044854697360607744867225915714681210070391625 + 4963921877303857727536312369203728666152509364270556408792999159107647346567121427484742607873371889230959069964077737186080579 + 2539117036539210376394880318723799879677288248068497337514544989379323165067241670457629058952981263712005132132192204500173772 + 6813760519782616773952896216661044250831393786872842763541388164566337619519250295645333112400558661044316307967715017816016933 + 2537593940009216399181185307950727066601997003943463162691283637037387944868769661465346762713541328987499170590124382561225808 + 2775885197315288545943935069058879566010060299863101752754477420864624440405321494564586899592105748495227288314078895511070581 + 5073590254176183749859074321316849201765757369989203202482670238574028719679448337609628523768999643298161243528454637871645997 + 4654524903507892912886995134469509913539767744116890388991007614902224668150391846827264198768560243067636303891131378158227338 + 0324734826151939630626306117202466456571054839140771329647402994885021118469683547773949974151585727386291916309232652285623776 + 1825578079957905035730446040937650014976367810409736691475746813209385827351129150863065044732028040265416217520597270250595073 + 3855654215693196726130528392601924163490164258356468808028166928343554047073423362885338439044483545871577569335583661986547054 + 7793570955613127244841652451443245937038624291178210631123294830620894480548406463322651814043971289378075631025886964612359732 + 2535751039273171851827163526482017707846468207349048105786558968816006070754676314714316763865097547820424829616783998998577881 + 2844480806501005182020568712353744447818200854387376634450572497810731969576672980314852204195217762355809650187750497828976590 + 0779679209849300532787708183193857610170295918273464149221680774855800423860839661690361920242424552243626034568783063475060030 + 0715723560396890811677256708000602036818903166537471742271498254161510038321801193648871563911124555662395779532361864351019488 + 0796637275901473841659277764647010680246421160415288649143217531307967149087210418850695712273237810379507829287822942082290828 + 2503374558287484037225872566037347531382781922322502069198289211129714070730191986360007963273941619249637438751324038507743444 + 1257552500220289953409007738059857241268432142060119245938800646680659562080913958426385782354999183544917531229451796428251407 + 0627725746927523912542272514587614535547975158991752064909670083277315643027595358743280831654266470167938798514468394097718636 + 8318980485800264189777412075113224818829974167411737699158537404003402647667510002613635249834073904159437111364326870286724933 + 8736390761693005617348059895960699070609999931133577397987040270060440645814471436005094800905267014783073740415604380803498206 + 5542024002024944354928529036523594800851472969896531771028010643441490945234844042008320398276632902810470392426566175025658836 + 7031032484519885828134561441713514585691824451116624144085217816423547864679125010423917860268671111391465300826171047260397179 + 8220783551779338773320989765886440391559510492663544076020535514257589749352990988564034320388602959557187208585104844145026439 + 8020438087951116022977373383495534674635129594766601601387483705748972280627013851396530590121458524210171753315286548207527820 + 8153810125605918943918826453140421737748512940456044065444292520385926730447939082216173702077609971171912049413332448203544586 + 0886669881112435179401237673978622874656264303143999122578352317897806033193993865036799045024203333380525337357889563568831448 + 3748676570310585965679075167577833926365276411040601559021494474638574451420952356408036362315997810486031449429712897242856220 + 0680179178809075888645900355703866665848623566100723748395628721560414660071214664781095082893581316152736759533950009932003975 + 0830073511229116156443164078334884149650348116571315260656550335371524295132896582152314795929439939447827419494358066689706173 + 3038785789686019127115381229380791436051546935860047229508729818282744657378118473627065099573727853891404083449592265655152693 + 7387679714798835215773140865910355708661822160467627107526217765214393654304740207983760504979185513943991488603347106187504836 + 4959345618457216694880885929572868404119594959297665383045694122211724921300914575522725438253647266552305439505601459584619177 + 0467037747326795908961510775114924268777468775918327644966642534544042676564308146590029193764372898938024544197186375500357840 + 8285890907673262212647988009259010379723054727978121814340184295658072413264615156697842474728575585169324914900743103535246719 + 8911662589073033021628854642652750279152366994152376376433694906661951714454207190114956328995857009825646477784015810868978338 + 6105850627169563438884040914539421660727931317710596144077279839188308966168911142486835009941100149861369756674171355191560490 + 2993431983320455272922883788672722733898158280538086533775288120030297726075605253307507669239723828996651212708874872223213527 + 2383871203918607138972250186349539349163142546547549565946027359258489597478748862408648058675393278207850385093331126182621573 + 9149363763947487276724850656041160743708661373179229186384365572255499194358074217364047819850970764281787263423869876082053909 + 5827019270739581666492975342346328261479975112685223225619643483040396563898673337995672909483700478627244101352870984979237732 + 6998285824391825859392150613924432428270654497491969804735086552708299672203935039153979762171440238901122660133544046138761976 + 9253330844439113156612382643124565174653829532487393981769888635312756386927331059248556801164857640315799609889660186200071275 + 5612390497528583434894505132668347409216226770741805847223173711771542665456899372500390460954330204857624315915587829701045748 + 3597132578062559495102590042788395347495253649400865738509995118091093608521019322954235222572297567318636643867386469580449507 + 8425515407736939284693677162137557410259923224830338231554842919234034510500493129925331580967001474100531060588153614511993338 + 9601991297057389436503665001505251866564553593237174176487901010113004032749058341666775216970685449376017846133214652240838962 + 1863773381844384208184694104858797647539515137932214592371546918752008772143433088976967184397882651789039128762093118018510138 + 8436667156247339295567342218063358078249911156583296510351786615409192064411950727914656163850098232887122260394676405120111886 + 7683313388786537579802951656666063632278774842670516448032010207156251926218292168775800210222391153956472045994503212219850049 + 8209641417161775663979384085179876713787424866821458112247475298894421880117371699371735285979992519666751909878379569083863705 + 5145614759445599831570000861590726100099887859826097034388914355367729544959518374514940678332048394297378845981970826760413852 + 8761767120217732947982706113384060618324856798940745761981931692821487049372786616858603289668185012412091827806837321112104047 + 9255297129664160944098264261547065105677964568103165093339743646349513755899758152316922927563473869566225326724560456097296052 + 8120768832977744822631836021474402079390526097477803448973026451821196612519143995594879311933463926655409414749552006489267940 + 7017154772060236322937445448043347707331947096778317016923510498198624836901896034874919545286197554142622789268469355512048260 + 4180409321511968885143370514200618650235742405287713769661977834572569077057120974054874981770237845015640851329981775003008191 + 2674007147813616401003929214576628097932821870524475792725335810151140502429235053500438517449175945097953478389066531072308154 + 2478433215760250770512406042154394331540911914042172939884164584979797404189940441889258451913067147217070836370940898306980314 + 1416691061574950251933857581530784660502363969157027453652188159283670553356947339926944472421121743170291855577403109297001923 + 9846364489252978228078702013876774947354134510165101268064021721322665802683013959144338916544348159574015107727356473797086745 + 5487580365242793847184389294498037980764980441864399341257536426029899353090372478661527651346349015000812904186890490170512422 + 0317001187750772629199900746610544979042670580491329322209673449299816557793150957519344382208574308527216206006597313873698350 + 3641287214039996737900834675182665853779449596351604582635503134884649233644728626688852457677654231608768591360986911023898427 + 6414868015450446904060895609231719309486232701910101120865147273052264604064433289410480856555673255517305129013544577242362891 + 0524147637426415811762515415524550268148125432394280267631328443360400295790051752698236429135771292548014257090019134991791562 + 9227410989021340348714125220582535723860559138846179511512191891037914244234245126229571603923532773311387103298341477228375501 + 4041581080402587294355936437638145699274625343476210354812865278292813236740766242635378473283614144250925302804707242340663339 + 0724867859827673965725683173043844289022888248735884487800477685080844896245015920731492673699852061747889861151283779392092379 + 5909276888786182094219448158615991460321912732697015860009933234510620643391119454097956755043612428806923128306819132701862789 + 5863973408297121204616907602368353757254965361693796331036727921299882051062544545347637276552415740930878434572627384251645258 + 2609867181490019825132280383807303218611438271972259358234476006167125808789720811193408861105326321587061359193074883011503250 + 2053550365140441314774770422273440770268402358845803831349391590570354084402287239858709867448417600167758148787965827714400727 + 7156914133575985423380170082307013620095209686338890246264669241382877333719091759478776099336392938215841439510174135934515390 + 4831194527648288858829733221197151800308714018772578642206404911045931696147282373784233544435117870290316107286565703640910861 + 3300965303400428799995252612196866095687126018105212822125411581947708785019993474053195560005697252054488325120896486904066095 + 5685043938431323336868482886553258817526871549549389321696880672458619872963868160503420041705844727261813948644337640127844475 + 8437858633093280150489850618743229089133908480393577494682517449743840953324665700848231841040716763791338769325607594504384201 + 5092632498177396936492730922026153200701191354311511401621705191001018224605697557158822145660532720002740219521243300566753090 + 0884695364629948365817606370132571392316227842180869160712531089788912972870842630687441550199592940590099216041036498458331435 + 7030125885795773170445439886698551870214797580800884149092936799091801845209138388276070168782087225547258102113578759536143915 + 8807215865608701057987377248776702944861046260230342503936276411275965656745488818885694005475308409675094846381271540973613956 + 6869008153507650455021791206721217199858946589909935757514740552973399919912521587008600090842850454930346920106313925959869436 + 8747302342382237757458390343882591560184411401946674013753631245032512422678856746902092711874356365404625893572768808561925896 + 1816616401614372016489584185015076832989812362352963164309054653174766477426767816672229374164734973950570074316503361323429424 + 1677262729710288413972124464110274430459973064690910792449284824422312855723898793069294265613363135307936039462077553033385323 + 0904814204574628728334178723557725337676246503641550973591704771295724843533583760990530372617065538876854581885105724368370399 + 5318034405787225786821497050581659615205871549939335953839157390829611482749151979571742480565357809673956661177238715716708421 + 5050974915162203984880371984109598616980412684284404767484126024659745317958728060034806278671739980663056141392010690752871879 + 3910704359349884254016812391071406772666793577154924194799659346664635964157482006918898999240501149700799097400684650477119203 + 0922138102426301243886965897610590765176893150415296968278489084200960754236095696787157337789651225430707548067049568646321905 + 9034532106902339573322445743023271918597056331210862099117907113669633072759130199009133076195985791779283506809079562559701881 + 8961339360352958868430789580169262538709387737102199957461921100064868143051486287683576990974108237901843716454745741895109283 + 3895519300319620380905559168583475674843131617139726705719237185238119833221024548683898215318859806049104445070815116282206901 + 3205107673082159654286800880087962054713784047147807335322961266542952563116519811400145837980005316237797804651103815235446781 + 4645211086556795731679627686638624553276782440503123281227932461374131645478394881186841410205689089468850242938656791425398127 + 8527652116361873059872046061450470630778597394637649835734537239971727675715042761592888819669786191505268650105293343814467234 + 4729851960520632361339165114787166123924351946142914574237488059076517558856540707604936767815825051810582920267228276662907034 + 4922524498676764577221603274496474839043188887553906964245432382389882944444308052516105844797654740378920402689234115734188908 + 5209597697295900954976185802188459574638626316316754990028635919463918798002460967253179124238772322245122243876066379489508079 + 4508289933039159505453489164861720999217265104842659882479905333119333431390108947303039851217725991104705191344280222412086293 + 8069168568134508776661939124641765187854999589971548041638843098203486147656735371454412494419404765242018465434846607552127178 + 2927086453284193065980223266739988186690361081906781869605569767794118257589865157784413584255650425147523732344110338440580815 + 1748049647890769557692421227727549481557775151410048868814718985045151061237011017099100528551045245586497019590105694556854099 + 5925541326979395577276086387515399363166724218914221343444459910602377753889752768375789640169881596578910501727353216027189265 + 0670300499827706283025120061244353545380543254798985391943205942681540582832008582661334249048815794102101737939011541318568554 + 1807401946172440506670841188965007674553832019157741404977051650612570825055419487071388288683499429125090172081236081328128795 + 1574208400432062514192736694804153587958619698259830513687209529110862276181211516095950235354568516040903749851761677661305637 + 4121149896620030430814848794433445919918770329319490730619096312332656236065824412598168467443676868836685315118978623516376785 + 7498488621509709129976594981432727530944618723741457356588286547102533914121132990321805599546945869002131411100756554367181741 + 2582026542886480869734858959495104201677107827620049653093381222272376273695750172303884972292405628020932588645381010082785621 + 4289447606077369793749546092089501817143072386741950941157247080345113014329756464038358626070033871947884567651488044623905631 + 2542825564877135509885226287724296817068865459213301536696178082552402072123707396192496897302967815948042943248544343979991813 + 2226470997115317096784601264496380718265218871198752715837658374418501244345114451866417686910079224568758319235433015428196960 + 8662720543840647608329817530425275416788291903848716280076563958924728751343578053506896388100895823567897044421928057610378475 + 4719351914296817015503837199703117466548446025449281302558021903566930798786374684451211437854302542934198900108681526080958767 + 3447640954611982803365820977016952430036387460526610055495899354375691830575753318086903113772624764685535267168082007345740305 + 1797213012073375178436558221355605782112077809669165249433528557235690262339894762165301931035587761808175461223039297448962130 + 6950060736132243209446984212914140861957832417030579738364918001660026811196800334571314378298274260059705895036596817108824926 + 9243829747951735931284002210476722019445511064984030772651417194277223668272106134988724834976681779756839767862454568373306618 + 4177035873387789691442645602142232402697759139202124087044601161733861189197322918438352811683833924407803890384828993570282474 + 4594126055178872656922618774167034354795564094725497124745719061896909861368756961278327080697512762579612758334700763137442983 + 5295668887669717485226390123467973887358507953479829153694623729169375830523050788966597377361980793027344718171019365784257200 + 9888285370457729318303943315282858750583399490083047557333008218529891417381026015175475841289968239416942724745429537867737999 + 3215943066766119309004524839024701086312759322446215895076113158100056596170634794503064752363481133827922180405978563689758589 + 5959944414411467463305736849422386192090664596675188756343645002538240622043092367067855848705606619349233737685916244645398642 + 3415921462522850660711019463447810831161516098186857649733922254277645246597288489872824421913456035668900907466154510857353878 + 0820770271351282269897729773480908180216209552917101530859717823023591831191252679348064887785178954716044181664367902784712050 + 4837078657362119194233933526772924288995857318513107274934487922952892071107573280347076419494020490239809987105400407903583211 + 4566520950673320089105623215464822027247924240083971798563728505499902175676964769999078225165976694000667473401833118202304025 + 6860738161875565205941822290237567447513259073024464364524976929966835518792473395436546988594137222229184152759954076791794830 + 3322947265984158060992158624663708425488918876383348951122905125836522038089874259881383269124957101134232722838965307585611944 + 2514815461210894795746476799700740431234580399243562016925036790171527515771508119826976806830254109945111480181093741053447775 + 5733504011133442490826886677777865571712956442700084777358932735387221216646199198889278425501261656719619101527490023033629983 + 6816820665025994462583833453804933866931009904653183983658207938144775757074429801900721418490709180940459786270732207357575723 + 8952696642268346283355069787962809893365964014926493914452473794524489554221368619837559042723108457610361497745820672215991860 + 4686726618791630599619015305428791046600757619220375372642195506961581791667069381025833026424470965152344317512976704970780861 + 7817535100493702359961847958187008692676255354707895369219620793484182638707169828174557995935583658475438688352992259510602626 + 7874029548817067666626239631331985390475404826024086339339243583071276348104332609325698630718922399423989995185805657290031135 + 2250809137006081215712604683009748641626154723738138936917095298080941105465629041740614734952469019573555032467949707456686827 + 9015780860040863502309304151201467772727168204445161990634325579174702838004535428730659838209979201561616665321137059277802195 + 7650185512550554196643188069669262493680280748343975919639135449289335914799374871448334387269516977974949025899212288538454112 + 8893662379603774306702720358700430713868475310661351513479439829552220384722225613968805831874918699875259504799262267715048953 + 6970047041565543406988313458814942522252185061892588920654751003945616453031191382091583403673677641380943374412110595010134653 + 9871101512999920825593895837672777862350486799080847951285270490204712290524251977042420133385216867854292673426124017430550114 + 4761750275074356557669956909154179090706612051478635506091941757942400068895124161242203046266249256221284982009220935209300242 + 8708015446206142670623126732884105024418284851295914904738375122444129503796268180002105711502782904456582492253779456800326918 + 0613210293625239057781585677639979950255289284707390038337154693725678298193172844000279478330485593483147704265272812526895779 + 2716164189514060813320272610067774089300292554132648786501937337701166054949053895064937132503546260829302791728809439780621266 + 7313188607076954454240146509025347232689443993903699487707438769611328865209183398377855897661913914996316621615825549781446347 + 1784361684093575880030474001414660619024654155783784777347697077774197795864389624206377564266630250281594010870492871026068899 + 1515638387019036333906018359538519902111800466842577317066502746814101599618916383605825219038858550204877062732542814333739145 + 9220084992150752811004335287492444508585899566926596972214201784424729857471199982968054884285888711269768545472118962801716609 + 3225729665605184922610258057387753797602084282592399424014307116412082926636660405157448703031528431483170813038850013412917589 + 0896837209572767267939653527113544043129466184693048843785638628896239995824306624383959725609177449846462355536652421863726297 + 6350549459745687058464464835566280558244152696093628407065101518502946110700562358545869437041517797874386126356678480069546762 + 7437438880206605630925397821472561939196877744334362718590301519068712375301433711985727209285202108430567240861306104506294438 + 3997013218626793371442945794751768102167128014691257491799130532817890787884088430906840628465718832537193051422942089432586522 + 5767261809159521411906210527732505137517003452232973525892796163942363843586179566469412536807588910846358095073973053136806664 + 3610420406657475104037145580225980872688624964111041381549594329404718245302720059446156211318636072750134363504069278172819616 + 6203445793416289171078116228949526537345367573758934511473904862922585007326728074024526181186924979509692268351022430367531902 + 6396903617968213357545062076755915835538061764765669442173658896006627193712410945197598872950553456423579139305216599382954077 + 0380250815827704962815549731957552434336266476872009617222288199268494650352751383734703683895685962764217150385921949138345511 + 8687569627504118278687806727964146837523838460065586633962532325989849682060922414609471208083225295893531164710651416235932804 + 7419608622045901350837303269139752477969857182975189849619797931283834755645259685017775129366698872709262322484867769237487261 + 2446574648357299934768068561355356119075191099390351323266829442188920299959413380468532819783426950868690325166385302101461953 + 4690378580819708064900475904899019106498140395743178471011674929320871266333196561704778715716963538368801024314408279647276339 + 2089232113041890885410086998151297290297216269518414003124742833718798363559663862672468722436254498875698485622178498338429914 + 6550115139019878137719854465346267455296956376622672210869101826618943385242099068657285404811000189142469975735597865828978322 + 5550336328979484745931555695487878550858216320770924583332798110114879836414978841309407295358874518788123614542792919395667790 + 0067101966073227418786203809533671075851186310058420930636457857938955159488144881158165188969895896949949174391923269110027161 + 8258211496051765933329722240348370716824091139227581167499651455166693356343053246387421021603939871942981451611393932490380081 + 1143232998448167618984488431281685110452032295577636699995232387576558530063365443650214541186195345336376561664260667081107636 + 9153874053518331378425571758003432585952239206770799268110257888073536748287123822972824857968518689632999374391956653833541643 + 5746454771428065810576182766708428737462219904665952012954717596322305804801076045993811560187169208752861306869132853087960769 + 9312948167988600676884786283729313554222793557251794907465964089218336400060941052967060271657136677975942167674352571570304004 + 6999898093303477247632176216594681728525645905467929567402604064471637964034911185817952376210008390273053006469300379255866531 + 1000632388106711156678341302292429215991586500122697419661097904387224375829260375948304920442750157857268831027577641937349960 + 0561600453741069995026478401094735925203677529242298315347820295756013844421038599646676315356655360880496025651231310731701615 + 2967967299264819933654047107088552569694325550743639578846283279457367587777819171468331383302126179626852498959303153806267304 + 0993137404276474214149260182488025202243237418254946278036864473980040065830274036040054866953015031416924556900973301250401325 + 0611401987313671825312920644599670850377089684826838922442681491359233283306670402386279700142617583474055662080523345059224691 + 5939710996631567268204735821745742750433473750474145824948890280584535509141301239485088599010310179272128880118496394992466934 + 3357460688499765569727929892732936606129832020628130664357730146150594561279515636082352905831482949527411745350155774277195108 + 7138561333287682465057643618887421608272303910896561253448290571853039520359195699641420904384787139962581486218527455895010235 + 5098065276517497532201660511210544476729427289544804994012760004734407796257346283172974549503877915741488118551582294732680387 + 9918245303994525211620190522775746453648980603544567886385199869862202445674868474533709002221515555801308081350907650459178667 + 8721390287975913893819238889792260446828081274233551710328471981963516819510944667867602212793558775770710289206007250029862895 + 1280952122455041043530594319244152931145497436315530258653194357643115496210565410757613267156777417895715618326341142914815577 + 7155758483619829149138641241642134167637824757268284393191488835351550697663275036059641871170325362834558782380774852273848821 + 9812670602301209189800121141901793479005817704022886493550881027819499284489381378125534965938777548562514868791510874667018247 + 0362874203793328000664031717659796956361927785166994482222033051420000873310315385500469809294516134684467763731164514267312822 + 5076794324739899424289073581881385172449093717540058394689713271226423655501988369216296397971568827556688651950460247532081671 + 2211691279142831153117347297369818334578478434502829176759746633980926915557525626263924160377780019382684610945724739361356924 + 9219339881449560885105533284707871200679261887421531149034514599874409542178946360778835736536874753087132328398630153344208176 + 1738323078966650030040964282424869456011617229198020575179773319844636313591780039750411848469791355249483448877218482996481058 + 7662725242856974627520011178425574682734942204257582618062074645522175607162830607624141450906516065750218377963070171888324843 + 4118042284044277227029777215730052173836438075783336538165120621022353806541561734384066342123951846452650796265263415816226504 + 9577454228253953925531431429190317095770965424733462598360193026659796995068726322946365945449373804244913417484873047389958047 + 2530447003714965976379236094037411278014717964765934254550861704945379408174897820528178412885512242072953354276409893858269606 + 8161920683332117194434729439905850512943519462231619259091383414069915670154194411541846032268055950920748136328515080957772524 + 4455001394112823835403683958904433147118332238523201500644925421808301905477707785391327088921953707802405649821266420465223561 + 6446522347006213132203935166470869874136295692811490433897687621265910913874552752126752166818595258011990560857727236113871905 + 9408818174849694926607806886600067803753381428797382723099805698620415041534972953179055866017711870699147517868454045402246335 + 4135626065428509052074741682443536368971147858952760160985560880547769122981012756994845114634562103177568847660082033374741355 + 6629483302659977998713743227246471116209038004192175569114510152669193408163108052671223081581651955384894038833735367319970945 + 2019914369819713476232512996482094786229436696697562766992595975532622307992117773104105916821954959122045124593739046172932273 + 1444770368011659028126820519729159232409884803442212877208399135578736969682832974964729860145229172744181374244786183467104294 + 5285602663449673777986234552062489192832103368544537902433053581936823853505740285888319749907423551259460167786803225430704894 + 0644806832972865011089771228494426041526498427256197014809301589227000243312341210098122668991020924989347084902763173739593342 + 8397927825150753855181618641584202156450292633924809550510911217351590362959737037094558684222129548773410325105794129798697578 + 2130742130526719507540424131716191473755652175799405630787752600339151530661377691130274509280084673031861647779131553466473489 + 8949445645797314751748458206320095870152672752275260151260265707878555413048057771903238190200758654160960860864191150393477626 + 1150155207111417862229200794999414320488018094694431946879621916439109486610009948685634866137188097525670175207351289611083094 + 3459879841467541763732336521769192414341573430800023957612803685733924880739274791648569413015334203212412056584388583105695911 + 4207107909576145869607620085461426361544959409669769028641359260476393776996951928885197026584290166920423018039379739461412804 + 2471437021597594937922441016847924078362096363319644062767483944790539470640965768192086646725793415577156194561524796709562342 + 2281835051710898850388364318434644955789879751829726732802303436684019874264646806723409567549761608858039525219541663231620839 + 2007932711287625313296243751903200023005400873291491556838807519342296983784742524733445763971687078693207166472588686547509634 + 7628738900800911617227705711930133205924637233313615650647097515124961199263711780307927527262674727498690057241315682922136505 + 0493387404859274797132212785618181333173806092520644500400240017059008198178246301124430115868753110589721037771703980382573162 + 1169775643061410030855660308847307357939679557417322697395889694976054211267593984893969933792226845025198715121269754643254572 + 1728088919686607770305974714811474045083911324960307426887087611368014116902540202262357011208475439646884185432232498389602471 + 9413509858059972641349538923181108900150612516616095667778909942463828217847216087159443807284569471198894585206492715160193699 + 6728843665008266563029199158801993529576549886997200057517865461162768723429256920925422142043184781462681238742660537092344889 + 1931599731390297037090231505612731169969829636622229470099002019655957459951531223643763907113518395449915860761987492535032339 + 5034107674301251502545019517381773020837552557746624579624919732008873147762835295630900229992866373514578020722517390727520774 + 8983019600230774694685639778625463724553591351398381775880431832781553934906986888770789153951456721760712116772577734503027958 + 0722579888130638672105073329597090462417149082738030373661949401575813793082783579270436569787902655097641040401368636813371427 + 7854245354370422693429496181630052949425191073877308843275368739572310979470712820505147110988781661197587183674125970895995542 + 9743873036934859621564820909920160132335721185173809848423866981847229831790016569684947679721801847602901060080188329396305906 + 3397337816832712119749817143233767742905059889912076656163289731022283191890667300707504214144077245819520343407565716275839778 + 1635431146179533618869624816029047896887367730042516939278216433734900869272992829571445669607086349418935403567352277456520703 + 6762725385281999872315155129365300727718531348063401770341896591345777984146395511533572557918080490707700609701643325567678181 + 4555558906784569913680220888302706502231120206554070127879841389783669163314482027219519085496782129580409038602612227824819543 + 4625553964652973015688630098326028308371988997070002772661734916972323600534194087341555003249709049635157603584665553841867805 + 5469615145572204179649517877754736243473051237336198742915870594247954290354530866927776592105619674425818013502199456960100742 + 0688295929947456127268347042202884584629259939771429635850789571181349570944477662818026788804604769581716692572546910654441173 + 1781053017263760670442837500622338443773255350157040419311002126378320391255428265011649731680948453211623587016944241093429272 + 4424881884807343597741531983608658269276205760340198024603987236049280398955549067330598233254907076437393855435114528768763737 + 6402747544261459973943024136936806092529416389402993987239813694282531255632557296852083229095761340348625572700195393957513287 + 1528386320984169104784676953231416483588713316281109988780398093348714641247346320098277064757682809088330401558069087928359793 + 4836620934876383780592087107373057072272745160875663949786761387509864704698529847777036861011698566433232612309834845364039380 + 3575337583851040701388845815054721473930456788213430385395140774983959957647809720764167375524924858966015899435919948180069180 + 3727628368963430480869218342563326331182798677393171005831460902561217359479597768311004931085102290184621530025879576836660947 + 3475800984573188366693910563609274312878602294132115102801727644998770488363543862638723091471157432089891694987852322137790631 + 5023683657353497036212732071088147337120821028934424904568945720202766911488162370473709710449329167955152043455364639983165681 + 4313458074953427422966761496213154547288857367926863109897916806997328848306557928981283734566043834603735209469550380544603011 + 4769534552591442528339142072463485535584209788041390319662187991947284630203143273451030277553655546597381665676996289780792291 + 8029659403865541723176070298858179302484672898090770785814054293418165410123040143090326214914018331298053460618863938939353357 + 2504331261837289138046426704519324433487258219679900506483638261532541113835978749947580235779347318410118894160450785891787503 + 9154332931976583483472163920590162126815140207546760699499178902132160947370072538150136322051659957346811166868803166980109050 + 0222142484013400331297859576897114613785020913334195683798252363342695111135735081039945217905782047137997143182303582893239120 + 9813120425348259494442258981684713118897639132890990099359593568005985530954284388860261356040562648449500126432442951864251191 + 9491055336614888264152467342246996843863880300943314768116172425467094897669780084992632583894436406804533915530813948074710378 + 5125880262000217074108251922916601396846452955978383367381037097928649700928330600429463193168987527289334840125068384753709726 + 3250963913544985283516074025079436289530032965000091704733601456641384410110473920750483277883697522865698072624602352586775278 + 6909533273650494192857472271669762600062165210442469141500817398520087420757013742072500281461753556164642072928308813935348280 + 4807129228896091173010215184046472764333315290810434138260279373142369497015166184160402673619706065463269358547161491925056454 + 7992119117554165493880872181423830045252323577778753354174393490633929436643377607848377532573742197373252323683113537849603683 + 8841806293434459100805456108210596607134914383853585818153512788887296784056237782465358856155449499271949927041469376892328564 + 1632152697497520229603928059316997370226452543375632335002549957119486189260078571706186257203470953055703949967851861921520731 + 5864396596718182058160283419308429964136934231008821382389697128204242562370820069167753381761875728312424003987892871207159646 + 3666084774918882500462621483992172725824109862896378199142479129987559328773744933469602552905906375001745899273316469658254151 + 3498338535962144862096688449703329334091149790999664223656029226119319000718124150843673811902580542556051470065598276315050434 + 2588642538822153267060185463367170199110995449008021906678609426788891572594252587471982661988824671301251499893937578926745391 + 9319707795744627065170409664872689583830132047201026242383522246999299133923376128562725383185342894837098008031828134646969110 + 0671702811161136021518386108886822361915633677386996222331112492876474384896788653692739997207795179082317779078270838374606210 + 0529680562308620614160670757652951824510508056181488035417621544956335930822186390269360882386498654576366806627786546389748223 + 7121344007162987446407144751532917923911603613369296361423444081791345960568825786153422255467670330488573438324604236300940295 + 7856126749900534423962976560155869500794418586760356971148877729423323229897743690930063998855496652306786264023420507384957613 + 1115472217398806310578221635364703110916537667405172225846214402717552527160481181622222803507823937807179294058810167262993525 + 7733396618045594337624445678237438829647882527257597412143681872681853625778555809127382419530057648275810262641644934924071181 + 3613929384294435871056622853422519700112176582857461049491276578382237331260522744886532614099866550813707901946900039411643678 + 2471863854966531804604197010815017888282961247506056635263741803813648407515388558830396273074055989597305977778886391310447068 + 5772682018682680181055188634541777077934406094474845232952841473576584969574909042981622739932442934509311768673906919851347223 + 1971820335809415226886329944736554280331033759806916931583970783266805147633904060778157532814909009520404718412464333929846412 + 9304789467519446866413824868897777103238294214707967726874145548954743749977770022421296628566823077488711722686581183789601459 + 4520829387352906480220193366391017100275344244933837568936172706668016811057327408759076674979685576296077953383462420493700931 + 8246906431343919288012465266462141639350962646993227082304804964566869105156074039984736745415005176673660764795387467919402546 + 0186162998111273052854513690953012281012706484313894676418003816742150384731546652072390520748548343581415404883693106949598503 + 7407453409468893649012012693295080963235028162714227398127099455397823529445343521263605978197734068303737481555026299674237511 + 1229395187707069269668822522188040767339600015117257223444650130799671208076697307072988709360546665590067811729152682754853792 + 2543283984004058807502208094435749036903952553879602762556029245920852075326946498509084553554503835502118795067551626235164267 + 2007797747581357604343336945727914338356814330722751353631792234077965818274628997502349441503414970786616526353391356822676384 + 5194656346701670632084824377074289402109258239302810982753490912710811175011533673266509733689435108026608580234617657393376969 + 9037146495591802460947583581948869619219502922722697707400434384802310554421740985009894719409552319891457897233615461251631720 + 3990697080273078766162376909117528749470352764935216917028329174981312070290561402015804824976866738329336998564205666524939715 + 7848352778978178394189920640395834604512765967920164240559275230242580756053219581598506048812354481467677378211973577424576951 + 9532477816991813127692436491685156204938010748592475096875883131377908630365761647389532075843048673325944084338736570456096797 + 6164242821944626959915759190590818947629953857895701779138738262444662644883838599728736964664029753263536337011632748825080378 + 2817015241236739478928849304183816788634913242150862112550226668153792859950263630837585979285928908928017849179569989536100198 + 3188299380080735588065637018955883708261980780287989654193640067585824757814983887808561472404025858752559638368589207857289458 + 2148159553153805396206627740954877447246881212999958661604167091735503989349952300666940107138834649908131455364478740204253214 + 5183812867943299697018327767670320460762394440257519747758147645570356514775758990004394658301628734229570022912960712413921130 + 2264795742893091605616321707447640168594382931899898384410937459110317820561426704161424031904340033048159158399357351652777596 + 2139572365125527551258839222311219599103367463992672950511023648604600231272790630354961828455031402437496547839035832950304233 + 5563173043827945218120288721053385228256759107947287607765533263965688120561373605092351078219345874822210656978425318969319770 + 8518350618323036588967937820117667974812517069373788130975907844737917546000454481446588184420492343516807727330574227463796535 + 2208092079415381688598883619322045535433174373692220944523386140424053570720154062384759984606718110454232154813303857905183459 + 0403764445312406400743177177292964855962834587085077838226697948324657642954983884229554291774482754430895940798928630071520949 + 1218078030268093244894387180566099112644808636942463725970271185753041625812549630461585448271241111674252623627152709755765524 + 4640249030477405125378434884747349008061139769305596841781606951188241867017869136729477063722445205619856063985162910427240398 + 2909590245662898324814954125183873527735419113049232565629860534526664160220755933343864533662307471463902405211409478015729764 + 1532024154051612895466466141175266647835257739963433595273778351297990606120134172421391748505385924656782899507982823237116066 + 7625676430217706141880242765715903813773188383257526213002250997251341961521914541749167347954676286972265765550795698115431540 + 3971204449523415473814450392924406717851351635913252062373246080376997499866289003353070967905385783507116089156113219681812229 + 7080951492315882179871809720207741914174481310077398153033680591523295504167580131795931815413662606081970038126846874489797367 + 2964040579217611595547760234190477290346436427835968877980338437548172752209833653855504469466390943293257324156532489625950388 + 3972616808815375498057586682316341344883202169607183819718037286789995473261003288017415010063837288806976576286819527639032681 + 1290138051725002391039102512231630818525813814320415691425261417707087230623051869853213472687397101016144678883680930245168423 + 3850834662586016207855419987088023334696460550057253060411826174208076438814838201928582833181083830814307068201908029863175971 + 7944749902703521228274612063687297856087416799604592533936372400167341391775276233906976252493497295192482610468181988345091916 + 7011096175582468584236690812621406307216715768647084636075068364924266221366474623044001441060540006895424513815585241978347109 + 9612362696533734373153334851655466254197093486211639205861389987966709302035551682330490724447416578042696870553662285651851441 + 0111552534765233442760444257765948564305822466469203165903339169326584537556214779726091179725355707166736526121645211226756106 + 5885039259881836616302187141071464709494663689251644989212209295897461744225634984400183422383926438027326803031066696585257111 + 5396579069429715251643225942479087285188610492026082322649552644481241838275988175206718743351678720472794668564948833054357449 + 8688233606386980591001497882755114729508367160997540301693192893291539036951478433163921320714186025327605130043325851253234451 + 4872214673472278544834646890891722960548978190052377730643946484747055518801507106492936171927846554906068388153908514485343068 + 7214840374326612339276352609419398397127314205763710059777054421447567554750695002090543962570373028396055745121721373269382936 + 4524482436241914482911352925071095921316760701089039169544052169552093783128384931032814298463081577630793680822839743941613795 + 4223734008339327317027315036935919017365387705335808468598641390301926191406305147914145568155445735877807426352454856646393111 + 5101170944379204574558835956241764204898906557725918071785044288986731351021322301083120247570462572136590876553271594974477165 + 1498954940338463049076496039744592188429182308195708965464178219513192666612550201124332096109168498851228361187923717360547190 + 2838593784210615507907908324852279814008797652951109874718831612968151452611605913542110950712021617053098075818112497307624799 + 9381906333865113269293243176861228537211612376105763917319466803899016867981408631123044887142147183129506705177986309824780722 + 5409043531218283220619747469806558139995337403975277796517573718341286548125289716392847076083882092014379916668361163684338425 + 1904893321014375227674131798347455361695847285890504332145250525132622615658888584205703776156043946440538442055020240373771823 + 1351830991497076875181168528408533516757044944191964801761366476485666222599596030732870772285002472325833568217236712614883027 + 7315021210616605619597435420913698876375528968662848736161937624720303296895982028335232063555260929924269983942028091369465040 + 5072200871530059327653441988927547294080741487165355628851444397293608964873155978474929308924899776875776153220999350338874781 + 7297806144047991652107617589673777407092234699017295323732250434070279346790076112443512292202647551871470787944370705490593514 + 8338680194506251068070541345811382066184901866943035469419313397753521282182668152084983612781310002659403231835343007351253055 + 6114581775690037701739519471149107309520083450078485755172388779153808947468636573364766942355736298359796132744647242525151199 + 7574059840087355237287159427555431111919013708861023222908038566164641505519732443177083128309239177653941203870945389834998157 + 0673474392377001399825892148070125779937209491690893896089896421739180565135864053866800087116893052683453216209088258021309774 + 4693630023596081716394525302256706650097913048822663453433130852833930985337805085115332988734054335391426675730296735748012109 + 1093024463171151726057935490277564245957695353097684106836395483499057575855912524860400186656839768087931489404973303617192884 + 7635877951810419014091014411375539957398983529537012020519286943703105851379947162885419241335326379003488660213681674994537920 + 7313912009934610962402221459721660669217906503605255214027757570091733853488694769091622366303142874602414314687218525998341547 + 1566050559171006939210753283371737704974135991991141945660050193578931524036467433476181347487862613613591250793557188528520720 + 8176429431061693107924500762483197651311460029641913001176379201100638867103309766025948024030323914130084770751860668764418979 + 1729648696441840023063291425166270194908270401060650039064514332458826292034060316832564595611388754933869606578691497545240684 + 5096948893204927421293649874213362565576773971352082850459718459918977951318599802521678656926223913450782713343578245294043312 + 3086541714606171194181739777107223773075014101828171109460641650405365226657056099487143258905930679574237317845176027548390939 + 7740302926757091096782313708390498469422515280866564744352174072524950077317896546008807496266670386420521998084434771204151893 + 5027934064208470666653625072824590692528078583512194513874229573957257382460729248431045517338285948895199087965965424240384379 + 4571860754401274665671127939865476298997613160622025616980368067727347277864838846767268485621173877779887690613158095362529635 + 6944876714447267999239762443038959101083236381747476636643523496718859843462703424789350147757356429745707937022796547995361159 + 1608685279655308172831370710312433300754386599666997983340912162248117716366440489547493562293368632280675661325251959965144367 + 0470115155279779686716584895721905617913807392365128663764858517955975388392843450401077964641050043314321327171303982059553970 + 6215103349524529478271694130462996515027440018395285605756916821272681672383831564950333676633547276622946473458222960324229716 + 5752661076880540890733587009248458903926085507327954333035749203073156883894621881819872469950016600034383209674501094959670531 + 1945586770541986321354980385963397070039734408942633942296911586196737659678600361467268366772660352728384921986880900512427348 + 0224298460720490332231265716874929497392701347632450314627063512555464017409367105505507132766860559659364230297395631822230539 + 1702023132625842749699356356536784362975613947059773629978196487288877402990298821674431326788769352305708774873068640207819256 + 0837874454109632180336808361233189153201698197837194960277668995755988025271886650717010166150668262322432532297058508033324759 + 3169311626099247379274799980132948823347592107280599635475818048919814215035606030291543579920124429871014029266938736200412702 + 1914619565140979302991699155094170839054951976790499833713849411741065459327090513567799966465721776223514774008243762437394273 + 0284830262288056137733605741424808121279641702537891966081045603173960192239888264018200262442793489277094386722616393425116590 + 1173151387211465492751444105592198529015440250049757464822160661232074007786672709170841572180341360083386765961004042180282066 + 2747834197332941363146926817441453515366505571978984487189489275517487274745916049268403158626553738640115381387510687487708488 + 1958762131814281375452347210594453320648975262319481726099981862965271971390001963271654018154213822420613244796687794506233768 + 5861590138913305751605474142329109238465204802867089486028021810232894377402829167243953763417451369079334074531476305390636648 + 6931736509544684644323440543056340368361669695138186889701847677102848670844548402669049251722131793379128120867567738961962646 + 6821092152578736586590175476051687813270318648206546383329391485549308897384882743702278026541948728683530021908873051239269012 + 3127870261792191598343155115866595959890760429348459173942873213248004394755219777755565345896164898508858847846745938219558572 + 4104690546998169355396414252792133064383123628337383872945199098541769741499506855287626343383400914652705990644014540006261236 + 8792100596328961741396764802811919634888917999468524631681735602589600555328679349075778614192998476904702613310979642799638155 + 6734793674993705010403616483433595873080508573310753327845752574399663353072797746592366100412052447212721125322772808600316385 + 0099515723538668132596125963466202152817452490708599517233532239221132293841708379481396652887673374586403485713968074564071453 + 0083805755888358130747915433250146084164753782259744459712819051842998158461581619972310157769421457011089633907439164606444507 + 7652876608005273562462370933960187647117519619868786042595158425921249718553500241273244226393132978251127763667423654542879946 + 4405249132813172389850479368504130884719811118887711374371841091799443512801595585892341132692059703325567321860246290919547167 + 6941199045895501309914547487559727954258599982156757774973817213033640726217789962907551298312065690327505399614397188477788050 + 5358645453073717607933338901589045055393757684759513577031387645637409945004898936885098068574782470685593557377991753572387018 + 4706013177574137609818422036943485331576839280415982210652357962891328244924452137995064340517319656166353370990119146719861836 + 6329505987385677903166233247184756000826411332850477352758018273420949926789280244169127178212529891658087198774279941207714390 + 1511370436371213645604523617727839098695940567432172783593724006252095799407942743832278211803447800402891197805298593983426545 + 3022464264863164058488714249339098231034997516428008392896433897781383885524218363385806736382055438093644340647396074293733782 + 4501101178543767329620885826562169899606635544112652117620964836027885674519772391619599940633712271697963657935450955634525900 + 6375010018855545330452050093482150077359764898798182405456683026765532905675606074372556178229924063905296358938093169081598198 + 8483257277634207523851089755598501951207216079577367620523344599612671928857960638762403403726285770712060711385777082614045533 + 8256451384331378443868986535492407706512110875647453641525322621598498933275339800741719049869908400644823204415096675208523961 + 9398321546440720870569872262936542811668490033035472870984698676634686438176528523891161540254323161470512628073841436944062388 + 7797071423711013392162710663609589623668119033549706301015274145920933018984092472146696838533855941884096071158160204252589379 + 4261414209517939560365542448209082777049757262017603674203052224119028323101718025778556206926756191607192650438859403548542695 + 1466289085237622991161102650836935979121797669268051582725264475273671975785294342068745493084363600896894177743687712147368123 + 9181597431483593985916614200861015600827448233462428138664038851972627461175903260548893373194383862378492912625568875647273959 + 9257826929421951643418775488431746425388390160227055490497812088985726596130954189607412047036836095076045019637105980229125135 + 0051088814685847441269344262748461773674703937437029964258894662753422844953047676499113437643607083551852374126649110465539183 + 9719703193787962011022241398606941751940065229976379345648357311141518661729448144028369831751739729767389915436519514302519528 + 4754705205114290966030322546625592332320235853494013451121235653943274561055976709436804717429731588488742125670116982095506624 + 7915307785043160782062481393173682663021526076353055172054644485732609943157735268019683657488875580064373381138013382280006724 + 1348120551409342824081918999927191374394809490457882851229963796819461455853157081977254041113267197827298870478281259789531341 + 3812065821388690082091959389908490155933727232741583927718485507099116748923648769090644447688804257458798099398350465758474495 + 2937863476645119756329442458144939324030284617554341982278719802555921010666415523070911564773110585363083165465312366738827231 + 9179756558387423308702990244249813252311594585173041207944901196092166608366163256489844497165091829615643175666074910233765563 + 6459378049219057988171618077989915820678435345205197081776728544947416949166191536837274889454949606246062308000247423136050336 + 9590694274127077084581072678020481871509177233838867384578103147792423645131300534630220077747270144036126808318115046320973761 + 0633314308759908977900550446703882605141401119276147159777634200043370016079844602659915203435729306675829065339742126589258345 + 1889317316284541412519941066954231638054475095114130395821846044209964998882207473650227876029465587838652109009674311273487678 + 1491201614697119361909884499515016131285970573442170426537294317539659125369759905519191669796894139802704690179128614455530965 + 7312991894729010255958350913145958890797364015827373553097639087944419042322472672141767845335817123220952073258598944857610720 + 1824787410780276399243095677626477613009119292679764840577779945279669981000204638159164277233130499426714911295485793124165881 + 3599221696151384019695918691913331345308102473844702422853474390767392532790500021180165318933884607342905862054572886894689533 + 7797578535955366187957171752724494492272818965402286074464704517072955420112819202222670121573771410655986788904078893257371168 + 3476992235872213742357632857624847275225481432286353014243838356580086497628026465199448029895990288276361657184717108337186384 + 7666621551208709893696388991140973902647787737649797506777580191326933697405674502023865297304974748640809764705859758691017754 + 6544825495307606554357924631329747091007811292348124154567821317868772060770803350068486092232254680993513246201748613742385991 + 6866165375349816659160016479507285079045466715841081115993221601429358066993308321907376618487248492349626318569998572862307928 + 2954124850369537534496609519161469912394832203382444510628904117251662671751490677012621979800464348066614680001698354593940135 + 0193499508454379205949576005154484505543366786538069430200252986165917146991374529470556848495722371613024998552648030029385354 + 6300091436093722524653066330745577837674427424963685925900231612998930766803747751089009018089480544176580489192755004987058784 + 0521904612577648015929532704786690696377674858853171421019639025087849558650954768145265982042719739087464082587058116910545924 + 2995811242507764873679857631100733041164546962708369112790103328792294311269786039292022283070742012101949352297665947227182231 + 0598910805263795572231168128611351576632001399408367899641814748409013513401170040370795100905848171920487777572798457368620639 + 5688904469919555388263250672582090539068694827337359228605791133091700320455439594271216798892203930514646320638691425342088585 + 8515424974655688512862245643897078195523156507477939116050565619183311712594098054858317849757764852624936019665610738326843069 + 5113156995533534391502169817952742278838176530218998980784387996273419179922080679783505603663683376521615832986618021979492127 + 1086319824275441488370793880965889728722603318901376609034648244802721809098732997770252918945517263258021059460064891744542026 + 1590099478966776519298307952043122519324124336024594288380180094489716784777893529727657815697554594607079223393500535902031225 + 7357641282650721485620638312466056185406173433791953981763404688139736645500991900862738958018055032882772556895285743906215162 + 1650489828204176805947705046005072475080530548765982426627534295084219207983407930870882583588364915870597364960371942080426209 + 4961456796449042167841011430036294492463136865448894885627513655748299627165496853898722132001299392052298889154231937053221092 + 9292679093929935825812492666003758036634836903177775163898869080980492856814299385978432904050294518519563887081873640579238706 + 3011512315941368814678516363524198263828364895022582836616309022291899256400386653229758118495144379060943664767132561955347093 + 7994582030787878507087359159314617931782658556072425334054967106060186618004693028010903789497198319676911594575116984344480865 + 6353605238667338186351983657599555627480760430658384201616896420757729940462911589836581183482303716623193619087127242146945823 + 5587627832512661518234488087236957525879895860979271923639746468639388295216331627000259398878042734326931204663332399636686573 + 0672965511904852366825996694902980930309250905369947812120763277890579450585046143580711709629358309790006863408567461111578107 + 7579999047873643551313574662014234072727914277127742448350969386406545430650595860664380236476144348769728322529154001617830780 + 7768720905776990806878980911933213548469388055876623124525549575902760321680062870410042191450149173795942693780209583496274718 + 7500581851674961002356261345542689400915034872242480502581980604450197467020488142845109390383270729947278076491900579496982299 + 2129690101587171429651661009917402506767801016536968984813683892465052790569498753467876499730105980696506174974591421872344509 + 7047018820490212289369541715584056487037206133357581281018603240803633328043751106808274944483601431153046581012102597333076902 + 8327884098495349573228357110403653478827808473415101824363258200250596339218554185491862934594792362506926494486378909931564949 + 1740056330174856891125669279294923651309763604203532765617783458152533228430452541997637109088581841891669514331609715059758968 + 4197367157825328214419156751555885819747937310581379204615061923091469679845199014292435432070508700023932922581376409143095993 + 2165125379005342133424590972755612895768392827051354709297231877589314385116008084334202246281649011825694669304551295469244979 + 4509728839111272144692019658264673559690649474179262646699331625117318888277703635865926266976720285188867979085670193580891875 + 7275477166128052446741208082801962510905074668975005769114065221711777393514237422266031434604625793424024653464475330291262873 + 0817046411197027445752205700663441451626769878011224256767794721900542448009071309280703954949009199107668829370562168637408040 + 9787763619368655981881242490879775693879040221802840519661369579710229328600940826654427779387311550329699789056384531195194998 + 2723448594543172549888888596962814780076107260643457934204621584814413545214573904777806106803313154411323713368897701260407449 + 8000951726014956095448794689858919573269714659606606617498924039765372767236447524498222062645212525371056330185170891625286898 + 7400634580995643373473457408678165048789850829161271772842260046851336944770097590727744202976687517001530085639423877373364847 + 6131960772116097152434381501203781193864171006504601138647645912125860654370952251962787439280635180850121164508129160794934976 + 8194796768491845741394186667260815254416308027847649620467735109219757947751470402197659639068665099777922925932497275155739813 + 5209664008657449547795035193830830788192397569777052795318568835532699855624203558168754541268446171707037486010417690857467487 + 8377976554519991606329945190868959375772837211176688945495596448296939525690240337764633216663866800325009183616688088580000528 + 5192787146614999641495067302066620692218333148024412938301229255333067720338121642154391246693289222550082295681213541896998006 + 8136852204722481664059335120578115477689164853072624921786692464359828604653937695373728935390680120663294293493176103289690254 + 1144435038869128719771735108732844672639943553994309593207501141582954078007058121278827020008994616209652065957537243296195065 + 0970656298377136326223895516660489631269402730038663872646787518014244370067321464425302758563853474605729399708299081361238244 + 0240779629525661769222180612134943092596901392802155389763359378856115803129803025504659400407739325825079102512268146609621569 + 1920020849630289059227598433172661405103577932866917079329997842631426173495463282180424424558897910324932519322784595681717233 + 1144193327801538649747431966846093543676528159861420323208804005782998653152702827377592130780075570401214786834816747288844424 + 7672000694647648348909906701159130777349487715893771185782393615180543175659863092467698777377397102350383295634648499503885338 + 0495630306491592179663093479474155305629241895069310776977867647781537028272341913619281785471238537339471770501056143359192572 + 7308837601725546836619910084602280257935558569169920782961917685472285154488319168403367545336906857013748237755825054290532894 + 9661814404701500878628706398803486793202614438164625925828662516099882010742067149392493627954571934045651513234013334682059852 + 0312168977557161126723210896500911203207572745509229840888786198868413208045541779692684493190694384662556740715047630385587973 + 8520266389063839477339561111091620930884162729262785462465146299021058533677470756448900131157092740484913244873616221850614852 + 2366892600338849323238354679971377016007007696850190096980341739336594207986799037588279474367471064265784394163814443326245256 + 4911325423638475961054407270474262985635705119625522856108931080012973303196967168739739944802380176010145279834846779349851937 + 4257810389850148158544144932315012034020829622092429506782620637342284858172415547207765264086812199822149360687311593339577078 + 9708659858477940738903030251204629213359548332123829955153191520032561522000846708640602917979387525987407975336034837147466054 + 8086930623135121532860695594083516763569498334428501641151038532550501591735570621442476271723263173645629791905305955098548029 + 2777352200022791503781001509067591047738954816120020121065054036180446105221458464420759433938919480637654297994424050557216733 + 4557327979787779116307153599001198923403057470538783746410924085722270113118125208362788921890249447415394699853853075390237309 + 4365884384429048241521760483369109759203884801440475321881130286288789565265074980716663859447668954490193155283240957032437631 + 2400761044210689572007006009552492603834440745618264315468884643834376009957185817870038205575856137576307667033965516109840180 + 9737040417279915834911486990827520959476936502177184234720809847197612305989565105760154340868284644203521456078055612096029018 + 9781808678278846885397125652129297898882169803910679237997846224593685450165476495607070948013373905740079438009246883252169515 + 7739852920294363425633218123401420673829295163516060432640021373043583962110762867984429100483394773437741380363822754539046324 + 0883431115446791272406513984118239461183841794345923431236238292749873478934884995894017966307053473725524062094771916898837907 + 6139386014396316197310075826416043562421564641768733346779156742528616231256212666391070181857228107399708720583287723130892055 + 8564495834035892079724353995520557131026025067703760714350598180164418444716168502414005579666385014431317699567383147791141861 + 2311406885413424305003701677451722846677377710768986204839545491722958560065098823523147478261771908820851989126482817082569115 + 9602340226869859614696378992497033778548537442058541618817057710375353486743749797455027651809309416058045995383235110379798461 + 9628709222162680949961060074815226201933096277151174310696525731658668144988286362519156716805236829848685383992849148064465103 + 9735346812240729849346428396581006547963793149866858949294858741576251512791660305611651687839731531035722282235292660633788691 + 9538042061855430905977346502656421504814621398394569363683719060626568625659708532699356988708790883640172621307887407813836364 + 6305019984976325257337569429166547690694053229542307273781369534773313407694544352991644928363693848808898178142342306260087117 + 1805704646504085604801764484506100460470712673185793035853367748681894021658904030806253312188697070560965442489042489792077571 + 2490985236219600794455119570755743690829793064352980492197865586952595298856978623488801799239792633697972577551080842006688049 + 4451839628325290929728145285465077829042998419941805433824084767085375358192064592570165051059371791323138480645291403839150350 + 2979438318932849641805788421308077401361414307061802172300131888869924632094305534351210554801463479850767128364891176166829465 + 8872921500436141106816138238492673770588860037153870977927285412564501357209059187194899313386454964167921543412282921398037659 + 7636485131279033828460677166640282160440679145358607334279812434544494120552175807283800350790566307285400625724030248887429340 + 4680751592769547019498010899871228144441828285042700998685644394131763248290312908027689367430340488843863114128754770298553903 + 7371408142591796865710653973046215109255786437157352313924442478531290092820677548020730647005559727973069973416903159076053104 + 0296204614919758433624657596498376245793058852298819735885655373134544548701918947319286620768915718576221199382936906689136966 + 4514861015660728180490886079334753171354215683899059435960727947953401618302867137487819801076786142685334483700384896695954037 + 2862199178730357056510866292501440152986864077701674864131708177930481209373944027435441136206079828523990989033623289788521958 + 3232125855905003070647322986167904784829417211608519129888545490992306400854811324029764732798696566611533605039116218287211064 + 3328048087467522304174357185558580322486932881453149442008314359000540253074863751401069345083176437332910631591438430165816043 + 6086110405144344067589331082608930355326779125945673110136783179380891079747539440654925994890579005806127474614509336396435324 + 7215091301714414443069868776064064504395207482808517829405383379414684365187710912963053526301972343897304816484149722894728342 + 2436471129882505774580140273945136647748090634204279933544155848974105586771383680141377892142181597367201114241681187884944773 + 2048644482475865853030326358622959819676030401734261133906361439604280224652350627125083350512410927294034793877892580606553735 + 3602935472072437248748601211519488988169731855279575778400706577254567463123219123896535430970244921999769114868734160215986062 + 7783657628040022836086246510234417653915945131795351860293548640058155931582229824232337815003665382949403984933860425849161499 + 7472148054410673792713655531708222900140217409627089428063743914621052166172358563633841329724840401144427912925448192355476917 + 0347053733535476550133949622008506766494989314867137093489295258193336447136204549399148001892481820212852414088927422900419709 + 9639078047884835538046942482094804161605891002036742318046907668105442784580061293938476627159719249453272549683221805416505790 + 1032786228200415283294994910054729118848671075845281886209463073179728081317785205722424406468440642562912784973899656483223098 + 6968595178017412521208376863115552570593292656764798517030930445070380603195697501931025439581550142699705302804245618724490111 + 5453654356413064906966652124099905267347821364144623020142756809037695527255942562866173971391249170311659304510623511853516154 + 2732536262071170918681622064325048337837520111884271935643287214208402090379942906531363266640024631740298714867728868944222573 + 3147285446615157276563228822132897878376378847350594831988142529113309891139340761458000809351957235529902167556281922497506368 + 4354478919601617063477169153215969873898414180925342349186710519974948744199229908589593712396666250201617868945303106857533139 + 6882511013607261756622150246671069745871933132400620002505947164316958006187665439907383822926483113411891198332966708317599278 + 5134964407461253261959522854559873663187547708050982034442691200555341283933873911454057728258698109359806239057894517156699836 + 6450666103279081547887551782344908272320062944069880747023544207556937435206656509659651679103507702121341392065845820245893429 + 0369780371537429488949966165797604230927289652620569227359744404503741546226260737989821878745670653730192856868459952515531054 + 3093345869807819730548713734544643718538694047498494322996726007960107180939172720629651622711868833028333458719243526925076960 + 7989599203565850572942150442657633965818968052176208211383992661670496993990824695668976291478797155039216428981397014999174383 + 1307119242405531123217610464790254600437026788611070015681427406612197589802556879143899518155467294982590879340815458735590885 + 7771734336463859132744468610337712969586326511610847632572701236574882685603506834926412287387742247547804989759024383729486919 + 5271411219228882208040644078382620627789689028134461694434130394862996168758457553833289759810275955726724366779012750280404286 + 9512730467284947060387240979546511277358650894416265360099607348235188428440048072383761268322342324845297508884228837212297345 + 5520192598997086640709924048681358015575115024163991652287513881247554854286841200564378110057343645081513230448973403055902132 + 7020240592700662201858752560247475343913953666111892278775820432145603140381127320826667055090149454135269196723432849201394471 + 5046712344141591199667738249797803701007407397593500840656021101416075518278507896267944040576213675962509419570331142339223528 + 5009173314040221242742971167778009936788547416346651832329001334847054317513290947080798012432976916063888435394522306337209156 + 1366848096908460688950147484431870925661107449748979391978321496249695501280906214711588783547789400280700153426360634008817145 + 5032320677216082097266187853807984797656213614647275198101803139086954569491022740666386321968921335192817122277500443048900363 + 5004785469025981206660221297903847696398366951138307001168655587727211921402639926973173862035209940308951165885978641411045411 + 8785398824958308479147867520302086574154227898640917802025901098713415060910391722736844682709559806414137007346900318504025652 + 4829177039724412998798470463159506613910620057768809973408365008034259886542242550978070824664073713620021235802691404413458167 + 9261226904113620784725763761828029554734562287674270893824453948307773514334280989553881807221303459863642843519335273228474128 + 3311573735232406552245381370523373424363177967581228254334269537766809380288366330679697723673023553333593300509406940840178257 + 5850353980111617800710390835159343131583882096987317262767588967118575624615788759557354550955443154249258491730584290096574346 + 6058742867661098727133777961247323273097355895095662383648934730004254372357455111922489913009492093823561131792526688980983778 + 7068373836217667990225856363415691473206022105532884987579074277226993152918608006384495892970483440333181267244554192632887695 + 0375929236714973683664267906774009903162875936131255110025871545553310661098253000439303508717945000859600253447780364023263921 + 3589236909622208939924919255987333064134666511205037102476749734554331712415072770445515704120917930961110839990243914307170158 + 6795584768746356073781978623124211251870230688353778395309754364333319536742360245765209901147398777468379230149142523181377411 + 2729948487677410474357762288343380948554393380782338431844676175646578459942584025062978984890983296713845183696219799180782039 + 8853156389861615819589926505138052323380550759364020828050387019448769426662074170464533329827565869171293278882331249180195752 + 5354617268287092363055229579924827016859348547054043349609066878817933385065188678139799271936447212380584467570750380867131343 + 6669574812003056132820086160683395897628895296098843871784268115803999250621428898234509785779912888254113882189729913124138323 + 1094710833263258542617692112795417986473641110466966207723302828445199198995397058382901854029835381782441946019335577334721714 + 7084654187809403875061887873785967514836739155665927380077234732823032340675248478794617424267309726934964316167994411232825813 + 8586810770368457480021270214945101098418804122645991758117744041940927633232985858835902473466474854825024480648895385708401183 + 5596898921066046808429836093228050083092077217562084369964360104846761170405526779538921555848456229448715495096371173722462344 + 5660195590159993019077789825004164832246820538076625410586718868028600352830449932992980717485232030870587444549082470943172077 + 0821935416600837395349048851468072663127356309332941980901438793730151587795962214031501434310617749617534269164881521735791175 + 3042072934705160703532059769445721283937901499649463824595439982424043872605434635393216517511777007087089174560510963232009367 + 5464155662396168936608488040261163576038165196682279135320764015816698209508887367606848299565138365679605265583581996112669276 + 6753095562768549798586933346781184629087517744898743057935941129179204236737611864578907720852163937289062427955626269555922129 + 5716541079272109791401178359438691238957049044014297693164836859127158377764717929820749372762244199830728156908190474636597721 + 6048348633690063166546832299456572409599753235001536610146572139811087134501881675589119526672410909520126024302026020371798099 + 1171674402450497762501699459068107617561003253876215131387056282446344211385618131395030296408469586922564210025675216461987907 + 9312371022806876440175927558224158477356755411023006311819103124252221341547172708634888791607917037276394431911343613744399883 + 0922159956723896116809200304280546821592880397796462717485456950002852867129487923589665229233372270334774238944990617682919310 + 7658709241655408916654408381196074058493866541161875193933692025333882777349795393761970679827330490202099389041851596493234215 + 9234545178442642967566968436599668141535683259923279950462781030512766827071494181783393026832191674347556257505316419663487762 + 0041257342453564273568929735796453624713683399848511617479340816490608890963355058355974856413150349382759095918170362098854394 + 9592779304960316507865578967321355607760068698329045954497816675023927602619347677723250166350520531047186145206536424990428337 + 4299316161376269795506896486995922307501710625151467203920818965364151628354223037516185750241653836563366411298238504451597789 + 8841671421275735676647633262528681899530392131503705721695449652045887039670882496194478043622621695748874619557992717633215233 + 2073059696519439089739646800449388322820261958926389800326850308700850275001529873409140035288149114816334962577827586268363961 + 2490360047432436143344657376283381577226551875079136121637392911221073093866166045906272906769849919522908370281254710635409730 + 4974848754591262059988003622570276863287575164608170178580822963208162146400835022943896925242423440936618793540028102479004702 + 4372126595413379264526984770633204109208673880518625238463206225086878596008443858616399507133771134539070683384873925072702058 + 0639171273649854719051709551224607779261350414555233764709993649110326667200717789312129165461963429321431418833445603440663689 + 7186962822361873750181210266660607397813719262382253059434948056476254707273143420389570046116876618519383113357898774377253891 + 4319529017033432347952439153798524883464591210553274851928717915148566352954737293867412627976883192261494139098284868083014649 + 2622939111808623590774562258070588172127827495395694013730379591966886930134915200669202327099882207686441261515920355425526638 + 1200973651071533307294108492132851108586204275141332635739794068695424575790972361088170979623763207458716935295604008671317983 + 1251374850775260697268191392326213755565839271682628582402356668458562455145193885654924842502488021956636839087993338831884363 + 2092679910172237700017761223090447686346621171455515944807634834063707579619074178681232780539980362324148874096831135359068248 + 7059799025589703414119220067452626516006331839767724497907056535882707433149950178268364082722639297792594500281095862497786970 + 4542905544332920101592075397986385645511891063856851014878633174032148021231620025882083670673312205077519194573640381350698919 + 1312255205389657370322617251904525722465432117955235178041221031184821368449334584954069933722375723026079372281725777733909489 + 8940234530803425309074547064952811642951856360280155612932727691967562499759113316867977300723413954039644096858319695187621995 + 1667713304364140592650059312268785120415368020836414159057787321290823207568631669529330852196553357371986318924246623685192637 + 0422089184234642438098080557484372830069143118691288742408958852833389685002956551956492581208496774233386094905265339874099483 + 1677835356907666147956557529262732608196197501168021350247232245111279150809917571509855702652690905689682229523319549019678024 + 3645155615476272052329623583943381582821256380614894465459876556622453836730749021655688760168012160726745987877981868221817319 + 5647755640891329597098392215119820185325320967799221680909508299218493251878104661039386657485694867555315346235424508828545406 + 2249500944046395955203873004372279572553883458895334843433140571043474669708074473381457065865063499709405786900325552248426583 + 1230511579171467602223112925195512272958191569060831817009891427720423564097069405239471201694564617244826682098552152177059273 + 8469866721000791525531110152439789939013289745066720962189402891838096512969001059723536174778699525713458075138245336864075519 + 1296905270266717168150361331577154511349585629938472384230294812334459038517468323643620870384471376627488513753063864443527971 + 8484849516117452587091720711551100043539596219785764133452403530020825880462282298393651618450654255243582938022557870602084123 + 1944353914349184905366261486479354722961723711488366658700425467290309892874206605011693831609609440448499484127167958439545979 + 1904342525350793098590501390656028964534129323617049186915074724786886755773131382892183343708636631327982725884104881408443775 + 4047731221209068512782993439144246721190758070966515666060478086425710216870076434550244885851035049595368742260028400195490338 + 3375747312957348876639595293489234210411377963219380216708693519698209655124852272292375830483071612875799792380567345928238534 + 5110079232697543396393866568868109799067673989898575725771625847005572590499345721422620239447760726870678880204127450730489419 + 1892883230935369730591390745517921975081616548082333381141791553938700817410468926449238904528671037503779324573001732065035519 + 8395077376884962568002904176016991329810132526312963614723727626088091850321489438757392596606168596638103913778878129196298132 + 3938927636631738411085232552592623008752473475775738216360990000223836611551924314564820835426069886741001153829625505334993487 + 1299692449183332553204542348863840181665273246414104121624684776356638436277872632132123576236177751436546351690643540205371844 + 9194356489958293805818668234623245496942584158879649161401045859846964460358471563904833418667460716546730472435403875780613403 + 9275256836090272445757731146730052254532930338266683064726986679677894399506235508548851649563290194895324537517696553037056936 + 6401315045565945782629076626066813595555038611734944119511046358367624104666208828448443470577765348785145599426526721185590575 + 0586738484454531185743029468713911469676776854865676690022624209621140076731906638884334409090253652724218159918793965233464039 + 3171209020852465810305033445747086308509991604961680580404820907479024353374887015602705890939142087700418451581794807689385348 + 9424311150932643701645157338987499029528852262438813754400403069738023146915551968014972578206454343730343122265559473474927849 + 7742146609950233423816671939328483772283214892322537597846916524424589673152890736557038920458731659652032921748569241119859976 + 6687533180189782962288035952098447575892236672807319984532899523336137857362773056256776453970744401322852572058367357860586750 + 5112973080188345114036362904396465766939815911981737447433859679102909113460170044475876180448426521815838110280974934802651453 + 0141366660566071877771992446357332649851216791119528638672163150044856967323023760152081614645879961910911227845879654515023475 + 2214123760185353539707121031098580866690882823675580600794715047520486504684525675655152270550399135886572417008928998130462848 + 9223973656232181173590003292639341133004977532862200821270596930208889426180465089396056658959981954090935260888619248916061940 + 6623578698318166136431412779326115216613003933902509874343492190835346614403255698238178964137991654202739789058288364219841871 + 8291158969189181550110191401002122993337707939239499805961356987899937471416091612952104089354586248344316163672726189677077009 + 2569911973118347742318591298716009672334442600647034815935927622454202539592391699029450660978546827587095337413939180709898411 + 0899648100113650188435064875802395140965508050973328163902047496526339571954451436627138016940395531683176282436292339394573885 + 3218116539223354243511329358754444736017570099304122222814440304223163469524526595019625005310578387024223128529473465323727623 + 2903847495538482030544840551895363794476928236443136637630260470246965452066473119820100467512281726986329810864283236603867046 + 4226586385557184936270267709088518321173404628666811633771213904835009960571786348833009556180773685058946093743512399598902672 + 8536593915600232712348175092402812063615932808932457150254760365196790780020038688785606653890320304533826035350207715944668272 + 7207307332779658122899268750088169215451053148485733154400660830345046074837509653982716901490942833776007996597381089382249055 + 7354364139715042807616100729619187431380023428907586266528433249618278407719620456619422594117403277614144426686677487237152240 + 7463017222778211045789643242204755641148330540930800826901784405753146374489626927527265867849180494980902054821139633747003818 + 5151230162674659769071431499839596583910959703956345024479063722159584629356540852497161935430481786349464090482420412307760810 + 9834488101241849496636150547202745300929538510953947644624667132590235877398283748992791388091916279125999482122365178401663101 + 3799117737061812716778711014651789301773605485731280987694315010080752800132070053513995645594283497896886041897544784262244652 + 7787706667573783951864085352707088626343810856713494836743287556709150843482692271254078127357988781374166954894723733919964351 + 3850833609175684557920955809259004150766406752693874551692602542748508158101511651908521148570349768720243116655926752800025156 + 0542333256075861408967459343438031423694963841751597298639419078331767590705140401244001636510150856151990464720632445051520472 + 6303430699933496407768275797041897577889994294810383735293345544688537126863233465001327982318529841153751728223029693637728347 + 5397568768462052741831355049132795323985421528118062025164276988946171985642590654143451292287062379578161283874235728279748519 + 4640901822963272018953105436900070403241616145463711907565248533620946580204196365483196723416387548557874992063706490486368853 + 2187665586968675889547896116950223441017696539693810802819756256217188102291391477467930773393197219210849036472348714939348493 + 0530870138541801269405772003173391922440292694411582576482977240988452402062182324365937231322664832700142793000599915699446377 + 3232764179605713808662558293727950897506959582972158149863534091415959234408922619772945504672047855130269189456164558749700864 + 7976387712997851037838832161690498586021679479533477214488890351913481087239877288703362839723676811186594991567854176580725967 + 8767096970476797579593159059506720944428573124512821132135870916546309651522551842044412513318859523946351494542237948488449896 + 0718064204159475781113170590472579807866358541733298234646266805452325502205676982790448617382183104529620072495546016035798369 + 6656888096932816475747398102488120987337320254949271905969490909227960204913812078261626642629009104843808070570261399892364887 + 7197928827518406319220242665874355187232953000643123084932578105682719648228431872207900564999025910692470162420939628457406240 + 9390054304943829673541677221189814900027963471043254648597886086990795714249446234111674340418457357710907778877224567169903636 + 3047190706971324195888140547475741620358462920833528017528636158028581644462796976018091635090361132164631234849610385434473088 + 1299169151001233913629789222426928990506746164121889744635941525381099603593944992448532482489564134843216370953945058018816372 + 8022886634541463283701288620853613352158026264893049477075544241214340204041747957155846007535087712499320675089565208063975842 + 8518974453812680488184297781261482966404248280615326837256707090751389480480211355208009414536208955423929547041219391948623885 + 3604467721690594055924832819820324481035373705830034807313911053016213471052470202123999030910736617997566930544442854033269439 + 0783963633104292458209399376532444272248160361826344666316224873723641667255667675127680227315908535163742986352235015659049712 + 4004639628899564002311837850986616952858773518487977784208052701702476955042845648511721265262737849283604073030798668836277183 + 0862408653011082563803132060254754932254909982790619138767168477417959797920610077885997837256974272446346326081237570982197007 + 0940886136952306043500899870090754863364443344376526643707265847999796477272121932881155662360934605500536289044543909420287159 + 9325468416880604404675394196786101658805312863903480479928341990160539724867416343519113232899201923506345096672360143197907320 + 7602604379899247751883206653536848520843218205588950289513511227638017895858870330990465204694386615676242643330003217066315632 + 0851199846447079085502271034855714656668178101657497639831079366789502032474686387227843449343312220724903806454747746782689424 + 4098848471040002241791388735422021963275960354775258076923928679254165040693087908221190070756034164623860222301010088075103056 + 3055192757629057465255631284293545235726639464473675957498678493846951810733281325747646636144880693592596312740548434768830767 + 6731474905682791005984276464714844713588718904361218261812425686803684106123652431919970410078795392818111582997268429659349585 + 7924410389518202685905806688713577803625532077879713115752972677622209346192681858566234259911076164694414416704969551453021886 + 9355683562980634479815919874568756218379958083872036318959815690363034752884522901587704723069489938561066700856799286608658620 + 0543220462343036193244858851552821480362000689940188453022451557344919396300863983139599553360452940548134852258624017234867371 + 1067014527356580183151961289434647684360706506035600010429135039073802230973345888131418619960777100132646812026883383699827970 + 5359069383361932605007503288578185157851793814788353694181498218990573049785293883804780055838358139459377587968253742572072043 + 4573719136273381835268729540845328454994954362222395612112318303745157807658681724375200294326161779060096534923740884933625708 + 3514458846264455850674231783280205705825729759163794635971944702176098831501306476593168602881301267771422854514181550204581778 + 2814589926430879599930014687698610766303495462811227979670379853246555977897078815634814137435467174275073493314846601851573261 + 9109412328394243903990091864894855454386078755925003658916610663445020722891205775398782367407839761338086985543481077581229638 + 1491723826525165284311575346657279958318121038102570973778417404071686643040506005133105712555305338320966176072017676784923629 + 5488218241739200538202629320385686355121297434909655261539604247574676965715827475716615737941607238002608903015929093309168488 + 6222350309549145806267049598652344478433516262239158892817022906333942210072994901250459132730572231739319182532518293889630019 + 8044072077285353283240535057997955717161542654506209603492744952552847242899140500411096612225095709028876598587942929972397072 + 1885954490526928165806858149219735696470308645981279734404025197278823077339850867123073835557226495747843398970587652389656636 + 3636990744440216604699149114584326945110057025978680402356462092308935861145193409488632679598241716104734129398885084544095857 + 6069902893386332364062130016921517943943574898468298687528180638591233629526536463888804022514538460226447545474670300837773440 + 0715242925233223925302043184620521073165032928562060926764419538572558168218946544243657541925010495652673050247406203961490742 + 4163377094941935791929068796922863289449570870715728363127254502097952823099544701660693419650850191571787642058768071578191335 + 2362149372830570291861457450525257727016337864275693314681112878356465000993320675510813633779009823896594571255519867010367760 + 9335339409871128425332395511671431500329529218909754194982323897857550540930935004728114503428724192561034251245345901549129065 + 0756506273973719264925319448914314432556471353593665242663682345436151888535592338801660197397976918922142540903105362128344221 + 7296939654818049488767067190718755957947538340790260392001857532393622868997477129188922872359726386124323878376837617352814907 + 4078579999111217939011699307760285871218819333972182125286903838312055662520500719903656687016759241817857273468272683917688574 + 8726333004719198815434960721386959090224338905967680668744954339106442434132414526246207631805974218944345895924595868424575128 + 8809968439523768418749746186037611280882890683322020074536396621763557542013569567593054212148112921735580176883820120783267348 + 2537069038616920940158973428724068585048795501013293376681740631186566951229973336427931288891824421015980577224523633941036996 + 7974808176187279818828936860482106588007126950454089943602952411737485839990023098877207814888492767150658782003308086338815157 + 1588659669715002646102364063331711646691061797936643322785359527528662208821134749050337274899095692843563066296876088924734707 + 4549130202526685872258479111021810868210332005793914145311147798812593113617843971880716197778981371491177307945521311901222788 + 8560297570244477829694687977784621455987068942424983136944870380427057052887779787702603030649524780263375021654142024115901877 + 2048774313776039429808088171712835186320571466269472744364892701622816406146475324290364012640387008030349061922998372137187474 + 1958983930518040048400877463606239970518078952389442564587925608445408847664043055091202257080066087803944336882062127350978604 + 4065348283423540496042896789726757274478123900698244046915478972359449728574613924262102889566496871444268574144572205450579978 + 3629438124450409423602990222911509881985430704078927765904795404045938118161221397917848075421341126252805098426191320837834521 + 8085534923914835313209677375813349364458599796275600866316693139878003025545882010477316042716780306226946838431532163667037127 + 9898915134568321964545103764074604849670802062543079353666823915979509779221620608508897413582424170944308180311897168957048017 + 5385323115399849956058889239701492340513864492761797303099763383900112373871513361204005145800948160917012448658958645510687464 + 8637322858113048873422361029279103210946558131854412009103898341572774795544194370639320402689943405658836056138282160542993169 + 3301482949893831756487465487869018898293856072780727019945397657149862423574816057140762598392679733606145316506298182753363157 + 1989885295563430148607778298379580655148124775805236404809749482897588166275331919278290911157248463196182871139898936725797368 + 8850340804158989499571102548588275214111587736824329752538481445797164191835592201791780416442465525643066854658921528683230761 + 1421812723062059588410998478367550671697961940333154251595442093624642651562126033425248558504164225223871598921143098979968917 + 2477995193068866106116650832975646638319811948342255800290956070421894468168681224145709091760495793451121243995417375669474096 + 3150729646482352886032550446062928871539222609285098660402450856512727724053427921573737445175821849100475781418189174380995632 + 7046750620615596575236877490285020288321290904270312430965440858488622217217317102253600290127052465317624607416177498383288106 + 9945695686299042380678429305385240697039293151977430358157956385467140053019250720885367675692664936064594234820657654969335744 + 5571751022714308898152825948152037875574841245733361004625842517428626308101356793475497881525020804091668118665745094943275801 + 8608762448666074656196662829963227928222015907465782465504699762597437156318531429585635263586424089541092855892902609967867982 + 1978685830753176969518395838040278058667840236176435782603960672407003909222439483538760352906908927302768494238355233209217253 + 7074071920319953536604510843365153876170171633349491568232092272150542222706006804946809770825099582766752656052960983718114235 + 3280496115751440895543554193849398007467023324006497516116534251153591572725745514291959829061315518724947165745450390160259001 + 0601737046591989613120616719919874653529282948250689745032606820130735453268070027901333295387220734852357272804293331117523997 + 6136958737937467562116926228263651346592589988767235293060122410789132148757897567424381946719333849272080001742385628150689944 + 1891595701639675010992493605507619576155702842803896050077803395482631144748035073236453571286662875633494080865014296782405059 + 6994138350962374748911276067098522195781999897499082597900135054301540799702368264182765273926228557006482725202228009397664985 + 7788023609935244035749201882811852725625300846793646185552122933557882704452555648205100150340311907075711931570895497802594450 + 2197653103798752067286172607092220822596982226247423576487125070944191009560709583893589326623076734376750057424185701225493266 + 8863132327252007877822761700057804325184406486939470443703245734365105772001424789573894937476178130538608010471355446757855177 + 8174190110749058109791874932401725786307915411703003043709908238217181652029602262116068758446055873309569311805547464496642142 + 2490958747068677929992898459199669839140241121204680850335549077174567238373970308977898462513690749136086901700597984427253536 + 5982357462083434284507903055152940486985159078049952746161034961672224995628192794860546561549979398991180455860037140923248338 + 8926976775587697462174304166383030496921336111150196335640267063653243971405939737115496867091474614902122111713955464436671112 + 2328015592752422584686538755738383160041067711192111211555671470860520931401458590260603642848665758765427324349701633338120285 + 3238367054704111120178059574962944110115171398341904274585267575082605150464279484097073060481753901121878225454945359042570553 + 3450237761306126967240618521993384597368444622149529677366929462149782561575513795963740446321127465963106959992420775690369312 + 3448814725588587245567368751607825271329254275986408132599484784341832975302652140521158378926626072460485474580935278488412601 + 9150780220021887436734602033408383688852530542191765389359753381850912455739194414678686576674855611507802645590418679170889751 + 4835292344245385826099978982021385208338079311915794842181613685383986799333650292340449601221579759524765161463912861431586003 + 8364091375971775721571844301438463624297900164446658688640976105663184901553656708363187917609334998277021278755741801258289094 + 7084708048206234641953289421943297010794421803966656094223814335341165874897678668246105857901156960186097878571917343164253048 + 1580091826012825586670694920435572709977363754508123881333362672498821977048126176623956391025928031884064853593246953559407401 + 1343143393297933839473552543351834063051545756389274017156011730389906161525821950360013682370064447544881706475110217230969461 + 3302514538150761859786668968377489515133804300482090273478961905590177116881654275768644498073647264106408418864420104945624333 + 1455642109436975199690456185370628722356663838058282076416293074142932077562024273500214654758558303856335007961702080005015078 + 8063031532965823241531821249811544926127012157501395220835632529512891602224510304171587094059291180949555426978545235398053558 + 6792060710713434110654251175014016166953632439786838514140951524356192499726146571336067500056531834668571621898017480292338282 + 1437695510093265077864080367192602710341444418961408220405302548941539890702354912153612054318858614633735009858764482449040861 + 5181414865532338468286437374705876616670683310417100729198121447458573292151625305538384979133781114543503822301014850960361423 + 0442509889959385737920714766510641471461284309092021412176656794047214218226892073311469169814612693044014585717564971417728218 + 2325595356223658506960436649084028083363095352384800259697237546709925440654926883086116058532378827751785516901620186132035077 + 5272017869427934924377297497212161665902064352062568107159660976294283182349751217848859566575424801083760720335160297859673425 + 4927647302447341405487506286250768152116103802235113601574433911840768325925117428685709060725568588745725091307806563183578704 + 6009173829226300709392490503960716312095637543299322573027471284752881663572097511651811613598957587604124624018835545870558611 + 9874256128717490827444943646188644499417848153072863603454092200052312279880710501340245614763095671533551439274986414901802322 + 0712116664532492284027602515056442554560965687688409213710573265303359796914199163349296608736358741384041138558244053035969858 + 9693983191087651982342027390681525334777714170455444776207288727295047097906322701667199571113890318007616548536163726817679168 + 6706523778360875477183129443881169868743369990013775836046887154518569535610947164990958856446973388802060554267647855673512269 + 5862057420569669693068391429181291253874208771601116624815603880238130385298427887023332027652265710135551985724073597417285974 + 1151313997638402328677281725415458206631525714244607205307139347412188214659490398369065819541976622293080801350270699351750349 + 5489131825943276548129703872359273308252153537674522058679810049913479398153870812359217912596783251244700635734540612732369203 + 3810123181289945953628771451906051867522552261199661987069529884844103683969181491185606510174695973406830793843872394354042162 + 3346242314263710422512316433607417431578705396179309838772547308651613774189871178285455805352015354652802479496815910335754476 + 5032059944587174601615131788722847272253927881072336845872496308794095355330608135957953660775615970673613290442946086962710905 + 3407385896995114869865346803277241560730078573870063366755416777507927736959074993460049742600768481558296737228998922109024099 + 0049052520096863687692070927701978011226142548782375715516453178031755305702747877694502859869129537906539333534520649523091710 + 0991259574063512483397592194908683392249793361680299501959035992654866098958575700878621835330177239453007223378603834381079687 + 1103177507554459538813745204571902700244177530864339036101223775180048578597548931452670546251696214644617674818880606435247986 + 4019388020763636749355438098141001952281422670022244785922521428313256185545192914769702955966048643204981030086298329088086717 + 1549239391810219717095199987772454895177623386763902046734720379092060908409042895882464384442634362486868518995850543330943745 + 5263274887172899674152253042181056688293450964020128773142784973127071891058343458622006778652971493625047746423062870250661196 + 2492300927820520335243072396524887229850551524757145264574209619185242101186100663595852135831547431534587842715149723823788454 + 0239821705984933412196203741296576026949577895980132509651253316722691651055934018399445089497754941402505430183658650264000569 + 4454480470480799484331207273048645656468167612178274351303856622687362159020726843169180682079344623827123515453025370828135970 + 6142817374030811769491227966611452974299687874240073880283247099440633899922286466254504368749938286010203764066551001971357963 + 9169371099648374900400474139097217260717487967105154156622253602791903705738661081630850020115390238371457432815879031763979788 + 5560591117813511863922620504148281644660212448276865905578433181502848473767100143776780656617049797235772123812344362645447507 + 7125601127543091335948203843174929841142906765885076202058923049770681372235738838189576737300366872775686393117885907972185950 + 3813261893105186097817193647097680347436595910522013775725325978428043833139417789267610377229028363642103442485430761044994912 + 3166100516390908023193075423476442023657276364366869002050485177701831320339505415669888608102030204859429175627661908828955978 + 9494583112215459385851845969134725676775320276319447511947728695272882901489693777569547667119292451041697329224102769821139225 + 7691777515996491255498611230620011375291757353871825879292337748953866037150788019954259501731583992956846734646612549716437169 + 4674403391449814677760084246730522440833433795684947826674440906657230316614951017230444639014782979009506122819959837960185292 + 0124355369267161692186629219979251945207193338015531285271750882020294586168274943975716404048435047057151424920598922068881892 + 4259039872889979839195103377532319383985569925201669042943584292754218542022884377759029683915124413393419307275904131879991019 + 1735669223208908684334277224397343396336961848404316449603849894027168642444303310792840158007116435560970914275701222063897926 + 4461905512399641675513869110628312166872040099906116555152852234330620387342830937229572832948858700069818699059571737043133655 + 2317566091257832110561031578973018527337285656514910017567896208598685109912802746001639928928505435442403312983994465299665281 + 7100315234971800925514182498331922330287575769352512401970636582041663941571732261396082519132641394516031353060487765740093218 + 9334108345710950934819716799864030596011645738530063495673802842261253827926601866855793893356025796840470669373855061371630452 + 9938632519142602121728449903028585427271086908360215670337654867014624403654411514574585082225609074457979619906343109374814363 + 8543685485409092161128411354085800792705928451605723409112677460751012429082851977989992688721655128865875431794910678786635771 + 7286092726668793850700794820169050814700948490519583438078010079869324333131287831724247406778611721612540484173599614481822185 + 4574626770701467258525092815137010178678255624898097602082268698327798870150981485054197815103745515005378748184630266101601233 + 6996566956298539914158437280054873330111337840249130739283399579411421525420812145476940206933841167306808654076518530796691101 + 8418268977140865314494741099167445020028244920345037125932530888607409097769183652295273473400544354104335924214164055029523702 + 8653179301531871439574603212631671179611383475494609355467328013854637990353997237551580336715104250041179882078593885288177498 + 6757096834181706624090949791934584516326051126444323415129234296822035888300651545387936037901447054120865724936805272897353272 + 3719471070090385271298581540906250911443020297189549719410313905300350268160333497598330190662838247612158675798074496367653467 + 7420546839654007142424912212795950734732168508855699265941182387494625335487354878640173067010282119575715050167662820992299427 + 8999971488927790060730948508800281979058687995045352068109470869864835768781397747295222955822196732634803342790733054201967597 + 6576480323890189237090109618880316708942469888066595108911237671288781962755118036472198419023002661197238821372958077703913188 + 0030541257153278168215715641021711922462243607936192442241352641161941478602829260934238679472069149540374325351015851641339748 + 2308535064234691761213175923993413124441933619616103905759452431159366446936203305785164404138919753229165645626046227853031827 + 9274311478528593074600453989280243110143811549871941292371158642466286143077576823957560727090752083042241440289345317446749500 + 1173344584450748636805732688311608479601983149113524409946668094326431976475189882181347248492781101482302481266734427266149348 + 6919145353409181506683417908661000530570384104910516382895650835980412723990294313264588477866084060873540703108364930450237118 + 5325748279790493246685409745464007302387808804042056122442284885720787803880628218787879564860434934892913815793329423983574457 + 6453232382761168189611119093517182812167138336965744983593436983776900497001902946217406040709180061277827817549237791463409689 + 5084186690867471312419665514325307095801242831316185457562663155798586037028408988187703062546161289787145296742552136882463426 + 8870611874224684584815641540909217473850820482485529973916085066540438294865034479488663791703681082228740535939513197426568394 + 3829342886981207956995705990631766515300196466846957375041259104048073176049856454632700433183856168388096468289412653196954791 + 5561500767524576355366009997865394697845244227185393733933754620619491997202491015533470742012384145261633852618565246889880329 + 6777844984653507188325486982839438152297369628419739121210603276755667853986365800165693953505799574103492924940759456778294070 + 2214788746856145315547663790110177531050862742765653751073730521273798413515040644084618990342819820992718598911810035213540952 + 8641245540354058813605493935866324134857506571449379897541736929598327494870227097960497570120553215541706501704428439721082223 + 1700972466803583171420254007427289345043866532653318330426834471075577492940413011600530531542381075895357213715112384747031546 + 4123673880740060770118806009141779021375877044026069684883815887385967786493701519196377144556351001736897028481481645941513408 + 2662387772790420942409426074953672031980544055539694698764834339968798663047095391766181294233657281432203121874861027827377503 + 3000685337077147654086746625753896686864534986031835702363775205640514651662788785826457436508900020141827996232430281971022030 + 3024908258360292259670809665500668877816383415506517420287409766113445399746700536527732408780456759980633419485517682977905050 + 7609884167715679957397855272558744514159873182477148797463658401514781751802711120892880095270644173320069885204433134067923423 + 0014100455158046473463596055055311019866188559065450226001282429179589867255611231640796556419411721523548855378235369309657647 + 9633011209397874287442661801560684815176053929256216322999478244794557838852723961384875065741787167826618848105863793521919749 + 5428219888294008773249094303237486065991730028127620139643719301859855449270217745813940272539972852306476328220561773494939103 + 4521537632739898925531910531504909038824924540851609471635849282948417316063275786486909546139512668787750779344864961591530650 + 0285764732059028849862258838048464137495797174589639632732738487543884739338580280553036435526582504329979148309470441850901993 + 3193744331770081476790157034764887938574991726583896870321256839758584043852505285610942913104942834651377543523173599555843275 + 7417116084257040522072018694176431604709041564144995596676144624737792695410277079523480490262409478745371723464489814999444924 + 0087200564277539488709914626916914001557170500699327915642055990350944184767970585140183066326636283502929299531353689075738930 + 9142572663076266551791245195307340496553949814370587843903642543965453293671993338189766065010527351493298615638788367806472270 + 3051117521339185890745759762693550854894691691802102995243849634880012010573871449566457109934687770743470466412945533888196288 + 4158491602681925772695910708467090530134341332595220736564785569416215771589193350272179369165509097131151416084829009479740145 + 1103853287929082360008599627015884781258703830958532256506076724299192350494313751000293453841630584783094561339455205657099017 + 6669316988454995197629701325242327637911706551201433838323166461015137492273818007712193923739461699066479249555708713191227011 + 2113634008934694195638896909191311796132499125975665209093925839375449400491235035672664100786917876149509780668632265414075514 + 0126792384563810279878665722622429577480527747103593555729429055584348852183674740137123973052149872227487163624179929217676754 + 0429035865573402523285948804441336965668748085575713483346016033116457998360922288296258888389027618101688101669309692510329301 + 4327425318090553450075452219201170395108911828576562899226660479453870050953529030012653173886753094327406771671224243820895023 + 5520772008782057192477714645125967892355088889936328957302124838926954775059515639556003228522011635026617680256545865946919398 + 5091701805891827972817338370300267783615596474978619035655959815481776653782092336443749908777349150397039742672328322075757599 + 5790089502501043722549854203882262801131152082075103693079735744546403353282880501020065196803852275180952587214373981006637291 + 9796322418193084084142426874342342820014220995329829353218013607479946651207097461896332568716316883980489998209799290426511423 + 2380307550005537574650358548246683232060877572246000949898947779365886734692122861965160733025000170093436288569747823376036955 + 1082935962455046112099818942036953428151667543776795511944294244788427450015296441783391903107987172541886534905100146388519657 + 8380489382633120509090625034073608336127658262734309778765867742476489991527857117594934853404329609845740341120593238746572358 + 0633586457978329098387174811695256037738146638558272816343120362030421967763476640034051908578551893496813666553354240880945358 + 5373098216766144042601726925416970539214195693276289721208185447267076741060153916852700809475592729479267755151190925441394762 + 0437558873199426030384531618231327018631366219163826316141114912440580402838580312314548478509711368795320884000345769917178052 + 5639423930316613774685180001977671844817204570499797609653987640525926925309564084656003072725353558374445587925969239833796829 + 1210135977251946489323174272650887900867086890978166723808871820517325894679293066521051888521481265231417131690626664853728495 + 0539462898410401286175566033379657439604282033567012883413399478842279156974842259796901368805265470365140797961756617874554244 + 8867613639089241484274514628778139575529407010929548231466056716290533770512410612299882134379199476168691871070113322417352240 + 4833451141363445314543208606007459133355986460223413209331799936622495058516670427933156376684533870032838911569984108849259357 + 4227813092685468088212208364841572112496680733745196711345105782294865361331232982776705201607924522572931046426758698077037314 + 3298920484699256928312414816543062270280813072616261084031990462638788100585936907797010649601422888227353971911450080527103430 + 8677297821634129486433214400771371293863980023792460946229497228182272173859417196509074761854532992353908622744248599410546426 + 6781620363930103389596792660725581404654123168036180688431615736861252151699433810032668453228299140054818608750957825124796595 + 8122906022184441989524946520995601380863784338127264956306250128205898953341684941467474429559908562531894365353100792345598520 + 0411240004527716081891095406341655736648076045216518268298111043258024354531159970495009766409513979584877788837540685928510096 + 8110610731150417715423694936324187409013994345563727775716872413402896219029394300366269945656385788061342489896665541029423618 + 3755150141442065122724114186286854845339699980415816422951602029278923264626041281480497555316143381278936597056953084064028022 + 9997198501283363781790158682287440631540353151583792163912187892594225150451760679251039984200332891341466144376776153588743411 + 8117278660244194155818259161232321467141273951036898758016163015261776236723767428479024530348209694127274271155128147667928805 + 0936167378563389999940015556970429817708525142859666613441735283201399969921725036498088504412772933143791841603758820099231969 + 1224164983307664154773003073878449221074064106296765689183370554165942272977254560731754387603794592725273703193699452227243648 + 0945223186347621257574665017745770814803043072264123465865881332861490934432664674134678310921895127370062396231037904388566491 + 5578757540264948131008953288936928142006135647005490612913881156326258717861846071301620618495929699330750590715333343381570370 + 8766152138213724166896984751062466183413369758646701425025924527217037621942282338912065834670044626031344011383552551288896568 + 3053487311706357675549287442389024758844523549667853410498690516184480612259764698839374235801509026206625335813997095967736808 + 0878702145089270046099454388880300081151816870001049594773880813882330822460954086402671799804568587855965385027526964053573154 + 4675804956846633737319204649690805027179329770063541964923158992410097311744090492573918964775287855196910884200372242948299414 + 9493162547793763389979831614732404846665474684277822658912090008789913594349007683276852208398902139951370774691434150042517692 + 7345730422542157756414350209374237744157462270676494668123673800976571405254566784526649041229590418069453350314530822807850416 + 1964598394787617389494252382959463826235528571672258679974212194662236832005305369294264438079751870505403383373187745093885686 + 8249944446042573821740194113388700642890510755384482816288425486723007601353010761537384611960083168099219424928983664383056396 + 3337126174819661239061831213486837993026986769690178323635308622147431003839607372786324521326222541843059384926020501381139876 + 3550125336344588588098791695947139914704682212688259894589141433972450950443922835504195392482891358587151935390940488550833886 + 7749712101826086175922145824388719830543614893730681609524662863877518177721578349626789661635402530736054829364302745002369020 + 7052231140791673822400576065079175225485411488088090330405642998541294857834801823806307475957421894499261138427284899379872160 + 1843292586638145520787104685467083303977045950130084986120058743550949902430669077350548793220932862849879063881005931348774482 + 1487754184031131275500703273842524528318488976791651801275003631033587218395976230647938697685183895874331282612016119932243681 + 9443865463893265996646234621765924400556069796282223873874118161895663217586723720163197972926787252465189277090874867985305943 + 0897354453697180183636362963351299526862015366834373289147517835099724224465741319067052046603751698502499127219361448464402391 + 5704747041899601180624074915530540633028597706644514489974845238123048510465569828429534100611326273262355319658327363672387706 + 8316996307878784269659645906887598359322978350217418291053466278096200407791776549885681670136754711514051366460206315185892069 + 4722848610616728633370187439001656108169740264355894513804107426599369076853462061213905264840303368831514494760256744683488217 + 3692367810726295806823047818393633700597950772879297341267237845287738595298116096169937443486203130496785989216239853131904645 + 2667811751880900529395751251780403233472004508704751605995052039171718893677809009851286227285227934697321953881347551922850785 + 6909280644240056221753293916337855667825910341176418724960272141306897770589964342155201798900696411923242239316269753447770119 + 0999650808847959816984860421127802079006195715319055574680057716511026426618826912583374854994252722086849395905477181959336308 + 6682428165643537701794115175085151859549462586484758294772142985146427091765603916714315410145159899524436580396471513525615313 + 0287601495196877948543109041275994870460190783889596253917385102642407519701386785758190101150573237633840832279432894588540853 + 8953039640516871936098610139590123074456039528834700886251621001651688622097083336798736244961699802438533721144359429291546962 + 9090712409265567652916908423800558494486073728012853735882650836864723820428807816418262790577395429269519877994493798687893365 + 1660175388130474812877157640023025667491901812382385258466335889928876299301453437354017152844077297406456989761054934994390342 + 9934657654239690864626478281461559020855371564678749001531999572350068313050489634121119934441378970500982348402296361517516343 + 6359086489575862410458280767790738382982543594459454924194612177893193423779790100018577922756855011303081967830570557786235066 + 9627300155446988370785806212844429529453154177930814144914555470252140016234923123986998575098139584073958387735640106379021856 + 1431322355214385540867355391544675004031897330982334142717560574603867105320387323557316017902469957357722433291210791176477230 + 2894506203039713875024969465668820869708991702780944843854568441944017095189870471544531770235169544173059692732034123691090895 + 9985087463071783533894010510378579436608410386134175083499511116916575290748570942191993555978994826375337547024070760036740444 + 6261306132531269467443124232293674590069389935930085698373191334535132795190967480627467212037239181698443751352939224782894445 + 2120942222786996279924477488386308186164427794112389492451650285444010405583566731254920895180572589153915684428013418667038463 + 1430800636064677716455907326084896393465425867531959255704442690767435730899236888138775592453451717734356391997983296892276722 + 6245887023168571979343600695324609549057431178812999538431044619282851448174071578424122279044132430998592688952289021834131681 + 9674276988668745718949139392247616305459443871778443070291211471809698194880071407948810420513382171773670397147925755783987072 + 8396960072488524616931349500116793025065793132740236508100883299116095620726458675309257154864629749532773543158061852267047338 + 4708002781694658659895872218532749075225884113621393683821853677375696999740077965880387656889715948194663339565410394344347289 + 5555870327192777337829881158886331270254424879662205835411641384434648950116158681537009743933205450514200494453854527945997900 + 7477629425593340948832945986684831020436243430891488737957650425170704516063535499519492960538931301090427592749932503236484184 + 8423876423875909116240287411777889735748877901032042101830839646783823015629217546200038215020201848216827890202734808048558954 + 0807456230133883710789676060781653192722644571250120561750361830812875165496905115518629620725251203869040049714454953862738741 + 5303451865971911125648060457840129182131488705975454818569283523145391216818437057554152537823305765736049257100852046148635621 + 1261116302127532039373528605959266607418243283938981652100937053779793268699698358833723678904084230346993115051100507293779300 + 8426944066403361349421019695464969608724905091684569968020665596067769625988182192985084507208329554219894020546830342373194912 + 9836620096551496246720748973842622026481410313119306152287268352751048064398407415273133860155815754408933010180348795503748753 + 4609338756911699625776639967309034003047928015509904888467025680057353339055998784262880963136510735792422530687128803685177960 + 3794220657491630690779260465220147420857430753103256706506076703567632175129351004805264212916552247643663829004772139169350940 + 7434241221131032055118140342385838086277269231509234123959703170231052929402882172699084758826526485094213048561191825363736939 + 0904036155468367437756029547852649525568053491591721559536888529587622171812488273446127650656057211625693401063929504404510727 + 8594239813337093390867462989975908087174105244731466049861585875653241923202495711120654077327719056153590078128352003621088112 + 6550980939146114945715655019872060022635651047970499718424015515740106255804720532248662461951505100400404921280927158680583839 + 6741404050546354494349489969507458195999859785965336806692031040435145352201853821004643353403220778871762826594034649052903693 + 5050161106286616149825562707832775275340760357578872487646716309800665185049903572794595588208600449320559114964177323489795050 + 7988668426398349050514452498533331732900030359537800440340518464659495823291497139184592287414133272356549392805616744235453149 + 9266075338762306748845630416478232159198106165396768656800162018036519950819645985549720852139273704724379986117806399232175170 + 5556988932197330115132604542704979085477903108338527639954740461587257180160289420796745117217674397152069207476864049579397740 + 2173348172420527062990485233356407054265180085263061116024667765176353870469789794863489543966815025332527451848905334447400043 + 2653295629344700441742575198328366052220017722996829827117810780652298604720896185508927603921863120335461979927552660891307644 + 0066285895594775046166427188466940243950248922228033222148293913898651489477743932715196100030572189599370661700468278120150796 + 9557220581453859816276169005234368536133383160153382159372481458293494645221000658600106273797363754949138070903261376602472730 + 3805492311138707905865671027330890704509145113408439234581134791375788711343962876719164349282530634198140214550594966178264550 + 1436926045326544742314469119616902325996600826173849367078861191857896132772006881206929709595222480758410968732831090627983535 + 1444386260983859263563013696700221044836992640755935489313754181471481261753184503838050091200730279031416065367564840157446166 + 2902149047863838396186395637335864504592375088936920775765866174611877001827681253531321463980847446832448377620176627133555161 + 4791558390249335499772225358752569718358080171845842601137108723166037557543519329054572216953276760772287383669070062122544693 + 3653096889815826831439877436629034472435210543189243295673175535474384447647824085044069839822212271287638158109858092072312186 + 0748574544351788265285261914954044165932622710335856937231283900552445994528620171010664109729214838117784033934235805145199914 + 5275894527081180465946457660332530286653207667782652877623355615488795343761394166684000047525776778529177571402318083997867530 + 6467109418857304686760026137696284413841248686101454431645726165291910757652786986378480149853820055715870646485922893256858093 + 6676215878298696393785441082359744916852977084427450114208277030042915360587042453548139647735771416607502451093388273522788649 + 7671054706470997891661682369520143839129305382788490682363534839812789784359519127806453517900921204537766515545890569275307893 + 1361042207361371441527086792533736691205317414847988400835638938786015770536113548366581806919926001472840811854920801842703777 + 3513103534581691803636903931367504112887620002748826537288400922168108606124444688399865918353400722960622289440592437281395265 + 7889386408564819031497565924192895193912656422791697412472168255473833561450568882333025985344661645666990267705103860364236866 + 4138536431654239332667925068305482627915123154662709208870044077990559363503200410357003059370208164876016094801255094919175222 + 8463391696176344840026735185830036495571599978819527559041511392555529527154011417043582657075386914403021244017762572439715299 + 6162318218961162791019379824579408557803275130662824155987476456514181881477682742571553987831058318649000691189597142635269772 + 0762970133488857814721372272166424064692356325030921377174309564434883115428450738561984323237757935361350713032425828308741123 + 4714351982559489932236335028957017819906944707422172680018267561533474486226912008423131335876195206249325093723564894293512080 + 2816500946584950779938046762589915909515704971018715869504032011106342871269261795583577290967260307340084652876419981696310087 + 2895004364486838513889537109545822827678603850445221912466809759993491507875666091568956682275842225830234855225383245575493552 + 2650099647818037615116956954341655646634963643235750472739733468509790968870462418042203958941068786618484819431710507936599802 + 7533481270625343830151159727689285867369942408696652407015806894633372367355011778476566950994358633971847804532262002525341326 + 6932860309305588424128816753568417315152512711756820693574982607856846643933251360676478873401876049759834996395397442053366771 + 6368418934202491624332453410763014824694322271983857287392943327020965722037743354197029665328443075456374222598320483575376742 + 4282586458471797802238473382178433687724169447427314412337761093512867942490521429740324461721167516599618126259885014134320111 + 6677394682606606653900300409179091142196198876169170096213616729601352901860163965806655227312385454363306654134273762118341113 + 7643573234932937551595703701897895283801028602846877296702625125220327139117379468939484216431057135643790896852072143295568124 + 7835389220407382114018498622358193237717282193191181508848234026347203068182480302817923964772670420825100195578203841958774014 + 0034680494236515185913110737330886189937723492058708152408147979713114102686546086347368499582981596157232052021983733385897893 + 9959931900795867812310134476649406402976231824404571628106712844354935633442704883886435745579659139240624317737165693276684021 + 7687653483916295211948300957846886688394120859824086212655110896478780014654869246794209169764271870284569926071280986536129686 + 5389201304796699165935771717834181664385244359824248801827481372360749339940576454594000410357902778074011200874064037958889186 + 2726930691205319100949599707692925525547420349048657283658532712722412081334373160958039199607974848481872853703890943042973921 + 7254087398978104571457211604241039805468739560240953011032729779871018385163199958508492807104550542120182914215024552352099374 + 0577915788776618918085672242537299536604399259342051743390425673863630842390420280176568564228989365174973256614738413491070038 + 6830892093137210682654019600696831217364160874783778871977883927322860408992703263164973180938595498029716242874574648385670449 + 5774283228582139254923100205140724149936447963980034063069342493084827233283799090727386532026590721266521634433539903773672657 + 8489342339836233604189107412549422519166707342446243631744337172427688799797300485425305108241084447320396355017099790987982304 + 5579039086144583780301772101084268454284211524135896968194358624225126732215388025582474957280102865197930121676550220972263090 + 3389908879281737422526309759732063914252217622801815648828128392852505613143446838612931228798897371072027044252222238376051988 + 3571583131629499703290168358948884937302565954157189422433659984916252703476429662770576623285862465399735505261324990848316694 + 9423186355018278041568884367207433805709684366572651006506138520185260823230823570755489649379382727052958581331266615555167678 + 6126444225712076374139461277391085492256424369818965208777930082776462483927136117628590877335005615182912506580467844672001776 + 2323186582401204627524733122349298471005163415025134564249126647383086521203590734419048262603709759435997087128843414545136629 + 1421280371866708001926278928901318288694248295906455469958649830300570517830927222281187526547437638030692046413330135004977193 + 4201689423423687675024635448407327285565295542200018160703811061939134316388397382336397162201256369493787936488029791585101767 + 1265877778847130342563633758037018164444481581498122824054055477037485608751037801526946223069038643514687690116234164514587643 + 6465410554863527094647350795029177204941109231775452235798798372912591022108733306213831496272836341289051922220644943607370174 + 4555709604071919166868299016817656945294419168762671940808165674695761877170460702219178063962280901485563918842254363745508105 + 0013210837712837766354170359690869396554185818181209225721015219925108353810498389109811284979505591805687297968690234266672264 + 3540066879463905504617792447842885657986052603128773981944573151451301111933677250259888942146768184470087035596773903177095378 + 5526250295384032490751656419926139482444274162610961490517202317645513359417017299610996672882236901128269120411948696682951298 + 1147928498844392902179227619628807696892271738030552398135463750372457058220840887917423404648021366673468670510142397314290816 + 2022158104950164034675577261500173802135526124382488977804744045573154829053227880877248106935421683250032295002832455111826392 + 8408395848784043250462314109208469565763023368052967204488715596813441318603486322106989843882974610129619714497130039489786739 + 0214994088989310972413925550111779902382656332396702390689823464515504633177056625665996413210331231059059122014949611785985118 + 5638643037266704666895115401268842632588292722777701463135298698439281447394022408579092978979422708178801226855288373349007705 + 8326215915178072795379523340039085009563169070517125775679474479863606678664704404360480187047960485640111421757696617713004548 + 7011793090984794876958820884434550749243106407550272966012525399145703465211673094494166304978135466245182409167311669917812035 + 0646616697055433264306514791141300386873739412778313053422926573847874849306566154499488632029298944379782617421929711377514401 + 9297384752555069074761141370510516463922575237795983591479132397584337422724053423993525662073888857524562744276272922807488244 + 1675900193060201503933483483504265157956265823054822690157216718534136770295979836197494827206847083365905242438375193125219057 + 1431083489513661032602020638770515681536739853677363483613015298018233407875797334225693452983166033993589897236847768729569036 + 3412842920266990322594256412420427432972591970945387529406395749977856430023496367881365081011414676715347811993981995507454759 + 5814144158348481510698013052752762134884248303529348153673229587940320030719465454064415732294560941869034046035698546780721067 + 3694293937312762744233869259702927434016315955447360677690945403418821029256532787548058243155743890295919743842535871205350185 + 8704385056392271497806649473016369833786145282019863224686988090496033200166054190979749241314009880507707963024916288921654292 + 3157093902990992972624660747840907228349704051194371097267625916545775966277296334446546102566702460108399894331979790861994643 + 6211141708601791603941445199717151439636201237385208163393264036156546491266459438443028650233309419884755515206198073403412631 + 7609935217879726233731421923555596716242460372189351557516117275999330506730738459524772217152788164129973955538645698104965588 + 9847824808961328798019186709647321679530290047204083126132050648182784705034270305452693472108814807665149578959595630309221057 + 2336424726766825888588931956562955321343032371214572623650620016457504060828907233038750693736196960807811513112341914628133531 + 9997503724107344142689181995651896815056436454295876248977561163594537358114242360861284248276610577578928061231272901007371912 + 2013755472268039887671228509805013770238575064767125406070391538875450803622634669600191763159687914916440803301533482646017516 + 5799981996920369911160876482866900908859555470100550461338722440379485926728401393736777675182480925560316384661340355950830168 + 4131746820931543634876854491169439418699998977639325418048790558796894160516876451374044889060607036066881936080985211558198717 + 8071462893187814119459304307555930509471933902061826760709069595504601694208191737856286699434878770893482761009503838844594596 + 7181730908337307386590819037242463777795080011670425589895801753553643404874388537396185083285326538843075531064088612600268485 + 7874226918011033625880877484768842271536701038369116084490113476976040281425980324472775723714911411152630252812320962593721057 + 0414263983887707664017378501754926805713789236380580564348508099662975168539697702344553508537455836440798954696577079098427990 + 5498272997168152869729083312401990047724554350008563240202328869525129660589507428406050419409546123885174117080636577540661417 + 2321805983098426879552953451815149973073351984882483766093075912871745174124737636496091875961776384678278562342333189413446156 + 7532047930885191527458749856036064187500060909405487710845907268217223665450938676158247000950256593423837838865029236735406065 + 4326287344295297838879679103933460283015103512394382866450845885799711951741393486898208614864273534333346921541450681108663424 + 8567495767845161425037712088656492510273651099963049803480674659806775332933320452431001042997191274150089937218301268747409008 + 1892491166044214033213915009098534855928106088594182060850901874215590307570900626843004514029616915218847005161443909006676086 + 3105173474201156958194039816160955452881468075916368040511971709028208813038518932050264340243550030216756906608101248802881284 + 5437478863331533890468364414134511741947560918971502005022258558696334726057777326125552089511046269814814736730962698056311073 + 4951554244048858298258123156812226947705933314291630536799208713986095914743504621255604040168912151175487398095913442501527517 + 1612279415688868683265625113331706654838561784474685978138326507909792993504451472859581305912676732125668231491237540161852687 + 1352117401098609459260904440848555453118498774861101544577811081137171667682199549961162875051222443028292136608108908775783291 + 4668566015341904293075901042719184643021339885314119600028221153413672044545251474917661767760069310540295768155060202109602728 + 2520334200236839012091693839792035322503068072072460065591632021254758742371667902074341537861212278319285847598815912703706243 + 3175268051143981660033747106123282192419159048635214903634052864839951778255031756400562020446144172393222917501787673701002700 + 6674523291734748122422773809147614700484318146175088254981107335895144969807349660283900516719746118645468637821636061386059378 + 4188188277626583767786502184322569089569789412892621297176431619545847378700138574560707680259428721989759555839556974186233480 + 7390532896972001905316907714622971854007628170763072962479615247643615622571558632228493177244362089074929594584800973845536848 + 9849264610200952816901406520106384682505741852721568226048835135789532787094701294801848704745256861395407908649513920150263639 + 7854370986367091444291966220372693018093730764321979930716154354135718272983430773038337101141108835455952869661500155683833074 + 9808115836250545782744528663456612751035343126746511715032833222650951208562936847133894670903159578406935434899681616157157677 + 5449933772771897148631641377562540641640474848389783754029100557570032554566006191465792063723092795517702238425793412416470001 + 2937905058909924731783049378468003437910238645835264792097079136587087350442777867813702093887200643761896159097869017005937395 + 7717133729012763683884090295651337537034023162131283487583227409327777370699292346651312872193008211062413650051860746533410200 + 4095695950110108518764643338298928366182339223897361738328378044503564041168430011712729973754089101835569129650304327287404972 + 1174584897511466194183788253926349029362049505536254582209201338252575420290164983455933289840278231035884030712260894346134552 + 7761765877961955439161913415420485543948776016504802146528406434389546215574979243086360938551004600037990661153084242444222743 + 4353062554304250531566068529474211745999775668076123932253052153101156786485645664269792342453816897835171506547074839704777091 + 8193385707206057241016991296332616186095885707895014417445978963635638843413167453713147741250557894417823842378892716883564383 + 4414701258878541571780503656512173574547903536405524255843710113697817741762054938128322216548020454736882148058230445988304376 + 8363544420911047180282206501238156287142986596377518728647856328365181602387822102287895774281073353368828111014956911375392578 + 5780430022747871965685716392391425352083934583867099701698503567269032511748940082003282777645389137257025389413017452674572537 + 2606024393701221307694529871431154164540614164993497271619958131424791186768644684669356636777831879397734272673335705649633002 + 4789715983933276471694982923444249864558464851612286765926229253919876317314926011029164829296322542092827015562884359904206642 + 4213428153587165381335521523932052241841163300973801287138253226845490672931816978773941803990440278669979647051465348624079105 + 3419168581475572983260190361701934633564914249990805271700921787735379441310149748846950460105295646015883522763651311765718139 + 0643017584581435034370880134992336308617187531872808223433939732921528795419567765739615646487503731718827467059811489514462708 + 8240926821672036119484675230474136343520006840157742512260506574754560864426113591474981060698558545401924390339201368669580151 + 2180431409945375285121040004138946753923265119496541829137171528887590486854621739462433884861201148650039065347599969036034946 + 1220794484575763660002325630268586558185893116790653322219525972500497727914800636242536069684827121496593553311794674511534108 + 1435781606190730034271758074654507450242292934136120417582018758847558210750517197211614624177861297537749923102696299059068262 + 0472496196020370020276610485121224239313415267755759579734483426439502592786733423472402917351281201878422928096327388672118427 + 5664545446808704741371688000935805171339458791507069541059893057148797349299303009996748288669321167515451714205892864440743408 + 3539189653746007637884781151821846130210806166359445842675385724193537198834368015119520365512286626859121785638758771673116936 + 7228747311262908816869990638505266862436414983330364594232199408818881369887998094729811275091341031498735810192826600585848478 + 0205817711643909986528303579098875467050350065610591795091066174715779956393527864740830714556714738435192795203670003124014759 + 9197293866434029742096641108142225947219962019182256790387923893087254917713809995074288755692595202295289706002058647970706318 + 5801028709225408662416729985040929435165270531028696258985082752391299922713342941633843800570338856731347298583819618303436452 + 8554584149353583626116529209271190042567689752495849141906628210792514969913837494587223513509196504949988416482688661169416704 + 1402557567228850127015457900783688564010064141030969351494178978419198543363884975731636660451573493841983931009293074401767946 + 3030096749835569373371333947576923588432247404291305005146406298391452901679290153566364898274791521766815033709118309495674776 + 5711698251707518922789190956913393869735623141004406498318629780886567378932420667481352170410684788247915724815490088304482484 + 3076891999474110399724898312925906240059216711193634437769661170118805829580169752019184852464954183024109801959695130678652316 + 5549698831705307512844145517641207234201273500862193514468462342310564088815360136277681192006596458241962992029526454841238730 + 6411622599480809121036108851843289420809827360922656655734346202711742438003990222191272251022816208079113097900823895134384085 + 8642218596518127375568301272202091207693967578318544987425186514107159773089906580986790334784827799489119999185876094206749612 + 0920817351118635692704580562112859516048707763068110821230955827967708140350064043987570026933663880446183554485511010170742288 + 6208781018246003491238792622187493762169792217017386868912187285653248963115594278272915569084370195923738619149855997663765716 + 2725282513427928049648973662146630492856487618068183730067763515357833597788940914019736675580475997314248706127026547890194380 + 0912098065082008833983417148631289829848433926717155189805055489641556714887595710925279228500591899600062727405015074732933183 + 5895616117549258380703685066950990019495929210886386708101945826998030626417636766877015647925822567530097432835311405452851781 + 3061662816058323226135782103379493145683394691280827163116839270882202901941521202335712663514020076981153846416619848715503675 + 3704213022599283410938645199398840870678548274677230864636710751729466573816253072905154246398964963820890925958414003660031502 + 4630926004977081614276851598024033198734821505047735799361816301169717640380369512425102474864033576302498992022080746889954455 + 8300690807062719013236716321873014112140959900671073008576129360776883572345888774946590273926184154530838752149268349654124927 + 3447912234767016528327462063192808290048544233618790028527492173810076784214345126091690768646666027973848294720038771161886178 + 5457890600658613094704911994422834789695852986406564746776631261869186614541778685993675186223192485017919263967183543307324819 + 5220338990377375643418843097310570471194246573225298484773451484736001523372710934922163010657077255170019875356114982042678628 + 3627624529201855124798528837400884425278033564368552915095248122583917121126951781145851039073704399808416096566055979179720996 + 6138215215437842405346946457258803271828305596332127664808930703097188386621950424243497121232196129953435128118553466623324068 + 5920381194124220091735356882290501723032521874921419228504863143247804084726835859796865644318358484363167764149683837216715113 + 9615036434361215242420376195665243628638184799766269042140156331651635843944014951375098750172039065463946417568449326243598402 + 2848169979084951950982695318867752277301100025960923376831113692149385936857810916874319944880663028251022532340529140647508871 + 9496200698078244875645144567349529530108679183666387943211721642572053750534478253516851058589093730399207634528878897274151362 + 2928780676487223500661310045048476864951396027388478482164226318809641027170548978608486524888062863065934362652787878241515138 + 6280140376322091582258435509210383633979192424770386485640747341583226684971908322655364759264755383681296473387197771187476598 + 7993834385710389281257683754961049197160221786960013125265044154150064439440391405850545737192660609079271627770663100625583357 + 6072190114323511020360786591498148692349156157375850747362774972374185937176303811511475665210532862701141979885066767496308496 + 6809986728266957224821129384937931767139546739620244968569547174693124128355961928311295430759387663715690541708892900136725621 + 8713302194814326105418406542612287987228114780045964567511737165272440568730052294690749670110950977545749571399774020053301568 + 7216372973252354647766828421771297596834262561708247359782436050128141372353679212726164448161015103612893738264244644610968102 + 5490158565324437536585310937019467679460278414170537463829112562515850928229747475007728895628087831498962809803771938282971625 + 7508575669851979183836777758657815365989035447083239066619058708444094473391492540134970134555418935400444033568972945852753572 + 2681051665685441434594259287440247146082524888648989023037549139977692642794573123372272447282566487899476245382067369090850227 + 3516664349028783594652935471979981657724225297147289075312362875423752912404004312370632615551263897637065247961679885605652690 + 9466216134195188009940680229231563219004828730503835830166900891639648098483491041893870240357033427709041628218884025561211450 + 4848574180102172215721912201870496816515688173491866267900855346017402326765363320124474261873980008204988494006538252079431490 + 0175523216285771758146998384814407339456495403123042145864725622594607160861096627528216923235632801268714390775921555811885643 + 3472489136602420352765486727018974617090254641528435634640334942425890346384541194932965110314503859645146781896767507525832148 + 3797532143892746774112201800929601204074380314303366575611389855222496601937222584569281001864863917059035591510412512996095572 + 6540831912166873834974788036724952907724341969947205585823842409980011722639587514582627960169448155988074691268777322159243577 + 8665277823830969067856126267665294223334216725032631778088124483157924821285251588520602045895388804877588758409591955378022156 + 6073508435137376529408576041907918073738449051031545977935509368280423831551346121480713109837860058648169729195905582970167345 + 3067341878979134838523394919669124325563435281537910461171499830549480992384643061189946199980549578258740383418503347009079843 + 6535435940186811905537955923044494920097170641355108274375772163581055863892145187878626476077935978473720854007118125956368393 + 7039488100826115931812511833016243383119511518291750301509797980336012158668128482275262947277553272940357496952990711563149829 + 6786417640541461059254040553435360397444650993725507452127477820766859236159070974204514281362156361495968903161994222700825800 + 2231234046323964842602361033236684311038633571563965762668970125159431168316364793191351729000958068187715242930876778118365126 + 0967020148060045963966458121640283348948132407097784342111426011211692372274414489985481236783110642969061229593384194970583663 + 0518863000584387454760957529314643812512823643579550158516331617073251164731368407116086238782619225015253603821594850218277314 + 9500480699512272865605970060364505765826990178852739273720908237913877224017867775678563171957729835114722642208632758208282247 + 9138815300684460564222550599375232818221500256241474012816587003367381334232108533309664763635997507997023730828738583077664669 + 8788277264997082732015978733262501251796460091814731315709354222338224334551918351172940509755714499856609104221032539934398062 + 5201268981606265439495692981057225390935909458631770334121087316181673897848115792408678690299457980695904707677321358225662858 + 1753894444989509786731779001286291244699622264775676367978135041545186928742736879462156569826451402964970455781449463407937916 + 0502111951096040580120210611615484977765606052460541731989539917916976249725653281972573849533515652151626503088059881052346467 + 3880078154575290219658231687424062098862063067654268460424536569017374872824177081255701341783967148208402475928724455704261768 + 4392256036256639333393028072709593018903870460743710545351823219115495656631234924513636506499865017761998475934414247147614073 + 9879823269518650692917107025520590107178762204459762006129828636469652976104262657652867426597078219790167485035259125893130526 + 4491505097353181156857564911252591317148670618490859288558887139051313551147429010258650026546020137477020225229299116254389267 + 6985649712270923660498384674089852650962875340575045596604964662128408959309248980968270692814095597628820086983662450615030773 + 6856393844414418123694511010327503283724147879193562418774164993500731367874976787177535887228795026180482876909284579667315939 + 6933319890504711538399213021011090982613851985557386817639509779738587337666166285748238443831950809951451700040304637246662798 + 8972237565184004138743415214250280650420991574154677063216686873786654244381615346208802365774879184715316421935088510122029692 + 6620712954831004627906209308475373401688370427674946161939930227860450185388905612087218953668667006558048824549749639289702982 + 2252979368901033426647735610872049783979382409247439935969647741186385842273253355085952551816588123321471149874812539836048112 + 4296535534263007024565979896369915411490254323267398694533004344505948807352166933785377686738429645888455485219163542489241753 + 3740204196364178691705296568637646938043711157073683455458837069839389554673644717418013786210053159123354215579725572298341488 + 9402853270709855032434056268150751702914142055269816941745088351607954708943354365301302743628246326922883750858759728646811815 + 7702984283703968225748705248163911320353463996186650929366431271533557842658056577524133407573715263399635592058138266058468047 + 0714364441200044139354320382443415251209148277388628504182113543224388038221246572844030594506529807381529435302712895155562998 + 0439249856337395882945730885613068512496256701244515252923706394988734280606704794447812748091162906835016774939625011625452587 + 8701684848748737861671752322431955447724661967607517009813604790923987516158908955881849157986515334551799664962438730731109340 + 1331695486624815425190823239475277990544123745272288937823732446789801006674641059010522745250663013852871097862751638189259629 + 0016943722810447477028299392663967547809929491638369830715943306970577569121839921705532284065788504261357162084070598074698898 + 8301370408134947453196729774027640676030589016291539644959237246218491449189371838582480346507102754824929019477369849852385466 + 2141296007314745921128534279212951822200061786556429858733058886029876384472876002241385397319110771995753216118435172891077520 + 9778033995372614700099511429265411943800576787023724043391866778854759353346452408608492285235768924255415140931221126895275706 + 6825951183619818611745057594180574765846145064255544523604725057011807870654883273137368630387060066151211603237021909384345606 + 6330524686796934177420756525152826921339672339044318925623881985016143335928837573713885535605018904858579244102576335089585010 + 6476163553560279805504121578981537068558170447489713068606370855078339092366601341950660196338341527489856914865088585338744059 + 9336566578276542977779339876759708356666986167810967015943735975240831465492474205336898814725322385265950743359319117386285955 + 1003736656415305664502391530550831810874960043692083942495595913831106487788016650162073804988081719551806867379947943364891966 + 4573789346107222063252149996048100164143705560186510044433851243141510350751823081763496713992637129016266999061673393254758192 + 0532366470306788734368951439658028825164454629260106890282620855033982533015451546843353901652120510130789111458392221784617757 + 3253852880221087799999614626290882768972817659832607861376923098885595639154736935283503251479471872499871522284582447822302040 + 6285682722317206257124522813577367514121775302484636697810948128394195942996079881830875566043123925277038343926112033315427349 + 3775226925665315936530276286731605375257672911376828473612175726312446039948354980701402997357293119532073936998664168131452515 + 9033989479402366425600648174316259705202840220576987680353222246016330572206033521947195443476632332503203414941943726000075449 + 3497459952076058462828783375726894554577596495151945532419592454939988268844456907659575363299273992966202955633347460395801503 + 3425070812671430759768577458384150050234482462127557226191091262303333548668785285283704391650036078067518873006221217224813250 + 1772566105841430765131974198596141137685703304393653624186537427347991201369580105964338526460016536799639038488848966636423096 + 6770176829068426450217510320589346020757715335312260267538371974073805419798173049507293562584393319422383700569196675270010649 + 8817107380879373164458511189191184591118659927137093795839429896643513855977855984835472389317216929700259038397397174527984545 + 9182176191236023496232040243155433201447895622909243154991531577802143936144665255362367572046313372242799588041424257757065202 + 6776868876338528332502171518394602792217092464624165442452676081627495348032268487133922812426314590277917132179444733559137458 + 2894505940700668608956696393712351416879091173479440509500831009675626499007967467374789971290965256917798968433095199887640804 + 2933556414955828193417995654373126786599609721238527340939127371332396349156901995803794360944816870450892560704118441975220867 + 8553706670591731040619297656286157301262507708170329674504933402137245881090232925455937213553504830839742590855235282434383116 + 9795978189578883639204205303262814903090980902741535992637415797011196591002116065669674171784371634354111486560182744790314795 + 4119132103638186216017314646897106719838984255536083613903341238051086509058863316947216192276628486590741349320633205188806897 + 5670698885913664671019828424294908157556037863822378418679559826760134301152250392322845741422553340998938758664406467756180798 + 7800330341660310724142951110753435998016854748165017611258286920601003037645494210716339815788133485140202482683448446213209716 + 8180605035942700911937960726293062276511453378796626425148211321573098417580088171144007867547815289216240544844126601589466966 + 7821272307041782298994133562164496850666805515425583415056198384421212580796187662587737326754702942280674718201253410570348983 + 1042240816866808878998548317060777151321655529169893824595029339588028328148179827446446643616423322057981572730612868764050015 + 1252481771070461052389437601673649482439048233841755345725688472923079857771939132303119904339949419801565589936559095363036112 + 9690992931777916802696331919514208983516033826094247916936120742724743873182994969726283601645253015955852055017097669830871832 + 5020330232719825823684760306159154637346729706124058199917604069885798242234996370123942691457916122474221663868046994104598933 + 3075139912987034850456516141324884611162536977850304751997334983975217864864834605427571083113425269670859785386338318467147612 + 0588929507981854517277972648054247858977149919377574480251256787460673116218337687478964763305472549592601599187647039007311159 + 8091499973422866102588159323886136790375349337327388200287148626779716184548302459458465936817938524771802569873742301251650117 + 7114931231277684778417144640504976098202413303636808727117937611520910337365455884518757181692362707318939628346107928380267487 + 4950235887683950624565704360578955553783208046483127644086525832912071037741169842458625817412278583829306158758057435134618696 + 8199425955265652644399992914133529916068954186792582922740480043066932022166380883075792995446339961281184510898029007416993672 + 9600726548050421231768431078919064425306219469503912968092554459127359674333330276775477837154780938957377807571696713004700625 + 7295599369136487293154800206051955319915985280570186743302107975100582206721744471004980480977594771538574498512856521123216578 + 6297798457301239668561079936581574605258366525996359269984364801565322122584365843225724581654618783605926367931879918225442452 + 6533005631078137948109852121400341144965267577414971222703110484819122046478368287561575133762804019638669026806894198861867537 + 9875087635268237028446411260770380453643015454432015279985047995719605753073640336797720945754884595273185611911133456865738261 + 1289442162696753398201423924491482730765830984320927644525084976853458311031303193411990973143614781325043459014068347046089289 + 5407587059442212092113638721767282263392344800170580359252927060347500966261590384053868270413268344224069405566567860000139705 + 8360711621827142923632844470555921440996634627172367848310520969393805873503222609811062308946619951688125101610027026987846081 + 0944723049476073716566027637737569127176067300129222186002435041592350356420231369282460258580648007773781925508162225156920162 + 8475983626059931171149310298021646566523963848825823192493400102745845807108661239544077702836139330088359628977689491846874286 + 9167471361458822389556369913209606973474148790242038515231761016355472551050907573614312829544645064709238887157780557241782741 + 7014298247554687536486236050770971039248187073536082362810060976896826815113357515444053263548215504897920396644014795535941249 + 0560999088691723682614108804238530988595549473233071643241045493910124491974900926784898185428410219894939857122959475910314078 + 0706992135879838500099998224229773341412566822617554024599579881313516475013871821845580144033844736871959630619808210884015298 + 3257284534077293882786787542863570138992146936142087051892058183105267975351672517356758026095332624891123361507959805527300464 + 4074440343205139647276844490970010808052229358468787479224053850708044118534407822903344480715673998402733320764968913814756460 + 7541792444051749131437550370667287159419463038893712135130829128921018730253201583423068101308427818790061823168162915307740555 + 1517558628903132612936551305596370414201320454890625631435775037687907085643182588609436062805330988597026150223859036793476645 + 6591140085443467002438387440547002194892167702007183254656681949652141186889776360123350307460795672547510863464622633652798129 + 7586611318404573147896264171755514255213812732114705872658268827371541849326158561820698871403138855140301594042187495345343587 + 8296969079616469879346007981374601146907653922591351081026313152884017339179855411584129459367820354848581380738645777750515335 + 8731520753126192088044684618604970364839081511006806274832524720914395021711036520236353757973882463981033460910456305044738117 + 8522729809358153390546384877141395094866223397312997581315815377215593011496352023911920483284381829852239261360027871178466434 + 1761342609588366253125631150586581982113849076981180786682830283076537811478367306351425774976563602440271445970009753618288192 + 2190966255981782407270090701820316391321596233574351800067587131465490412933509752425381764960420707947936543904169527628499764 + 9513655081411394282745221856716659032453348163674130701896927299389413958771625248039619427975826651601280801943472380714643137 + 0617514295978753057337209914173385759751936634152085643157967813155609425512280471102235144051790721763863647958187237685008587 + 3639355491023500583172147594486316367021278514106274611239107265098592491987675254836995000835549078267373162122839134981244694 + 3032030608995234928881439477961757003027720355891764881759463215674265954842081986273329762678139617217680974433220699552082278 + 1162323720318256232198753258939220028085022540772566418699150206741508982674558652349158167206478285853624098497667218452569282 + 5449383863141380776369123912608347050738601579475359170938129811063143046219515664348459639566915361115334890006657006031842097 + 0352577524785516785715741803748070461694324222115473415680064156677430016348738412256655844328208932407174179588633693022145069 + 3240824351920886083704779764410813380504193208597077988968552959949184540967132284829781189340533621232738907229081350464536533 + 9963137564898255760485048365009768861444430624328428769392562608655048396702090989488644412080235346086820241525013306324575413 + 6313120896902229376551555163469139342705609183907471905448131939609829452611107992213294654747615543541094148280055017927542670 + 2193326928610645174628017287211712211408683079421721839813537852939457890561997238125898536070007981217325358023811789787011723 + 8243869736268481951401784440593310926754240433539070013976127357814953175386685024013642745787559590618261612069606519053423542 + 0179110493828168312231149822817828204338127248358983471224771340698766448231962762617835559498180861959832229135237920163613151 + 4787386815157272287656433720722356482569671165537977997843012106191355180546649834098738516604856452092754246704403258051505371 + 0634701773994997694376147550495812360818423051628930021511577756465075343321034591427451854134383867627150784580620161049855432 + 0766676598258381037189024267219785521248498516810290597640526034223344261052531930836169758828566004912961881921058343147697444 + 6482511785125094948376527886610692241647293945078604787929517099856009510498982203730650348969745313708621728477885759515338493 + 5205196085155489849560658125068733947071196666550006357643461400687947338189762369344420067691692171235090223284004207347050790 + 9809626775201561107404043309301598988061425083419682730787633868247584100867048954636838021112840948572297116645919603622359907 + 0822943415366943321888436141210445288839456758217953163265370657515497810970631795622846252681104767475177503937782564413276889 + 0099794234571476050102251924980186262893747705880229668101192044145818046711997376029940219465691893053496893208450200931362078 + 7338980161503676399103395907119988361285887220551606875942870878016149229490400212073840391368478482151725734739290023095487410 + 7899326915683751786630813196982092775796371026481722729931635095642264999233728389534905015911812126591048864589797672830096696 + 2751118177471534985294175817313968889734356500489672942275914873801559720503551024017816293024629330339229860581633938440765263 + 2579409952433198069628120504384999886282779583918285844878077794508256550262226622072460752726666294025165627679376513073930940 + 1557518549380248705140615993858146675367318700594928368305022009826106738355680320673267541599976659073767016002316705812605118 + 0706655774414337358133841048392051795234166451755892548200847217249090290629891786004054678210061272314883459040459769608941760 + 1894242091014594788195514987048397793320863358408872612791768967887371355399390803287124928045545098723504490408131463760999333 + 3060272094521186414251733828941054176318890330197109603090531231771409739699564694060282342629340263255630493316904735659002049 + 1028815907660526325417480678219858187627208188992524766305787455603486273947607751634385261335594552079352038645485771077029993 + 0683468157651545576501200944305620051155390867906355388005127965874177601579306536442110166029928489048442610212141268455617318 + 0988081700313980006604864032962026305268670102163784987963985127384885587927642407664223367758558519122248185218742873483956807 + 8435692954315269375984976106264988536738299966701776101047442064080401887709348151446333391726616352591853741366988778921917957 + 8956328839854159854532673749984321247777028190876411555620913589749860701945785300696279975495557163768982684990843868186778431 + 2520325381475441756157721367873710939223796803781885424158254911912476533014496257166233162377942526340788173572154209732321202 + 8180099306765466453860728219641256442389031828386563717730489464926442454808958172470108839488494541309400369186661157251374638 + 0628247148382602252920534144240581556722670156430583076620252695866327968997749969112676595494827895760196984828212360640034869 + 1083401588117745555669152288505435653771338944376475705488767101152826312238533625308441022273664874833693060276780849703095095 + 1156085057274283778724094356821366624982478225088443694900412624860954703963723162086763699442272343649549404340286403255643105 + 7910121814653271873529362722249047841930063953194714561480180469523505989148782328178679381325533730833709002539304255163521040 + 1625855113537607234401449098110230513476322963277630854102799933050565678807805089239388422442620697922678611315082884292068865 + 4371620713456528072846857825011777710835705836437187394614071662418465730864540826899869210260117229659041798505650538477261368 + 8985576750846387981996728278040998786610281073838965731512714567426037576813755214228497693635971824751946973019990502558550741 + 3401249486943615979298276104790818107736649764729969044884395409904447217117866856126816079991915988836153438356752147841144170 + 4762938795985970542856369222277414531064648102624695688826552014393694646959714635482411149329964264665288374841117934547255987 + 8266183745098026650707351627828760547702165330658530132998099760473617506446329738701905894912433667123567916471538563863907720 + 1749733602645901685261363936495062217041689057898136406969925562689807608184144495204588063954048062251421026224871438707736424 + 8548102168448428644279598842714118177587767821370906237000294038845928905112282335030976267725288843840126116450813362024012439 + 5938499597145637343173003399875431713125443282016722261731991805628239317480073706051380874344456692406363674536084190692646142 + 0730500561374089587897509875647211800809704761282604727960645054003482860298243507208373227297725664305984934399424216469588628 + 8419154111597746163254112932894914530620901371133608712199806376981269451117389112518987662727134188058972066300128519445766440 + 7937806580759161251998478953470159484262859343028238192145225348422179576900021837242945100592904945106701907680168893307572302 + 7516873429370795478978284132360296301129718931677825172903818753611017830921544550227392257770205145640364461713731347634995836 + 4812445494938381664839724186613091405433366166945041207304600303147241282114042034521353097954231266436563888803937496834589712 + 3378087498752524611421562976032943128888258876939559646852575538636633313807640898785156463287303741217790696080003514700600687 + 2916828602935343245489574829087284839505734067476926451104496434541582983914416281292812699388088495707067652976139900162078153 + 1962925444708479245069456050692574860960690835458249514553536707157865617717301444683893731781098151767222498616081872995504896 + 8173903682609218746993851247188524280631112843215665762250628484523471921122641923241385617676960635551184550463145418449684690 + 2919933149036430836155770474842583951453613631150982113752681626101371527818957365564134323888669717562193735500885632774199608 + 1609040194815030093545138643057865379099082109649230423000768558709693305039551156969735710643672277845208035827493067182565724 + 6908049177553254273158603203912637795720376483171212869602699514186725461068506421013630496115516175113680573200157037543353536 + 7096806396941038667344905110986317666939904573544009284947400783005195693194103701914010433669991415780015087815639572682791514 + 3680756978168727352707707927350530897842094443052210887958488018513662258743146529661558086974070289076864455883890457256934114 + 1990854389059420349848505548169668954938843880071111806085356892226974097003547436768393216697877346132002814225746150600875921 + 4374492277982018508835930955357380285574652568017468028145914088210165891776161047538281175076369924948661559170128551211440651 + 6393090046195615488795758266312386404911848462625030168594274415704463604586947949625250757933039912135660379167156550736214014 + 5728243934436503311699358540925223297549609990942386098315769782770878982264993140803173130768644963918006938211060093506696811 + 8242993502087208931436768299544970974899425557012952209431499521399155627662162396837380424393929443574272383673835625796387465 + 2907417733054963303298412175669470571774232019901402324926626651661243360954715973085766036500273697051651414938093042950467378 + 6785894337286818807967188916007632157799934091531302525882785328964971157321099749451607078727217297793573097237856806946698841 + 2698558719450879861393803875387234736047009367170703129862250880475805397892793129358764218650002148641764709592993056227677164 + 0081971305438865752091446464085352177755237063190907377734114566649793616356658589817576855323559323530686449621884731840150788 + 1826939540243947080817186653825740075444935631469715645767626335326860305087307127848152820195439244125563274241365606473310540 + 8086243883958240578268878611599696204485799969418845316458163879163274209827292559109804125366908746820981499563030997204003905 + 0386391010049409963011357239704626669689746915426124197111331235480408669200583724344735150698143659880232480059746405028850204 + 7070621356175994235487518719187218494861976025281218293612423462113181646903473241591007825352754630207984555163787848738511210 + 5746214941035113394857005157649321493185603337720914119128667915231061424163637568324581504110784614852811094476768652380182856 + 9112517888906528267503001049949573135127874375506725576149307826638851599758326023611417494647191891545342374452874064341534379 + 2427813650814077661287436979575407398921688136831196702246080880472345267198382221158754713144173467705458354166291752011017130 + 3427037443878854401716449891823089902160247151232344993329995686205840347612271617101573796125148445827775208799719717001561364 + 6663271105359323644532079372626792834540392816461024173260479629489907065371009161907255452160867279588979514640773444750654047 + 5973386387254971355387042682264494417370956942797373987206113528047687059080572493246240752693790196755839336183495531383520500 + 0786113322119991260636829390212550532753074849695602064584008995135867708856455125847634381213436388672553141147016113632022246 + 5315245540985412852477846866194175059739189599584743384794049685678013782286205098025299864897730658726559776885622145372207093 + 2947046237055804495388214736381241294012375243250351412075115454784594240484997746146442841037234277389231586332048832314609602 + 4940560326735767175083614737052886039378277408442894735731934794992054788139312451587128497131293085948245032106415584594528368 + 0132772291233611554088929401128017045937329980274933241381990578374018596495898631586186020586965351932668997510872004538098971 + 6387651070790112849045385204698059096706128798635300671169181792420546539133767532896269735055635232257735434930885609585584847 + 9016459024097607724588041340562451108743288014737496316921528251742165151671257409207041532182399287641327587310586187223956817 + 7534883738445463926481692970148340291005837757179973259685921796789142441810657257829230854362459214897426800925224271446152113 + 0560193061957298132549489635518745231685759631661778699250394638322691452161479836232887573811183208096513244778566157714733211 + 1547430295477490963534296984638628258877576273566145152920369666682577588376652374130208299869130148553971805471715526321961195 + 6131510592032893543765491267410178707297913936975805122290905928404238596549066769665229727337467790389337961037867643489553699 + 0609065177988688342181444376437189336384085173474299503743870199156371216381879438127542687917993261590322648797772549606051885 + 5486486858037007564853644084702405129390388809213365108089374357918264647019430516503970264903210163964653753490047274772902330 + 0461300174226405350596681300475321223682365336534045385167141718398138848125986935473489411898994178547406946367385725330213907 + 1293509274626976153463652826393079169386713361776443893666230924263947932847701762953659799461100689690446626123374959253884277 + 1306373580520533113454583490110255646387329350405309931889447247185635126485724261288069862689556565591921946727772549017471108 + 4575946994632942954732825619796920704805541065043930109567542878956936210283544264617080903536339854736947121491562648913229061 + 3705434044613436537344272909123399762720035093491390444488810776264889843570633561219106570438196072991495500597843887820183050 + 9436774296203905562085230110417550251074216179370977223886873788396051869595539699599654175540263842606847704783570758848289347 + 8739544541060559735321933455321086474549444477666793232318769795339438758735396350156993223591143789407202109979058296632555075 + 4292457420547255026544250001229816943682894619632431862491477990869504856164569154248439119907994750443837979614731379296026483 + 7759359950784829354681821925764141180511597239315053998175532245470389364554510124781233539932768390441633522487434841829277108 + 6460068597420725351564334958788443977520626552046510044910725038151710003467025913052244964411427404827820741380296783360351862 + 5211054158075000733081570753562084145801231533068994378093380973748015206056523195741701721944088905307131000364624646104412959 + 5581089920926259625216459931700561828077094118449960988240945610479754976194870306805076133937666171790939426378434449418282506 + 6039057527913534217575393813423847928955750038761332266774182283692275076570170104686335201401167177077211434292507428463611621 + 0405115165537284758792010216853186661681734615099607405177733845109910013152569350731884598363743840624814198617754273927011515 + 1407618016023682414983073935592618659194377480743081488662206405541839291934958759003119610099774589701968015068594030177949217 + 0790315691986911016674475309797543936300728937674591920985541138152579574295860682375269717640514911824203818306809998011275060 + 4382117983381412972994275528147432373242673418215434465602805780063289348278856395267652713597654578622689358031371373016193682 + 4971203890127140128708179164505005602256484886747097346823610758765747601150832737555748482400760746795103492345268624660081193 + 1238474101549902789927134668369786012288633703563425355984226013256465916402333622807942597885223175366854363298056733781480165 + 2475056989181989715935840837103963570756393472493139600699839539995767516688497969127775142807367604482540314805881080534085920 + 5110483916952128964226635567750120557932419254741576165448818621280817929369091427028028668168593266857526132988629197479499338 + 7382097529770364245616319813419439630747996451787212372784898440040645194051307376865641947314145623284843530906118562837024282 + 1180719306858134644273288620402473339088866088558646666749328622134176944113672979075244216767608666882416653166422367766359934 + 7454692494850748528168077614552490356358640467830959916873691009192683520419187156489031520981784955116022176529954332656159900 + 5703126531777606205672012335960434796458742284617167876316278828807209603472901804370309819783462306443611963348173237324352923 + 7622935915352142387734818536448742013947936195902370636105913778439778154319304174619967238291501475263405722167671985219327033 + 4192469391918128902822325360387297654953797790226858555687025028458729211895927349803665945095655786671449147679921097155626406 + 2780677237649339975622761955036413080116980723465856549727438471457957358521359815258203894427475417964365478268462653223640340 + 6384355742271287800278025268983527483432389226283229170112845354988683227778986191910815226499442938779725664362022274661446656 + 8983529286956750153487719136198257278584599062333134754547317517831680020077715886321603644059583997509690986046227389994861108 + 7329782796097322937140185361853575699691754834694652931632748528792770060065607908729085140248378226282625852546158156687855610 + 7542858690282896923167331772353246169388345238738453225427851985834084721866947550098641275435407170332769801857389664211235898 + 5799583185812386717849837795175430854770749931463501139883970148364355569591352178627597816164651268936590016366615235430971843 + 1626691744466309451182517845050907803525893409042451069687831523577743242687080029262942742968372360368621788807914146915526880 + 5318459023686131069631243003764992320489381131276662425282581511713606116289353391248019203404378565007089996278162834011328054 + 2940914263304203321901619997487124198689066488749388375440671721678381773728920019056941032982814050260828373786697860844945937 + 0935106263610485636127316359361586585062460943315331019818757835533567856247177900197592421873824025425985298148601575872003838 + 7678845567273084139170475285839065925039600025616987691701666903861540800590513965950744386259900437461673353720707990879400851 + 8954549187260534626790030686600472676242184422173770737899202674956746463128211733652450269429272431346452882295888511514249530 + 2678743312277245350760231139022995628706226321476561623183303095250671287742041881664219630594695703026351221927214229218759706 + 8754746770599874955073426285210045733061478934256278154824723752843570542480374148666553082213624470594178380618511944338556770 + 1258342170448502309847524118053510267304683961421264512188294654208652383435713573419843151024833136714917076044792376946554552 + 2686790894179727162588194653073820095034068415445717821765878768235572220948743946189649565838289653662296142578461681042115408 + 4979975702994756010947392018214486397764251254586716632357033001934850295130508675410334819960903160411122706650159720668896818 + 3588969475934951426055953320940144471459990302441248110905750552714828775127383961567862284258836730043491152173444309138622805 + 0885835602018492226235865580484440117123283431801851414462459989105042310153202450298431895243159623304698553633960555968674076 + 2495404637338396778354332975443524901010204103490577360377282407257576116606492214532864036869380580423420924036214250605437552 + 0273823801820228766960129999040441972228765926389245168282516822705610151382079832776017382538534107323345050070717318572440468 + 3719693296470114077607298610532514071278447231443437795910351532332738448270051379404482177889663554053263746637709700053641967 + 9828951429348008059079973550469791268813640030847883313731919419849614743360559828672182938947231250356355114573949483277719010 + 8160147790535337222916241165963603517851503563087426894556730214593005608351479878086372777584308199478067490440060949884647159 + 2948684894394971841029364986618911826288588400559264365297543464936912860908849309130216792677280193265598685884468366012698447 + 3139146768567604514882268160880542261286448423327913447026774946542138981930662613526814753066924945383435581070740645979592320 + 2648770517875200683345474598491811627153093170689853703611806314466352414707945002443742160480066256003350127740349411901099140 + 3308592816806695381210143529051488111319581220479904092647583948868369653515446635908476209492392955841254295107008775348098134 + 9546057832057661112548846778480873064251831646186943320977718022174333455691510572548784701482794043711785251965805930805124302 + 9797598220825240487337675580868560618123083511865310119111306172185132317065154479238514833175902325985968356007574306322665172 + 6169700545459665615556940263207457415925074513750097043236324790451429771342105725243301487094857682554118664272164353388631072 + 2065773265591123476370674843120027879502951065822173174917589895449890375502164860452910893685397468281488262706240927914630538 + 1707471421521563472417257512298478800552951214730430454446551411959701879859928077389843110236600965268158074916952323108191254 + 2504020366275453319690764881376901720307904782764373433647976640867427413961893744590272111954111461916745192557787193817126040 + 1588579151481338108756894573873934357158704669830936720767495898488860812251579113152660788061419535504615986627104261122375990 + 7331623622011754370645778091243569467777379728540842719407347993337611435365175147413009114962875879124181378102542276566594108 + 7484609326756980072187285780841286543812762762534587441056462410575222582806689121646585229111979073490526305371963936438467919 + 5706586317647554978296224372749817614542161459685489294484897802898801747536653246958762657311576344225567199024088879682797895 + 7982416710167868709570332702438980645861985176457876981357976675349506324625350574864591977896798566893422693217353865223434242 + 4612810517637816971256206727690640808547458195070320671241318078156152911173576755031013652809873321281227880993755057868636257 + 5869566853914426396407700744200965755799089377206196772845889331869496057116760154715122075783787728423594874902542137832225559 + 9589225721722482637458883619679136109478999500918895037360018469933679740571642521146059558547268528193088694289457407297389417 + 8114608149302113225536168603740452239048816211285413122470267658232185443153634579198429078537401989102386028340268733889611123 + 1658771744647637356624539664960206812688702241127922503053926273465214516451739790546967335354319444825617690989800359892589856 + 0053465651697302095039711511050038742810220818349852842019182724663703883278427036626489847521335203092583455303768771456368837 + 9461783935995459315552854731516681231226811974225458662840484653357703794689886592991537310946084831023202899386375997693481512 + 4533585921481186000403378289480817856084298244494770175994273545179036968044114231324393781909984894250047249639320078105176941 + 0088337423065130496692628858394850230047403024636567775158827661121094757863694577077324592397639708861018849419374525563390572 + 9433907825695888321692655143225283986904641901823924591220365135713855259383744336203797993519930945597887702113356326830645826 + 6988446116797840398450853279454162958768243775646820798515687585868046231740714350466068297160555230698894793181661331483900976 + 3228255598385373641636782196372646263654896275851591790742732186929071139789500558984105284755563028281035328678092579289714000 + 4681011094010579149015425103883784622081638214345888273901960768244903621448040859732301956914911242855175944393888342553563087 + 2560980412018398873410432462155957943116348971819529996430919042949095207925589612393187400930103605496273814170584912659092382 + 9069469616610979589154787060025562176784632650316733720274832314981371020706161084351225782272365506817110974959084699634535788 + 6765587755549143676480283034752182178980320308874937062805295265849032617917049285075020134633510431916668093086266525800515736 + 1987129393090049213521579473208927794007157494973792406906256045288699283419276005662236119067885571670938877198469481410429981 + 3722619269607651225319072582934109199126677644296125933160645018724047938190291886105626593185859522559253131444513872231301882 + 3878903450400959596968323921819162239731394330071230682797573061816799122019281619186466630116704421984435128057686311537024574 + 2171772674581440679441147914828465322671796713303729214917204516452594596558898159147461291026535836576291138961274078954494387 + 1278996875658664588862768319875101010284199226028473900312140448349990579106956212227946883352757991736474264479730037979113425 + 8251737524782800721142346398693390112514424073577724343296177123905498209033583895128953063498814237667366732979745537429555278 + 0896743149526940034664390783553213882383502205749882093466354195761918368893140199641725113693740413564898871253806941096124190 + 7796854830589872123486600630498401268330698814798157768931103798808711643064916232366065296644778046047073412187780619253278677 + 6500537503531609708551372800808683958268146390074367413801774325497534682441389495398023074938743544207866592122064463211672009 + 8374007659269318743410884141200642883663626493756879447578129358932170292700541285549708569643545027306452528039696051958912164 + 5461313220523803049639223578843432913631643532704665479011316367050573380692644563882130994146341345324086855525040200238888685 + 8089200828994642111859047971321583377842360402699515255215765930754030446170133309029861283548123601950771958367816928039501979 + 4921861981592932540366839797291842409375656173168252866766746284441002285941098783812692417408647250610811303546299712956961745 + 9167799975366484899208629064327399424255199740686280222254809555146344897012896217389558240697588684347940576269967072665683864 + 9259388885200851860744997606520800745929512006692275733677005833780389985037437438896650034386964970221299725643606029624930990 + 1923555984126235140744073661251739569863134027553494228555366490941034788475845541690058986834251129830243447779754071605873640 + 8546321296959618681680784347875855095908171158196021873844044080735403609307093046577378976184646301996038465275795577308210631 + 0292841602799520083981301964025702228115813520124006499666068950846030422607104364257191751077960220252620197225981403964787782 + 1502322992487049171872430148257934075524270686852895414785698734102981748355080650539194240735935759095611779799454232906920170 + 7645673745116807956634247517521534891766878215315481669195796109233157590171328181080639943010458633508897705148841450600988472 + 5372622766288568973430030404326811200585106334044292931194542876927622884286129265334479806408440904927200146880239590676743160 + 9737852886366125426992930022076166695307759649277919719824038921587655496096287480936269368326605698820270793854355939980396762 + 3180790631743853089037422811844405317287386545411386410379668362987107109358079426452748318127402761332147799830440163526016129 + 9051792458167155549317710812956107571797762247756516089487421498534083002847984096816239076561386593955153876706013822381927681 + 4173095560231171732875361485159122658902814416236442472154640300288401422165407659115651941434514022078384640403200843998671972 + 5966470556331046673745430553457883526280940892044422560744252802816860579980940340917982940500224988618235941234788610789509168 + 0789375239650015659257828854233372959702664651151444414363942452653680312005125741160555543069598467797693116222658921071003474 + 8906623899466461239060702070337224569185523906567051838309830757794131815206179504935357263945463042333252081048931892858013514 + 2565946185596833054040544913117114680329109501977878093743966290348734278988799428312347727405020457211698124070822545220367599 + 7887639027440626642608258462581197685627001806341140783071773706310063459682140433859377089948217599328491885205500920242752765 + 9105042785087589492163764806502467978793005126850254340679666786999523605304678430709511644540488408967072195820451312364898977 + 4806602335002501148210169758225301946374240051070758860058332659173580299590222924023022260764063882929324416573334085874519685 + 8860484115578005776711551777005731510087855975894724843956874006078066036507250577776451260714027733005242056180700853839120022 + 9972510062716845450929888769682540876602068670550887529330503339523242901354677312818632650357341649500497585776441604969459550 + 2623606137079639076047135393717143616094073824102105929404170935516181957666178130675618698894069752882863773580174806425770058 + 4036671892720176871088682314351824213287902597131301780764439176800136663620269901795969751693427552587437595932156820043424392 + 0677294124292240149296066696637747776445858679559483174535961774585189431151122220911414705647847144029722579499169874681984001 + 3515611659295600392682520429928899147250410034409210806506732173247308027181439461299331344368884698174936563300497600474483708 + 0063773420552619484426050490136425686777123343387056930411442496315945289353053161802745807953399447036489317450479861853401831 + 1025437802898670603956439520711493780674154126180902484921242469929281393551385642769157018539956452797615106532069322627218483 + 8759796578568398063968102679425317647163292357375418469803494058822777510870684874739268000355169575539187937262850844553141671 + 0520130761108166376660600783005143635657232142524978468353606381401953088627097253750920455395288123559132491257402067683088919 + 2890887289996966535342242107315365601206035014159576380219737883962373302977227719789793402712556663655879816814402801231940391 + 7075049290134330330911964129274745947329781151686133509827045508476840011833420977165532815261601339404747681713954176358695787 + 4190862513692697255977164180664759574127822507052658315853043337010650269787647027656260221445450941719360532423677717036461514 + 6908155746961875390092893184110336543104604423996158420042649680420697682015958655453176718660496277341803127921088518280061343 + 8331309328194407889735199978235437818800306669005429636917360222653217191676841870581785131998034245906906399415366961802496511 + 4025301862689940996141896458524993405457637230423945068131717803505952316603722440206101338781745994056920279938566008667957974 + 8407156560172061727221211500538117499687747789630891734019549331980906693172176957439813668311313041124185359330130579817813671 + 7466416959132373028000515440426004927338552129675365950832267054293724597329240325990928091976976797329108528262309484406803795 + 7029882344252063506996455416881601769204928489785629548747090770306190718064516950313796925310576174715934481881905681054628070 + 6880642279419324327941511209000580929409891074059158709439715032933825582097408872913695012908119133558817540571147731630417054 + 0450976304961807996926719984418185237945644387146277128118939816965978556618267349869880710186417738649005061794411263100794703 + 7430304052534898545934660709004803179571319216041424124846029027406133093839979267839656729246840664461817790155804024698154985 + 7645544772776077953527747512204638297554270388027111651502874795299134795410937797070656228161921719694817879801901345933313665 + 1313410076049663998827811921356048583498283359569530324863158193199961087225704771561935232487625934010979224924950123845221938 + 5542450907649094312430747916423053695607417672358828335758664117685424978394617325307248658166202146920547925646776725087468720 + 8125710483678181819120321493187443931435742819361342552711290450551262872707443639793745995943576289709507020621251828473114770 + 5808995455056792083922234742431742082106369821885564948694790039533752228468465967393391425326441602867483086230714643155046641 + 2407915004627569028579526596926110527896052886334582385573230907225818330304996992697006735418150830862621130034997989250568103 + 4747836691209220024929494385208567863244371223110054782899030754719240501536232821233744154670656379727685527957774155672319475 + 9632183735133215405359145903218054467186662532650851575633645907886287911612022173510068469813052313582577723168904869118582615 + 1758443894147315526858202229285381300192667883978558926059924490571584269631902778078169815289434853467255533171050775547788250 + 6827379725903576619807972215479471705793002981926808670091729392075163455575073588508765374074600361763199064144608650998814612 + 1139348883195112842120618191199370895634072657781661691958053236883789482321308598352679539450892103726749423679416567117182472 + 5628380449503846780627597266237186381426941668768981275727365655268389180764025467621494196092237996217033830813378898293373834 + 6249982118767143075646051931844250281862161753132641089322013640269043322260625061753846454820580624883961230554153956989845603 + 1506389246361534372134008198497771836659467625678409854914006570144648661265229365915719554541771143877999578976720337073985818 + 7005263179523699177762675340194056182817188450058666203568903779623473238455975919469726862072009578002483873154457672262756142 + 2974648493466373909300392298493641388947991203930909247567333382267233769728042131150238686456747730553128288781731025800074389 + 5103801198075821222369482103926218823537252278659224466101143285542928579893855240568803378461857010249847636234366813910593321 + 8255444368358914408018189587539831385866661807993390145935560791507824844153502737089683973595182396850151415917641412882278385 + 6994623624086457510788033568938511176649748143257081559534249807952079088004873263643117220080770572410226081636499222544341556 + 5868861827549149829709753995576140261303291609060728919357591890769431437067208298630183272025511291993873213366101172628545169 + 3536668590020988868465523872067378130539719812107645831862475320339405404292929655894962610265222780223832442563481658864747632 + 3855559579815655284020206856324714890689773172461142431850331038157366681406979208119201701019291754639995462477549126425391350 + 8450291792039621077539436402960450989801386738795258875543765926494042577259109968714035988972694939518009619956412673656801521 + 9433075795122748111293126771649210779744396506362417079033687912993766618349565561906099136133480366162159291355560623721579187 + 3378797875509332216281558051343681937584540368139917115626876588840206579792879445323063696609803160334574023091211019696117960 + 8286659856511129135392256673984667705469454940089344874655311260297659378259031305125448870028720171028350742267966605006358033 + 1559883131888908511800248016547342952257309383028102249271256078844439208862517563884780187208616611438790446776997799461384713 + 9213000700276768725565441947730287329227888200262127732583001595805481558214719061412862292967561082950848644790833398460564723 + 1237463356367627789252505343790157426584837476951882453112990120548575795054118752744721410491509448371890573822392145256573546 + 0705282244277315586839396249472907788988824858086668101214804950902161992883203183045693099700874860748969961552066568180233875 + 3649804362910298143091615106831740058421008356128934335979284102172120855125136327683861035088765145754792315464262726624806783 + 9434730144784579817482674138286237679514020123482574946846405367389289759453442305761634017866345369865209680919734485563877769 + 7735810389258589718835809442124950108708303704945904199371845065484839372522859566124912994258804441548671551838820818437896075 + 7383779025406555287701082383561184897642996999173556341153509465466385364878232088945280693653997350128318569872380406482923450 + 0873625836034957145587001580511059464110231294763738687292419746897783167632026738408026265866915946594910670670203196220111099 + 7591072259741426420367322902499121885937012842290323842004604562106110626665272233088406003591488022718144482545987747891823870 + 9175117307974364573779518417573849521480439605413624062061689756346227400155445091604379572899069013192269044493766848399848392 + 5240204070345240378009455038862456326732346785249576960346569277468135720674493354585769115025511723751059422380004118585409709 + 3349173998694448270286501817135410477702569648480525937208264068896413487832339295364105296137401893118290448960552591536754124 + 2721855377073042117183109540215181252714104113649070283807754222580162122302324470826848007123339852921541117150545915474905734 + 4442237467667117475961916917266329385273400917266015718314637687934575915917583933649989627896013912399205012102463085560527584 + 4091026285900629392132231811067909337191049861336953793421590084466340471776345574531068461460044327698926685026108185944785273 + 5202568174541673346987530914965105932805689677456919213224331168071054852507039901870720345655716025476685968559834858758422493 + 0614858796890361150654138608860068135509273139791153876597516417474596470901950497034522305572817639212080825359999795816120790 + 4690019462662785935463711750437540580321430169890806355137538513325878535253326703788253684313085653375194280379587086774403636 + 1192297531414960747356858854539457018921020998476941206542822005080405209643807598603349026957600933047420780702135587594220420 + 6385879114957936148095665992720513226197859511089355764654052901972661068207137358088876405026746758171573905075146612191621724 + 7225256074560068850195651541217829216290435321680622077492940113765770295891334808874940394348277026794361425754981697514840551 + 6579386119350941004072171940171520374772062901476128261790580552298150743389764668933362002827319670377285437400224631386514541 + 8225060930462866114265671430768226751533399557663700459188510439035058277166158167696828360029527807376628848000272330091576713 + 0060985472860653127812993949032906458731116791182858234879179245998734711417931089452148679024170798661176089885161196837664106 + 3722805008939449259124307009136610112592018063781886320098372656598331954054355261215122816645348365251690431718100984807641151 + 7671563753475866652087409998956658850991352510305691362750704516857124752942784347614592502287785972007339688267613862027066735 + 1058283061155393934892259910225706182663785747481861117691921311446649045132526185682558542054377226003665649454406375422089246 + 9732227956822666337303879201449758438032098745926653063569926833474234804332766368153105341066282800778041496886005184241210550 + 3671076559003594556531982936604847786145732585941552091406028722895252734130685947197552543811727116647815405252804851390263345 + 6932108260738047486627928786730592183240725916073436786293871274003576099287405402166418657664483313714856186223383473022466647 + 3109816045417430083537878210451471667742535838802468841651352736464574926057073048472886864367560530408263557356129708697457730 + 5131047990674797494394562345612521219564146779615283892037401029449518064490250135341621616256327661631926681344727899774392825 + 9793560539429965156147946048811944830887554283992612919784433839525971829092056423046384752108153956186882584119526879128063725 + 4848894438740997315189560856906795393017681147097928684567412396811955257068230623390617279746246419592475583485164533349133972 + 9247196347885177565475533963701634576057917406510305607776085697222055528129649096213092034549229625900854393776713393006598014 + 0895574299458423626122169092017122327940337399418681543962293182652716019527292869659349372977261887962838657423721599638764034 + 8069818312801265892359056947805299813404068292205524125399036272188934298155723014962611157660369164361085013693243392717540968 + 1746313469892957608005716135870516847580996237870651257913684437466577959076954626426758903637186057505535214913540381448786350 + 0826130380070802481888865468100577235559992056039751752075537240976306665243883422413804381659448597324700429367218879041686316 + 8783969310605138136810926575209117557352903553802462523920408350875226887462880478648547408932195087998226093346126517623953622 + 3655963588132204550439064715232312197339282921758181601943083078440247650220106399066615678880555199248431536315260442825292972 + 2898418712339146920156618115849473564647025888554958680753487875973131958912468912448106432964749351366422577093050105438712807 + 1852498129286540733225557917645869957332090278845330056842464816843083325044360873406582227952116884337704935341689726805650922 + 3976284069253193914079828201683985526108157492968673193265258027640406409120387997580216531505549000204500196895696438933985023 + 7344227386409800578949975082890327124630045606308364332447462178940410322375677488036092734345158152279018751575711953710675611 + 1365860719506143953539467521806358327791893587420884033512557356449628421974197081525171097681451739962654458105945042338824044 + 7339951041651291336434788317295707347631976285149811926440821662705811682404836418364754712250487175296474328282212659994274238 + 0212161973979980092408896174977830808566631947896643996545492647236993898876722578200269918604906863319277003087190525085408577 + 4872695328272197013637039406318385585335721591609046713028487734545081008963689929406578869624586103965589484238888590831714070 + 3093781382852235095749474972285903266360882836791963595009076006750220113661602476802687021999748113402446232401462878936110934 + 6435034693320558902105688910308538965196623309949466683973971294957981775446228096356658904951613108961843850602970532678592796 + 9900412913465232057825708257994535036127184304885007026505543104350741668197223958911527343764741682299736861152999772201279599 + 0514985184283479308437214277006973884479296109534451984897036545588323471166529442587769709637302971344236763633165248653048272 + 2548677505362732783025625571327094753804197898599649990120724885114160782630110803234921618274764179324553264262464188071111602 + 1490102219572319216164107062405778780633273426833137366869390517112371874174117264586848123441331500645236212846316718716883477 + 6374557134532066647778099833443353940716636987739316642710720220881882944339283639205849477871629369917099561362221287484469397 + 5537933700604880504714026554029166587597577826204845542181354963551493735767539318268321221914383282788245529093887530478824907 + 4539736948571324006868573970323898689460869616752573795437663232396854974783326373421982301397494963660135114656842200560632231 + 5417628879269942844019831356484605118567348015685889718110291011794547506306795984565230200245047127434730978214554859175571386 + 5244295129306313578981901753289283565322938724988065200258490956019375699629296714989839545066652554067148655850643910689520282 + 2971836240187409511885225271973597558472371014435493899110877817281998758924278138897958733963027723716372919312791817550414257 + 3718036377547310037822620295119160273747183347935451508155041258644862468137971759991204189248362267356043409939280563151645203 + 2059403653814048643066476915696010105560937121353588493219472721117585709084500577027269061641086537899045745026346755806963182 + 4321247098580397470005864122314116779988792921164422171095663365610591552259489098505982208555327107941284015766148898178511334 + 4129075760977557106793231123557041651779523250483585239932004312719534628408382643294636229121610127684366632908893383504173184 + 2529072874533404417364878145806482135038499775952105421793815591456627903830117948809720387389717200574623969207051170720940841 + 8319746694698707336604137199806790228573013581807699678418425604568242103303802544153333753105945256725487631110225791990763711 + 3880160358558853965367146276153313624158725831047412244380280879089394407413109649993209520904697096729360273647396579418687376 + 2091906829462709596208568404663223009844823381264480008433097662223468678702122339891481765380241818468489069582210313140199504 + 7634167069455911451763369770809802453049016134384625283172635485682336911180471943157282346432504400241673963332048163371168819 + 6945528084709716553738011980160563280642542751055915815221655609127228922438332498633425574184424076324567457335614537707491118 + 6855985221224698806898182154405013337026345633363958698774698699505064139860586968819626692305575161911369355200549282693239574 + 9661995161189339321012455875057211575581587182476156883528607442238967236926672903199283225630412167629967841892682077069456544 + 5556977126081270383421853880021926196747677623279360503448724398127284807443362608046943892392030345708092629807650879718315338 + 2008556770184273576766805643194174770708191017610672185545130733621276522353464775534219302741371801405182864900478774809576537 + 3865082900785088869003731961311138273432940384506242628178208362272250891137755623037615929981020628600026015312604846649871045 + 1810271541153370013506194385701474067688519311563701121092950023460871685900667973434789085894353689769155959515852286976707125 + 9220855281244525680311255117572398240118776083069705246489217127641378521494501271090294888487837045515780398860147999941580644 + 7341485956164711767365322167960284966203049807458284565556017984048646824943506319395879136232290301571995491168074801397213067 + 5371405547126368328180403806382396944697802094247261778722922120527093199887586224288144259646007747572032786762234373440343768 + 9641998676406552363362334096338343938226513712459780071504106769464358782102176567281764333076640338559714360625098972864983029 + 5780224793125175832096440772460219675603258721147649221639684097269727175225573293185628479999177881598175668238919939024400140 + 5871315749737173437146622211284749783435729572078139529891438562616324259909214610231102730312223921245301659630109254504380334 + 6697637358599635782137313649853967748604644159075078379860391872979880640358744386814475406235163749464766557762029498100317344 + 9260432917913444420430985635427292687992391436924828756222785655924726309271829922076362876173530631675597755661167920958784469 + 8008272163146127952220122593079694523591964786341879588418492633364085713190449203278430539536800444410958318893570820694596913 + 5865771428552651226808077349460469511350507824410126508014924137043903316541107301501243645730254790431504727160432598689746741 + 0797866504326277547835398517451743711623314102885283925539211029404096358855485908679412360891989483761400122402649553985042303 + 6315338269917337190802305575034003552890761126872174385267928282692687307003769845400327640284655468895977857113820663582843212 + 5883143761391732179613778683464000760776952507578651405618216504779945736760856433526347237980076786027307666785673805176780505 + 2608019170724255979187609288672429113478903050968752935506997075853793110328285209939065370268834945095553185289660445134585271 + 5934178091636548622002305410563118241322636012045119794891759960583808782939464117247149044590174301040963274743429124451974081 + 9822212841254646950102433569804383682318140936706127266382165162763534213426673482380144302560262856995513292329891211427952322 + 4939074943058922639133209628604240951813644498408022254626546671648111368884617471264005460319454857408802054462873323814596304 + 3567851550694955955743156890344607975932611999373517821856035756405925438219730313496771878294219292907299376903706456079314724 + 4355891716120089571168867921156570013309057339164893294310027619061553640293850173132141828093723591781265620877693908024633891 + 3432150765823697928455051347308237232788126878764759364421680111689906395962403729413891780224106047993476140159348719814489238 + 0234684991575714928121012708547654894568292786765465546202194583822334911755447378931758555122045328265456840620648627956740582 + 6213762564459648735386518381734716590458385722741140951208497160837103126054522292981022939593107580769282971517719856277138950 + 9795430658880195944561326976463238641719113418421451290008508454179670774519228875316092692131997401436104108663905564902246214 + 9652373982485787988119955149332007099514930250170109206849474570844779657182243727422415156736246473756296181666403081597210612 + 6363221919442807657179269261813196315614323943076172547080772762082497876523976444410926957078802241443845971487934887307740781 + 8442538716705496485993660458983193034639571775952652456130115624584796446966906201307091498198760859970990751619599499849168922 + 7540755071266549940783200519568012630337075342163311989445430751720634069245959298519839175642543857453232073106471321794307960 + 1699245059009156264426959609151370644710641713396754020166970217700932248280718651485571836633670709702375632170998942628345680 + 0816396190588432801059693946646313280382672711087244012208759747817406868034578850546787526313820913242493648577159472787123381 + 0759322746357530465987827894614798343895157467747058744481984104257507440485290934854164189380366013210043776529824930881371048 + 6385658080000822018084506735695449199723297410443658699992360702264595362859622022028092450523165950738306668328519968101921178 + 9290969633149036611961423129438616262578501454017560337962795366936304454531175225394994520495848281893733418969823834849646325 + 4866905011511861701376543806753349151579844197278285044705460570867283644779510401658626041128258372474841328027560368075591684 + 4097340967374048459759351247293757377219970623863320131555594933368226711740987383236414710324945367020743532195606500683770435 + 8777289231702354648686196142357855572861820397757772835817870476148855333166772599103631182225390962911857675993162562793056451 + 1643701292272316612682496492137369576459996136135417810378930005125534965897227946840522877611416279622753205256995171831362038 + 0366738891350724663780781742018384952618867530073606447030185424566647732433327301660674858875240792034393577096349757765316310 + 8289591408206074373434407333542355057011414872348953466323958988208406535831896578204946085981588003478321397316316325936083627 + 9704718565559121039339280928457498417206123777131839564784077774260566019404908403357317188872113841441577298919813210986548633 + 9293886303171570837540716535349361584600602170148405662530496205079833641395026663688854207586823003823193883976384903470625532 + 1727675041270249998973772127828169098733155135266069947499638944765750528948036161984830730668217006998355034769138526948886812 + 0092789759212121413625842309085282315688319684507180858726957280563112424218015623004324904038907228951254860936129174811193610 + 7248502251808372373101361237612617365642190393287142805878594705588056326330546884029678052177636399750149538893582015648656691 + 3367150919108114535725714981888781359653934702237037159199343298241562681613327166427987327289684634196866794561168570101129576 + 3376393226054192039386172081865991731275655717454440752850294664224843539838937920883445641690602345087514795742186569107517414 + 3623971382393048718491241619316545941650237621831224965329865224908967972818626887372855949653336237529478398264567160685068577 + 4052813893095863733367924664141451148648087387776942749014403408537141959668060633169208644494300366994545481397333067992909358 + 0667669402093903159518564734675653958529086910570255872008713355774046040785518290333034404789497402572158389475386895486868259 + 7468963766629011848413788837165962853506507117471181320045844652746289086413801588758664510368868946415159144280007188633881726 + 7244685543653493127669292847190750279258471265994953355225441242455255911176450067019362851931161106818923851255323971731656588 + 5234890473800747514454607303289634698091529945347698407177688996229422965619449293992367330399443066079751703944482713291326343 + 6459044264277571164204689989304404957960666476059760392612837445978755062781098058819661144475485054149528425812865761888665230 + 4335062014272927898970122302854052906295227383275313276798239957308395793035503825814636802802824167294443473540831595897555019 + 7272548964073946058176039524239703608785612474858328053422538963447385787828187985994849316214926394617015487472147004996421715 + 5996250931763812814551030631847429127490485716717613966608339966170653265360723312151608339298980087240888475983661731432872181 + 2297536852364764322872184823063403907099469015512172454623275616030363118664676670421610327708607480232788374190290021972622793 + 6341746181410744070773088966325798253704849845010112635545932402181743821794042899160348845322610793015131752714444557452077603 + 0974929188283489944704823132680006629007254931129889666199080416689925517182595848963795936091170595822025233402048475030835352 + 6345563891720858751435127759306670956633219054037703933137927110019397801896389210768937954353107771885376564624836527498565777 + 7406605189056950050564580620487220225704555865872099535962165458171814654057503675391062376917680202395298499820248250031013118 + 9646002186451042668001138188414741520592517338749162144757726571293411846579111672780359450504540363461450479439757376293399965 + 5620887367929571798109873216776069586763980872092222280624201174614361433514239488022226011723867237579885237366697226018636145 + 7658816676965243906096876039909445364177324988679848256414790985301032302828151276736018655718069421805321528401722943260148087 + 3504531887253350368429518151187892137924735559724530027941664978322897818820489478004391185810494126054267658700325358193119630 + 6476950573687760010199531144942136546086284325150545828401223666989902218958065517474495615521528611225439578736181496123291235 + 8141273699960775743878136458997315091877968088833966155435545803714212437024032432947661397098373986850161208575249088483734667 + 7526564869781879172205819920641629162261070844597301726270751056013595355206013946667713217060767795442616244184317275433955181 + 6807778755059399042252363801724898729347456888637350665052001794960468288523356956423878794195125458046129085019792922364372832 + 9606605635909164393346308754559022246397895156754911940817409436883533684563312856180585298884265000503280045621922703129043223 + 1353282688124152832117904166784884443448057703427122162928095824570260033806131301099883014390489674198929314751517488130229287 + 3941712694041861559776002423763440625536805158907454771393762216105225325673929237051966211204216493810015246774275044495594616 + 3694132772158289887311123798026659094603586436166517150338257882694213224057803554027693325965893134619716724281180373864668897 + 0965421930380580362871564338408316626579345707567981028006568747619015807088576948951469852219385041334895298633260796214042764 + 4365061209195177145333592267894941789748549729388820653503884365772532158665492262305741107905299439181875779535940222413616201 + 7002692668339856374514202085788525299569973429859432424389034479629705876996023622182434169328690891870930429505413389490533136 + 4295933444463189433951574721728951160043627069745406122977006157620687110134601604174649175489421916452229565760756130297102064 + 1960368933597422050626608328849588309269037647433491188814133197810733941601294848194060829957660144812059760171213031036827489 + 5163673581923411040228773859014781426438397455478270422462230943695383387244412044104565525899545629313341781559828594738866880 + 9340062964014870509227099698887936675774112546104074153547361150335199188541340855227153532746778775047019132401967059701871242 + 3486224254115155530038741441994666898680466167832566881940775772365423817200581937154559007068187829334117784945473428671685916 + 6007443619236946702946484250753989318115938165448366527641686620981129998037010871500824063178061129082786722904909804168031283 + 5077049104333703032159256335893142225775472800145797927383645074150506549583979834771372332786212436563421519736302401896553214 + 9328253090460566002578048864828230612968529907510194421722878024618561333479693530779323192843841998003032594026649617397117033 + 6902940885468724446328665796554679901999854957523032465138455983570952184108442966984143957137952183112915545991326476857170678 + 1147940566264959316051371696041947904637481710293264721589819021588178200143221071704512368347198312678908673679523259812561827 + 1664627873674389755627490418493705966611982979380988314739579220409030725477944088566536789756067951060713524593551031845158984 + 3598081566704365022254984411009080907751257030857437625615151390400729972784657938585703465777027605245686537246903748184890274 + 3743523412032108137414706768919475408652123860125336712812291505493576913938367683595349130153523703056997225766687176144402340 + 0831940301479210349558229457276992358900461281585291044594812536347699257011182959431429011534075284989504481274394019519138849 + 5294182590907051056305209676408046536522421503936187377406071503791132907536141109384530248717758304915645762984125835020638228 + 2925263782209751558565689180869492270244285946019041108330056058905348740666223484108200048676063426609063511425234359377856803 + 5066811579460770402822516077692569897555102184861090248580603480179709451447581598869819018321983813091599472628576647298283510 + 6074763977940235151776420120127969582510026900568916108091774893522283047922950769687105424389690185426520673414305707753060144 + 1829809239775426957360751626081187328513913192137296926783947378382044283754109795780048763911203026361961183033933012273700578 + 6256148707335785289325167505290076615535370263567053348838880542975561767345020465640090418173271179915907484593965695502745441 + 2416400711412329501943051474827325196149637971289654356289167838113336024091716837472756809029018726324544210527893716549434408 + 2077670900805210878733285491095692143052856294682669529394939361462198474814099442765549871744436963471806447226559851872954947 + 9082929602325709346337243734095265641562540772131425161193766826203999287761238275537747088073534676484013517045928815906520421 + 5721840157618684926859754448303249283214882375060250302441861554867804071849460117284782240184817225436567120551507130457965054 + 3640323862784940017360312940091490694469989530945043763136591022334344797040629558445856236949010602808244365211211804494530091 + 6701192226260174575156745632984043284760428280836716963199179332091776863302070789290228857289693019520852953529236479717683160 + 7117865720410815041230240613271283107726446255341876904224653305719269008887983911844926604802435682901331270611392890319564523 + 6692783449614566649026808017316150504276465383033625466313163064737973819404507236614011588134611220037079763294452798973884759 + 0914820111491787540225084826895277018554164459289529667607470230351077932208310255555375301186238522549530796497320559115264320 + 5836662613656654780353360816866098001238641884282152191319830259179620144977780872729828947449487560906147944637380292807461055 + 6561572680280173994959056296932010485999239763428796091258639640337313710982242786240160248574519338042692530967139936885572234 + 2825509566854748807330632140109077953768464116764873006974740017020211637781546586566316927017884251448954820201170637677959988 + 0832497323156260043765386414739221132824464852853436205409279663532624738981652928962852787063322728977472723705113895939816648 + 3887836720640005567311856937351200913471468555895780989932698604802967755682558413334239668009044766569135994431992317817193615 + 9488541867758126379374062288207207762501971013768400508156207999323493728384215408284344930017408986904527951285518045057193770 + 1193456086093196883061110691053041347131507623254475732487481683124957212918787096719880296652189465479161772651216902388161935 + 9023602670135872848924155417498176225830627494225163432154996996459879170929691453342113731711303819248475466023815067381174572 + 2080493294756115922317931111866355542145263306791051695700043555158422272380979294286809277064163627702612725392431921737967789 + 5506584820111354803017904304944193794950330337626863953844116710622843699200721933361001889997152111163384731679702997569228667 + 4453953407265344555661480951607569587119336749659238396970668832430048807500071385571032957421002113212240607304287845329689873 + 9400568404300352678168177542306869394633571699501805048687025644577243527012594817839631515308187464636399822139186673563109194 + 0383996386779379889997394025888104236940479474160100383602505977089098334042031033748699121508022116963448387393566265472288965 + 0847531693445140037287515174964594859379085364324835476807557964238229721804605800683718605401718393447954937423707976551995646 + 8901279644569224520056558762822223149315014455057454435980383798016264269841766056870811144787284148299586773970705052525539895 + 0256120889703056267161520334600912740468642740690884187820554569479971860126461193414499951106260376564440623032634236822171234 + 9700910582776001785061958742334821043319568168457980526939228569330951842352229610659307009566518307187068255993195333178816924 + 8084009439471986482548298108494644279210299285939700414080731141355145274821687079465639330167799278714667429384500519830074150 + 7502762255088959326392982513450122047410180131292434743496089993750128169949631240918611287380175422097126458912263961350683605 + 9825024574318602570230904976205086057242856859840660113304499069379218541308171998260227484149937812807157987838492362751492073 + 5236013621279011602439272005713397632062733928777510296548649421999353087528124960783236699168282936749555076309059950538448044 + 6316174264399599155501461815935271957641181470379962431535756895151732821144407472754664303419949275610161730902538833181412620 + 4057262138394989003315257406621046570918156102356055537411042166653273066886196141130782850554134831168704085162214611295749827 + 1728494807516097505065593608124398864640297391491113562997206711322054216710834884111534067711304959653237337706486015754839628 + 5402941401919360128506367871554679221289967323748328989926516006333132440966780154068277893259475878724270654107817685397502294 + 5331749302510962305291613004333202326722920832094875206002590142911609625146433305314091631233538797653208605364527924132244946 + 6532771118816432093996083328883576769019322364788699903259151365484388584381218032915424365355589731770063912720956702509258388 + 3882789530639893098899335537330679624810372563783381211488557543067129370526059579061942074775015254040779746533167078485769900 + 3805020437690986060459807837031266916198079638277454221416718947378635541609908151334933790442634344916435987118766221380030868 + 1492873283652410067454455812350782971829174602968575413579966330593167559586103530053302924740897504468176712345572924410751989 + 1402681422012394852214397745855323854981769611609240399129690457712558487768725787104039715649959552365787249656873757201153712 + 7034615208236270834171130441362610841044504351389336191409989539270321328989800821619371048375553928712514470949748975085093770 + 4290878195796201049040671016672715493368576254144716365945552067883559930088219118750514982822693100430367769784775351909372687 + 4911033872681823931983855759969195568792322301570737362071175550474999508803728901587248248809147697357896852570255543589500900 + 1706971004869558605860088419347382200967993695904618287963224847080176675951145483137675636512072408162582506993137174472960694 + 5573663486380813348973168761749599259962367833751791115712074445847171992391927789752756447549332777671869328971664763925290830 + 3549115232652328982096333522858191070453865857146234126898896140406643330756492575988127393599824952457257137615690188707592890 + 1525981890012719417710592274397314151142262744434946961995671692595224961001445969622314797497698000523423663899015096913051877 + 5058249696800337974138653960205886721218275906496709288754537792787671454609339328245451684579097878838116584542322616579053187 + 8462720851869420776547815997374420654356793047547706068426425982466357700923014078111329124212863212450480733486009748682342594 + 8687099289779458763026259506520765785275805315714163404563447144528065795533004752634001703743154416316364697795177031670571395 + 7862389886797621228571167458335190181377137309906389411269247283889070732381228453233824760431622453252798014077600435024553202 + 9884611862481302466807813924732912660462964877829202613446787892509006450191623119538981968974508042576824347741032177030382425 + 3275371888164672951716608075300420614160898739974183834737152799222716640347298255880801705875381815950138367820787575063612645 + 9756093031018363423853254508819810837905492342390007409090686184553436757595124339753724654015162734521998021981012802729263275 + 3427616385168365599989752741868814273183927471411894804297652680678085002922251517971806076560284843234235639397961184180625624 + 1126099034992853577542894567722591646934072315106827450408752081909824273574814734547622072209980280969251694858199479989346866 + 8324744163428589301098203537736106384602289116499145216551769186060030444438336222899526023763743834415207190662514180019708518 + 9860319477002084962218177584666884101089885263708103715532250072465740590415811526551340778700948662719303811079801949032990730 + 9442895797928578191430950680716135775881506952099465712614129706777971670822951940768332168877767587109595551931372470789023062 + 9676406861977772053008009279919036888396717196766804819265649832410502497794545528956267262992497398344695416980354321065043902 + 3430450368036376703613028439245508507778168871582511449294099014869582746432398446542812126358198966694091267937409209466063739 + 3928978146389085853115437005111689057451518521401216175319263947818787743509560003599577334399518674836615112723186476720359894 + 4447676769726440097553180938842032872197723469668279942479093598413513198335476789357764400869873866217837103053672831807359964 + 9438439139166494727711797686854076602382501450775000543946895474100528401256910882752544466058353451178988269998012104071279388 + 6796506900519353467866660536525382267232333410870940350598284296015115345501330091034294987205096937204489666809908368374224287 + 2156069024262468587697645236488193119228612123037868983120993219205723939445417381491095019098927648926035392978843470867760614 + 7821524721406495642677263766762922840188657758664683038649201210659149304382137313140079079190066786903508941027377579459577045 + 2846438208088991099137843881611431007996513901288343001595074297103385844197112994321057890476648269334831505632974358825733750 + 1231729513446989718094794150861322831069880594276720936717092445853573977523050237490193119260788535329095088882720971495287598 + 6552792304258966749461747651069123750999083956204720301600561922121624443601785058830034234673249878353748610370038504030736047 + 4350618220429461920496227812205841572163867546971596032105207072905191109123570652010474485250661135080242831754570708916683989 + 3648963905128198988374985403745574043149005801382728738825016196793544318399117519577715497903566248991289200713376389062963733 + 9079224255192675318799042558252967439629275533715026478752109034505102371733784051667760885774671501306079109448761994271014212 + 1512159183483513720286072997122368280567403105173759926916954869853277451339001028186617037332009159449259382498277868408842981 + 5560323178755830694146107056035341050323807669577457330458808700666012312546070466530820114714620579338594279601664840585122075 + 1503852393417110615057020185323349829356846940778480270527833679702648854699330937650632301666517518142397830288536621388668145 + 3710500442232649775196536006291799614616427004022039024161898799546077671371127704078583325133930080437162856065176543455363091 + 9667028302235222877392627005222715604718844825560371250888081705125248380997161235203510947690674677658525524540413177350345055 + 1651124581699981562124791312861972388295643691956825406823017359302629847041679857625842731954319702741028762561310737659882575 + 7234973146912955319568057648697281752581304980681832088301794847222733894976160526360976917273669474157112988773823160903919773 + 7236452528456462658486826400719408745377253190375111579049732814880300278553197889206203166333133501206064778109147665779882391 + 7682375338032730875672864027350071637472437979382544031201751667224513438710165103834022186623616196654886225240056588996350179 + 0853897451837131243025169955161135908558413022976148659863288496875873894764829106676107357256982339087954980489000376844916919 + 8360603574420141848805577433559168689130304284043047944444385048148193572183817853604188280975779635124804366554607129505815592 + 5620546941760373757081442569363535705009166704002199788324439031196454334794954999272772623824166956059123197810751221134756232 + 8439866566091270892187388961159863817415914847036125600694319372852752155914048990490541073567566380258061226260248539927574844 + 3029318850407273236073024405659942071591211229297986931569472429177060698779317028894343293006454758184946754805713329630249820 + 2687678405796666588388227397973494711846620655765600330508932225839545844068520955016865194693435829894249625192750034081363961 + 0826642719445444861688478619229100303043863369218122546764063288271554588608667295145429271395132923307142550915748046259216532 + 0468573883399305338589054269280928735368128284996899601120318736730996079626128417354949909634397399033464297120851931573621836 + 3410567460401768661525344506338831729399382001213762232285178082217011433200810491330007874531405259479829710109345021089321397 + 4652171379208756546308171186440327278368902304830062446989533198226580273246735128676055302820200408293662986737676930578153746 + 2150739333645551554065559172680067798805779396460259578671413082802669062176930977818789038399646027209326563780688854879437364 + 5947149323195596075203471654735880096964253215673415065855952449622950653788545812330777657299303345667765138612882163698466977 + 2308935140239438613941108953213493640813697893782475635075053824082277617694735156671731366529539638010664196515846143425205110 + 8579861845970706058547725114635120976593327222009873742050798971923964666256857891243866172081317410728590091574945331275284201 + 6824605749924142731964725200957618055202505975317938345133949930752079669713432776367891693447902213677009365812998801001720273 + 9233059182009261025428591058709759978362385968915457411652886788541048883340218037203772730667179361924214082717915090369829831 + 2313518106392278036401430877932921941234750269539064717318812526416633477902124303231275087598527988161235948020286385526463743 + 3838476810771838510370563675061364260967203242139687527568417240328961372800287193798489828795160993501686735937478711295496291 + 1519858055532723186083206022574209495517859134830555261865370844903580200999194798031588523243896559267197627522165919682799739 + 9373974604821907639636032716761671130085088834596447375314712571767917652624045445822422980937123575808022402072804691330745798 + 1179538903767384713618264919378659303577920743409425206952169277638505227558099310711226481165660388253070855325241107221381882 + 1789290788643749161623308260296145948321831584631161915478987224126348775962249568727630631570400533850489485693171250304745466 + 6433974998050768158826396562741859990471614366251286876757878787725794466582791436968613297526831824776182286993388108679611273 + 6110623308937612049537824555231489221014173246666865428966654501963681680683054782880195354576356714786682961340119163196471017 + 7065396261977852039518801715732959486507529242741135438482938793950709913003256496248997903954928882444470989824659787821204683 + 9252764834270969572461432198412629509667322770306467304657216423067070489844755342237360066917220335677138645076622463524222641 + 2863822477918798068216749348395676325852006154849615936810666235080045937062299799315963185719888255745874252084645488043646414 + 7004033498629565919058730350299817723186869899372617107591275993421694639356397475575742082851089041949288607800654160534708316 + 4190299271083535674187523239133194914262331993315335908926599556351517813335151871562105201268635100775530492262605262924734429 + 9412474523205479108160235037378746252342301320435142535429384588026050874475919119800213524490595720796240406073642925771858154 + 2913084106745765525951041794109785827673640207212541754087108553407118981892598453634040675583256537303820724542193091642590800 + 6534476025728340988278166932729090239881218889572681282009000341783806869952125287383734393447529192404697677486779298438469322 + 2829214412991708861478313576349293840205174852775802339069812401323737815710652651384534932732051408295532745074816386764349267 + 7099631393624915897100017625766879968866232677413779562258136847735611193368355358377164844416154018729080207420593111993431521 + 9679117084184583456113996444214687961259734088670459741393316532022602071869803421115792325270648228861169427886111180946003583 + 9793622141632553469977231970499144123659775068372909299552862631976151882730222347477076919808461706462627308819362671717147651 + 8286017842303147776294340423265613507963077365773181170674484922475010476392279295555883161702991597407378465228254838715678283 + 7139981166981912432328248939664037584747665029041762831645786266577343138070260044935844528507385472563673503510303215480074901 + 6952789894317576895242795097137355300336216988450939924501915977563360873810170551299455217264567889345472118057178061331257728 + 1694193485067381935776175208128377412895577843695434073687471815717642677045054952476930977756497488385115713913555764776948263 + 2231234433522295956531798985522781927112508008839457523109337600193193052076325806292222155384767900607744680674492935529295805 + 7875818939048046279625548208487559794494231792862975497567734812838016356460114239167085114060525364762528245992233228644094327 + 5021327908105698731349894818836329218148701613108177279681910593746940136925470307141167410364253643713010143547929247739518061 + 9070977175221547245640857484222877237472955055880739878012461158071643167060432840330043982130511367475881160956788509827952621 + 3413847694252380420294340031416724229995257917239755969134460592475590887547733435481300484633477930736275363875263891668995643 + 6581430213176248276716948697514387283511867935196454364984608140452221982505162813367283133818168866214263555481101556955727420 + 0078360325719735185976311476426092189177189796469613813653608015870137963763116020948507804890688620493269983909621885486957143 + 5618073667256477516793467657312199638612399475873899685969826531992817695372605952175192740133201709617218497592077143464993595 + 9686528263740598514413702973825670801929614448327903726180967797157579946183718568106283503561970266617924646393019216381949796 + 7239480687825534075396618625255444191589146664116441837547061247242846107878949219756732241373337771333630723471570758001480280 + 2126415066562760335451168640052256439621013367706107505889219639609857343988288214828754545448713238798703235273922756046005812 + 0281498418252644767093639973704165385252675952065796869316299823450944375075913221341612192647317518382010547568017829174497579 + 1057968057525848488438423398887379257534282986505898261044295544509349907137424691109525427205047296410961152317113953498675027 + 8037990675600906293845109738467043233236225877257801109348395466430705164075214123065322814006154190811607337254708305938085250 + 7210750787555252394437778367913891376849871377061775971887348544361550409572803722815881181222850658661431069707417398802536368 + 3948215469610248733031315237243553696794016591253408216711885250561262516305255457076505242344244633141474145222490778655694723 + 6617637025342831507631846476937783337058482960397621355078541340935495458638237325584632545957068938913331687735591931648307374 + 8523372206558862816505119548118888594916440410353297374883874035661877591624592793870237386066600870369847319996357899821848884 + 2706665246531670922861049993051412169291896643639078882262700663889473964251112689202969447822598990637782956377227324903867608 + 4848299459820567898610921948177867341511272056149848749209193175952272681698383112955078617288403697439760095671946801857673079 + 1356542472568516852079785586485413072353853487441642185000260635680413178133480855130718255056119475830508178140915142512386038 + 6695877448601376560251771173382757011161242171039619918232438391997384640483554361477105518555170292200647684746099630559477876 + 3728050473071484393708670159181207753885192509059591605951929761162380613874243004953769191772521075466929499282741107419333117 + 7606734018487546777450475520310398974869459655169606480072758933265326533542081878074199816338268783853568241202511239916973258 + 1633835831994903654810299535109070687398984404650301845605445387393310102422388713024846802629758902868815270339924811537344859 + 8928571046801342106880818013492293682607259787490363620233716285093685649713330924728743681650501355104561967670012038426873625 + 9125730098479474089046067867529096250921613432172766348896492595710398358975815806788579245423344223729093128465048555061302778 + 3282236766431701005576011421891586267683372954054171332350103840612998244535378427127331925639537865313201470923709392166490250 + 0060953065190643840375181038485605085116833098863859869877736596835368776079089936760138916464834786551291455693169964704950417 + 7199761056487159527818318808980388404160177710661891595418127883387542011797165555082211982772990941128288012248134317959535274 + 3151702008500412396300814816932022272142827209737059555958537947102106965289850740478085447869942031637107833939492398930644696 + 5466978918720768258413199259613003866496795654264247159666752558539556973496507886748391341566752558990139978324598436936793928 + 7875629494705039695595741518975797423129800053333398650746169290789301147238968164288511049704954808998463415048261417058627843 + 3675014761845381637345570687526385375856012330298649384510964329070850231207976330807099687112778366295062201878036276787748707 + 4186642715813159153197640948334883431130155154184492235081536887094317988019087470651733545171824399201735161775652002448517265 + 4661100517204949080442753518341612732523752379970048081237708561434446413436675964518402865361477156495973338379138615279891674 + 3104047228288563492721376497746751756302186258285396146017997376211045579689813619459200950120798719227167890408329425880640799 + 8361120737152440781721610389840480574105404073477545436637229579684528270718993412816918987324414005130598864358095704485655816 + 2635022304411690520549036888248912012839104866750669849182202670549996591599148236127250813538958602763034624939004690945598644 + 7161693686069093177957527866565203934639363610988615731752113714098234889877144865056494208717095238090181742851725619039913679 + 7926731919437873880030756176008264549114452715998481120029937345677673326677605995613852123446385084312717926880869469763207023 + 2138495852046091769881664603146562927499752742224823433380060312750362684368906102817542844818392822621059272739767561472497448 + 3487585927757204836571198808541456058695288628326581580540815649602826692062251298954681717253220499784757374087955966951533070 + 4467286406109149470022526422047665420981641926169730080064026643952810388751979407214952628713107539097869076094466606508205808 + 0329251645328585224993793572099403208481085245076448698022757086335438075955415420248533451214205820043135499362946801092902796 + 0976117055234786919615481110380099853162437989837673156044051970682580784609511428623279845514623277521398030431160849037450740 + 8697358783561542570626868871304762629606530282055602229180460161462702998318108546783149370269213126706148977779508293460733304 + 5685401232626893164468498498310349947377219975132662081047738432680920912627837266028376099158214591714411685177672935669560017 + 1991014855525662209159171891334726717439346791115150429082237201563017187579488089876803702248258879215762021955798945536843228 + 3358779497231258973228903279307787602968091467986183211284685640196892409994105852728310998830904989480714242762651865855421586 + 5348281152141939663360571564939207399533427205490276937846050282692131755481373457167966144301656498283646918663467663563230116 + 0442219576879355438661813222738756969322895770177941048443578213219939881424295242319200710244313116242014329915750902609753298 + 6880215129386746871145799105266743824027120004725079746962555401718867449525806260178086747751584880447035314395435465651034570 + 5590819486053989106201536213480377379276227468376756122798396628016810991489235173054754920663273388709967201645610835786499004 + 9939124283008389379680409146709896607754411605235108861950292912142332714272148567105156028757875660670111321491114463297009230 + 2097548826892083113543893580713808393001576983724545670281722041343097928800752617116438879952016563025042978404320211936405203 + 6082731184886898638758782020161455765775544117220425974704422223842521161418889571069655363278462600259872240060382048674290190 + 2889620681353481574769346958935531281292735580442822115141047535414968598234054161580569343948696497621906027825367798221210232 + 0975609392326975398368477771498401808897612300017559800926232766502316691201583773217274029458304062931758320244725915302928993 + 2656060793106179140097207671393073878144623719159743370358884637219392258120064605880204498430784571518779561821815030688040645 + 5261532754299991261842655852754335348627643855237017342819255089240352732014055394202970458645445920979909498339363437891353307 + 2437642062562451324051185886722830951326647012880268770841964036842838215823451274151497274115272960818748924818830295293023164 + 6427726746699539771500247174272715628837777269348318525014112099038948379809971189523179740600410427829712055609005231760641337 + 2123549160662241455227582001148252334968910254759170985955722387116765936697038502260200822286774138322324033501219326909463806 + 0821193700130194457116090490985590394866182284594574006494500813138155877966705322490599457628280712279954157952750704655060385 + 3280391474844631197279842080980749627555722515522776772617462578270115902754706089142103829738218939451926197117850790818482759 + 1294311329582945102206118794968530880988413255047180804846373165792608079444603588122636074961065406623564621335429415769062656 + 8977139076449153307860216027207885939587708357239425724499000050811065643249463642868728678159848609219920477201880783130814232 + 6033248813331250043643381559597258568598550852601730339407737331740193572873459479638405202147132462334764720678461849283231967 + 5244706826495860145056785602766589976181173320167438082817365766859974115630195914700440671364272919565408159761417527099133015 + 5244648245024168084347025892989203801674105350823195087890804798433093162301085522657402786073312465657131861678950736152896502 + 7020998265858326008838932594312667517103689364315007929663379806725932670838335332530002316590322181497959301133051038639381171 + 3173858772156448895864459261457987925785493055610741437909826143835126197998316368571824712159171580331713288750535891179500215 + 2461289349520625956975133669730507522155477555105599302736241191876700580974296813158063100071375109901417730679844357856593047 + 7673877787687493268983420698315905381260558449663590054448103444553449366277579160597491777336624754840213430260072450113764481 + 2114017564926717940676432504294232477129802350412122813350795229854770687737407776153546967564248142801354985562159014016660409 + 7639567903574424627121988012936196690968952173335045547572877439937623104537739475753166073603089257419976655666993295754279243 + 5512010810515840583007802011584440810442039388430026796415104195890917308156926213851922793907826473532250186114497099571038088 + 1090443322487112398586196562777035714693242567109619766467418285811180453954969091778067062185341924208029182725946749209676264 + 9663462321929487207790152045012463956298339314526151434668136673612071349597053270833334450801647517402244793354108502290993012 + 7465047517200443480317342789716535487720038254767800382013521445375492608318405493546080410946096145404154482214436078102318897 + 3241343339884810074493047134584332154632775327907375423171218727031001503885369275032870180181698599353279959939076928392091092 + 3566208126745756363429701058439360596278930537654250601183842796400352091131220495755538686838579076983412474092980588063067246 + 4135280622573899686743659033428766204732217042537180031329938266218979406566474637509065330050474399644477629470645922989131608 + 7243489726801527985565622807882110752891684081535249425920277363697188485817835521822988850811873532635201983418016593214492469 + 8143017528502801938786431108109170005870927726570176129291655180782741998755590156671788445329312481442984040900285747284336895 + 5565100360014106030272353666080827357535103165363399802552515662750922553611500390854921288593734087100792149327574407938377815 + 4240318921296779247997230590857031671134516419731819431863267883435154179769593315054293181367248263035923946261410558920492931 + 3065344926131172598974832603770803242453631170305261893085619634353617662701712503317939637731383890741691116709803904180847998 + 9640635307154881695674450558215122808610162087865073261126743708282066313632270460083280371892143332906784831299555537946109939 + 0645039315913940793949968013785570770789031780794104310782057130859521600859343415595288573910289771410236190253921849657190998 + 2817116940059523621717397073394274259776453515913607417038665482821641102656240840561075406926383495205691566077252073640483438 + 6876828215210014803339974347992473188369840859181281062746399956666218336920552262054357048613213862945863515439475503711072752 + 1206178405392180823761458212656703549891855527651389518191357531805984535259972031066177734136716154598488260571189715523538978 + 4990265766954047391630449528696946350646833442858182431131915610086870866589089866607870181211091256487223226710174280311854030 + 6161821498017905298626518871081902325899313379230902725132275803649959728622670760552023317532682229232464170889758455581169141 + 2416184842590677978922625659052895162548385411298782741233394356631320019382233371212037232115448059660819419247622831630454503 + 8975030577721689746153882576268854827896373568358085985637110827886139292888578025729952622899410488518168089967179203288999038 + 0077221628423351964468120440528719933928163566191359047160562478933063353123985611799118577768774930246047770557959247998776831 + 1721135782157358288734205102478591394569267133297228431858377971925993589071779657700502192679741782178657102555324869244446359 + 7869917278483084269980405860197759252589350638010408763257025389708116328761797581159680452123249311643134587279719495772936617 + 8130672462738712860454774853313086658312258840823449860002088944658955778609509469061098214154416089413962879973327200377762688 + 8704019840879290058261002736123709853095591291334597972059260229183193853550672628813904508834589255323455601476677738648315934 + 3234707347670711573887321944356094703845291499731243740116195333742959154260950396149564697796845304852992191344817095433298019 + 4556001053283765367945967785584518418747873282740299536406596053579536242035383267115157980628785476579854884310834210027387315 + 3952399660098012461635956108592408478331533765191761940733106633178973207757390760027945616808844645166556348572120907508405281 + 9620717181599113391181876705169833156639227504083941308593882555592005786644351550764764616222603704206370090556397818828816448 + 1082150428965180471148236660642979232846204673076692680655912004876027643170213363695294926023526278443457817518033465638673749 + 5350172689969152071949149368789531895369178652578561324968877842847433493285130074155790255799028895045897756190837543509860775 + 8482306198938020753154634340975595193686061652677880586337892305604321362120530299145893988789835870281018804163394448979511499 + 7488870885383052769468046156937025798795341295237597526911841052145121608390932943180983640617731865473642038426653712735002335 + 9011612227214170561522052833657180847394409367216727282193072678838450183604374539578667642858779645471672950276478435834423943 + 0042627888400396166577808028511674909710254329416152368725303977021338640330576476481308582201268866056584880471857573435293178 + 9268879578435020158729300163317051184609265956929202720052876516659404370185319984314639348524347471621091689443144604058655054 + 5852357719309697687694316961668030847489545691322959818739069805501234210837740692288860145679956618287254425865421435945272722 + 7947183003454715593442541393266684657719476151125892217474788448864376694397034056195614730803146207684810002655419508268188406 + 0212392708824827732017576889397138488570370042723523923833128481673477500325568912519958461261978143669880070457987816169424188 + 1965090700335288348865794109082688653306331467742286624350702924857750689705564771477934006408695884251431946386364556639034176 + 6475202723487206164676214732339055881658522754087991356304799053722702797567004357975452415295767243300651018833595864642447417 + 4933751846153559955643592816488612142322342560545913045826692544542626150928640726729092043333739064265750508139974673275834713 + 2427576527067163076789990338481516933446902541780767233056948866977560689363984682741766823172377515643032993191346658956321461 + 7240324801931427740710853207105854320415521035336023346171992089619399728628105888007254180361185035803733126321368733856723085 + 1503702321045090573654976317248889826950138261936742489712456263150062608622387827772363799121813242734818379753299053724286228 + 5076095412377646585652542244868299631686826272014334350505998081702990345584728215380800687580035780236658004071510394469994071 + 9933250676927268802066614172669848689165401909644815070604643321993975291059605403370117318954869373816750869659405704139511279 + 1490487519262534395623800813247168885091994099496258142463552140723866858712657283749576144012562970919330051773400199590563572 + 8265606609996094143464919138293434901647769730550988047626306005465014764814728223656959001378552960458572921902571777313119856 + 0301901698751025073371353819870024706444286250847057963018585025053110220589734085318599463450687736352183212884401020231957087 + 4456959908526601850236631528599915374848039675582388183944917813443948321814362879113998039695208714072018715891598727749400184 + 7983572039054110543265312946188122716587941443406593149730482849110607363599698686119685785597056173835119438876589991354302327 + 0157777305454082280716591110467065838967277498987788761274920512893356487762316080383017175970582934458813655903151031833258038 + 6820568297362586686149767416323236376371752928724979488399337093603770184434877480032885947231535650930077949030676059598788698 + 8108972963805156390445400882624903314064494634772981427763122632358977184343156109534055951999238879890515883719506599847044143 + 5178486334616508289086769240536520705517396788807705586482419714104331671474772634945045486037353039747544411584344166691513962 + 8343543694892040940224135766807400138072678909751563547074645700842179499138145819361180694589974178543789544801347334713872045 + 9708545131525935820756667264787954116125739691093797584888706242100925330533736446977764101332858478855148268301440155677807429 + 8363906279880507853775707450188819239306527160717217937065519073363784713378967477694756526571005707114651691767780955073859818 + 5651083308096512159550753176200623584419958971162109603579598590262428369134046173758247656339396228143231420340091898293104843 + 4302402395996304257050404831355580727247848379655438560342120245630874884033522016540414633929586663157231554069390318916865498 + 2822530065271711681487170629161962249557718383135273443686990757846857063424817696146359531243469019949939521304535035359286967 + 4074330918579124906980668220696463605660380759667033381676449310911291881680221895239419422515427861193964219305035700436309668 + 3698935243696912496491762756802269973014707849066246048122302860046406677238810686973357352423777172732249145383686882436002629 + 2170964033471347644711273905006241361125626168342597916481066003694402986372839549149179850327741026797871619199281396638967050 + 3740578777458341247832731137954141104761544067127564384269992513879476807275980026551471675919580563967451050762083496336212971 + 7234069436162575416758566662736313504628826119312240011212647893254386199394411434394192850902621006968244175625150393585420756 + 0819505443586556219267270131584242241933754418772049304646166400049758424842433111724173775260453475529050201556290830854251309 + 8694504279853225298817987700209881068598742151871017058490633074185456825579641586256200310473031416146096103034054724162968499 + 1678422417003132262043356103744836118876129032014712571839148276942048121918851516621273265839886300177612597618998212159348375 + 2526979362189085413641977979132635792430656327264789820332281372901762624494315668746921549021511066663733746233883697857770994 + 0998995661761657851385372991367035240872501467476816162857262794643509591735415040438155899974797001865973911239317650890930815 + 0189734426599237495702149267240934080052773268635893422129378135841786547348314154856133018855495625125449892981908291205858083 + 1077322089308800545276469380562276682750368988122928137210856581036772006900205486477908581832538965073059726766472615915649559 + 7595664231420716081656297104542741477179939201745233207227457362234020070465865805626851389405073254933773440235630530654929440 + 4561326689796974026193323140357607026602878702428514108628434286473624453127013395116455824218643518830181373377505009554553648 + 5175104916514700448781338224183451234036582197678358641053766734457042147404203339056493172875783393464733980674769043154128903 + 9625053130166787806916253108452498110678784874573415439254136465274322837153616892957540974054903367967131773174510386204520192 + 4708907023698793329968287054491892003035884220479471761449794976142360667172403302792534515419470234070842851218805657152102504 + 5165815294615880424810698811972894519218327570376404414484865603951627216319921021460205245622341179697179353800333764741713858 + 3375832459808523959735342163302977206974789134934574309888193442489681770595931407566150654834927560855722717629843449379732533 + 0696873250701946777504053721122628669489758761941472800177248115996803185013999823071443413470671100299081264402635064626229095 + 8025269049201568533557667082941257090329107268081485134499591411578665111542402290969079825247733361568938034890137999482482426 + 8413571137578802277713985161717245739847221863546744280234586017009016274669615970285654793200770322063367655004275873714400764 + 0799707402410991916198286689965775278824664119744877317308731118045964149958722032731308079677323234905411311426216785693702443 + 4397846375057495792019955808977919911307473873070308655227892822037825751568866737076516050806909779275729314309462325310751161 + 5878515311252357335941687228452716020488777361851148660668041257248641752627888839374533734775241618706657533250097255962909759 + 7924103963089477116974416014956752830485444377913838660792557425488769129517146048639663168698011387132583363962130759916380103 + 8854627858331158799334753893263279859800213644437374816465531701511843970386899153300191498875238863924442400115037208900760391 + 6931077305054934679510399257137017692212293765671016977117885559987800112104522229358688690556795828786584220491722127422607686 + 1161689224772384204986305992766453244735906304538266466175104130240871760142886069723737054629941552777930420547825827115890782 + 1184882323411827620265622192040661772065557335415769691870166844416649885380327832148533301202237904520864333379649271453239928 + 2427936123038564183450762355240415926776086706660362490151633725587501086167861442974904906015877742003232322938651897499721504 + 7575735828907721001810713381085000197583517056663976862531026160720187808215284714716227545242555746984605470134836970810868686 + 7690274030579086519662066594780770842382679015250578750543674207604336237491570959207826549369435808803521562398005006071237827 + 1591235570232351829740515082573934645171861807176059621044839781347865804129548447089911918892970375115928184446756254541226685 + 2615960213766977626603096139489045595459731295282305420627566186367919926990597793979775395219871115824222384407322704217828184 + 7269890378837649922156673232477845852726935996940584696490442582150880559450498906939124023442999694271016368614887466665480687 + 2492299648986452580995323839604907135499552296977074591849011346778726414701224990442027943081442825619102646860492552917507521 + 1791849743502515995886083914654782544108637930226038487802556564179211481768559160141129157276978288393204371047755590042629364 + 2476979194376897909780308753936290021359131405027064825271771828980164040364357335094434041723555965477129434483174161190644661 + 8416023154844136801169958073248822091441560069684654659045233353502161929981208692256561137140555110119558013208216615513472071 + 8088260724856516409808086622373800856820389920242427841076949364650960501816473316120878023138924750918248626057879988336142195 + 8686116426096280530843620941389111299655341997827197141570086674404151699053951971920289530070752071000490045958486626799786432 + 6549357623845124371617655875408646869879278421775346320373177073222854384021377119568271293703313232299103659136776571632693838 + 6591886804108118051730248844194375009874244915537509136047158661056246282742880964703031154340229700891206754898355101039366979 + 7268446901106376070498745112524561027602391892725887518917435705098580461006376837385629028194839014124169131891549609455012171 + 2285131899533028794555938374512548939747904214953588004250694538667660139983891321230034509152717542342156366790660293952707870 + 7433656872059365457021513060668191880971221287545847083471271690608548455879533083319220177538857519457319889888751900959653068 + 9242848205306926609548172769597825608518368367889673409305233019839916718283755877093610440755381268416027885226989117854626319 + 8543014996495123544046729990961256012932771211075541381188839964005105738775284593953696325073738652709607173130510895811417458 + 1100281056074250163495442070917233405800039282178047058927490789657980634481405379098411400723381012395226453993698124096414583 + 1497707784106353163476884094382224594079935684207379351580860836917141337699813295106036949622008098195962892923132082743352822 + 0227639803444432864090266134712772762851750164363159986164200332551145986599690734005702172852457747000704439537884708919681464 + 3297805927942628853699179019515733067501114704121488080361171310117107236329567894778609250864163044875868270159183178936230020 + 5632160100910553597455671868785895773407892040726468337688933116567628214043646404787040937392191211462332257825317687874338725 + 2296104873433207092085115555734422123208784998029195153841807872132818719198275132977492788603520666575735728468601968901331765 + 8507664661851267844375807200747151263758160914796423476220162799279781135476440706809418288627923653896822426541736985486808537 + 8804577755163112469882477676592666556395113447285604375941404675578061757730014398552781158003833295830499727417346600077947853 + 5831914326747916706642066586312780276779650520761789440673709492335505292573240738337240722730985752273930258542997960743098240 + 0068020053146252182779250786628431011150801984991349353593228652822215156799328870412166924618702218796377703357100331644399678 + 8109188902158713215146842638263856459757440491023323555585167449490157093903282451159411558188534514053282926080246371635200972 + 1083689238510925211444565358062724034393858074119865447872227462830480815166007221130324188970568012551002420122076677588668537 + 8348566408824119448641450955381151117598257925347235252204110951120532544649854733446808547885490496232547849386772180981787081 + 4560676276145414580213909440734926632475864478909927595616312861612204269485671554044668485757818928586611911258131650112268582 + 6442754729881254198230970045300311192828701003356370115227215491493010569367089158620723231028014912810350816540331381099940995 + 2865041663295338237509904105995789610569727200605222728767332785967873952215814407401152907766797309671425581760149058652925760 + 4017820912206849712695013871311183547029336150750415340954915312119753021914893470116876327839429907255892388374033828544982922 + 6915440546354439943941953788638484102813214756761743923515532313884486004173505190595536349294404018810183152351908266279594331 + 2928244470990795144278024903861617956853603900951440210459677120550845092043556188794480813102688176816346489991301120405759270 + 1186435866287315352826686449165308561598819563912734578580650689933009781657638259105653726859937343022833693021987646952723005 + 8712542566252718904406054272317438859093977264257379132707981296910101101713844533871886378161442772031073848272459192591830784 + 1058110999534770164492882010801967465978671453250245066874219221865094533085057504007502380425647847612715483754244102708112443 + 1742666667868535721098914454487184166505673192687612783065836658057498575235907333228055857705494275550823062941047285844371213 + 4854496575428807093051119901176270909165842784911651361479733219811770760153017103816762799215219103460967340988812865617828044 + 1917561105792307812885764646858740340976693913696981626941718101122829669609931847477816007131803415395929587982744622533841587 + 9667546614449025826471505952967761841638682554759010436234535597997076544716136876213634826200883843816631177929989595634824997 + 9075236896089146108414434690485647098336762127620316996183949539422311636347004018452729032082455756224021955521110115243171929 + 7022352504520236787549133408418756692328586206498166126138700604093881377702931259764322041155662852059678496015745189492835117 + 7091800587591451755394603236816915477651467511713772374848670866752841854518597403280700140135675063538245814642015579501650431 + 3475133641567131461159293976535068676192194831897897611380261311134218099223461446586431446131415308645022873899564559364425282 + 3789965382702942084656483383865958903699057640653956948168423022124988840895696969117651267238844593486453639829783832289036588 + 1651772364049655351227109534629863148340655489696054950189023140607819232747963074764923819690470465024081626771998338862194589 + 8535421442026745607190566634422441543153174467912420591988970152959270609189415618141521453452531554132027545470737271909694248 + 4266576066028018898848004953928316732798903447774832407967130237423961865629656870579836679541833228863492849112635373253768730 + 9318620813778397458907750295204099889575365028367626038475757355404525059311775107234951920852829456542067713455662881377001712 + 9660563316063581065664074432670545816492979485719464785114250983280531864483884025594604925138921571079067953012249664289286107 + 4733006686229685087965270923863015490601420365854224908680910247314401508516820945614321593880289181386292705522860502467700146 + 9595467875394655716250868523623848001720836247002935008259127820208612390799061964695134992188932480652490964335096936081240148 + 1812489955447149372964288932685703059456499125726325849419752698359991222537673326627718506868098338620828381688669635638529284 + 2277365318750471576552640984213353147488350298228497735938404810800516562727031985237579073707417430708173600319624539956749453 + 8558865515990107426689500711926656694092773040192992037548490908808858324669008603563963750417300374317505710614289622964156217 + 2457409596680804630516887336784028949728779145781319560216200606134423822190318186800036885710141555957030479473061434184735920 + 9100569805069607595713477651532945125488629510591455102444809609662844669593112401315706794492448332303051585825039449951564890 + 2934068975480357331702373570405176114572488785747724819226534222897314789801301206100799457068445592290174980265109976510186964 + 6974436264361115896790352170073260547419486352304459996628335808264941225228110927615548124284539746249063361590443246656233810 + 2022987197590236256417410387584617910709314684989417286318087666015073752226802244527631727840148104686143554769788772100971964 + 3931314203567669848668014170818609543271827823841957939988437792149776879965413983671414699512124596470803895106449229017252962 + 1646897058572253319802460817369397398067528887800488520057974357980724071070615260303277654527720835652573050782049698374251316 + 0612949136289175984348022991134845911118529208723293255584972808307452158666230105816460375784187988904522880654792018341929152 + 6230320383294577758148209875436786980246088588555018398742402423700033755813061790265512976391765915810238317924960933176044915 + 6724326703636717615730930803229989144709304487765743249773045992631205387565818549594275877262188712201760168274734486308418567 + 9793449160017973876181891146468573134118620184336387033315592292444997748610681437980592831049932965491128002640896459624743912 + 4292773888056347657265747923515456543197563688072118373801968694939175467616839381912904118459023550508906592936405878500629369 + 0726575398511990054804247570050536297610421442312874646372000460857738421341575986454091454129764640046210072544927787587872609 + 6223497359073574286258812426783136238045789247117981734256875260415121593723556039489844073919163685845325053278772517808357882 + 4805353931456319684552807410713836603840908704132137938671395582768618313934438378980539779778185823334069713366782891327854771 + 6127074671224214243978383308821083055917752075116334068237357481944923919216084154202678626979129283869929664457025576182992309 + 9095642603811777857467738034071749226163187428061948529437320054852470403172207781014210493833697169288095448800181203251014035 + 4736481344099852996408105951657679269262847981157582390462101509329835494113215114942443801348682136828613264161536188227115466 + 4003055863718708771225642500990071025833297545571403747979992978828908605722348616364122656556369792934466258936918430294297508 + 0884716108700884651920742851823456839844922966806960079344733214332219603718719129110850475334654765668025057309956984350345154 + 4885236271502923816983822161323233481126598003985902081480145736364185121032980985643061033399360057443356862260970037248156868 + 9095109506937315402103438551736664529148909771957666146775454439817301965157339466426336556934667643823128218330998524081566484 + 9554172468178139926024925040064147501158211448170728837042601105476806693933691272219558658718966118313273471191896511638062325 + 9954369358233682690458005171274421730241048095790588467590844502525588085948164312745806267036443692262270244497152879755376313 + 8540761990884030057918282213961331175575293790886064372121411245265558611444044299259702033859938015653338871057063134186390567 + 2937295853774855369815055903708691070046531641376115545763368983982874877046797588826386810643172084809422213611867667864377575 + 7456129086242673800167308357557286842740029636829456648911252509981444991813390655015368895052836323823418477931875989888413494 + 7619903401290202996353920197163165845104216512134977822317453208086977782938058360962563863616931222677006031494617743246676098 + 8619837607929254793532399964916863199570819754247459608169557658376643077622610923724449371091028101105519894212018425361113161 + 0198232737234871539712619394554173033293046636313472444724663228704935678432306609229598127499957898688691002287353410535746129 + 9160344825935915883479808009630827527538308033068458669327511758149831271072074138691690968888119139014429832927001663077896093 + 6075520157463461341098226057137016444093714810741234441217965271334334440753561468859945005901907007749818800609799068435785758 + 0546092246435123497159753904346692263278071121042508101131684892541656872975812647089730436015791483195690674123772749878087282 + 6758449872382291050831212201949792798424861556134983601310627614120558124555112900385099751123167702480059628861813816928572678 + 2294380967592455168636104873737766456888729486890507823276579714836828251933669783531511408873018452811541618386657467835047578 + 9771964953738092240932562360117185595020635073758269035209960005817272212266420970453644822258523689081214708732161974226486482 + 2078896042427351080221479050978223463317038184395717248909464597626365437809427793625231151897894098417132582150723722131356816 + 2733651127665461066112679225653017158187022844835577848138599970119201959393371465576981148627618500453766449113619920556794832 + 3098796406035170187586479893078215549068777188615428168013041309627717475700524281634638706348659216956344427373631234955931788 + 8266607652077744997152631910857696622624195835857414262086680438204284388121731692389911117940177851680318293050972437430080491 + 5263662912508589659968304863826115756592152285582835871560573052117732379831943224939230850768149596127803763098910581308889239 + 1399259544384714811458348148272122374447108528351486026748375991519038080289258112233626298579932128994892803010854830711867003 + 0120562601270662181088525907457246972630366755109340652778459673777734310903812432648671068725042051752322546900077059823883777 + 1071975377081858251465844724729282629412278512504579575631776161691808267150394386844729953211628319505799528227342615586982667 + 5142190253907427483211782117002935160362621628506088192922092212154140185826659904555543974037176549370222198088358512119912742 + 7709122677369521964052899819214134971313049580616225982506654419124826044743127724976092244678406630989264402052401911579629855 + 5241083294500875288635504487164898666527862404520007162909767182104068330196614730977680503144106835763690135404371824827295654 + 6210246422372066059297630639990103921525353988425004032130811899385175353438423745075299078297982811812894692845392714907314914 + 6639687154171290857100923298064297354897427312066201467165805288117452112109293854180789331988821851079333157010919824197308857 + 2725453575267288288994357675260613771455378866560128031996095809604727908410382843600101001039972876558637948184365207490031492 + 3022829447684501701771651529957077694566855215179433255048106574130176149607854191690519660804326926806696105896923466573489014 + 2276500150756721393101309310240889850130747890241895231090329328679796493201088708899083812272168509412763541079565359287160502 + 0441480433094880222135017379174984153891031352882663477623197838966247123264644246447696041370087767283894667315757217159981846 + 6600209627389381111032923919248323966625789375205223637463959729585017236548352912218466643214096190786355523902607233701011308 + 0879209770503108176937425508560832114089876275039410069927508813642206128497418765988069857902212785710790868994707145334746457 + 1573213691519886100372421851125709104684878670999887084420803400476797705625591520633797149282934213606570900108998582064311163 + 8676807063736715112005822408555267407647050728641117839753641320386536310057649950460984214505375532528456592558681408856748600 + 0458633214841398749014431880145127111888700604235741500367092065118505389545560189317863466505700948103428117858933891140917600 + 5132202176401630576193346962510769965520088034746560321030328807272795203005246723655044384670879356197070618995577734499503916 + 6506939563329550580672846170456665825955418030610189100857896112174782009029170826779986506077333681379230762539236049071683000 + 6370393487113254502942284063528147627172601717639450424195980075047464787096908959060881173708540962987133431304917906118868338 + 9267746888420071021500735075663336736361717345091433424161991124952838871022030399503645263408791327784786086730026429717318657 + 1672147391408891002327479016767689503494648768717682253138108661180075426978036916352251329255918145397491166698770599594009604 + 1973656522713866421729264353952482643307862403936073686775977710379738331755646451684387173747099995521827339722863619385237499 + 5408235756969453434913224193378329404979503566466468217232986076880098924660185616188785089771941834979789440134998311199906069 + 2232778818840350786605080110308895419763433233707234872571290509162878857914634432096414764357358087088039057924071148091731175 + 6015400792410124384152213047000568844879712268022351230585299428537516602169557527154990684330404034064121063393300034030430905 + 2306055374539312465651241264233074065955242079361211680462145344554747450796349210759636113482252702608031612245403353997125476 + 3803253691034432130798363413192595243576410393487613462409388440991106589264853952016023685661448176427389232941666704057678369 + 8628747721532797463638681268551173019525973277356279608142072485533442125834239673920151827309537064739870526314899247429664781 + 9025827660968538606553886333865132013576294269585884802265251611104643759277860774328243246331432389944537967831541391858902940 + 1930816587488360252688732499160213070813273038333861895643529140656993608246150830322861238139209540926180077253222099793719072 + 8959519042048720068153629627140256241685908963439182993973204720950662335620899080859042503691987552467007737450276337233761755 + 6288965328635383011799009079228464765004787324704548708119617161002013632986577780042057914052383556753286042031709306907755664 + 9921350932285357024268612614215975988614776231803905241441720250462994526451363159473639866331342141233807338499617054943944238 + 0578049360816576019800945237402222592171684814088734743903979539564400529178521960883785173251341874550331866956766247772470369 + 6083904254700701911630159329372053705191987684688500636724033475465777760911461588784110437867357713431148790643538763108521995 + 0296263770538400456769346062348737783795801732870097577376952964730500440617573963135158364912865598645263299913463769215039071 + 9483488255991073328145731534454837990839423394416473517085030613349147333787972449423197209621559003595529788900553100012406747 + 6566884594766054381929553636693829055015384572992260492476307544253448277903698366356427152189807274375674035466963843196695551 + 6323074679661834194813723642658721376145252523971723277400835325217197190050897668239821693181091121061162219401288326146881306 + 1808318984353930429816050257400279035517547964016766257303295002919848213345027516727642354899576468006486504355233740324100211 + 0373421583654094261005790222006220690243740321608605292144463259644370384862300052723119124037021639917903672109294422220446746 + 0968367458627898019517765631253210766036998155063276402536135475040822567588712196840514962484791203840216962030611173316284918 + 6730753402413401318179055308056338575836289967262947906669540139949663260817034924092055901733213326920487904492973772740252118 + 6813399504142772729322264698007839309738863435169195740088479397131114450638902610593694986422730992468798340242051077542153965 + 9094257292692469011371694239749935666279240094911204646416349941755315640280190692332906803301138668428433338486284139761451437 + 4927696735702519573953727266824755919361553550569177388087634691983381789617481807188380885676894329271297374663349552211867549 + 6214976348118306656535007501010457882239285954427884872811741042673638154912694956412208130004776408704809831151781445974935728 + 0120629582751291565009219505554682954747176012178127728953108970378564330824283571745236870527703343674549433801104649142185888 + 3235814158776446629647585300745371840827518705724793256416163401064594247074494980560274282618040988687418212805930332830675213 + 9481691238337366800610093527436128723725108303743340453678113695806808341554588638276662497395500403037304969340369996972707032 + 4082676737625354210464419813293767706297361241754982481007296169725698649583516782177058747437891980516222464440989464874961596 + 6461961406394849542189779035893533584829634128015156718397540384299215958366542622049511074988966488475073248255117221338638960 + 0142933164629079463406544918744481398396204306933357431841214352733485790844296470933212820449310522157583393441447538375216436 + 3436698506912676403242337919492000906428711269510381173399936468041047249569064777837314598565623718618433285256806067639636763 + 8460415932660725184337524946121929924205499042071794021186039050613143778222559008526610557979170270365704047948250328090311884 + 8815703597819948360630939744751577068004694199231149936335126538352407733636909351409964233765563167198074923729461436493523959 + 0713926842635856417640343723268323797389202591360887205782568996458244122502082280450763638212538223700620622044815212320168684 + 9492871418408066338755969200124883796242190267635257673723366249954282292979482645457308347074754036142876356477739278675875440 + 2183538168589813954235091042917215997797441009968993171615399263341109892414323128649997905799043937988646881424204624530006049 + 7733957096488341212048475007904035717627062565794383079540365496869348281433928986222996400495215587152772750589584231009322321 + 6967167721546910451512704467642578730007590171739084668065616508498732163764275594573615283985791091469103384452900988352107000 + 6807413612465354023458660940481659053886101973060578770973513038430471528121342377174140575232152423951725002933862875035962993 + 5491625968951170241792359320698419197951622254963187269169519754789130928703155856710378168285319433421425146672702276206900357 + 6582314544521282948303668171056488977803778991914594073284490075274341682398796202525053587573368003492350674264590216915743030 + 0229180917308822559423399370500197589688253700875858499871606888817412759424516191276640847554118760685723541416666202243509736 + 9274208984682823732942979222927492539292245964003720945726994325795924579380001664666341956208236538074900737136200088724900215 + 5814292572624892701632682972030886871485930705868231267185916589385811869703139406294452824977282139608709779376891002163708313 + 4033763100173660376690182575379995726083861081926510802579785312647154456013703372795547129639766049095465742696104516613357933 + 2568315805640894925038031436747677782703800879694535494046794349191040639680313707242709239136167699797774023104845097743799234 + 6763080953224487156488442945555613963349180931811315907436001825754710792409694328952798340996992622252003347436512459358128857 + 3954533989335010638156841066648473526011867397359480295694595402042037502438174479721797977373598413288286342098814213128179837 + 2396433612158432510452891115965816912823381888049756989510546093247222344511226918341455435352327199403241839439420506108676964 + 0795850610161143815844607948060775881656537958435083754755508315612517655376939244238451149176008256028242905067513932423707050 + 3517402986146524008574508829340726577308717530546869694363472906429850377209335971237767032862995433224020904386089476753728648 + 7922151222682324169544546785791039508552110735905147311483313421452486749631056709157326288104257728264776617306059521303067262 + 9433265821676424821718658733270406951796862690935463256100330389699577509374904038151899940074906081844482171701461900939078601 + 6186077218855804555456232441080881439587655776678203701080218698681846807414980313213113823373021577317623820418853903404980853 + 2057729858963790488672801591735476430626710017313638370400064539747700089967564851982820372204387613607305955240060602392589527 + 0383881550897793438940267029950019121382581949345028853214775595378737481122241954444306274659828618843592228475107234699152687 + 5284798962706326315885441962112759776606317588723708150855167126722288961236786090248841992912344949773249220873179712041971922 + 9678187960541674562218790198419395947752158216709587927827286969325482868753908887434457039802709422399284864987575179916747347 + 5327838914777072714692085263368643404584146218804037383216974773265161119155906542869845216416813947477024304569196702936579095 + 6268003933265575972147374394617649572960257762413423428779104569461013465964897200866208582709538990234194911357542427621601938 + 8074876525846270711334089333528645517621667077382560706349198812216415510664481057225472908752257947691952856523071940619013694 + 8017368030459649790293701927587307177007662644838805113977690349437913275410750363651007980050566471766249753077608880102272532 + 1982797159364965178888531580373430260986522031868350608333752657707407931000254944024943348168140524874484514493735113742249981 + 6288538584949755098193652659249807271937205648283720864311553381239244146100739200355642491916783137202534161705603274089556521 + 9354739749045138253043275273268328367815186805183694069007675806235940663397422177024952828447038786641822001541524569479714913 + 7698528117160783953905420058390896481011235446749390616223922774275291430828661119528466868454607218473820114505896776059375354 + 1619019266174818706077047840193129831420498197596777970098691437675408999864116292704117680089265101055969410774137278714249866 + 3704870678985840970113166302795462489950063082099943547515245655672648446079824717316402600594084559028770660910436751665528235 + 4429408197253611572221699160867353954702111945889329273311821911416970564822252007768702453855504730931208682912670990901446785 + 5056501125351085290367349611566587022633517744283896529455313187439470673480194626772000636195743336806541403680260332379718964 + 4062991551971333412504544251310884322830607074386974123640580284992839293238984564989258127209764459890435786526862148574118080 + 2625522665812777011614768650094518338934467618573508691312860257788451631146950375887371627144471854275002143114396671788841878 + 2226696461215179698643658067033045890658991544538880319431666117259518073995053382607108900045909290904771038098705696699068324 + 6726532088338857549906950143621062126429461929145317128221035122460444306074528944822699784500814789341052158726046904507897034 + 6793037164285887325166583356411787362893236497739544799385622176244058491240539097656877256235845151279052346581850041111149908 + 4093573044381701004333825958081420923185855648955716595548583153752167241574306747073123301312447687906770815027018933422227596 + 6707271839374572454938209957923490292030537274459728356418336773458317286912917431092307541994164910938497543069009665010432516 + 7241600538166073336929364870095691302789706058064621204209320909673557421090888354529446748882788614331747011940455844576764284 + 7137143302702161225320499515565654830535431434870632910006167776519433451398361978770695152191140156154509207190258738746324525 + 7177837461622149136708945368215880972643302158259696018853584758017706472295497707280871705217770629770641478542481671610250773 + 5554013978114456033660343221358867604345109625580200393288313536168463029481940254044728394046188030569648323861618169629477000 + 8748988786120543881188413407361779739580428614335192009085939766971185616502526635854198592751325209395171686208426924544564152 + 6617729010736669611153048037379873649289970538055287963581277014784710903080627770559078145423490012308690390159447385760636617 + 1396112919025930755072794022535421762089970913319020087082933809741223660404657644541118861471741622430838236195432385726159361 + 7249197652757615950334012535738132798576509936889286629270864681020298782574659494783085110319815705595177485744225974776618676 + 4858557343521566530159783491610288461205535017137620369901510860776505101408698469561089138749268742702921025433191359814405089 + 1405508073047405874902803040100792069570430571449445778558936794822787960786336616853548170322337310425822658832018643837559079 + 7255075818431908394615699437073631405701119134607024097267578921840611418622682373870814723883284591259922905738590072345115516 + 4240694967339735201081972989105259182809574142617805837465112261091318429255228721568810181664317538777929819157212160575829023 + 2748237669200464565992816533713130419647283186413179673011963172187269272224647869974262327569585442612854368077691269344188871 + 1222760335817459965853292578856201576938118519312855304508610105281112231513426234814422228921425942855517206703964421120719762 + 5224765636718330925202872259803187360837016560225525039097597027027310508724003400835919326880989701929146674585353105826375662 + 4608686356759945389820261327877835956104857982859971343770150256738677287345081654437248462809898624047205228119203349515135144 + 6762635128848980939500701402251709503914581106728361156687648893186497005364492516596632908393739083848785619442884628144162198 + 9408219837678921746467927680318487696309519621970987584546154535257273988915610716263345779849862915767049642549659017655936977 + 2878461866210176159858735856155729710212544372367962529421415383498942572742627275020994117127943578105501057737118382232121164 + 6202970140395425040275648643808519609153095822076099220917958127812733404125781257612941188098229102786208245263355552763155862 + 3412899983063072356219645639174430993848691176774827540248823520470123385464397586328853608924297363157128484769714643392030260 + 7516335187749776239975100738544129195651952155894618035351972235899711941435830137791970183095848641340212385537760526454996975 + 9326117473414458915105300842976184452176417489508025383214692364884363250764059076859137855740438113389750789393201920849913143 + 8213713819060950631004232834986002902474872793703875917119551478078092258435100422531909399249521481966638648761188280089875780 + 4759150755939784604117474362263502288999681621525995527689733138120086197663894427404346527959682389904515329738583325486736756 + 9325978425209872464237977527958499931962722888446298443732493719892549369851302316811008601401750818556435135705126450083049922 + 6347121675883203194927076244218929133933870815129366063255106247006180593262999464959953693728515646161688550961478583928288648 + 1770297585530292141472219789662846895032928913171250259285237148388628954759446094661658933173846573153793706711301693991850474 + 0792606603197595851399011444059807607822829889531316870539398964731417122727677982590799094547174678976545309066723508642538395 + 7542251187115005568283732133757451228935803355815247833157647444961116649664568241618566131440468159056245333148920222556848970 + 1686590915600101341570938724862037843381611006851337958368672209742162426192678307570447318588843817286911928534762475716887889 + 5985898442600265569905129276649109155018541224177922670883691334985077196371351903258301592600475229763499481236752268688794381 + 9908334038229937596478744640386393429233365920050089472460888907538665294038594595567391991275514366380037563916695381509760722 + 6697176988394487279550132960940875716670256744139528862226095599316038741474608986574869723524996958686407456560239747388319182 + 5272345146409276991368562911742268892736319679968918454777104809692672080906197146972033144703725807051487037561295160467451538 + 3361581138752178146561886363234614574825214993383047665369152075131490893168140965966229773832573946751662445845244243875117807 + 8497747825333018837277204487016088859935993376161231128402571833027091271675038762646104326773996163504827534262519513030402352 + 2850247104178367791237021165640248127529302018809122924281078393572312164207913339929888292707995450264033189457174311609184073 + 8924909933371581642458243436549195910810805622486372258791244747556044533591204446068293714215938334798650520367000310196349472 + 4508128384366452869820524778886955415968833938807781198993008689473057745756213279992800316467476453813822465284911857999907387 + 2023953430847273884483235864052375615320236609720705596526699723117087569499174093607783752368506950667179330339328300764225536 + 2114055767363508202672868934173997107264743852817603394956504753530153541861401139621693806395357957937922300502759889840467545 + 0621018093521434841220357944235687355230152336239627344725027296978480489999738827553268628247847786834042126152054295485896741 + 1728177905254640772617413047936979080771772313470023078251325162582234445493894126314939244900306139362255151328277418578396047 + 1792422884816727055970087290849551106652457784152258102530082023142369893647618177451355631227247379577671860849853688299849551 + 1175037347149672092098074310747361251964753674884333700769847744830036555394374700856740987145924794681060765600644641697283847 + 9174589667717240975144336198616364140632445180996668524271118863864525314244946497799850056518633949293612226613509484575056441 + 3024489420602308444377762407441001512681502589345978196662197798484057230208048085644756143263157845710447555275495197040972213 + 5990095737215350840694710792788564049039561363466293476205766559255673678361573392948770517450420686662337759686497763541080151 + 5536095650185550909008740808818202276021308469567387829730017248451381382214473271435330569988489076831395673641296020100168963 + 8691489605876605176450990544960425812802030262532258796192840475047025803288315858498575542856190938582743335067317105863072855 + 8766959566097551451268355313989562707945501704157509911384107284566676448181401117485715830603954518469086610851712800284373857 + 2622452939630203014872224939693671859800249164641618680985148159351811785234412541320836473437263872332827932949209391274805175 + 6798235720998149184680985250493187047397164050502295623889415695762080775856311836882958794525078302171514915009308220188324579 + 7404140736104785086437030648484406734008243907361526117865122472043884228991384547907143497695706699559582484787176857952820522 + 8804256451428134606481551907263647977538193140987930551038510575189609463453621867637464848455610801693723759700181203650436839 + 2454914648531519297448584075603475998203868332048006750382533505496359960760723675619846780966293281981298326598027774066580197 + 7995861529357273876737015678397822856184868318896981667361295506177063218216975663372922918478316465965515092121524544927046347 + 7075516111646427841984461388320881450094372462158722036978724530408790912720869813138049436688811195541657354372228803333585071 + 6429445107361977048898774220057765467210817429170612447918756002833100352538329968035564836996813252177717820091122268457886430 + 7174078917945962391527335388096356842601813618444449251961003226992399982772853124625379285502923443657958530018722098893816397 + 4966136548214340660067711135963960273659031432856630667889996071606345454141323196469871177597395097849304859547230071866679596 + 3726141431238995322616590363658851982624885785492321657227849247981548495242247508727680411775990290110420891478204977360853532 + 1644317907061571688813615690182418379232646792079005297020445585096706983621152261491067330546246215457831060764875633375743540 + 0260037498619368766791619780583839981870124397870392302778118229013764892065306663721631976910781105530817819103416467777655922 + 1257160865985307861172892171513923812618825522832093610372208245587343312911128848417617475098350804052464802003464019493811163 + 3766028847159301257741274325560482246090419451830573366629957679849625493927009484554531296839025641820596875488169323390321224 + 8232388226007759579919663974563407506786051531271638328419810743863932368666194478382016978871056258046863096095307264426924960 + 4549834654287891305590680957281622094960361243150054432811463994295196664383435297694301203486327605844830810715344529812950660 + 5753311902123482227347291010505867923405362170620911512612976729652957268599586765352146177919457594239032123428411979879139233 + 1756522666058959488542110121660842887596621268641851969762507171503624064440144225359791257651455405971257235743672383114242117 + 3669744927951794530124706132421697781115421405857509254735757547057701496218013526040546290811670945415111481766033696065077908 + 3743986898663416455838782244658330408591406810811925113737418608085893951934341548820971030074613077943621026895167359064570606 + 9471978412930979202834282673808363212715221979769900548835760002508328425519756934140019511728229374555172954389643589129389588 + 9455543651731906114795743817911783078297338344457513508249293073101170733009370971042675747320086133963697038647918247059612888 + 8987238012717473365026512535048463787033301244418231940438539856074603360903070483058902057658066015083363248256775852399567354 + 3364502373064620236820638615612559600453180311037005397530277541350185917242503038852432559174885033399595723295543954546558084 + 9899331087165498351833150053347482195081440704956752507876144131532942935103436324218551370249739155812929164520262875021494783 + 6908904643032400627041773579937621950623563067061899745276566450404645141582156514162192031414915906603166745603027411059622640 + 6495757281070400862553880509625330137059949973388167457480215447233006890221821337932185784669081820552176614865399261551583475 + 5214987707999082292941559306056717820096495439266384956685554643672988468125971218644583921446293636673793845912080991022068721 + 9098075542650837679681095355197850211686123726685262897042587789900344672369748441583193738857149324437982999889236683375639656 + 3454737499177458611505297150687929879276146562076664745364918792408073476880967147036390541767431864129948395331642282070602239 + 6878237499611110425456520778926623547629857959652095556385934261653929146175223058776396057712180642186976052559776640567287939 + 9117825842497962507655739795549675536045986355442960959176637564697703951624943028930326642942379066897205661256857648338706258 + 5607249824040048715831055763915681630425710558796489860046207669351392908027930067134903067626066854044057840603625024212216072 + 6132093035960157469992103741008683953459144927130308314821395510817197195888871912314613073270790771658400690547770532514734857 + 2289766523163076031024159344583085122839051296194651927355671209701571188590931542840886950235609126079848243347538568462648984 + 5766639281060869652151900461538022230554309323803322083408453315192390160247383316259588161796028371801133887539960085255308323 + 9483650441565836194775795637439945189737766569777908677905305601319160962603730861873961369931413625520373523170442339205096446 + 6397277751314562067770288602692729550017088466152598972362685935373861021657565974015373030623318967239986491125515528075018887 + 5402601339014610197678055292860126657475597634829577844878918241260173909075027791997352414032212153167271561905364752619385786 + 8491863948995147633786778542070447298998068007279647829967199136460489001972567744945790789456373114064713748773853626265799228 + 2370209092117301003097542080527068882722669167429990641325299940901538545419032212913930826834352316812337709858765794889107909 + 1398631884718147949515763634548480975677014453715972288924837802795200463595978496786857308537512388719226166051585776739717368 + 6941189534316796817726911487247546420252712714875639017653467949442416805399033991555627055669486555645886651826109264153186819 + 4940516166674720818220542130511334825103331157208156275492549414655335399338455554953498955587141484886410449146234826660024826 + 6659792948006838082450272697160209259339168888357685416533244048793279607628259013570705943914832132649302220555803191155769678 + 3450607770354143996892622745433805449122734203977711922327068576407370897444833149206827486642681899060356549533970828759001934 + 5727275520263633514968976110225542746359061074870472786303946464842833869445090010825025879958856002949152638295200941043841906 + 1327175710840731608371208629917959139504834096615996636184118498113010168900528468440699292352911245996048410672241669829930509 + 5804872329617982647538232786144744032881485213965459136524837612293635959247462464117508493059931748287964717902656930987863246 + 4277723315738568098484054986328302182182023008609946701266751039890388797338292226205365731416488922689962862442504898912370823 + 0169167783207015850910326779335592201489472916428336283983741331168324385837589731443211700684040249551018329769335204931232483 + 5298537282274168905097783252545295159931996045324669229561719918373117774516092756810950028198012718738992851067743291059615923 + 9444851345487696935698137109913963152214976022384665735269814043959675847649595558507091607437770303094115672250928216923641250 + 2149472592686716079768844857346451000286201002122320769034758020998927559101579776094371380910427183625784710226757782544230415 + 0647876642293735785152692483992423954470320088754545909378609961100700126777198798362991474951795873563734734785888619665299138 + 5849838488444430649533263787538811331357728938722568950445006777515651519234515285808516388251516110101450462227962034131202241 + 7276104739525907372419126181186384546119321638501786879645354354875497667502927550069197442007577146458961731206493061524033007 + 9422217503140335187736221742892478886207544102369268483447607791356773560830807813772377547585429918129160635826252418480968692 + 4951724274446263780114357613049442315030582695389596800003586264063614032462365896162651936067640252887621519671734335954108739 + 7454566191860852039559843736923834077952568697550937244831873949705841445761551247253789687164216518186201016215799884228535871 + 8439893371971012000885553951535059948361302183174942319645796198457357286423328894929588756597087846522596101434099524110623679 + 2208231333330844864465745363677908966068876448934931718761801046807820975248234034617078513450119384012451530340905431793537946 + 2305572597375584599916270867173159433891169944691281508143382202813205881528811308590035206333627177252785229699333403132814188 + 6581817307307772248849032636830370028521484024024459152842727518740380359881146898101434552487760886134249651169919754088451088 + 9972253499037895070298514770518285390402914258598519025675691003304065496834156654347189749182550625905099172508363395356804877 + 5758008808025624632351941198979018660594929305107322792450818499652772086629264781844489198081813129733546688788720899531192457 + 2745675328488913480621264293304705435951452309540398654081411328496424730516137398740590505211615977997709945823736263422098774 + 4319217301030265407335508264753089155109074707762624338354639950177679811707826932551029618948153019495825747590381756914645981 + 9125342547489286004121333337059776054538539726153714180036823804029952720452919240063140345998373975940156807239544138619226508 + 7242675874264000704878339896544038336920890771642735504973073959953113142490324395737352393349120127057115852252907686376626747 + 3473321596354209308933007945651010752129252885281924230373167976919072240297072208573755175225599946410500654362886750707794528 + 5727589543974524706691693259117706864773673979587751324354353742658357813584415514973239116989629743388388478173856874552697761 + 1142418605095869987288446285147568178401344806595851658792922110020211362874700057924021743582095514290749364426026381491938886 + 7017216586801442390706943294273005287782115442259090512088524168970016375416554459606914186390125156135455842825317699271637907 + 0211233315441242280840462166926685973850749956345775689925242698347596240183158491250150173733543845430700552741593194555804750 + 1797724078344241125893042060239537330994558786922162379383591805537659608535521283089375039292199790021670953442916099772863332 + 6130652679697033488878720295305832453720948952785209088953761883766005724826476556165454243473790630572440696210857988190704713 + 4744821686581324503785124383460438165434233854467259677279955943920755162775872557500679297287992727542016808831027373389642811 + 8818850180176632238377551894120301699425047464434209428644888921239546400810384063448594908229208386662084553428371435016786566 + 2565402723149127183692936818466510584042955514361987237908845951130503356391102529543147109435545190864583265738886354448729716 + 2555888389438655691918145095510314610669012618591908132566801282747594112804817710376968735883323783155393749243633468461076212 + 4037970808854790499072817736929400553034907676890898900783090149602127450205466513482819048073679969106848951996174948205730701 + 0816030875372524859030697931442206128673990318458281042368684773151576092499288971063578724086458233384930941299441451767263066 + 1664521612180858396451529620088930659358500352782541669595817923485051339758066634536721977274523994998146473981701939017205602 + 2524104027099484717563367769361246592695182470261402965977193164101572566284710942794698915634141627566609476347965721168530986 + 4359025426573155220274777012266852482447049345363636421786714781355224872652596955092178684933842367455487342490049229104686636 + 1405127824749409497462184480237538519293466992317964479311951604897323056429690265101169427550747026874617333157171121236924703 + 6018076627013550295381656119236991061160617457180144979226462876301063552180250667955529552359828561142316939674528337208856344 + 4374830018868998904944977293261195517662546966324518234611103690143089662138017933662034152841911712239931096922875112835748433 + 0236447221655510600424621887641222992324877860049632049076965940501963553949996895966286320389211270787434721126820780971624253 + 1124118658886218410732481795333541469161905682578320893049989427979158879370075562912903672274463984603712619157580009287344826 + 1490073439715132975375184719480763004789606934374075237219980119217402660147346676094869754304392997432951402325274930204871342 + 7507088153751893726167389642050254715794421419546083151335746591084804700733010001661585164038391983336305667211157845088930512 + 9454605864819889656904342091511833717539963300409957365660591244004512939427858955522107791635547956216918186634105330346773979 + 0658593516322846162016300446203238142166026181710436615937557978420890524597354295972144917810824199008158678995080211427722929 + 8980589661160288330719076634082892363742482807739228207426629330991685667550752678607146578792931470069849286956087928508404855 + 0981420843325337105199162550260043516249035154228170027681913983488364730292863723816365277728171439162179656110789246164875870 + 7235989772218476249654125554327002628917857770756363184283174214585030441232386973067535578285982100385381595377232095167172355 + 8531968481709055316167180990447601481938541581517577911736493317452245372585792259012856477270057051421673563226983021870172320 + 3966519268023261060863087111821082801296148611252172465597370204173800451852480272015584093876590792853690848377385063421097933 + 4667059194375637666825712724740535719642601441210189891690016272378550854485280624499553958549215837331920055819015130335235748 + 5180652276625067336617174370015460185337302241346649852510792894228685353669611675801310899772318114006268028233834332313504023 + 1941303813100529733477333374209673305915978659212933725574700988773740701325826021523545062039757705261878074707241548966802269 + 2746067443336418197240323253838643666106109625323987238695096142699993722607024221029583744572542375113816178166737688431737737 + 1790082381839115387609873262982695752275538347088304949304931589485737690198187441832377091589179048950816796427590616885843542 + 5552689266955858826481326722121453449315123458065490624658389457610909531278210069460670951157478754958271396713130819467585412 + 8161144774814776141255994752061769287038765060690866140571952344698969957192475271081186838639007943816699743960034503332953194 + 8789192141356424274503562578603345033063547574284980009602843989229909463071658256259561315235167835094522110712803401150014304 + 2269120125327746733199585385420581800688978135760399189023545691870920243025811096318243711254873352522759304218250492540601301 + 3220660009367443347579325094663071621014417170436158246461857082697811419327408184450532404128001876815109034413458694764955526 + 4236810019612678173215181621403086283786465950563987195979676317579127299901400746488219293603220797858502005948349760508971512 + 0842456999754267165377711495312735495780613161991580964945616998690779002045181519007002606802172925174094502143404195978695837 + 4416749583760585438101952975396064089728080431113199590836008764153005621794368480547875309689843049490843783015113705286745691 + 0795274682904383996694242263473123412015847505963674606830368047427506205910859669522416907398900276339485220277009294111636658 + 0726660439712285671104280059752886748116228091939311944983809111670167487220776456879193368274819545300958924106260054971842623 + 8150764216086897115298219326429987785009191738597276238467913392040684511353140756968540557235239878544391001829270153861846092 + 4383222134341106409110971398373626248863354871646454326385144812872101996077996725153807549596115873770116755372384144360289549 + 8170673501302124114120744895395545744756695363267571023745570418014263093634951684729982428233593809293841917967048459961199699 + 9763136038244743451806991825890314924556837135102471133555361059824564665398157293669951119702184740695499289874076409711970682 + 1422421956968116348857989939957276677533229421063047970708284154758036180433546990214632661390471026182712000805513222171655488 + 0790454789270387069048408785812014404576158995323548751958890039523932351478622587142638056133836919868045535455845844392024399 + 6828229983228262659292226957969701095193296498963956591476120614340834793473477949399153199148731691820887892496627505449096093 + 8624492093374718033878604413583151815223479591147786368391299257097621796393142945746725700896309907581595691253852161958930992 + 7107729406703783687280485106218574382700030054257355689626925093581880354626104182184797971451190514868852721286584413091561305 + 8741987234103316893377380144344514006198840745678799814654988835056150781397439910157073114301452768509065135515533734967678598 + 2735043292667576626222020726140529203825880750760734206750175908534901067729659839678099054130592189468939769616706044680647240 + 2763006819383647925527431911808115681683993973822624367816274873450252222984650251537326892288304742295886859351709349425297650 + 7134753100395351301348083365117683812003850761712390745630056031799089854945233811860729771699517948808663082113548033370410055 + 2156718353193091760663949540389192861228968135157606923907872289234299014121301709409557692508414639141148641363055713300497167 + 9323046502608972228620000366263176485575290223984881067717695579312796433503231136630486297616245185739116228913473000321724069 + 3402413948021099348085449161508115950805641814124236561124067595528674925736958070838477983849773356429271615279624883406948406 + 2586362309829746055325863292755259087415528960697154410026073785183365372343620398551768197389974234910915413966255239135166137 + 6948141006945340339297784658800718813009858499271702100629421441689482806248257882748211373263608811093415305500022007093455945 + 0842258683716404942736428616895358695656655266518974938995151040768012671515151979466768515865903424648012383400333040320383895 + 5049269512019956300105561497239010604854186206683961343893764070138734690927147819767835829400814779254514025647466904224213470 + 9569948375696342652641662102284605174592869950745185014008552719701570802715911338264166097617707320465336842190177333964575034 + 9428680684767284183633020532362541285325879314896297017757679938122092115670160403478099811406505218708402491047782860144041267 + 2048668363875460097326211666406188941409324970507852534507916458181293600129195542233794471499710031501087442970014489278431811 + 3405993437193068750979763065800204417948705854493241428660974718747020128492308645680153785966021095932035295060527677641892559 + 2814589083509652662902787080397228682431174828014560598681492336798258054680671382857806718386021239491601389601875295478518945 + 5986699496572944083337074930929834075993621216590713141225309670719782429561351058677320246208472110574056384475102009208825158 + 3701143845992716374497567663523592738178836225177899343548036997338523733500001300643656167477000925420983129066143726434092701 + 7423291379038754262185514882391794604313384501082737513845672893062736061561920457702887522180551612186897189287428790772663945 + 8038882462960387008399150903931548842040303337569963977574310341965170156166264463639669524288945874943197641758694114087360524 + 6755427287648373311476510042437767363082433235534497669444705172475485394287772438817148371693824101932257743465051113814804574 + 3302584529244780057393036854445554623243089576362550605055694156880682183315829897197741778897975736012282052319045886108088033 + 8087176493289867561968800923375092924482419715512093174473694625106772042668885277666098646361898523510402733964872800445131037 + 8320007995921770348498605128869111626930267035943426816435809551556518111290098800524644244409358410267473862764842446130048523 + 1436098828025610017328979458386153232076446194265248731690143382189291992244935737904603822794261840119592775301158595671929956 + 1859896675014716704798696047818739852245706249557223427847334266658566082156593745460337399765187932861285602937611319183698837 + 8695387218535720582564065835479455701900416698839376472323627804365945785468346621682197696163783828936362978547295808542269445 + 8279752484506847142094417985544033613129823835703913986703044915444548737906032583690923865665220094573089105884291792454719678 + 1316169725449877686068579181522410565098719766530274437681078973112896904796812316498589687674134438686508004774642199962324204 + 4690063619499878869524791692206588255254568407388459022366711747832387099104508881401463078787110967721065394141648606132537550 + 1451429470869671002057789223158518659342906175930490990163086609677315590447420960904216338864582531646704745882645257996753003 + 3594769224483393076962577578336775804994360716705648101110515582304099946203974654110102114903083901640907564773113403226112614 + 7842811390980512417623967516307862595714647209118659868698680060437058188686064362842966029195804418885454481156401460457680810 + 1353730331240432284758809177395482784888827256712163440645440749728289433010840369051942073911490213001477219496896397735829211 + 4601945158211709423733169616586120219445506544455684681994448828365740758425856347182450418912396580393258871768216932273389644 + 7546606883962070377792485250777570864737360035965255716590780907370097846008363755114568550428189781279182714576817370377989913 + 5909871699164748481388103916215854782263584875652627145927520783000462057342075067627629231607264735052014948668522278967261465 + 7789853062938105623444363261994088544665616630390123445507860288440231593034911635167838522597643333127458708364830418263896184 + 1286144438352596484065325500754944308173042437315362632781599996019422261591416810474894175619846059414717720198222378370653571 + 6971462477582470633206125394932199429053380382783796898399516803651438673139498531736021776634684941580638746309619120992683170 + 8629432822993724963855361987882118654589234693568266212440633573606219295689682039033133123609808063033145394447533709295411896 + 0281594967652261579794466637274919984182923757681634332365968310833409307348568763974412665592870158544818035335013012421932763 + 7655826860692715418764005666669293766929001138134358352328235302135813053504743107776878655717896623753934484760219931500298692 + 9290168663678775972562133999711785783179036668870829240738642007250789936063529444287722257668245891843786516368999364205453698 + 1388094089899362163718773572230079214466119375080348978705038480095898940916060131319234067470176587422484787467679366538347868 + 8017293664803927630769729168954945146012294840940686008911896485848777037133106837925465110245874730110174759001141830380040038 + 0120439722450454617928179479243857705288134086458602893871161972846537382451740227055242495699985657918659780373398590814158015 + 9185549346791665800883510913273745072991047690371888044204398878541170797025220849684634548447569944177523688037116487344544844 + 3983330147768673814424552255794031561316294164196820680509267685360230979960997521617397764375675161021883986966830273621436840 + 5559819786199323213875219658620019627595340113429135282821726501703289978583492131096279542835050405087347140325687712807079487 + 9787946090092230362250195573096660493646419587912974580035697132589473417918325240116393969464922906025196729087774385693764553 + 9860355320714920060965670358032280168554148297437945180860387882403591842300282814921233640661490871801402207762626482522032047 + 3097025361491117451005377278198487212237099544908247111077372764356886263791448989161160949762415522639831639294698581458345985 + 7119461403366321455704765813404706513096376229662175435103856904757065360840168635845572631764671801632765978886309611217770123 + 2355725108730791813146700353437818727398062989969964100944171032459233591148110740093249920429111285758187817891195538479372333 + 7717147589069034365041184332554553609756818941590171329038369697464604453126540943732615622700321916184110353125350100127752260 + 5400719243883713007355805618610788516934976237500923767706894033322172234355015854525038569883308926393709084041999484656996753 + 1283666031444516796129629651038339271512674202354596553588525167158551065999313761923723647718179391480101442800341777895133996 + 0753973775383179955400385390016380992296547654995782315767306424246762945687075752145691419815405005932537449947304486849576643 + 2979180958396224767297581462043320034127704743702992357878029772922817116999851784773690688789215232089766369127969016032601856 + 3851573261415488209314332793330099314068046066211719044146103127781354079770099732602779302176734228288014045681315375260376275 + 5613084622744138175415292879907528314309988380989805830104342547726499059288400078772029464667932988421246953056079406071204771 + 4586730576036740853854978952480253788859203002939257757392716256983049436420156853771221502897572109716517239674204969203181474 + 0982119350191052441755943123327258611832950316806139591389360751863567226397368531779203766930988225110737707276225086269268083 + 1166609927459152345242074308503846915870742513191815496448329154263550697382001973332037653901875197894977220232463712982961473 + 8742250538546251559619529217497793362557849446641056066254726761640756859174902719692841027963345440941200289292587371677456563 + 1787473730619074666648808301286212846168364513813858291223488226257956569272198811926719725754005926219281926579718279777830444 + 9964885779070155802556863992597887379404305287991864566420006473195804170299129414259096081893003248613986369776375193541122827 + 8679261717535638702784929128089835277682571491318590535314932208130153018789998592505582846756436233025096155853923159667457622 + 0064101062279216730164192200983393569735835140706754353527254528463606619322108164129797836707319607352924077829068257856221565 + 4098966914598730293864163204728437998349124344700052324246741119119244973881766239805489297351925527481613098094358252765642656 + 3256631812453399632987567720287450907847236484423613740997675264597104916297183865029408528402827703543717537820987540612308827 + 9763193844988062420108359297687488837148328286540087218373263127565810612066788312087172343604520200144217517124505185828378183 + 0839169941798971803467138716750724876136916222233258526467257984594030393990037357389464526262272705365500201964650768865692587 + 6552250604997641261294087071350242489522328429130222914193744223497369981001341679952214443941383946458063259049876349424028513 + 2213974436158368636025109248174911312580051245505113315795959437260475388392500593400331863318219524296806654096778830779216940 + 4878685599516319690797457606707664358483790224825508827231099632903629838432588023623129489722939201221165328880348763488094404 + 4425772854689128756512183299147748549960529805463272504802739617344094375960651486501133996216955411590283887952698362709773340 + 3400068591062085249345178361745959828363146278918068111168494145377017234716441154409189698261322125169944980545699464089750536 + 8846865398199885991570109728269877331973845988335052515573008133676441111176443077214835337189028637762538757833593083011292020 + 5146028640720658045073881058022137119722140728994381646856170548927402303281330627742305686994941764560406751703346767750713886 + 7209258975092391507951817856714755923161856176501059139093203502102911025009832983122251947751287786516716014787221574638939756 + 4031047248735708744857275535082996528246946792080390060989384866585501142477546435169883331570932498501313613151748523824910672 + 5636536308963660510951867259797466984603129916969819578084787382312187680895777499152465628258228314680156051454804934741689251 + 0512085879302345402847429395015269085320583560263939898103230391420972595529857458723736782481282792113866713373594735837816637 + 7989131244460061235927200538684991689192443600011394251966967305334141431951393722271395226793607939272662478632186079903315157 + 4105861225129127048237596511466748710669457275423951266966241892139141936555720690437418563605034436351637331842274069357984239 + 7714780490538701008702866992517751463558344819912101444037343071198346617249265664311758101747127784897043351442589412949637554 + 0794058900554049165331519254294841158439399536633260010261808293322453935679510287405960977887161196498223064393352481611148599 + 1300801876528225731545729262391681879452425698425569733040068970789105907778300649408653356394071182530765139660697696280006682 + 9500403460028711452841481826687628011337250118712797471026118134978473459279189369396543791538899643830373887355243212938105191 + 0873118171200026341001915337132116843336126642682077009436271005094613931653248785836179383736770204896797782028704969977499350 + 0015763840495758341501065058600781266869591393444306380925176998016954972799133300711081355008885083487358653288976991291458433 + 1182038281534129680784410839850542254891681906855217404657576532842299794168911463577129652659153953666202320168343676218151354 + 4489515205537483086890747806185147028159038841561163491305751443503026033718219551299657596422184541173585136713789948319572208 + 5427049518844513938239013971033113865769356316346953363872557559769111015332419532829697997722648255367995610629118024243751562 + 2407474388820183495631279695253839995841338363502759887550630065930650395810552864219034911688436057782562693639597408091177372 + 6597246835826333390472023469934087393575305915386587464255626374910540525559513620612895257369286541372428722814356277369790926 + 0540482329932732167361734686964636330198342028336626252732092257904785101659859937597352536082164206650257784256989122547150860 + 6958569549047812907458129176134743095874743438183862052347741885494624143736509130890665487847350948675120079666371405006768737 + 8780431675373547960195603385932928721012510177772630104840609721475744144915357267790854338213160647630650329373129575638594956 + 9496521524390891252020171500116808958864975665633521384560269916937417268750283135245520953900937858745308291830904258244389317 + 0015367958131832930196538448945414897381505579147872992058659675192664335486653438990141847260783598099119731774723267313420147 + 7668586967951300028516829535113315808229408687973080784960696295388250987543953394689424360452251573606982659417899250410280988 + 0855610169950498351316129660470090096789046559977941298373823170600445713232790694833343261118257499105417238723309775430866295 + 2330553865870284141777533356762036585595078938692432368606760459748846645365953536258322870084801797022785593339163737467833147 + 6997226216417469287126591633487052682393389785830401431520389186301156111690874765557617527284900760279233718743071166517225051 + 9560345000426728260399841368953209835209100487337639538936954570820031680886090876109665021023200759147113373797389077298422122 + 8175155068276335352679806117326566700814346009488428499581701401590558929437455938924635624938224553855781741120788865291783407 + 2295536946679503673362429092591476438921243024065802176610048872694278802256805275897901963915809617356852239830206442834187860 + 1980560976965565165140981488552352620248220002599581191144636050647934285203553865821505084561426414945738261567792216102403148 + 1151908591260497769379834919810177114427370448525005415075150280396616811812913926897078347185577604045023394052213732465977204 + 5152624009308747654657296667409633669797187558140762249677298229159695566185953786763883703575683368256625993695568514289670471 + 5898396239237604417219674285036697981388707533386023577734556605753254850219222927862511398982564982295186931657039590148578018 + 5932796785525089331274908323688642021701636412080489905006446995970747450915290182470813258134915840332610387871533886024451368 + 8138194206803987511384906150527820013265474338857553899093509868964543274546783521373587071739152356855552276377502435950664343 + 6671221923018976396144288089085545597962326938710922261699996323322275457923099268605292778087753199123847741515682942101433343 + 0553836973054122354894964985734607674790792609106461042226839499946875666977767744836458472114784382708675816804952000351499560 + 2364997010884637465860014885474868656892220025469289156670808481103243684995557245150848863996066555128792257705475749161690025 + 4110649532154387762250909130921439734079690118528643911754202049214907597563788601359791270067268169269560624171237553348861595 + 5940616224028249469894892261151683448506705471885912971357007128279832881479611563158245452847817654715394431167451576558923691 + 2701950548115303007534807474569747157173002064876638265966317419898895957065042960548048125830083650783906003217529190210069108 + 9448438509033254495362865744281724512323137198768884725254104680523096628653622761003126111128301647813853623032837646549389708 + 8800961571279179907403520239170262557803310568213744508717356574441764473623277516011904000012404016704294869157929203333991614 + 5621867976685621217499877201966531190154493625522363719922688125680349437187226891224242675375445798588375405091275415995993660 + 6776602064451444697704536229609651834393352676778641614610712731028707328894803760218379598569050464723477953936124087430950917 + 8609350069628812265374110081821823052163446196500492527833170210965201939797385205224718774402651526872691305286672629217382035 + 8488697066441224751559631066164022076293716903983024132971083317225244640782734589625800094058649006568726351629980984900472989 + 5845746441409288197669763941632849306888745439411555999404218596367981143977695990224865577494042079971012624349908586273448094 + 3944731944003065116712174476397673714373918870846441482703374457072218866041336694655582361341131880499845103050687313792470342 + 7857292237476195260600973001695477364449307421802939526518179464787823934178232688755800049682688090660718430541383983270572304 + 0611341821464316878794523833266573224644012837504558841156871904475125652999503438286924058574554384509785291956022252381864357 + 0405626679943651292212678664558286589975871490755359605369624889948784641951887207653741241486219388021477385980747033128784838 + 0349563685997861866328510113314436119201124870929479544327167409917885140426561670911266619220856732660355093308773694213795936 + 3842271417777258599324767675283259950186722960735488702869088413460362934496727774403713216022454808579752649987147082209915211 + 7262086846799716572297263071380322488276591389406786696601706848938742607301811413241169596156442149745813064652698654676224030 + 5774876540806221409456713575924968982273367206175097023050483195829231424480633395579433434537883182331511499750784779245974304 + 6819745509357317439429415625378554567362388569070215909977624507836378437106698876357999443207523376055325643289588788312580731 + 7833148656904363694334569121139758945904938915660261426660062808527488257575416983895078937523942074734502850315306918181450849 + 0874641305830980547277712020017148651915548171250649493853510014278214375521776229277631115079740388430042785920214556466053488 + 8302249778400205215684880334891997915871809162392886542987069548288428411471154533517912205528047987025944754683578880543791606 + 0358320982227642668267885208147099122293592290139450664586369209811129197752858004803010616081626472750567559363814707696436535 + 0313506752837594147209139665385131531998918025147449755897149885365821721038971422038604629058413601987368885444084132780675032 + 8698373618661979252204221364880007737028947769589369624595251994724054095272484618585409406539000761630748495654887039290015310 + 0800818173175869261167775704612174999230343952148568401102639665953327107535357309312915124706207238389207300777172747117401698 + 0640073150863859675544943154734483059715378564796905159762945298307365280446171698542814284025032267504158534248530901828343035 + 0873201504993233632733239057534034773053022444340692497950449652566396669145334447109018793398061041589027430348848568737315985 + 0702523531880691374404054678759180464956226260133696133658291458560416403819468440250477647013266610552428012647058409477074911 + 2679888054788444461424298005407130238905755507645631966764120317200939342102226493489457200513433158963725232826211305616759400 + 6659241756332251314783750854468182797311328498121933543014291040088680657858265588241030117849346100683667795040402222839296842 + 8277427249362157833641670896337597700968219737912856460330555628526942419632625557211562429343845027815601523792180592076379859 + 9754404607631948362062894438912954500557072195072644550642458309860663622333701157823267362150209715197912528880882392701349340 + 9392967484360182578733939528902161701930343748675665636284278981486199253820383071398887821347218338053979003089742707812914379 + 2904235361284953393462862403685101898073830804299574939556200135991635904384199077467177409693740584708928799458835571980205648 + 8121614185438088992376830836290018683875444583668400234525664787649173577729566744205001928280399848363250846307170382670891227 + 1379156561645180509829419293369128655964653490776933715927876086576622995107120980971557236204092369803081979966524323872401105 + 8210634652239640140303181717302977441319086010060056823202877048062527278336721358234059108992008083109338742139836036323492605 + 7384031376893772770300054085703713950658765604751229388016547464754511995220292088356538057488534591958960218276518555883565725 + 4074775956662864334941163174462487475635543748972688834049926463696503634025310758502751556398690346342648412837461668031647927 + 6365750302288055740676475554487791055706610049861824646116595120976061102018119073494765991803213702717674747175954421813209939 + 8009331937511328151001411154015547213063838109162601512214845406533014265983012161008264010599651427488015290161524354573353234 + 6470978945561557225050621564665550894387519941185513668617316911095236397590508616848692919250154411755818493336504839734750031 + 3525111855377922515708294426372763399105358667430235504503228627410198905334837234851992023849271193012460177555030458178964902 + 2832205291216922852095126506355099210740893308816704635379794133382523761361826241501772732710458333973916837834880210080414250 + 9084082447350749526849475397900892283815818083030975632291741303292925823304366055091504295072069505478412237935230243114270458 + 8733240614953524515745727759843129756538792646920469274157284227528661937418719037781765126256474601006075476554791323844619684 + 1035243868690685092085007530104395247063420667025726455865466535541087734271159372906562129287612463548495628710375386966180600 + 5440542501876451157868698528285357586655663503645304099842630588650168915815059917415278238955617758631802903768822104984447821 + 2018849475721498910886528030895133588236820109040257215930892013189827568406433756483461049360024443491773721292902184969255790 + 8822875627013591731684908728396697952056849491038175568000507526035874582989907019189676297477355884544173196568562596540184740 + 6207027832469439408465681825635058880584562540284002435337574271598044807397129809411607354965616450909115426381853724556891033 + 7221658030059861817521753782741366902139395897501991336285575875528980544038829626149666345302799699624831576475243396464744984 + 1649540253799052538081391692469181324705607910980425515252483873483980593877409055481936471747872491282539042199279780879543216 + 4236145733824367590860331474571745015558798839670826761096891349398910243527132904379844441054007921880393265550231971508677926 + 9325201276405157061556423958329163005949768823959483768715570931105074676418085399720398268434277889429566019457186074673651582 + 1556755082109554008455021604947841187746491317217027281220528571996910808491743715098726471698066342041982149950618417860098084 + 9612051527440619756444098523237719085720236857461176953239899550769256325996619384467815272576473677824512425753715748473823644 + 3293706412332532029368150574309147409666660955800738909802362577371939197344269404239579009973609254902956047445459161013030585 + 3889810572293351817285095560307955387570122899356894847953368306309169743185951491528192204482516204225431961214922057114411745 + 2466537795850541088028557343809549480793529110899163252329393397207265339963882361084755962562912216879860134066671514387618346 + 7860354854395803331508980945959835169783983572284248855654573657487835485311040917221652836888254950796354469715116733559514443 + 9649687850645361629683896013084952406507914922578933911589068814423571506614639956792270631464418346423540206296752844238915237 + 6020288012912630828121914201273847417936995938147436941121877369382021368921214557882494996867880498498027992143690818597132057 + 7464732232055318247290946075477625177092427701352448918522702341636498386700884661390140882325113012278493389309349523351396213 + 9696483275515491260944768055252019253491922403588385357522280969636691193420388846988546363998678336385777443993831313531774583 + 6282522032399446565965739736752150396232120722412203505719106262036358824681398508892551567229346012725815333843066908465157756 + 9407628149379572734413508114861082667244920525693627019900560538557779908157912341364139167913811711711544677292025506854245811 + 3464634373606321375959043076084467134891991975403488809906777158185809859079955799214529934428440394715803296141747865907907489 + 9423993889790762040142434803114305323935291193328498665927373291227929076575533913306444776443880643225751481031179680675214923 + 3368470912062297700011980465345274304044785588310672874869214201316579834207228249128013243107286248089143869069547088156308777 + 1414590222708121116814503748513196371955339806257298864789960510451079590735116383580469454857965360874314128844784304143454069 + 8766678394720390254448078037404671513243310605018703312189431738938607517130277658972087080448195787216475306011123823302381254 + 3391550184839202307004590614178501644771630600861096494601392733266531850599404613838770697571965897048614790913072319558856284 + 7803230787138777594218452988887094396749088370117209351285801556001096168575241228759515079363186428923678980339871398190852582 + 4019696628533985636279505759337532628472390302841917324608852947709111244515112700445738982371253756187679740389512024539739520 + 4770847899134941839230668652175028834007538603739876886601634289336067458758592877494727624461743546957277223347887135182085175 + 9704365765485920770156655545282270424007413902597806432869012806155483311798101235310454409760720811406614955012826140011450968 + 0313480515097495573412839063893028999786645804567919951099814820194282264604422806064547777371073192487100289094441987847150568 + 1657543112009039941765308947835121413396501421019711136903259340105124014460634621836811024214292779775980478293474663062122820 + 9705767650372955367904858685510440746508331239334572782478185604370866609254504064506288513924921428844442806366648997093161941 + 3489214963851233247024856358669087681654387218345765317192165484089902190489810844772030255183904855574220071570304690043795231 + 2065091959221855386411960322245401320421129454685844655947550889456851989959823948526569728196088066488438899595441765150072821 + 4429114819428348855107669954324003559235452502739679008927728613312163086830142833511895866448006257958165946765071157730382695 + 9882679827690443780755577550740154748999710142655073573245474660654485200341800425388615819101330831466686148830980748666684090 + 7163405135812565179670235235614927720441373285793867065291904861238349709700184831060873375476942470039510660809272264903320798 + 4462917767939061046448018044214701368685457860623889616757211734619696932095108903120448131130054208365085745531785639497736359 + 8218165839330532616994196742532527473553555966673141549749982047712150106818828620285541917373915693522694719282613944281399835 + 8674485087809037160526520795860814268331241546826667372648249043039257847644579120849321232434718628926179993145231262359579173 + 6402705380929919120941181769537062173912605142768108201761013755197467816367902585985810911153925853453654100594647121313245913 + 0666872833826033632401371436548685693080139022484100159022033636174658329127466366162032910540421919446428986161784748017789598 + 4723199613767942411247930612753447325541505390129994382585659648148388692327147276519250190560063905452973361339890280400124358 + 6913416888336681958297148217827338479648390575317941960750631878321348332412104016113215430987661026879407929196484877377640061 + 8494663204235300224243052398541725825482919073092074355975063032796596426605495082752541621103997044605964809112021627153615430 + 1932408491193512375077001954464823146678231602554522550896013165127235920096414910813761330938337552089472955671775628068540474 + 8216732019553272236739723100215131535386354969462704414412180804694918899617675023795044921436432605559415902678545425651517812 + 8025247190590822148102225680479409002058106823871348717740963812585351667254545007307100968605826752214724522314039708032085185 + 2898242245907570507615621864533672777989484514162394933849338212142607118088404798508269488444104500180113716320167923336719325 + 6087711919535546884547342110103435389748847458344462232091767124995184518172878034781269231230242533893228603793308922587510107 + 4591474660599204864799066811331150365409997858447042372594886218949250820247279474918230135657009456785941687614114216570961562 + 0712145092385555182611993058740320634997625075753366666542910024626577807784857468873721417913984050547176339602792705731039726 + 5904226911569176720780206777188612328120845124057780320649670149526594811111907198960857717925291216166167928639613716137663067 + 4307416456452371611701931195073322788105756639763524372948315105493615715372579618838296610933712476520491005806495650421658587 + 8328103991782890592563008949384942150246156275152343753139757736003563406755966669814359044466955928045317799518086337670918431 + 0138083133435376046718367707916060720252112445257291714225747183751131216668718597844623190537189131972377334685833227229634752 + 6238721382625606157004023423898943602807707672999152909288657052128785368828226605301253816178238566671806542598902348311422328 + 8320139586923410723937149546492213794676826048701166669784481756530412597915193651538414740148097847037639468257092287852640305 + 5479022830982203377478476331811758576901670233527290215872232363518816501458927070562308753377018843087767143244104321568604135 + 7369186061703793181459759961931363593408835426106781211446368072605366366571248851597783995945722926222426820630491316650527779 + 8828573417201809585216027386210261861298732060253123609864528252840272478045882739663756003736716392199489082689850824432511971 + 8111646983909651153366476446390221276039522740932580204249319217339578537772918571217444956420257260371077236650618481206170288 + 2935054551970379324008798030984106801055948226939968902171687217907155340893582643366397894579369212912093597160438593641683669 + 2485378257568528389277310889609277386833678172566456312002344737328227016110453362502908568225831332260414575845627976066579941 + 3482852162228716106007258452673841400279159876124086723321209861347673279139378292982201754962295388660515249705755465339980807 + 8586012495756212505119149505421333725699491270326513988475156468533804482583378661782959257850441126447111003717332538997317723 + 1776086627675735007130894098661445494477133237650830139159997474669449285984774365441233470966013545796673243563388041724650925 + 4871204375981896728514583939521811481161849278118060344334503543763509824336823270998963842004711517359429526921820434423765506 + 4949119417418804810189631493303008698556136954410752013975187350631734375598695358460132019129899037320268439555839944615572946 + 2352205983666568424098911534581381260867463768189900460175744875437666192115066390019086651996365032553554531097825841729484867 + 6396761821871154925250940721334814793716957966097731930384514803099552848004844714015522077211735687647117734547230837853524693 + 1596031648179998000220637673943792334209148422484797868537888852196932416293373918035158752836265069893009384789762509582269339 + 9695024706050496247098862490788952376578622083442656866053965079277898118236124486093149364786379996025483226916387856904200464 + 5207178534801739733741859262250257717063345689422848102283865760573174574242830519134626672907219548945944321186449133371889496 + 8091522599148708961675484538617588113615426169855145369191110338586586013267131819054886276010519517578355159744969858769754154 + 1409888192657898889323633959345553144675637666158270953101126274823625732454329591205013981131246606853736622675628645701807371 + 9520905296639004266979383969455080705361676763621326243504360544161563837353776252465278766865244727756979870759572455920688699 + 9581386171160687133121725147597447299189214610587624098233087649334093755829602691095533964193964555227483958747057992036054166 + 8721053344317784071933338712749304229416314171955616978192540365793299631623144229526476496982594982691261090976385827573975900 + 7821592310703338108652726889016577851582851275588755649801212540201927028394346407971389167170778763825909054893860501536766294 + 1680216758688189041294684581042122535978201496230771039365667061380634389195094311357702877874169983055267901138828354564408227 + 3161070157288336465271541894601581266294703722546655378330486847268915166615856440605517140340676687703279431660743947236511822 + 7741994422834194190860106225475557703581613419594307564273066500384493526007784089212735294217591917854424698645245431154845570 + 7453435530259083182485810144347944810673614929556646679467919668579911140259730381818980942598880746925296760172341499274790409 + 2328005309406832991426090784212693827689769275846169654962563240745452602435209585710235753460014401490458336687380630135023071 + 5366592739312999644456849006548399917819901894358497737731098338943033079178655254808256654806548883980302404456845406302737523 + 7903862311453131512315977712627346676478344399846058399879029101474967706599628983635802084695117268292559579897221003598626395 + 1226042367447825280036345293351132154926212820976803484997329381495188404459278925205516668444497544901886948777923893344531981 + 6856828147900151315527595804653628550631963940129883617356848115429626055627960941822258407367220366681493979858804129725050531 + 5342427449777364357294403483728929672993293331804282077540029002773232860603723492768689779320843055290078442091489307669129440 + 2646993961014124319764296539370434958358249722078956842849671467698536721940846395173191197670777284048312934901527571955362838 + 0198542559113109732314309858412233715215167131228324026800689688315670022802995393900835564840785241774828835077665262843753444 + 9550183762744591451958276893980778053478437092327149970098767098796188062615518630585477187237482484844353645352242801527565339 + 4554133259430221270883589344804016824319680145988501368070988742027201586296359667866696516024912143872664381709357471736498210 + 5093801098192097809224518282804541968783581829389873304181998214634779593308644761544892301474532546795113168811568716153209669 + 1410860371073926432124196875939453572716037044352794395231284292433400177009767688979893244784882963302195811252949131002020348 + 1963827673323077855623143768105648991600618303185458508264555147286917125868559346485583695956446151749324530132278047444739067 + 6874456031627491486993438537612795741124963717273593326065380547768578196708046010574823669488232340781667689355939847002297664 + 9059011156256654537948571823030159169978023672567790424242785131594034312912382632898662220373433122635586320057460971136026042 + 4324851680908243245093083193503431558790765585803419091388697495752260988154385332510991556891584925155976792883412406678432776 + 5169890219592441180988843355694784180780002217839745830787310928598719082559628331291213329365294364549008762394123896795514907 + 4029304916499522070046006091292088087865888798317559803991873835903034439822636248876206336683085957754970026069257438125567024 + 5122833726152490145361691490840338977240905109443464507374230617046450541939205551391476680636725777819582830317640677472291259 + 8887879121383290774133008351057610071339235010888965861277804156037797773751958774639837524541250075316907358014661336099985243 + 8039061153806899718406603277773464956989757949717475056088907096202984062415028201715624897091896396812284772715615886727140592 + 0697572299245622972158982736674917157478112408603912440899066443377237594315710291599368603222944799827489902803052151032150505 + 7013603271652485049620063445001242816749693945247727354086779497318820787447165373787134099987577277741625609459410605718145900 + 0792184428093364028147126779227116462983472771162905140500152025984437549037622220978921623538498863508150200422542729027788614 + 4411728159030287378714419332373354590292666051672346415137756916116829485503628039118411108736302251425180386282192968531233608 + 3508034331771430567756401746605566004814192531598982097023747313496871602413228109505959309225451717487757635602112764447022631 + 3428939513944422073187530514913804210377096901814387277664055693937327821063211837805670103207586535472844416128884599982345779 + 3765013258236529201610750246167509469405857415384290132571908547691847116538830356937781623544344792657443940779980096189839626 + 9024565602139835552337325332903285437411134785405743434839219379066510469685518924233636921521087402359934033983973385991471002 + 2649847962568274167726165208946386788572121523811142222528040146116227215917720262618074588389904637062666528544746561556536935 + 2620030538510199023964637151697713281829456055441798954059894139613970616409824903577033806155241943903044175681019965795785283 + 6461188416880024087073825761424480883587286299792763357082205040327994699188993856940062456204962545880583868705703598889787721 + 5944413986797134250694896844973795638537262177510549522817774683727110576630405084332924025735617088037709220742387561124513292 + 1615973751057225002195236737059699517585264539200525680337988614003524501832730480276366257598203042140690301023569755795697899 + 9008200222469601333665860661780983941015300488620597776980944258674129973552734738060885268066420909348372616142102733523433267 + 5003598890783029733738430164315966147920008508177297711130783619606431201578483617231981134136392404255762575061631480099367673 + 4714080230392459893569173674100327560113467502678424574866012722633975629063693151545366570327641280682622355521718987259238801 + 4739385038824895235096103000674296240229268577109938375885209481939108319170129231324096236414336990925757528939018270228944966 + 2361210030668060864499350273214477998565800871680472680681932947260121232176894643185754378295528202618772690219192407686919753 + 5156059412217536746848726448056144396547837914584560922069735882550291341190213498634134528385275982127813806960692781201779053 + 7966885142214723811725348168549783205309168240872140544601559983829401790243561220385975487819401267336194223205730538148703619 + 2086985085185073545036414851529838204481235650803097024838796015231330542654233028002529608154776678617456164886732320375739646 + 0833105952434512974899609076351921948939569136092110228925816092118172001373677700416412487399777738494320581470807407424704877 + 8185614688665309617727123329966574828512583312557787490171669059879359795468437113583190694186011613831079902014081217754134725 + 7131783601536200912167420913195076409694857630710552837087267662216383925992631278943851251589580445676689967886327863559646484 + 9888310805734900531289699098784350167801387862535778038559729898236704661594447329313866535642213694637004811239940871137589762 + 8123715241748226553144892581245052850529932097715696995932059624924557269075540247991049472713937530723957720713793716760718395 + 6093034172460809629440737053209815131819638726936540787299401716655839213840485847609031890782549934060830350478366179240604434 + 6633327894940509763972045245237235718323112502675490128278367355639972323817271838806709048068724517131782516093900913433491465 + 5582353019666679291426183344951264862654895560952921265198755899160545875749490172299073507227437486882523588711701507976499572 + 7489002650231525223980434094738594856401532028510616419177773329613390523750901433006132084090755184848290450781826037290985462 + 0539323854296447671459242043430937704073386171637825236119340677027183609466820564020370547139050173937355911835070350187485451 + 6965582154750741810065288181652685394941853476132562873871859640024361243300296805283748325817168878484565585632754351908511680 + 2886210467566660836736517150078351812871682359935951946868379376912994012664524203941072154686353570579681603704825530456774626 + 9665362335544365210262820037867343620764616695075643840510926473275049084133707571284177399685539645626628023165977084111958392 + 0177820463043321585863992470028736425683626513381632161117010851699245594406701811450201210813697392240877275493182279748367019 + 7250981623715632368538564967386387747576695271655268440119068242579103997269027655460321699463398768768277613166901925556040578 + 2730921762116366900155596821064099866827590787028023864778747307107976624095851829841563684215591447795700215410952638220148923 + 8642501753068607515960160175361362264643558443610150876742595480796702902130477857992388072241713968623856298400849938588555032 + 1187308644994319305723690746675187962892871980887310999328792568364489164541385679772588717510375815217942384186220430941913143 + 7605854751867100384861067666196612302899049367936234596159545293447341885894031370313641111815396044152641244256403303821921174 + 8006560725678932454993887223171401960145271946857211912769628951507047840598467703395747670926287903550867839502877316151413748 + 5747061868485506527664044246509977629632520838572005928929416857628593497937173916677705472302579778727680532363758751491026938 + 3023153622006915734476058970896478596388304728569523091701672491484313935627044876208043141561946195882862365574965158147452289 + 8540852691422877019070250316861163162391778272197273383387116022030059687803664857766804536240988573448290819394431972776651275 + 9021443311810736715901066501558981319880316837771114344162148017989800388690774710489918382047318311988709068050500771418272212 + 7599513906333939122554708100671399521304710290565461919067937465641955962609388316053120501043224440969693966990639899533003437 + 3190313864768728595063193176469208637792413542897116168001394022157595453909893711585707042678368387735204900683732630413423309 + 6043003917729256108805619361421477310316625655437814740309514638761344462517487426501249646525209961899684542352037279524879981 + 6813035487710494491438894246146083397270552071559892438473910394670225142289451782904407545380437720612171136664498766583513111 + 5704425501897608539934816199146825064755643795555188152948142674213138361295684789361927194878162187162220359319096077044697338 + 1170042273866788055113160203247185045523345121557337349823787766288071325865947069357672811750151752362658390610542086745537803 + 0182650295086344086825098102966797093995388649163271139864646408250278380402342942834021881070263294572807189069134900984272374 + 0906668841731928141540118014775032666661994283184008007242068962044782267000273516374045366478779586459658472979356032532424400 + 9941559950477797261120283165043361871515058911345852440301289987592080477208449029732297262652194811701835630896804400526302181 + 9586422168434769367306983212903836891536506488360440148109923788291834492143450307170521991049310812325101209435949795579328604 + 8845618327364168114007785559410459235882830447965260478796725064238526247677648804067848274177910485949526784938820751326532317 + 2508842138180368207641530038974478572707059622379262380563191970615374835570345785749767510398007047615953484581417608147080414 + 6150921916969845997446844026937752931358496152526223613349123080269156525204842351030887676736715854630790139383298746726376238 + 0031087628812333418550306049252849828620365883770156880965318518371047868891562748685920081560624079882621440888924178323074068 + 8556547813934656680983629186991073869359264408784267940961601835440468005712703124932656473056207782384291231611143830784642169 + 4764006946356475094019331519107580885428818699148255825445877812529420751612646315832517900095651843319599421976422128038327435 + 6209251031135205676846184796239439073588798115331056299413787815047447544760251266043212878984345103105431840273907195809002871 + 3654931993884850780377252970969582655676559449815451929264323578834644743068604576736541418957979028943061560532360261664725787 + 1145330876015831126155307819990268909839073491920596329763420311698726840745194869089228905040694957988171983477254803375572985 + 8257437969668449439729079801079379205727147223003815670652927114347162605507272520770488283403449339977650008075057150876981627 + 8526350745722665602676982911174850303165259851752432760991481586280102205346134401601648981884690319798225175260769925489404224 + 4638271898447020123724423300538195550321048052825314720561544239062181964769986570926083174181155377779882057584541395809301918 + 6106817249634524848855511452769182264081765291797239837907787970553958190403210902425419707216288535844322802242224844682625560 + 0987012833422099095295557450557916850795807069003361331869709388270541973078686998103429124404642889230735965872322730527661759 + 0637705394090134454432592452488278594036085049343720666733736875565892704518648963039960363828210137149300479545174722900885474 + 0438909745910598389431226270312843755719991811348892485728211852221096700168476622881940496574796916264512821293932878797623865 + 5429545451401418793893535526425687987849470147455674595433976709030225358630706349020692453458568350635883987698939555558472630 + 1147145098629672646090540159437091576295858909288901226882948677153091610088843747423989951237804279634707873305141146001310035 + 1453067258355914230711608884942303119909820139748995292741299997309447939834224950618749891034712331269306844559292626045946290 + 0350632260797112269078999525007760708741928859358707432624911128337604559525225243942115958112015615876335010570860522898738781 + 1402978628312279477469329446037732401120697968328000813953667479029085290308524043626235410022744559135665074491331563473370347 + 9337757755044278436081677756600946862635252212939271849678018763209718297572192696470355304192247185638719953361091249281203364 + 5405880207322161294391822123973103190408090878564615457135856917654118957703067143223083955082019279925860379183853717628861577 + 7799366841975673356259200026023839542055869990618462031135739235438635258865047764693545067810235010528954960166478294307447628 + 2027467028086256924839310527875817129214597755080392073496545377860632428440004957401492609606750537328284161904594401425287572 + 0946928415702129545673169191304792948477302426781915513863540380482590408165885780307409257801864775225156808756934724074392504 + 6885597618942836774284752567772379904321306380471869189416734595292130350179577547119957964477389742383246612250778027835962842 + 8375378564184742787926400597138354486910116541106048723078444753508902260690644823241797242756355368838174606975331846084479482 + 3212968824505986851162688090961261899834237009593445525206396148505570975743205626589129717163778397732428341839974826649188402 + 6250784433605236331523177619946160387836454523224441645894992796160653797716355919979290100324224314406791061386652716371890152 + 4400989435392530316607884601954369502551234892963245103254821300716613610559994576020035792556553491043544497572846045958494663 + 5437689141597501417826982456539318735177994543195003033035189307876601341936559142966278723819207128349590261078232012690448383 + 2240565515565951781099043148895044873938264025267367187036427905278273314523689584565134739736805096906657362307932608184624022 + 3576329018410785775670826940638079688618282322990520892260090365771287681416891560096002562633570097542699787911417555916230717 + 2453291822907103982064112069025122300625453433920178638265846617355201994938801382944512864303440296743023682910689965580508346 + 3275346241221900813564939920509014369583021411699796257800366335780055834288641882272217012847000156622653258224710526325808198 + 1761823047477639207496107226016946214853880512328754599996142453344143869395811453079561049784458849323538032761380820785136205 + 2258773098932947134988484220635633194802789720564239663961212480883691013756304617477696306260192353528126108628749643695576613 + 6833244981505084786837439890389565039428783638198451342774797405426073205683183254178026538685346206428799444442723636136435573 + 9080842459252171303872018490896413638818633597602353810855257937546412235233854346618680040369752485990328489156699457496819504 + 5734956183309699603857071255358660306282081929816419207249476965467352584050195709593369245076183392383809049796820142290983389 + 0663950400843838925251438784404925348605007257769726864605575147487057019983649102686292523010863667700171976798290888401737766 + 3133554911232814826547253321321519762370231796859406653514455605268584403622162920523841843001241629651167179835787795168834729 + 9915875102181929094696545619337694209374642713183714372607433054204210229685880508097695696888633628128273726076768020385810595 + 2987095117021662238907432053186678763052465613665295736124815230360572136345177452861949998291445717212884676001873754746660396 + 2589155650613427623626563286829473395485125944790254164155482476888221798281733050713864337019212875437294907722695910181965531 + 8195108479458493218118347693154287549401864008165971140576262020179031350059154171267408221692360825699802778787719114529741055 + 2994227854778559135194271668156980433699910463754412118741685322605625614010496732911474348010716497147621915462772990056635740 + 9885103937597375812527288674502022238204092589207503781840088970784707532373479354579114899440649532568358342845263798451171893 + 1120400390759648596081862269355864764100400822617213332109125827310532445408926542692499006220714769552811438530408840934868695 + 9637352403752939344901814991765254063329438135234927589317161742716459240954818619945185528105201605559036407476820639345279573 + 0967725725520221343652248725994878515580037117626550685849684690414565200284452932891511103030564811419601323232328459974123969 + 5151667166514928638097099027082126182546856178488195923185506331245117707219875304117100373941938587261574361349595466933901648 + 3122056019614029244775838489907181693402454194031630939340884628769127341314464687448572665248434305566402372170442289658220344 + 7261444332642187051262725693834547125915901896179000263992637439997458766108204237403853459573909864356641282495892771557042023 + 6977452997091657310159593635773017261586291897746068707373152247429150821576531204588421265308077483457611680883539505380780214 + 3922860418447742388907173493206552834918162458673611316176697519544920126038326376534410690399328547067085820148163398020288911 + 4131844303372153660043567296613439825919900174540571926796003444468128320273120297033737036976412016725245066800816469650561843 + 0565592489986925533018758592782811877964316768421296500160427160146511217146432195095933744734673635804950107620352420106654863 + 6645406729317349776240373018557665618972564221260681309297356903494539710063100566543717860365197783559220679304253096607594218 + 8395581134093404449211217585032937525052183907591091053649490577579801329664352206258963567937765723904612138153463659172391420 + 2858367788679710677058155486700833423902690944634848842142528244040019800469662248189870722506296487688337321695524703236140988 + 9562335938642263288699025637860876864417622879634601222106055965060418025394207515941236354344664880329773638937529679471456359 + 3869629127425084307826072099872319475018151572502025420028453624372211412720817771154291359747053407476074728284771551844057529 + 1190185706672366345077026144989614660307994733718658435474012628808621940611349704306495070342196599139286091306151010932970462 + 9675509101851273861946201556462769919002921112388488480221448504521451553534147109710141587683279463216951321945573166307639217 + 6672697005271871616738575015318763914957713525828413258526916822948066768551357315714715932196912191677461856418144576263544333 + 4907150429612203297659855554908990742757537394357200499303314336795187732766056993269698914296065846201908473023132752908744956 + 6150083396086150456609926582054844276634569272470435640456573226419822868710777542210573165448531019738194685407995076708226492 + 2678786284405544977160356904372320894983311525398796027674382539921414318300162458602130818377816924569056780073177178248997811 + 1585303840969268907598807940355932272770894001504038659615940425154386157294260258784536698627961267225191113300660353374029144 + 4866449090853757246935294981633041248861600653432843768265539085865624263955878975774708775312072236190746445124355521953038339 + 0619885412382828558999175920193016334591402367369763220140054897008235791975355396141026004273210423619062237213937060537525842 + 8976484958039104695613723977251336268561215466702146950426183444969792826975925369611735319989524615202694816932040830397174311 + 9564951821673710247264553143623225237946783695563652359502341538660577772441234930760198015851060420035149363908475167289811549 + 6152784468367404157734119802017549287296220448855141063864170092034156049229526992205564211402819767239639089903951267480899195 + 1084349314003385023967647400823528491190700765335630550586981662116778098851626565057148602128362406840285312235675524872617927 + 5940674859942896006453306875133525569054425493267698876245403823203215376527985578976643008721792339745957322665402353157011446 + 1029563432263058113381593903721587363928336506888785654392441615160711392515188910321841843403492466442469739247826795396883496 + 7172639941661127457144015058984534581536740542737103665437103773621233103380626067034160263026558390443198760839727420004712631 + 9914873013707039718441199896815680469326923849342274027255430706708553663676894461369886145860075954707988128252410758852549672 + 1551922530995012072301491677655182006822391780785787705916872826260151900149221019724939267128249948853451126842232399605725462 + 6980483373104508461112547210954800274259585332622017453698311994963928004018795768275261593898964198667538969022507330787533788 + 8940619208645823836214853361748146283829606466502798396069751370937123229891589445495370452889766339397264192786388083894708555 + 7956574006856378561036342289467521536334236359576203113726730817643632648603038458281607027513534064039819509732524551295593096 + 5939647576077639500586029620496592494701352335060993013958711501324112331829653462612315976140447947573865479895456805542744172 + 8296423959232512165579460974983453693457497491285869113279013506974543084139634238126476293873284263151589338438860044240330996 + 3782355276288558083473518137834514003242038994143031796041577911531844210313799581374155317783854201414730465792201716701206550 + 7105406465035531748842630956573813909293101829709167100331101814849787778408887961527614275809837033921260676349397115972110690 + 9643615107680266865840715334731751157919061855580521203957602157773380969437003086918579100512932764454793288187949797876169125 + 3320437252833110321043772044039248321368660878095814104499448998676046985620748260108371162632325229365624907230743947154301806 + 3552088981131531046172808385452694435204741530370783735986679874877536428004908486014008409001068550950540888673128998784481805 + 7440503329453373467657006789991046671852958451887155184801369224781302834630349870843861530093008719949904514151022786314021716 + 2709390621195321800279652002200952192418979261420927427122958490897500556999549527116421814590121223682055231817153659082402135 + 8861992826208042869383343763880314283402643395875744203109296333659792215641368608715044344315779183133340656043459727198349780 + 2734853139703811794155039071217208536677070354393864907407146911703003457454092806351920281851834356124440898064979131802059323 + 1762234053491518617088128044036706357776327020285634889111113700954005526394521483443227952188980642686375398780347144135711592 + 4027397751732022026309364751091606371427768246571192961054471672221120559486812200168063013361795376094462318094221786026438363 + 0392038021743121561693528064882454352142444617962196680006981383051817202169379782864384242280286939946138589599414498933359730 + 0182070858522164858867574874421689046928982559988292189961850204180007351631664423841067686122468503764793368632417463823286265 + 0700191191614031195459835157848968083002627564348814468750050055060620960050671214092145749062318287857521361265309131257106421 + 0309993332034066779054757057884677047198784197094514566927373158826040214788501636945490789604082561095662632988383214277496388 + 8146430655840989789550968117320096504739356599535135443521661785643633703575650679430439992282453217709233862686803968241138826 + 7498984628272507825242938050646337866580174070972879570659031107873223367860364402212183428942145402115290592836227443279445979 + 6978276114539892419020829624768340474210713091442435775100177879638010349673639613552216581396012901447719087628078745824194120 + 8522095336564609176473140966826492093656451125709888847406519188859548795021576488451306844892007565711047730272408121668647900 + 8524767921694471514347227180326839537161579546977834075174921433329341884828393393398191832645952423890037661848882505051151043 + 2944580067530192277404349067174032715610611074091485944569506105415953050308842454649185132382815370040650599793085560858695708 + 1141032332340176333446374984947231196716478639118202128308413932621313966803046203929215874583358851861354789012133869833074749 + 9480985593249065406361871874582636508161948209786505592954264261087303579799611153927773325602584185048591266936288024303976476 + 7322835259534879703369663910307964057121123765236316839734559189401161415410496300232441653039670294405632163031483814775087095 + 7887660928641822340331849719497888363217187995951806289777062854449559129016492535377000453799053164705981391283757823729876400 + 6020813393115291018308864451756852473844549771230553274019875173525511163873500444811237248088951714603052752360262642567865853 + 6201967072308522428055969416019910663232530141827188975690227560728650829855364963013282370083361622353100870401742620986225707 + 2869802657723987122733883328526226736949680510879014974422147235169606191520933028844627505009715152702759247026991603640320467 + 4241131697918560404418795016499808486429648304834823604182336854359989655705275261891160035233666029073733408580774645759107173 + 6464198087662041784095710258475229347049766003901523983606673438365749432588484287371422883288614656304912471987516429205303532 + 2029089639113957845701115097046043607676790299218866434022020078360708383436488957906770062559366765186955585351813372430895635 + 6464504289920784076224333417714908863182256990967502428628619515039237321418833968508382684390570422398059844256244914931448759 + 6529784435502409492045275382927262616866859838773431100600230894559679830532230924353989524323228472158682810144077054469603044 + 1378563204070129032409938042343154208174485755861395799608824865872543930138962034925792279431758568493941395394754047686715676 + 8867499345143102872671197738475892292486346568581939250404454964808538362896520373387072413955104371842316500056740851235207639 + 2274346030168140429762079586632175197653839654847793978202115595048824365507532766797058257757822432716594523867292474757570615 + 8116418268033688475580223253494948603537184329744599083311334953737050247127839879240255833527455107807664847505065047983484396 + 2629458032033571400314592548790506246485500676837502841162113579334258598171571921210523629971864377357109335285657941548264619 + 0524276024669364832317266608416143775893545796330992023551256594493130557067547024156422646526989759981543218213803553279470269 + 7049845656048970965053022592938828183548869262256486091586477018991837255857719144475359084653581143521408001578287580561915936 + 9529610539570129132154472887914287431871889778678946943105713104741010716248000242330469610192173796870030679714772937881344366 + 0545264556901297919417188117578751509627881737016436472816406518703771084849520268761391513510275790321817000658619656930708957 + 1126630442325657535785952978581421903165028332745161812379117711348541046986438165712940213350699237254925482467553006850919218 + 5721411832634196862603413999653849373180502518946059378586343176647830400545625593156677745062236816423794840646924829283523696 + 9566889818345214089079695756528442838502922581513940730675014653702918250796815796276266282500947845827720283326159797147319082 + 9317560741024728849503640154852784294588264197172188120649331980986731376355567665746330692183280397742589194244588569542845631 + 3577828329965372354724624706136258680035391223875847298805321085928193394693686066077198681054782793606636920380474314204706128 + 3316822771568615892652610314018713244424614540516258058981790879447066097870072989300359291800915299516058342141748356513095635 + 5061676595203394978368391202469283356586340799916518917181619890218937093078654617621002548811013022192072875054917226111499567 + 2293159175827100175340065081112035701753220885751903235819929349733241991099088182499008327172200193308932710369190557345577793 + 7287877879088510408061450710486988984638957628372307246581657037353807145126249736162916823230146250853818942298633104586163230 + 7832024984477944259180948598164959684871867948848537597567339850852013498502229835859692193114794153895539003144519694217709429 + 8852158774260606249546637223424939759148603134570091996953512424441839401422606873114052812717989308319825300637980593162367504 + 4443868737007280155976070920335648272365458102007219456742917706885599061474160397874769568586074099945991122357965710810304405 + 6905794745598083595623675442819199614676323588131811003338385631872023890221085694977414242799825541355735846812034684719203047 + 0457011399186690441251124301781521567240706876614307067167646882762698974983127872249705063133235031055532098528898796399551640 + 9652581539551646223682272835407450811885069347498654352393131589816331647166209087054200913809824196442611900896852634745826036 + 6159069172552131589074592658415752799244670288018595097465086916954714517572062029793973193555030320732773860687445556056374048 + 5349001165930930982732148212936887040004758525708856986464739067246746909509060364496603927468208068059374896651091078566710130 + 6254982141720413268677308357696628123925721390150502950572640806864637896561429156063059840807574455370484872143372214422469569 + 2175489787129382942852202790241971823638922108920609980574885762787573196139571654120370722438096597478384547338469999448759583 + 5779677161907195059713244890541696081649739347821725617254499816041573948157136918495996244811587574062062152794567408848302587 + 2529817818204143798110200493373689828340608796471631850589769739013205825657411890682974212480864416875107897957894840172709126 + 8663943826538718474564967927014748693701498556781723819074861406711142155938775092841806948205850959520646877840367557220520678 + 7792447422465445177106699668289442956655097062959653482152033676820332098951332376110889269353539366684304599313150351375802284 + 0121046685822850120961765570267263832452267770816505513149214924261156051159905321694021977473033018289683251782668439030324894 + 8869657128937432079954235872959567283205921860119040052090516147170061627077989260167387744379514761600478703309504193576305611 + 5381561915778733491108127139487324618000049052071735127115368151009776782599438434551832876965146125033956869670863387976299721 + 0949362683385697791271115461446907297573048650262795825751967646029677499691298037462050809938530416641818484223928338242122429 + 9766820839983470977275951789763019956067562051439591397901411073621068841669094149499180916451056538781312613407170881646764399 + 6524347269748594984863393554929474287488214701192085748591350202439606866037583191335302568028741994749726846505035406608976877 + 2807315518903493816008029815670675803410749049697801438415798820359073479308467800153777926573033244523898966885887408576598556 + 2253435971693966005243248611373406144205306206628977772254035623423592393288603285157497164481644751059433660694427679833172764 + 2802621839144263944769655055452576122669485060013276462140874654840615169333830556593045220363613387004343762888697682047116295 + 6079893975072940528060570984236651746363761678873252309931727588216926947288076839743652207728678149523270862367475616321714661 + 6924992946415404337508448250054422067066309322273329866764351438985216249046429085623842949432537700067268248539671410894502789 + 8240333706088312915806196572306355577223650119535205051323962302240268709606481125217437426747720173549677961990418013172593155 + 6781963827534077258276934309689853954408488415498885594714929736965951139633336078246485722224486449322009472875775669311469575 + 9358007010281073437748629060353526682504603164238126641900438090676758229061250503441387135871208008336678965627603224246244049 + 5356708068957856933330346985639541006539430131114293957097055267024756313531830324556261486697384925986987181884646073628504968 + 6088781492829096627570053299366443750840538654491246720498646497885473443660031433479078885663560146413659899024021823265546612 + 4698755327188359177076358836200498034389012684305157808211750883923932482111066086636126223845187785757048164121301047675382008 + 4187475464845783395113764420886751702440050366103999318308171948006157647282740757274766917041519563322385269555023048099709528 + 0571195389552617367126852668538451980401879674162973150705011024259186076369903231002763667511763488135226006543931654677750804 + 0619275562362999032336486727097255819748979447931027384044606019902431591438640635467977566427621673095319535200747603235302696 + 4867604449981342383768009732025809614182230646572537976384930951101533738349930256172344711040076994914315737263468451025930022 + 9527865696943210023342715736597334765710291291516121893348495349788313734498145749015674214471321122949483123539062028956769641 + 9765176523721839937410174251025970316488964877877371126040698433360574265827174483074565633308845572364434646203497713132542776 + 7378651477723436227947997821691317672343016210083663443777377182287912898006288444888091959123188074922030160615537818420033213 + 8447189492947088531974966589067358589089364485475991918412867217338548681050492469752464750298772894247076136639226285280041834 + 5454360318746876235873485912565983134779435530640178745325450114100396790737296942281564432762776663339965033474759509011312252 + 1273643557029602462258772262515086262035743506025601400592823850215645680844288819770466248021756708616474262140257830085882080 + 3749316335624058049683001015861489646556394155367973498744773935515065243970160613827515488862189910777219950612111041830333142 + 8451480666232257772267491027370674681436846933893722515862731717525412660342458091112720313220482317659721562206466780128741773 + 6590252632454850440238194247507400433748088629955607174486085725118788995595732312569896819608944355538496441101640124949497789 + 1257684894384392174484251124503854845960148691603301944875996738800826596693185375085047729958430171553740436704869195063748372 + 5735178593590752060263331193146970071579446804835972630866651058153595857973419849597143669821080829676089777998056446703836684 + 9360907310859244502541304513473974522087020370096397612021384703925636952795854616525882877878108950663963286923299046586524224 + 4736748114460524678435616682271235781989815828869520783049700875658488695718736121600271316948975177628944650186309894116256839 + 0122265134749874764508072046641714144031116931952372994620287753392883858943809994533079487667165865233880719017940897178306317 + 7314139776044966808676160030164847624119585864721750026892048897546015469276703858536945215709271741054424782569701147500084232 + 7758065860697872155705967293772173137656465001477901257876428931468366029449777184812467116641975319314916341175480998066511678 + 8213787357873005347083763974187729721493820664650580516006337664286359010259386041876040802392491656717630783835571533641496104 + 1539726264552952565436503783866624559510200362458151625173082533487696535010112807775556729174429917223668593210128877186508887 + 8321470309679685999475535888469479559195982218922599887296055650137375133750432460874145869352229391171673429325865805622380834 + 2056541359048531447828515960692963929079449940672170706409337197174760052966541653050946881379320800572898168412293068662723053 + 6860373992960297640329729816572073853997874011764757398797944036292846733897735820446934726176024024757470895603256455220029335 + 4569926110072668348278664329257941057438032693980297647417188505086076585913708391932628924011735966680243663432137597450444007 + 4011230494392556854932236273332089389934747612548401261998294903567663125297736568382740395489945640372131150054623072337132335 + 6844595318925439547616931848005923901307170686601327728283791660587722758968622818978597514280133292570491476960507397213932185 + 3642313707941792113315508020910489195204450745180517492522873324890987317406946100562361363175345008151634614618218325839525506 + 2427692898230648928178646301964171781644216637535917410571457842164951317391990752953058484915364895813865613835337731245388877 + 7010431184482412816244666073504621100130866578971286677458525711336280431605171233723698610913008947422033976946085031938114793 + 0877515916454772093488878527862660314336276524158489551235818954456016892617227185085470522620693855915519816376238143161430319 + 8799443736799287358483938545063592502641553678820618531061987381595925735003006045937462381053795139314188939327005235192961861 + 6759340733723316487592044207138087167698990178309899096979902164464364089126370344350744470572331313727851480014896363857798812 + 7052560097987652474276867365814450520379120040581256992867022098643876725081745248682691582583629292763400638018100065591005268 + 3106774405492401515494177672517042073837303505772295474776502959089196445416987270369786947855131616223965006450641692994332025 + 5855582574286277020845503779828089079164761761910842413066849248818854888626393445367304058754822066188520015897444131019700263 + 9198472044843711981048071735258326011544302082682349755642269651044020224003915379747598044212429909878394016016714106491656407 + 7815377808589332772544290119723706266101079820396212755543706404343739006942558946534655221133089320660150834947988585978442816 + 5845893139549225714132593150193123229669033684893833205775336633241518807901847649594321897137880458298454663559120194776464523 + 0400879116612606005027575801357996533825782630360057558670923510328348895013335023158934967383007297478557740608358705255176983 + 7266683495403368714481550525556638200455893453737443660389337826017810731088543589057015038655883579293647540385262180527785917 + 9515154749550773405200793344557941722519749405852747512969927332977178984307036495472318127241347248808326472175619457986406723 + 9518368191888409210468669956186116750302181387390597344128917877355951593149853095697850106850745402883068932235000062455347402 + 6771238670568019918070196745624606843885430053371888544619960477580892136283363206743364325496202732003423537704812210825777485 + 6482929731992099113054720411204927077100453390882438863808021020983016716953161187024589380636187873278841457216002930842647147 + 9086580408882584727439595283961649388079282398490521121307077379799427026353954996467076132654318458754445407020982965846766574 + 9211933498567658239813690464315557516873798138696846826984940696375072209871675004339676866312551085733908702422475770451671522 + 8116601759554721517887607233127079564923984623323605008410478991117346586220447102577578587384958136197341044972808673740184098 + 7135146663669772129679997894669791690347234150535985440597324857772792781041329129123706810764665585549577867626836104138395091 + 6171338134734949666403237923355751356314985925381428193696582138260452767497882006262979715518886220518431969713213052164146287 + 0631430030464172255146123719714749762611746753803707576735960990848350628824677285326419791772891874510486806367078208015683527 + 9792995724212035781617488647953282247761468865566020082106220151676123008979512284726786406279413459522157229217252165905352918 + 2536766618340462486482122665210247152075138704341907443423031644884751559830028648873890163595496896608683668686938870179657834 + 4207985050934314372862959059606329918091261977012574425026916852113090691158385845006538026326042605485030114114277066770366995 + 0403083121980863784638665369135497943380554934143397132755814677874063414921737247611566476833724738395380308234640207731607371 + 3017035318366003181883008020161130977715784016586015636467061595058652062869875350107267130020471568933409734170464250203156306 + 7978597058687788859694752086622825044743069638461579429486476003366615826282892684888720644513019714307671128574626623134255754 + 3225178060856930853571262377435203804205020419212526191171244624283460959473575918723283729545170705498401123341048944419740415 + 9391613362743685159686501403436221835235931626375947101387495019232220333271032937655938586143908770909065649064710101953494614 + 6134742532053652776330925214492259910738874571044952830222662538392022245336085949987893286559101791675451325204933710093660895 + 3150091954112952712726674404458997796890860249938694466648235513572474974162093062356467502005784802581269257972393197375619808 + 5518818055326965608441276354480052128774778908643152331498791242682676747511171669510551698928872813137576082004507231113018234 + 1869442353797750668263237704646436989107574039444714294394574053634166211680018322567901718394177095139221750525981664718345874 + 6533895638718548550755018968962814261467954303937753456123595613702977896395623181616704065331577434094624992851719491928609615 + 0190398690201868871739512766894228210227318255924906586297140986714101681237768762073978231156784378903908446734627746278198818 + 7031625744207762150055633900029138852849133531239672839021846058540394772383588961074862090538883314417964060795273709151209027 + 9458808924606129446923894166510777560369040702494184195952257501705875876785777050661631817125173124207320372163502777664965913 + 3571992627283246607384090417534713518631913006344389649603958134572814682981286787015904497353080342805307719694940285614675633 + 2468021847965102322233545270789228088801077254585303970545296705237224231512698609584385993582329483075661032700231251161660423 + 0192713398720255736106913269405387578211504390721637672765578917354808072397586108294538148319234789867624965197532780016350565 + 3634551422633123938462201786680417505451646469018713382722643171537409460426340292141021655461958038710203141816197429713424286 + 2547844227738650654059981449340163279595536790994781981453043554676804995664853696521066106987131049223085671186846778658607485 + 8528870512517578936416926762107480564174061090150629794502095506665701012457777925443164598343164919674568006002249856403680494 + 2627259489744462745552373437029184782032929858142986221112288622061305496355657681071521590855144706970497835664724912122006599 + 6545391156443312660152544214378226475642958908136790116192718647739147551525217967757101506789062053773824320749961986081365820 + 9807243716856995753119727006541625638999515827040154011379764506202860312616961954158869599676568905867509226176218277805150630 + 2073942766462908233406965969896132634247796801676354098426177499898295515362604488579021522583028021857262554533983809115858178 + 8347131968232485092731301472083865394183193666260253997648555077371404915951205500140212998582177455804377214724298329527661383 + 1594405101691517143629153539833183982495777310394687166385933138800061962945009756356701243200756906586574077923344666352145020 + 0197245967822981167194710233250484229803417371108743341686105467298388178153158024123847938905011673366872874417478036778662336 + 7258512385396982458981727808434299320938547592708453258132441101938548683407696744955847650770224320115020029123283233005466171 + 5842172497719189784583681309409508840094316855599405125810349460717428156132068389884811129531014665690641559952450142631134435 + 3120882941134196144363251034342986015603525881548802680508329909569735321266175483509995349121263055144465010373367684170785550 + 4158635639323481056067212351252293942485312028596582540399759383658505450921291350114073361212206891492359937785370602986743900 + 3248674367436665982259747983227106329784209726320992248877150489251570771053020539956408865849029873307934125408634817191607873 + 5454247998356721456240658773994350865596498454154991883699218368604475173834985657275975908620474089305230670921518592231403386 + 7351062162946891390363227270397968233004651810177775309863584286429947693132180002624305405957468154601633114090431896806560396 + 8578733043161456354664012245929168398575757646163138337526746639222181428391936995137008559247216584486677942670927998985802859 + 9200314360845834380351667184778736242928721806415925103242410837162869501355174790557366226463713207146043374288777068201363073 + 1884840380691470035098733943006470724355475360919052895346183170077857886208887006329282319454011758272954888828936243319780379 + 5906121108044999002595816055500975401842454091232971454535066145382445630442880279299409925299375855072691591936952415415855608 + 7427547736672177870270669416923472904176994726042270600865769556468182342137641250127961474267696372215125069986572926580684930 + 1283565631209283359581543095011894542058022145233771315616803743285668523226044837411757706026740916352039927306329889089649349 + 4270078841384513763036784211367232205576108266657423596077336951308763566593324577257390215814671195914760219863020884678789417 + 1094797252284852472558752948074017934025826602284347674097641546447667688812462875419412834529814608042996511263599028929742238 + 1967645060681138182820884931078366878249535027007771792225806188604957386423876036386080705880427884926800392921951044407013636 + 3181566611581199324907272529442720663293855144200609139564151757908337725071341353176155541142076746946246524270499526229012582 + 6539374062743440091085243475167651698361455560983223707251591133463685518000037795208788191244350973724875956194617703899137414 + 1430821502040369247348912270128694893351423782952149316135243013570919313886614565161358637079094402119428463930234964822013013 + 2907845492061431274313604396416192334514224786448855288597321564420931438182778758210128537309848899766746069430202195659612336 + 4975634130177816916191624410591783555638901610254745557743055701024321622685828565315892206810167787457147305784539222040470909 + 3426187794037654633853814952285180680406547839298481434679476618025289610702493051123252356926166123963245694601391065308079166 + 1560694708414872555648575097110162943981198563540849019446854403562264846931619983425916923587136273462584821828465235074422917 + 9261979271695865979574032703343588466946379682055875729180379739323087400969273393174411780309814669530363099378105348978942035 + 6060070323917526453062047842877465074776912567111669196792162790002591482979059554932579116312700674668070694919873464603223754 + 1894071532823340571620020715489409265478540234593867913381245139145940908648942949383027523114581382713294341230059675979933347 + 0475001838386962980608799805753326787172142674741106499743819708928855603482127536974433291922816520616537305575646417283646800 + 1407873654137191433607314317494815145886982224527312502679184216570574189580738684704012553837521804108283635888649341886347674 + 0746298331021251518403002440748995086111379224255590828431961727677994867561042572035686044830391992128329363200090117946273786 + 3394767633292754355096521352490384715569381533683416319072637548165685703657478638050012390155682264692286629389917053497837436 + 4659095138863302858042866246863612004771584058240848977405503610643181773657781348444480569875240316081167661626347187543347285 + 7911879124009359945066105568437670726515538210712672838972140937144499494198784053146413298370949806905102557089313540518536047 + 2387001299041180490187017325756798839893484841126540625119691321202951445764540357103908077323391792392357443606419429134662703 + 1311387664343269938420538390428981548672980222893983525849983661962674897972783374663857036358464131799985348402057774789061484 + 8274461005931054626156020913275021215007841002783185917701579638808358640962009486666957046897388731341995785176631521816719220 + 0104967747699292212229371707417874791998945791320492326714053322534677090261456035102963665329391198512545240166335302214953529 + 6438295329258114463806507486440728873144766916788136148990852634546220929994618127547833759089567150425084541257262887419748944 + 0763510822819190844430827630471119922358130707131670435790654181644862502449964467386506947657809851105256327118765427086936245 + 2850131634530202363427136221800593088389014446941597649063703366121196898996686256705732620416208851855006823708510518951595042 + 8751603030878422139220116631069675693727662503215348707642267571256820475012856064445690912370994140681017385311381651837184429 + 8337808674514385942347760110022916345088925240957432454452424792146056100857933925448423669501901023480223134384961261737051238 + 4413770733662528673309544847059059161282542697670213119975814848684886926540572546980353008826625285683672206383376561174283585 + 2470179376522057019705141639334564346002921054122405868536589549939044185327352857788406922050956188186959812914331458433168181 + 2179183768538040087965101925166314083741211822328135691819236749579736222030235331381929418960851621953749706426251383153679388 + 6697638737127992949029219495456980219928837272379992149835670720157263752765848341694925460132961677719444757263352390287952092 + 4093217437367696270862739890376907333913414784572650839225342564140670817115158483271922969611210426005659701735005263854191680 + 0504868284114293941201391805305848644129473248052919285116546768968370400211720819698688057290313111673099410825833594935299522 + 2193387285480585675810105037896679125123370546559641586098343943853768828725430307316784909701983568646060993578149869405653861 + 2934591075689506327550526527978208181872636707486069235044785075612292358262482648814374144402086535106182407978781842722397427 + 3764043018357659628728101790307107498150768318990432916850503907920600389618490690749145152636599605594698036095369786495988258 + 6957155927715716313765479257750780421880426026172174055737331392383266819616843853222801559499877374057106670897236097150948636 + 5427827682310804721340200045877249335498355065518235785095376215323629999016684789788057540796773407165234965827360566567682463 + 0931247633662980846735922260231265500967979148521116776842985570907612389971711829938070907548905323760203422391349321697221760 + 7882789193682587165711403864901445874796286061561018238012019307540878080647271091752229028944021330264150343818926048069144244 + 3829234846305757977743751433953176195429230057570537421684266250781148509555390682508579644164157541082064669789683815095364787 + 7604939164496265670478495045765555257915418238903189606069500034604107925625520169975834751123093859423683572718773062691097465 + 9536565688839857043404968751102502068918401627692404156712144798677665827278179931457967293092502383995754188611043728483106278 + 9597088053951878542145390264364113151329590157432302502341917977233379257169202042072712802096599668573120272798291944153363375 + 7607153187541747861933137718609189822023639083176590969309128534131402001720049300131597786926920331444518080594310667529269598 + 1927075329456693896562301483770530596686903351047943440879405951056391325510081534440975417269136288862213745763314617080452571 + 4793088300460286258221203503876214260288694619740795021100096527276740956582412254816142704747725930689538001063488725674114094 + 9964651944235263688993656306565044507502459642744800444126035956827838480470927964887269362894767336619648517065502062761621016 + 6129875810846273188094595526245494198400294797450838878997940481886389039479255372079045644823922532826285987109316717080651452 + 1158870497644577891842220310991400298247186591687353490986090963675370236688750155704648708257105452733670085922368068618952508 + 3951586474153083065442516047977847063483146004542723388081748533379792081337808607910165722930346295608653437371334690508592931 + 1348798137260798951844725481726752185101778730990513125012632961668430932041485231492712161518123487434868038690945449294611190 + 6621726374054578571840509185550584952608718450715584685612358931363303426238432883301985179247942967408291991891183249754595852 + 4638603540391846589823234253913403535906012903538328082937776681713183362324668976651509798060188640593955628086698902190682737 + 1314136004568121579468174164410670114683609747309631647110337083615027244209788221757184880343776037559026360829925134683110860 + 2743916110589248861852284646250771021137678508599837301158835778690463663553082493519868901155377573114305779992715972859595723 + 2324106156194950900453760356879741607730365869344607490682695136931314492042609961479060353962654666877592314030242319785217157 + 7037168535189901999950898708785124945709252827963059451445136357835564541820565609455192709322939082485154440865255543678569770 + 9896528396971770400160528156211153078421941311469208430939294234515837583618887123400678449175339595403746664662044325400329517 + 8261684885541466594581605303831216257932122772017718190045767780517645346911853652853978624682959833140344555022435113362676062 + 7591075563360347900183625940068873872381827943795851765368024187038497412028598183964746465300474453614206176090307713158346489 + 3374371123832409332000144159517441149498304308931146086397279524284139118811410468196667079250510555507523645907234786379143531 + 0501327353064942573752656984727083020738199901757943687656464477159443799349546909245912076525128236088399431523118269843367482 + 8613396151458427790408589367894556692924575676708650976493092298687011565830641071449135943255849354462437020422889320020232241 + 9743887743932345248629409670762729564753828800124861494449000192569258881214737190612239921652995520457700328791744959299446113 + 7181302058928852380763877100101757115044093853940723929209952955676211472249441292704903663335543383186649963257659728968301134 + 0388255348661563721653151594456333702528830265445870529546222473972548233646402200780627751622560467191291529956825231887562559 + 3526669851709736895997935055319638614407522325558293993145073133898821442020970359820377176459127571138998803488194418913023474 + 8960318055715147737928173496291103297340011637615159200331936657806625012838282253984371770704650788787874077528191805071976481 + 7124181681951361717176138891836878456339953961111533220751215226320942283255447821785246102801554680118941275936544271258524058 + 6005709566240667298294089625210827175355499791073268532752944587487068732200218887976443970173147332812756704491687536620579417 + 8523733324824779870890616722944885692254782796148238417811553337420218355790067774624307813310722411932853894530043351212104621 + 4208314480849782328920489549263981924145677154566910149000272410262683233827903445768177081248117495913152923052663893776265183 + 9942787773857699223811513925994334863462094677096830079955240744467436994912827703793978101340756041298804409547081408298801222 + 9436460738640015479585458718857778968516432654013043215917075749663128588920464616671554576564466134592276012302780087016944245 + 5682263919237157166619832653999221365676490237394196490562353201595416072759662040168607378605240879904649331264075658653944374 + 3188760460625654041085468641256306887215807672289682883500357801180231951265973876967365453175824452139544361480252271534860563 + 3489612971636788170285039991175495323686795856259626029428439316305263410995491370010061781397716962628385590075791887118786041 + 5311327330508694662530309261695611418858308192623059112240071130884198746415297821301302430358551661316850076909001762997643991 + 7081644935973288072050639441580584025029531691351232277986672643518925684337072256344249262810387549624475090299911463668556533 + 2269997305729536278296569991307939885225827949212711278683260974334694618965859001446604029046584493463719653785353337281283459 + 5669018591396191702482439366148219818778884802332484502882028894694251543216632761518648364549018220678109701293026473478656784 + 5216611642715035439533559692613121139357309471021194983124318134640525984115565217254793009252347891534891058775512107043759248 + 2075136627102497321632846769129196363043810766007725332614332304423370092169449259610020916402169233919813196199842388493441962 + 5246508710864902175515674209765293421695856922741891032048768583212886538286815573096956696932708558353574597425799726517739782 + 8036312671737074585001040104552777443725646270711497123342871845885341214930320018750607319709014145767035316932229927380726251 + 0928548556204438876091471205246192546298228533150898999146677973522875037893164503792472130409496157160476844265385841682474739 + 9233703771903675834839283547585483443926383504808637869079921199402511859863654798938168359018632590649252624952570683979540091 + 1817221547279336881324191918747916105439761395909101897519754743532665651720607836479601826466707285601138161807075561528644357 + 6507813758533570073431536118758351858756886547831285242021547001802317103965340085013359438004591048652288218222633904693766526 + 5939230267672950104631374960137514687520839197558900123956846637455545802654473302741665702939840951606373658402834814254928601 + 8899091999774572904211301414279903590789989799671058329810205159495566404297154849221520843334449344645035156970528552300030222 + 6795649886498390391442973828383660673784035290138239807079635557460618362207456840361649348840778636144683493328779008559160150 + 2312967328418841937893181097506584921132253955130661944022425054340098558673444397656011485902801524597729549862183491017801616 + 8364392130149044788968141245875416756772094094121947877022476352773253705820364822300001844264751712000950605882778006252697459 + 3173455702957684349309232875767407323242741753471239292204928826580888927330167241766284958168551480352850879501139241966892452 + 3677753858072439789438100033278254013052115660199724677408997086225534466921024361672151595117485386004966423349406051295735713 + 1033555069901179500855772626876468463729168610634688507726870943003645664213844575844814874933857419440136881531279514876328051 + 6902431911053955232595350941009434993084829394137562877137241909400659809326832785642273291709998822359902244140526746390924526 + 3598394230231172238038637497155035177663453584383356974229908339909881383831792443286626244348781344679035766390554002582686748 + 1986522033280153369322100953745103819643767567342601672718065640720320991063977205827436045236651592119137181084201370425284749 + 6005671239600468501156161076186950720461257574394357624099400895752471978287422522141370855745760936595412914180235254380961690 + 1248432656688783102677099988123915947205672369413239452092262942922895352363751338938332396260328925306803441684111264080959934 + 7043361968005295354938534781857472787124249512274641194624952254981027355960086055922235901916884500390183949326239914435749876 + 5900769760705257904732141569222453308536443186947518812790214535222294555869866712002026766787105689583023017833746154510155688 + 5602689240796761919744677404697558271913792067417789140292202440216539736230658588620970781000844620550456371994946471279052637 + 6983815257060123566373254198705908764725007305820906210985164414734561111049679088421536404461082246253221142258100082860407483 + 9787291977224975917546280204714841440857941451156318425600052380180319358748436390813045531423344721155836168161085909646309385 + 4242317405737007113338681399774018133792533519976132559943781717607228562711266632582303687475696334211416518106220430942562440 + 8001103370755032373531777436355301854609759653124445242732075706459884158212645376386153155459030396899392086527430085304137547 + 7061352207839212087427452963168038388774060848015551117972221521512460122751953993512403134647980990954916284061921026824432536 + 2639034110356917513777636397443311536328136804898636889890450733741495575783711662670202058347655591164148410498512181752116112 + 8649347704311634713230582416874077536749261618798919119607870454970552954421518115988625118329175121493449500857931770229652333 + 7998158841528743978260913418602919615786831528127648656825638874370061930628233997562266898051264651939263641927874506380487439 + 1169319905978231587648398211672101766334393172127691275996797499245406750863796639040056909542250284633880406494091612313210866 + 0317572128063301907416088057966656497607301508200217804677889135103287897506118599601843251561058377858126583470533794642274814 + 4690147674695890988264540020570125563698789420115878750835681272646540842126992805764557197985389253255527910197264650144295636 + 5798557941192958990661384529989091262630978788566879170732007097819131006336590152363030155153413704404260928053167322809868601 + 6850987001199817141644762090308087270676753863496477045191783385382914059759989907264265980509298271071343239640773196627310409 + 4389027546704283892663222266104915372633460042956234973983464977451929104395584092104280081159181521725125037452942372440981206 + 6675905477554320026243055974304148345728455542853879050278442548087322107774875373656985055242105650999387599625064478196226162 + 5421451962648003632206646262643905337837657920982111146977004270602922886008501562566012949545116457517171981566495094457953170 + 2653749527617823956383177123455781619052217065408026747322738616321944929384445431993242259268884094539560852964142946672208945 + 8593461023191475746268918563613277494098559522521079968069246435865433845367704112809898386514701303501214965468624316127309978 + 1864190494247307693037266993358200097794635502447995520938928657994547718890764619887745240985736437934807473704761456024575292 + 4959121097171972205063831718099245216438006228886790229146916547085014590026042332430672777678300137100806650898573540666242384 + 3655898393459642632004541036291612193425851747783279795401104056847304510228417238922574433467131806129145867390315264166063875 + 3665579208506648402815517926487551967245716952452342336509872884242496327353828450388024010049265610889985970803926589219237453 + 1676400095916770050334175293677803863116549153471866784271105726012628596876429530293900006500470621643237024986843048814960581 + 6303887230138382981362522022235864197895867379102358980372057655831897690287262572451017096062107356032913949946624176978299116 + 5005151176823509060156202781958197462286719252108370751542425598689093613819219880986961622340717811406826396835254749852492414 + 9810879199072089316354376552239141698257935918222963398002559226752773027118660428719265494441568442234264661966547139854597318 + 7873099218250455002270603753696336287379126088262705830929170584620542532170428705348694262962278699570554235741942919271113853 + 0853097378201921331418681617335834926523454159799372408812168044016229123296540289846574743942294543985242874224122532498334672 + 1490594866688679908867416614545427520723745911612132408696699789261886952468259502210832466240663473598353736119026236378375966 + 7870513434223037902717553793135590258545562641705185546860782749440609431080399391577848963291799745623426666134231053217546405 + 9446201870461219368892707181895875357863356844636097852807754420432074309846001997057609966109454410826649254380546761753175861 + 2761057480832813584246237846523502525922933474798627724801784019360724008460215340269094831023982649184534291701279975122991786 + 6747259709148196213568727070749193520741364779274424639307959421349714799461578583982498969579857164144199424813392167578660320 + 2903178417498559526330742642780679790900780361831699904848420604973586382034364851787093357442413598696765925470890327590522104 + 1850819839601928427102795504066478105300817488452603819717168073205087377109510653761519361878295067555599575161123548496116519 + 4527800014440544203257680309603709183834604758224679743597378438522340853371773245388147497516647805604078269186299047096706230 + 6498133304861002880698895980139890714606455707071690798907848409609045542981039802321508092873754941535671659985239738644320953 + 5988405032666743320254142929561597654494413403431947291535930103688912359712380841156852022207805099821357330225186728532082090 + 5547768444839618341918220237864475011631317876613320699268333350020360283617553420136149953194413589978795210753934389762807735 + 1597329107893662665482951708145282526843200385584016605115945831916977370397498490572333755725067314085934032787782477551454989 + 8425608912417288932359069001529317862434139520899814966998471303722622773872512411876898983545914085663888123444680470167948505 + 0434379133165396213883414761877309648582182115178764180968488658223225128338783723464562383576437566308911246233632408447704048 + 9663996367177301008227471941256368607999821009483324708241288407336982656214907935931597532047696000543001055538357367423684843 + 1080054249718909513852149584485289714580193379500564799748250805755830508642143351393106365614646908548224506838553676335276275 + 3599779694595660288226660287150289204263669082115248096828431008225170485272045909181946378454893228880239576553739907190878426 + 5885850036699891408378122906193395367309415591691241926759692588330412581784093438940668271882079466692153184239937668982303474 + 7878175454828248795271539884473981581982185106585811627218428403581816331240364769920118073711196193240357920319448764087086718 + 9383157433735677366088538314691739001878394272868474296524756761536638899101995873845026009993980779305151574599223381548532836 + 3668859832227797331952981131294963911962283005597571432352599223356213488863688452877543275627906341710804574808946808990599277 + 4561238331796792049632393877616772107198692076748218412457533127281687506143050581347703755397549089646358464889763941628738646 + 4287040673613995225940479030356811166110299081667864088662964809883579567473005653984288637714354335572597312336813053771357145 + 7067167172790181728147512916597493867072803164173683458648511730308061884633961295638170464699169569357249648229427546009552241 + 2411562579887913980455816507682929933659712945876292627871263596090842188654178242939374681016381916432972311121058175582055725 + 4171582020877122298082911042822107332503076877376941726903575210668249614607891518640837866322224789915987615341840992350582413 + 4400620040237405249285698955673350511161843009038833792839643496604322064832266848854377214512824709405806535993728236489108631 + 0795420398459113177519012283723869747981824916722015034363766243369266801152099213940570568038081676315926730528271844090048984 + 8736235449371678977947912073661875499227319547901313273871106645387069884378420956151320072268281471236296252518071417869812398 + 7190598905022008877003332225740349664805580192380729307470319849086922459614014566654582713365646665851557294353631593510036953 + 6381552204220558217529826167930690334372579521383903206328505035888174852614555542283456959315756641772011982607288085297853686 + 1349874783384878827773365548625629981523061054390679273761674753812182403462337719746346989770142792526923785272095298042279054 + 8890444037528702976987014556298735324481383261103576223990679497009263015064472090831542516594399577027449370238294863246623636 + 0336415324118608522678012840335823229090847361254516690870558705257294993006716462941193893800422308988102399798523789694443112 + 1923359529945753787122624465725573807149022119989195390997561541611804328914617110055244794800371476974622186846094996027068986 + 6556505900937451676724626863029277508817962303859724405355623034880805936586542708527460464895044273023827975806326940478307069 + 8592969583414428893231495897818982129258755657382413367672348099201190652878055544751096757376276397486791497622706985221853529 + 2908214067134856191896613437551307015999440525676444599333628882928075642102806483213033250837448355509306721853006604031173677 + 5140214739575524129341946985893116412008106149871779041808900801409064849278864166852383463573647719274024968463791254976359299 + 8847571119606652336355242986018768524604507411735194803338041421026584303361841828532589747052208612636774062068296366532983021 + 8655354613872561646045351810915955927958378666435016019460717328781560793954138282423423334855186987151419088975164710160358441 + 0049260799204162100696414303845623303274803491195157588921793903647526766706979672202295037308810197036167390246126788340972486 + 6425819895447745350399433314412535917516434906996482513931003678441923085763619185652238830813722611071936854791527455947241273 + 1522067822697883751451720158852174772439898925807262503934468921130385503850561421474472046621939053613032754307326343494446468 + 0373529669975958588899685583408106767873002561071952257411549791159364132364256139331134266337194556486549929770686277721381623 + 8699593258141567800940600698126100601323395696274203924322395263563919165964829715731584976772134953809087705318959395613991572 + 4912970610760196588068419702343479920035578132234944550622679160245214714573304402887577273891607583288099465093463035431694610 + 3905758432785910691737893861264914959634002377051354781210095863851654985098474884630562136246052330525659496807184083910344772 + 6004796506916845030772132724200525430268203485146341239363234592583508467825890468047631822102162429469995405739029446103026786 + 2936254882880449606977442748506803270167246097479977977827447584435796513203817330397221813580364844509174311882193765156654656 + 6587840516915974691152625347076034414185867253449830309514472874859872212804040804281552578684775759016088925401886242253588410 + 2136162082678649695650433358835719979490577896244051036608023014229544782516370023231616157535453095718156293168346470255374077 + 7531511647981041419067438947595659704304601529630424537788677553031920743289991068705064547597248153946867352942473723492529159 + 0056165493810107660174271077633956520600765977621759777545425851195592595759244720831020706108951012298629188421930844092200174 + 6642191140454110070088900972029229475358599582028206307088525106506003848087788102905904900131739063517620939825620312143365317 + 0312737363283798477941966380713988316123472457978241774897278441026567305606285826664686434652740990763564567342068867452842418 + 0562084816143782025599524978888894444210155619376771675521151554796594041637061218094181094152665322539245369886205219847245940 + 0029405789079825038952711651290857359659229927344229997950428696846444420150303484487905236128836752670607196713086924265912777 + 9562937968844743614454574043893713056224816312429825464738549426759328345347674841205841958347360767579803402491577142236137115 + 0533906692397009484027899629862953135204910641799594877569760336943034406380230261140675352675702660262675371335224685084951739 + 1782949915965578201764231201307179274400901440982114344774078855036237671988151622145580473895458193522528339933303018706591388 + 2624100076711766326191346479084275280944607050965314374143191066314104835834695035041295363869510686680641979042639548470149337 + 7092183008459177550878010123635992307868170928762105253223870251579666192277376903965022436031647547645865700232025464698571152 + 3958091554628717576397311569044621708700856680671753736603162545139430701751294444844592994780440200375396353670083705904818899 + 1158314027781793782715830446196630725174972102720930236759032571130842037840584037988906905557214975416804249578167992887315936 + 9206031432141826113994005343808438088835006886050009647865275969654889753018433197685269199002634601456210696285807629459472336 + 4978328489062061200804108082671938204870858983057488740461332416429168822452529945581949038775475758752323372301506063733079805 + 7738055653647518591404108351211994677622659177154884456890162864455435902069510745121823508583748140331565330826498449431014143 + 0674653178829590152076432119041481195951363053106794226287750227106636545367810520707295978843237959311321898828560534345440055 + 8038620990007430479290370430002421271720574168054663731040351369363896772189503927548376910184417619479114290519008175905383545 + 7118330213438952390733597389988833345665275766596109498963112726494459652684601428898616858980054673653547857404417055361966561 + 1587037091185968630608431240360245295772438686943763646925036642543820946055469856983284464996007864493360253900748905383563580 + 8745104358873817076497065734218673552778861792932465886098953358042048623712145278501699290745480384052380874247143800362538370 + 6251997645750683187872814541336341689788360883547457593458471177846675162375769376759272289262293759496680413378317765946726569 + 9307054144320271279835934039640502070988256340708987512314880763049398513262419383032058404111149286657762258132166819869740391 + 6208679111601546062938461491996426928719837110414091479969117767614499297075986816870114797028327349760763930021316392342344670 + 6195338739848107103644806413130142942032473433624064988762100818410644021199176248704887358790343589713845228788844183335779186 + 1206612776301905227273380391656909985775786692526546380296204581461396277505352115889617471623174433491331255641939009226704644 + 2188221413330256108594133828534885890151834345250541767462459786862391647167810214086311680548340646481922395107065550293841987 + 0422053725280997492804556037165046616311376881740818579026242231815216233417949738101116086586716392810175144442461269235250030 + 1446402688506317648015492449267953446562377233978895904366659114613140191253374875252211719488638375761957759777329556920444079 + 4742234209552120961058674900214350131325585573620862943651827639544267432934381233345762116672659741592229252195548093031985971 + 2686838533752676886446680927399440863720061868372851834815109578907201299828776117754439315722227995606329153759209194448678185 + 3375830903591078788002755338696975595441586005976260188707036346541857769978992173498220429575524475532930877665817876092460756 + 9351987353933462923395374235495972847763917223789357531623204700947268441087397398182190787387926517802157283116535834305980686 + 9492332135897364643664989358260446062172464533880475533980243165095186005367740562491795933632109829107385087893207785894397713 + 6433768862702582156901779207532027093153001807004150434114821705300991777142257598550961217676112326241485864463713890885328141 + 4370423630135664116118217486548726531069411489498186055038679029605744527511210064431632487827249384739496221986798075711280160 + 4424010886610887880437216748921409021429656729228727372446155715321241952848523185619209556774687672654909818027324033748491821 + 5647085557243826965464774431484515106691575517669395491646712200606275072075247550415886971532904779039992053369051837694948246 + 4648536696394853995288135284563546131345084094639405448329957974626886591260968153163248670156108903690012016896947562864068947 + 9335817025706673645248672808655206936988229988506868855512246059364735571373658692183981236508753893624162179393300884572562525 + 8454550045708811850843967602772364889207411447386933113146884803720821905371224276398839301167373376393299604166530531671536817 + 9469613971479940226446065344175803391558840869442680476409858979317446638566865770776832153252927434674599753345041690804354354 + 6652209314699751202444785726308628207785053079762876873537555813669271605409315256570040001991644970781331622466129179499281915 + 1961444894849498696928429106294385830964606511500699941607840002024216695044414216800293243595307021832292431154543081449089313 + 1962091622249577961316459709116638715944104552499484128514903058588880092425282180366103208523455810521574844650965568635887113 + 4368421159409460609897114428104781398719260897374658539676968461604386468189383954460163078825080336107872167576349496495408685 + 9649536539795842583228826048018046721092374785553431643665884938389496673231436870435149786802809160883735413992798925929876704 + 5235671264707293479931013726706891341489539237837731840177933783526465474894432047982015526419973235553573918270319559547403086 + 4039735888376366609018757028506161014783678583356813250677778613982578318008203758267120384291005999279443777316382864592311739 + 1217739163779382661260606469702245656794710548611797988738048091846590739807732824364552075368990683393959928284317293320069867 + 4916615035875154768600732328677330949063202236875210951540534956404960395079564144372822026855682749788976197007630147709880516 + 6877745432713411450666647170018266444463633969867263093231179811756276204043142296040101066040921365338143870829243201412736978 + 5181332217031028793650384590762724542630876907198977592730043310368021901782721530053394250577461993296684728562642042745578204 + 8059743569954838104598948856222744875810352375978155248926213114786009876969666524615446586588275065587752809296977777941299366 + 4960623850950107986976011274245247425368704858396317272530283837294761704449561833295704741998045363670811422098828233894939307 + 3391941685834457637274247913999521308752675840541536848418544996656831007389255133631777457133457716285009673478699826403200309 + 4519130151833287959851246691876615538787874185186936205145712978930546123861640155395430711723899715676633532061887829247109590 + 1676546877970973940392277995447472865522499015178996256227821980732651914936762181112328377073844485649563827098289006561421904 + 4935465846415256812459944886042442740776629289289624483798607070666905637221701286036356829140962976615020452048228461943046845 + 5324252244416512745242538847575585469682159371913734134263569496276780441518422322618507872746192259540742513974372774167973337 + 4061947105362693262133270759088934938816594942342421443896871674922874493598103930292152723174036554995062078161445343075609331 + 2764956618470182052214734830103729160245043907968784028181813618886443201986039333396356809943270121754709713915646568740151206 + 3370863211220134665256513439944166456784396566762502427753466744044215577692010267595936563128872570057590311781066772952724628 + 1434093271982951335221748052776429614044261679575670437872151960576974124250079774604982905427771724749469647670243244251475834 + 1955236107353798168181042526280355939682930522521300010742221556820749544725933966041624888393993154502962490618839145486969576 + 6290416028546495661266540757687391083370341491184427521635724821327522535027514382783824919995740288516481937621675853899158115 + 1271233716574270260984632585239413670925887252984501086126979534236923438493445631129740540692858583194337904806381657298903618 + 3300535021488010384891010505876121956740827701335944021678777354223576529240510607458801670448052514469687591418109583216371899 + 3485417441989301906542262637698405742722722240100485896839477201597733807155335120248775000837222824525999750714790729423644465 + 3411348746879651113262757268624543364109755847832677598538228869268434533167862688737780726486206863057323257234642767012961381 + 2165814758833781311422742619981746792464126525574786109619341095871177233773859607236931880493129178559812250332066463408514532 + 7726034975123054527871123751165334996022991283473243555448093241244802428165706217812562663617393968824053366244173854470750856 + 6095264928940472527983481330401867205683258753243162756860090551147348417813873221392674935402798968661528287131244490650915944 + 4846998428123345187768488062434480479219313046695253889842680691405315693254169660178067961065703759896641710892485894972873800 + 1685615608144031413476448920807056587474093195656920132969415782126007882727463216577625078022336565533036012495150175153154793 + 3655761747568001155088833871531145294046756206587264284578974630056937095900549928662096625015556765632408742933996850251895951 + 0111954704076325038375601656210245491836721039674987643056715722213989286056097567862156918863302428121309646750177612394901330 + 8415584072851574023474900634488379027144152280913594573298990276864512420566377677406310761330579752357658832083046689763512425 + 5360991991088493887837058948075647761797269956784924198250160336333432026534756149206974204145691725795668303825556473066440146 + 6308534942697410882776557732300657800112150355078878291669302663342797528117730903433654703116183867380240849386640798032108726 + 1472159005438778436757327262797064431019220263757862409221343714482887707767271424863105342534371712556647665588514796238299461 + 7911386503568215258552458522450938485043355503569972624134133652411157539448177529209200030556438822689089819514432813580599189 + 2365679543813190286281972504483805742897733392239676734466218958339246807222637911353738424980809257547217933600526785327528737 + 8206666715147505843269892459203855284050942439891047557154055608815102510800979065603928242478158845237310517156379667384978425 + 8564365639950704666389094627317673103441553979461958229265682055180735168285879029143428791049454750378104825426147990982959332 + 4829102499976584107337249497306375535937865662615510579219221293219668812136853030161705938471830225621587949094705819774556069 + 5123783679768692703321434015951275136482214434898378095577232958805557078721200098045359198446613744587543829867662788092598136 + 6929950567989350660377223378484336709625123004431484409297585830087971734242391343301362221372782329683381841402343240854937627 + 3027430314645534840941417243615965839776590781088050407903488696621208213787375420065466391992905505392720776395628578270203968 + 5561557545896908531566696290176040220677116087315281719465429326728445015278079287297460019260738872427151255654689514071849986 + 1828538379287013993210377215462458395873947138158932974395044262987261065763556796656318930386507150893214229366028840942649836 + 2063121041445493166725834460800448260568700963104181570946402318291105228818528098805135391601388005156357001178185451101272800 + 3370800872347836800855502143109732296211615709327616533336180819117537969874343031967516246129400847851680499950308763513532698 + 2261251707986576560067694894090522658489287994163408241552992222074332750687259975120713193581210288235466997453538082950570613 + 5547333609592722700682015971929817349283991994515812388316385424977175852402318951978198762120074865379726347089860459367729850 + 0402544338102912384265553136946539662518389179790301064640333604344279296879018653656722109731114774692564467347146643170192535 + 8993673525857276993127971955065805434826324155448624528360859774191561165506877746667502530039089420897916681025323026574636061 + 3901599392791219781553830625484740571991825540511807354859441733493239937466053566374517381465227962291796387571020809725382544 + 7574422026948740113868646418886560822423385797395522913481336942061412395775696211559412859927044430059903817069457531153931671 + 3666927872751409403909634814246127285265889024700225210198280286825210509773750861772507551910169158603017385059974490577083038 + 6432266277247351230987806521470687675699096976848067098507903096237956371518053276015484587153777797643144785970196659271124201 + 8805175031746648720776866745620376390338985825396413633102505797368825729966186841638401277578013322523402620704692665720430906 + 8623786671348700175861755678175427019767971457395145977447813890266721740858466375677681653108760786751356531141090929913781526 + 3195648380237469630693855838585465684458789117617495694729011729035913248141836338293691788762707190185659273515849140203833275 + 0597402941284234251455344083137079916499435796408338558567042346638713911874856299057564768580158647502818908352952487514100356 + 0970868650564875484386825809898953941148685658470222784359891344183429634142985332602653810091182805015332286021467238333362385 + 4744217325804259157671625823323830396696824326946849733799160663706608011805733632306227156863544912264884279245494044730337851 + 0084125575216079610672037870038502647338343776533232876650551512543864312081271558094734273891229896844012952524148474639077490 + 3953838752044271045872553760612072547541462596253868540540395181295139378941954659771594736894686221229277026890071243182491089 + 1570455075037097901528554345355410026197839647129067342374536771901052967778273115724862482455356615889491970844930623438114267 + 1113425143150646440502818701009316634243943336310155606852136330886016200376990719743484314150050963993583980070237708157561869 + 2850497678307680310432965409960545878246397108725852340253836659713228648432015357639072103145170515437738478376685162370275788 + 3326664187179079200022042294919767104163644624649594061308737509813605056856101998334843842071022724849290393928923994480353310 + 5498899160503467457596940573659595416916940383633806231810327042150722695852999362605105557507669885448657908253818192962915295 + 7340742801283937313388827545354690848045358633204829321755059875964474925792234042792682433581007092726558257928146358188938017 + 3788737611929951605093399738060446796551970972956586328702617346062935531918635358396384018139217900704517134300111877098173771 + 6556088236400468643295262663772005261144129747959817416429151644418457406109514416151746327186627985567345268051259611187659664 + 9265455725916581745797982714801820234080260053210177213938914050671185571980281286595729366143889579286214314682943150406601728 + 0316466611292764222191535471075816173597528297677167091929792260801201488249926367457821134968651224754973624583045814966898991 + 7240870813182642979734405654373311183972717838426383954790596720674570866884378092938010438980361304392635321123093916926377699 + 1098769261784660364965755629864526449156402293650490776352458745073647855811975287018649518441512140869999035534937655163547223 + 7318570673563180482204840468935262794048795191854962451038993504158655689641517360974735911839513301305317748540458018312631163 + 0444738341332226086089060414609016104084271113844087095538006211914540457624942221411569773470678982159365460154412977671269730 + 7214452687225977763650799051005862709711542484791447215218763058978813997928801482608042879518784727437915756166238817248827266 + 6180378877242192988083619217841832407955378736448569454941330027911152317402955093457538120111385592095583433817050629741079340 + 5629107620334905196700840557766414405147144002648539402508824797133924214385476958587576623195377053042403089302692454844253984 + 3318554062977863170044352262420619308431178765567333623647941692615442475752129139395428889369180754179899164103774056228855177 + 1724684496632837895268448877487345538070342201067523252247951553639414362390924781555578381060846820725528271757795755177666280 + 3668536899528123873671104403554809934477255454000919778770432207141030247047304569687086172422809626838419879927821205317757198 + 4281376208790055629568334266876725167967493231201019877577819781783383068774238210201096426961674885308966481435486534817275888 + 7577712459257967273487604669410934219901389126865013214764147583539515778668315529487762810385482472159142915583111160208903283 + 2092476036780853093515438486821087167147843243339127524062892009959789660882873649427006559335981769826686296878365166850602867 + 3343172251567689761041900651298644580155321777412234282871319882978374041565615637937824367712999898962026386244164131814440583 + 2523107617535787966332348997625949033914601433430397210697903069041012073594953603672415272693571514416319482962732360550203007 + 2354311337820780136418582226046355285087018441007811818178174630131348892691010862349686382003869512529793089372921566890105315 + 1170999065500729991421364651545352790769082161371433138736113416719659099975772914182032395782369105406892855739430280792570755 + 1474708015575641879072739292610329996968899496702225715923818519908679748009454327877467225863186123383312506444593821059541320 + 2519230317068471671990663024614062738285094805102560284217361596105049865919692357067522503590280759438003713619649669926160819 + 8477593117311192072667283113407927363527106554972169624278711433088640030184820529565097341512033077210672824164404101920707697 + 5928625658638382607550288328629457639763193426953494665267869864411489469568811023649446369996193687172148618677078694284120641 + 1646459774821145583534736023501469753322215654392655710781868598002276354678420510784519315703507997622744075405271188494799548 + 5604976454282399594837769165955324714117059445288436250408738807427315530171196984735484375626981702836635871509821590209332491 + 1535805646302302016352504827863133089568000814854822798689081283591430708834238105002833054643250911507660006657799194089124227 + 5554971708100609197716368094861383459498089313293558900360605415466184945588159656825590482066432370186681671169454435798038380 + 3849073431364569441656271420494005561747519609440641325324675204133825604638188550112139476449622000662627992498117594394096623 + 4191048491581987672722516757004987334900086209495744999112552193520096404679809481469054957100693375905822779214877756331765654 + 3967826927260531495518865955487463010124395050606347758705435971911583515293152693887305102817702226005465633434328368776552721 + 0431488077940753541035965504802229919911746684489825460131664577839381215244988219702491643455403072485117531612606199932108314 + 9410075360076281631174487118204030545727872004911310355915647215932318325233997786962419782803117783722823043531791703707719546 + 9979899286512850189031098302495325193753351855488331350658951722090011555997930787556662797780665452620638874492236108755984250 + 0652520709290586245394513350104966676213533639227604453023649959625928591554435452582297988094318689720723128469217871904823318 + 5154138924950867908591044177967760020371009497593629645137446770819235001454567589699623753759581616298742234368099793781827967 + 3473470305718567484348272233839660441345062709145235638650446308235096448960992127705010353860654270452060145032963280540290644 + 0926811026419214969150491345419181845874142492157134486078145329290631845342202476471135442659122079092431512088292118497802805 + 9354612782399796245605885928858715130206027789349453872862552261402417530015360315458931199778666063128483794096976323329377872 + 9050549362931470711847062862659110650055274307045585443522892077774880073956334195774718662309192081402741882514069042809280212 + 3388599022582995822369209018970901943500870352576118339149315315976479926966165136544818295802570738444044829469770910136539354 + 6564372944547448237407512632251508379320872549342100765184348768929229061655816110427490635344170087149155652249787176557737086 + 9304726910793034348084164624446844756267779275838929154374342302538079381563499255177774157465080422281305646532991405754916981 + 5079495135477953063596578815549589683659295982170939553637877137130071575921564130005951724009912627770427858856970687414583660 + 6190459320672966822341653503087470382689354052580606552329874275327388332913948910878502521194902477705810238260537165258752153 + 1741863988657791139389205030367955495311579034712194218460880036525975053623461402320730996642095747448443229185546281279794016 + 4885628580837209961221029576497258511104739050257941549091025711288015307691459924906488083252587010968968824529177652581775801 + 0763397108119317156892696282929270919177456927168774057189218655020688126030914415663313590555442617356391166888501048989509961 + 5152773773826793584772678203560374056030587370542989568481592013810907285435722199937156448541686535030998055918516459522290076 + 1305239048493423602262076973364789510528152271858803400583562336066393859447415629511735131940444974630579121650398527184965704 + 6991327733592729480669828930382613428226140528036104065114673331048967012900401318314500711300298883332334369070527930012816139 + 3452427216705740390119289172699570798671134046758624232397496740015824965414235594660630239994200610360038450127723765597890208 + 5175730522105055786800808015853823181610779386663930878893825884556056314059074930365519187914921351319328315180621551748091601 + 5714910102916106131414571159732353736678835156815504392107562506650484480968671954066774178137781734638792008562430877641109527 + 5369362810620715036409904025968522864824364325482506902964133711312038294053559282742499233287959154156854383883148516152426070 + 0230923585180985083743915234845529953134912525464096240500757424789301872897111680226897303301395426146920411464973830228585960 + 2828878183082532630135919486366960583430058092282156338048743819662184574743797715878229822611358535700802659064501248149009579 + 8877808967697355352896283886616902601338873980280498803907441157295597934158728665206373488691687917104704283343745205639622462 + 3315755549989540644308207351384163575736340700335343877848915517455194885659684732058284726257857232622941934453881121004726782 + 3002928241602670019659934407449689182082678896433504272332382719662522606641231869982252041696766531509399818750721950486163498 + 7932472000788041651204426873094409270765907861252426634561030946897515784875744395710037381070458145660220907030271894709835605 + 0606375828713960156150750275120802286593052131450659403286977242629895839703700510410871815684746087294738637398861554742127265 + 0927164114710800842124744207418934599056137681039495980981311410777428870205405129624149605463522859752503128770836084491952252 + 2931015631747347657009129018143774038849625686108045440606651923845534431071983109500879593401459457270781303275371634919948465 + 0387570468949867854454498257661547651091256802128345749601432500529628510635061338338862610989893855279059054348321900538486115 + 8602609964344200881430293688135456245345432239342905412584133371544661893209862399991442865006457440325878578391699643241518820 + 0476780634258919055579958686158323045730786320160920071950074973087521728400869220442510810405620758553467843454120670874658001 + 4611389884432116865691971525430161735365815156176932740053507703667082841676421694566703484160697073157865364859324160407900243 + 7848340394578239725877088114075619051748487906575872632940285638137907126466280399912812673908953355586620975122613901023009092 + 9989300098497815617534003740634757576144040056489564419015441642507944260710401355749819839918602861170379515547533183230261689 + 2978159531889967729748526061427217809996789425967856884930963977509421860822261926488518659963801830737928324899351448743506636 + 7739373703546853709971163541284486539624807396328266253157406157316793793115843617866707276779926556010088380028395990807722966 + 5262595518780890084621315703653759393744008415536932695809891522083236025326969192829600448033930003810949789949558452866508165 + 6709958307107045609075677759152351429582355756238261042407300818561928024091909129169346687529817528488405441096301840942497835 + 7939846806218683995681953891663100594898796616302246789629809345268814966245162531052163166438108697094692065750286916247302592 + 6376737923232528630569024819762238692074089057479592609265302063789788269041103846131589957468529143458603367428237467202691677 + 1164704135075482622437354706246898083995113224930951841406301203169957259318901636559771075096487643893444519082342460614778341 + 7571486167299822050740707597065176588093664070641995447134130614103674235649546121137008292829783010870775335672457433796269838 + 0786000364088666248224822824647357946129181563136369891309362023665749511277214956791187825832905762312557124459238096857752088 + 0224756578418586950260891776975306306690545499717256072289157907934175802791666439540405671709869057148319796761025632922961188 + 4317800666800783644393485986576298736917563650897164304571720738720115271226750820847348337143207594067034889090129746637573061 + 4992035733871695023603260755794332051946719932307664611429871720394241080075351265170984927835215008078524349098428854934511014 + 7791275210894880460866040577708447085440157107534047266197077167838868317086743808903866856598023308194718747427381845326367182 + 9440053603247145332820937897067937394376812799936768352012215925676355028026697201409962671443788824047418146714929473243964178 + 4694097429621088759426437344831944205038778311615485599880533035443309753228841592516038076111818420993913946554412796041546011 + 0591550477943256220239415601324460355602248522402154416815822080226505160015237485088369250676462054718340071691237191715854643 + 3754782628510988470286589139121850755775569961153502324797466418949716647077195388880488321524207926209705534645689175931304390 + 4293579894293631845176289384983754244067774813502510037057302019611329180738850594681778906215406264239719011424001198377631320 + 9407877792875650325539404181214900230679005444970369243950847777718535539213759142124477926938032002586130641694624396314012506 + 2378295522687601357905408069624354294555654221781438340067666919648970200524898545019520189688682193849864964964428853699551465 + 7923565501350073769051751525297874085786148453411032926127268603914648170142127584914619282268063761170983684501064629044484389 + 9840829700300902841805899697228329095218443610475399628627070805326825976451593789370050027841655892248443960659103428515769018 + 7131899325280315528312838930296738263099442057104969325259438333829573217299432626262718217616786664813337230788868035555543551 + 1613365891642882106953566519548821305418260262459032678151796367238313756913498686906585565640299870573937524634136703149075431 + 9289249177275626622021358990349141206245802827466686634188302681734388914438573274476670571970132658340810522019108097685976679 + 1999547679043388007539431538024419806104005321474063902499212939182657952169737390109212206767202350076020372910741798343053860 + 0796380798378956338026387089364560910203624767639137927998294096484424294854533260048523991232484163916572752125119143647479084 + 3312139471300109845789877486922941094495320192955690413961709171195278169767812527830359720778178037462244636938901054061989359 + 6446495700380140348116004473224522745585963020017740642418321329101387653563805874445580561212083040164396327873544239022001568 + 8221316129071405562026280838341093594207054207388991782744751735089766826502781865742057843922709134454840546015717044077633360 + 8884079984504038495190808918953678045353356097676798230492279289061735280457857280913457619377057884683523850527395740839623992 + 7553178237304616708890828475106185796221210507905405468874982714460646413397054645663825587287675092464040250385703334315092608 + 4773590965589763472535194103574470410955536365729704648777555516672917330870335268784268577673152078292448804242825553568245947 + 6215819528050303270969774851839361036143312160025453398613079612450766506304878967542263517886001609950018287965333798559597461 + 2170641880151969257726247627112079520687196427192459411452224132231427774555020194976266757454256306589376845325708061001674166 + 0808706168526831621497924679232450195651965661724083005213398910330404632324992737223126731122399064939390308377239660504899222 + 3551818900906904056676616710573047283299775444456072812898768689067250392820375890588789819477340760813736549269624861064751893 + 0906163675906901070688176210778473069828249578452605511950224714556564390138087101450788624170738723043479291100038259738176381 + 8078282667536765535434830984808011662048300628237758542292327990288591220497965448597597894673766538440553768610799486540893085 + 4239348796188542060619155351521608241401936444825596707153268722768490308653700045149495791462321531911996176024726025953987339 + 4599085925561530429435581768120454911625188723603840101001827808010649207159239374191781479981311865586606666121770067310616172 + 7104627786436327756821840719455701887978236563257187943017156401785911149438142292942970899875188032869983742209547431350943402 + 3524068403178617373975067637980111980036408360680020858787573852832862969725456560160112278450433733839443039332972392923338691 + 7361417128175114993261450629674608141894725708171510038678649037487846100911817687890240766440318417379790915067480509929873884 + 4192563045095005960884279637612799513276543500165975164906153877957210268650229031342852943158004290795716146485254485943610979 + 5527495850605424448537975358841328894172810067249914112763981461492106207569150714303562508512966364997576085520454249415595925 + 7749567920199753428291369733514893066123672937987655345561072264405494064545300253825630928142777746597418333809686090132329222 + 2347190729828800374979423249344630750463633445579902195914226451238506679798785890126552693482294276302768079721653123608475225 + 0152265832264604743532240505688517479981918489770686750786602858928368893549157302414453807821089110756269039234757397043529808 + 6533482130565176488100655388961819118126865617901005108218775489706817843329452026358354168685608881349897826461107138466301657 + 1298673036456454794414764858082769061588499493558362877721489608505337579335664200621558841720543957496547716133300368539580407 + 6422724558120550176442233652100893764139597343252110471726917934375351595018103999311490022927771281873120822851829841201522060 + 8271532119297676915199374389042651216528118441258413260870365096855873207948565556782103615860771982841168346920959540519710060 + 6184875439923588759440136066343058630113336838104030510817176224460276957688775424874821399346650313045479118572616668489003296 + 2897490483936533080760701381789308980122333755911815060695347160990990030052801534871717538234667743972256918252210649169228903 + 3655303333861985799802708736697214310308014845445976122762735834979387407451810326226050509201808567673064245381176975037733147 + 9657194682720093768010430501297373816646166065617291768151706574173498067197264972548166688571305758669319121229890115185819057 + 3103510865220902456203344829140970552995511866958564974902239021728149583173073409170941518663482580344763138822732758130711321 + 2350688930344799523350604942490602629624759567547933020887009924743050812335493964555189623547661668513628841842940808414417517 + 7886476590659571641831046458439879022628434419829165109717986460127979081642839919400368933401267954441646768446103515126565637 + 1110171943300926097143589488105661141081024879644220948038639183302967863702059520939356184545779690411373217502283638534283105 + 6427345179711846867068806487631152636131101160079927489950186169690439565446479010213897921064107507425078506360801250554414400 + 9449471539328516576998441231176991412965843783160858329264144663894049487064693073174535162944480509103362252131259963289347661 + 6448977729584408680822098278848838996541448014927561863895692613238880261580223887644439627676547583170203035028358611234118545 + 5113424393568423046116537671317616837784363459294529414397028767453793820041115557136079295159075170242753593066820395440768961 + 0357417280340583283641050541304196888459267811242609025317032935293813444330705702581551660482757892548218860632259447912758396 + 8759325176891928932295819377731294216097307260061594553902071464538665097894582707057397147529275324299057601238957576630914051 + 7741473646777114825234899359211272805439289189063644808522711602498268477174042815308766568204260129647306647359885729554656976 + 9309329125552267123498982148765832181281490321112798033562587148057414223743472931562572470841497241968346307379573830843375864 + 5689803719011022683494640589564528393539106647783122400405858218032186185463041208001667912281578057825422723357469418158669943 + 4135592927602852287576618966571253116928765233133651892018881037343848794704599894714843595981667962009408311650894622157342917 + 4255899203623494824224271003677968232634091967503097880844441755720576147137952557139636719564772738964156856519335241825543143 + 3626415788714735175257556917344733999894086186508542273673131627361802049868502277018604195271807930087879067221107134172074310 + 7958546281467926023449343568661101832138815620051349600621939712639392675220715111033777811540451328852498746778968470255323001 + 5507407940398075053567751242109569783310327198481187906287038704370431459121242392319816826310134418784694594320070284603132253 + 8500952612124145512973435903996934578404485074378319984371754538530064680891506823775364453662506914230333187130946894042814136 + 0265665148790173017555028894292865406694173385138855281737615651927882128657965562089006870021634293021436977249028055567123606 + 5915024874219893422458723773331806018064564044582475437209765195603359789772265483078502778595048000442697079452809908661825491 + 9974005988977051807595272626225779862046223804794634926553502843630881070875123298869912614128545778960915871587536819171698115 + 4134066090737503736509722416899089791584075227377094759873530554067748069082533106208531237181423743510501202120010884006504203 + 2130661127717575197825945847274376219456565491166146558949366985214290031939401399735403160414646904595040915898139346351713694 + 6324612167251656207707087624536097155449639896731425226748776831598133504224173609907231060039276944120772510687900080346884581 + 6779168745096711200457711019042996058420593520557512225066879514823155886446534991145884583182566717602534510076749929656585763 + 2645365584973687585388329644555202088022989110607367050144776537693714417352526613252012599647340542087230486009799844093446266 + 3564846704113295525583758182164662009216216712683832484187612989237709031101278092921642250525269665257513687371728284688457875 + 4269555170494408895577906466689197972679804550565920918614809933468304708581306933698168463484178291731316450813136298166976686 + 7026547610376955852909877173580002842485362728362791349023862313373489864426541187364755041770087263084268647054320360965911322 + 5647079585282992247752748756022346611926842984561046976951468976647765336240687959117772104657541464074764281634923169020133548 + 6986017692163536989579104384975828200486159266813636401205178471888697579916647226641294586286142850042407781409124499578432265 + 7557633520998487338874304841131912835862129914096167258884138035045133191763280844957441725806050932560746430226219247549692154 + 2059549946818227720943211781526111003981250924876459433602235222747377311088585283118957625555745513105052583294040713888376552 + 6312790236548842295363447664682859100743206688687480099078223631017589800121679494388116457487107923554186562511797306252062729 + 9341961249268388400507893558690543848588537117611908256806356375473026278316829039260672100995233732139958201591529357001905122 + 7622440629036046952745648171252074362090378664664601861125598525510174413032785951294400218362705244805632366004605852186841943 + 5591402799903315324575404129541681549710964981665090508369906992078809669693743879553048600144250375936726479837822625004211533 + 0078063724382242661885925388201522364426479724179540766386042648425409841158873221737967588237291116048440934261723138640261227 + 7668975572438016377259095768317171394189060199749631603972553612209575383312005377253743770387375624576792404785414546299669225 + 6702311775340274741303788836209727482858012234498189667215083952930215080983474097496335600683835003845218991908331419228161974 + 5844861014709438146848025778890120727743982063500046236695299463240688553674143271469625051120980545361183599015488717404464199 + 1417923931690244544999340897859985367002505948231379127672256195312588278402509195472407043750082438215262579893876014989408706 + 0852865918577980935645894147403286685964996381094297648429648506192278067863183038777421574419694387317777907505729693297708412 + 1477876485508630104652801640230580883493634454785840756974806839665717736338880683347432665781835143575902380330089255654038083 + 1333574195103318490380293307280457872559202823396902837942959887393577658742570521479101307298105809134466724699237489092865507 + 8231986011655928132234768712876079867027010505901813055232448036254614645338353115984374755578779894249199293331904818734171378 + 5291198257745669262198453729172996916240029288161181812810389503650167962679364773038871747909175248874112616641407342566234542 + 9827656930274121781454100476261391707245667711266140909114058056141317855910068833712824192869630959336254369672357008292856548 + 5323877306540282063144065009953089367459505720096157841731259977506672262970125862602619551379971955654409939177527714243403057 + 3533286954907536500237907021493132000340867715658050587581466366920687545465498963798769329374590369604149184427380755601882748 + 2772451245387121398103687673837186367345979531432828052838695364605611707914643359500610696276887453665009271796449018655863587 + 0698238146791660163022661497107232088142858713995181413650802098858185207125972232613318849001183174321522406825869523281989408 + 8598554632732565974534400037249824032956321514858885348539735224820260572526802963756049116642833599682551125312131721936464816 + 8777244479719589766354029439548567013317807112981262942768196141952117452742612964786718669561362298781178596889656657857438059 + 5923903176580798552139931019374192553986137461354795191944498128759243022494357593594711086051327159717361960027267213667050902 + 7713620888965717050672864796196500874403820011858648932283473719914877636081597753296264071668416201048071423687724652867885227 + 1226026168424754948160701743250583052114587429759744035821120491264623002950973529144113414105707200986835221503669020815368719 + 4301615723202468195623453039744894794833018107887889921748034816356630393443669846540007477652862272296203141137911353369865567 + 3701305132741529846291547614776780687562767296077648285050793745319685122361946265802267010089656480989090754766793951985030256 + 8873911333836369977427224870430320356503521006657767633627578973429639446804587551411591770027775298708856911679457385890346605 + 1569544828599021231532143176442191013631066377985711192575263159095165119051577468547654466026788861257476052155683756383480477 + 1570683253965182842006010673097287497172850525327662453055182206979693937570550092128731857505346441332074707878996538911947435 + 7826422261424373910786428920393564290525228206911026303685173218951588837324122530045948404629473803092607834231045937648966971 + 2638900097751822798368796230240210897707934867384226561665436456581464223307579261127638844885560109562036790807667670390644417 + 4192581432555251427389363044896326951734847648428400345150360499669512737809145524003991223977279428592712065139442479960445332 + 3942282183806384991949767715266661401310060486291440972343510267352817495541237489262806877081824812836064827724828303648923419 + 9223072015234086234796090436383818568296143232241955872923081786551697504279591818923391084950971313678554302938168053766302337 + 5040295146817500973605556893314901715843407186937767008367308307925199801486021624397893053770707845409279496052311813731054362 + 1647014082822566848815080638989025226353949427396868720941862068805915405636344175116957293867502515550210403185422186297987101 + 2299194118400856813156210708210682041625725297454205612569506042325388570654000072012600316753710747599029554756191357595113351 + 9406123252615695607363852828573549803486496914881699175306276755265739836369938313041363024110056929623864023133434302918217876 + 4012400092952627260881136088985623398889677549475347950880378929158923209470729028820934081657587476645444580153423943137551662 + 7552074556799764537114289715930906335072549730926411552458159805302034148895295264056331531618830126090300007948842259905560480 + 2034810936658458335936482208711459668407533754842615732173788255099444966005654249703291665433879743623245887203502319367176453 + 2055826854912228554738248289886125490164761646368783638608966701408500405439745351176591154838568604792386814062201460103196028 + 1704883259604470302949798965476058273811653448846315941108597287428362004683627667421915628743842382745845960365444382205614441 + 8276093407998769926806805283999661528492618490261728950220171409852969042576745011296912080496971648424710213822281461166346433 + 7954055459730823465679899905176049956104235683646988019468094197473567154076726095028250041409673376986848760985312614035795365 + 3541288526820871183022785627606776202868249144458419432875958263707872906136295450220559956136362126175679096582857639739948725 + 4938942457166622758688764402917253914836669353169972138509951712963418233559611193066044779423979184123891151058275415387004481 + 0186693532983400032989768484986211599974215771878040648121115240600011282719832395142348174280309789242173034859607865458058836 + 9693011226500711160574222437812022981161460007590617976243921827767353835606291414448435195278815539213466555449489307049996549 + 9509118537609881549110785870137427018215479109414974529881125038407426313589072435487055670013225428915901526956102119247020213 + 7469585110154725916486236087220807528982687428584047123899577899339622871539124688449741918490207266633825962457784296958609358 + 2301098947514645707894405697878233655395086728296961354861714139621104988822145498752087551938260818588440041204929785479253335 + 7195002791628422640170129886701270065601981205842819128758172220230767271007555891989535523140754390046908600193906165109046248 + 2903714800754690075212414752414239844419261581404644710369810146988392192489474219249291646325601976712417376991598429990116224 + 6657841194866308789835186691755481781807363317310203480516610021219245717136441915610841540149737012207330154276656421683007775 + 6496393167312732418345038041143115847682160487308598451735321809667649213873941020106124895016322422646066096706495173559340273 + 6190352286444996698010567042083025249630998980474746852300834243586692391358290885793710964591096599205367697354040455225748995 + 3808084112830212575642888231806203048547309288414193348028410780142000603799742289999737003393558049032105240979729430950416734 + 2055001806906934446231057752350125761310442613239626005937018173389749155377417284662314193484961591256165582045826903566815287 + 1770910475516651085946142895420353886980271498962773028208448011256576219469415630937607816862320717646276543446021775437024856 + 7317728070174544541281155663261784538153312462326658626789839195595942323601274570763560759947639040733318592217361764664122267 + 5163497922629734181478583586735139172337995385407882365183581289857390438660661367597010604158349602523776584737697559311077546 + 1232290524053006728473192557288773310853272463002083064021874545276391652038777534156787659533007696087737660972241935746823998 + 4820797373925070252089423136204599368358477176708061478789645953897583587905165644362770501568086914083487441612509546270070041 + 2710844937068669762717114936914428075765570984673461573362652998653398467217253506007120061287151708786386990808903587499291676 + 1722239692416177387037629004556867021409013954231954955946248469232703827805268278720272112690685704443311442687874485358911812 + 0696442461522918873003473056316397138103158503920758588244927506442635208935867088943853508413143951321019830428306333251201396 + 5237490053651269730925587281174140512120043151663340911938612562084343250088788816613613533254540244890538135550921235569055235 + 3652159735685467737870844804342436795620955533935479356452033442056822975104591188103222254197338188275216408256009062112739968 + 7134994798879023357613115067249723046493042657115745023241318111461450746096281739377465898982050597074346498759749836646750845 + 5435539953004427145646816313257688146440880667736243466005411373421754461366941715230523658976477672479751504847483760926576034 + 1189232066364746161715297654667683387924489405288055983423309925216635045159783671997425077719999713937624968743960815866938439 + 3458042402161473455431554634378956977066496820341904422146434258908727947177474383440746332129391825690966243498723403254667650 + 8583588769346353411734495459871858141713721510897174001175951449320360912321580651780695549218819369972998610310409490019288172 + 9334204527475060600189111850610268775609506754404225935699578359127242186303638934810994186504201384645847184324944047027889017 + 9180203944559928543575350648779851174917364441299737433952437533215087774057147807226819191868491441590442039396662591808502513 + 2164065534579878437699757090955883471447031879403082053258427608568820018565147466627486801491876503507730663614122066321703246 + 1913587358432681308736116815399127159387589682764288441702400713256228014611237877207779478537639968530764623959147519370506561 + 6235255735630858442517033591935698933960554844760005512206225607812740106611830794710056776637176558829867814913080368920324943 + 5410646760661322485781048142156629014814968811323925705022272475371023640394527122828545405831491808608741154836760565505004928 + 2033787078461763925201661733809116559798197426225447373091087213252755823492809148960852025727421510534412088471340160144342242 + 4053406317407103820908867515275579307068390637321468991384194322089645112923727349244540751951979469134053290718220589958599078 + 3285805403257089050405641613610899794397383496324785340103859171172319440876039603408630922409574370487373867533449326075083340 + 2983815868763252323303322070522064853273357744420576029234853609842229699640881843769482230526051119476446187157115583149336835 + 2361402646872012433986880843871560611945683230864891757700569780134284216871106221826645632387373922861192629580123373279881156 + 3429998671996373176825887742582100895464377776504251588052739302345778540285554961799280437565093922440989079226166655301999596 + 0886198944491737540229136497483278400920360475905860689648388002698383026711966163612310598810941558644533048630182341670726792 + 3224790998309426141510868353814679975103849323867287287851298934668662832191399524482143116612939771691776186144211021701423317 + 4793327096193585617231688937441621332297850907599875602232326960040073326201864681000919760060752937975322888247984232424151851 + 0809471069558103959275275538388584472907830398322459954494433179596574461777867507710018713571052848608078849868820600263934936 + 8295056327643509778568235977901421687599218957335038414287972297917509776356464814745628543893936365866982215021206066423916526 + 0069175389099655621827463771703163016234772278712340002459468537149630573879420643113985870282366118625694647368265400040980694 + 0185330675548785458492267177712810772887558224559469934081174511045410475070695699952516120170917198086628352522241811643698589 + 3432240470257950810314775679834800845473620978487244838484905235351184086387166599707527028976915030731776500593580501517198631 + 7221196580395629622683771151068414253703527355840765726766691589948635031125477445246126627685840897423930890628894585553998214 + 0691851299476896761562326144030082656664005132402228246129440862040530711922127884942717942941321981606132599740710622690829340 + 6387805954414104944165651355643971413515987568344486496225929165033526273702557885861628429072595508259134031569932407466556139 + 1855370060311355098279801028503699206359780131940779590143641110125855998712927294283001777864930865688001454553164651367990176 + 3395026397066375956526282504048669461521946610830298850923781230518236171386053536666469499692151678856847055919172630657325178 + 3046849923385707165827109497171128710135811605592578271326373856764418443760349195924655728319788343802029428671675457416769456 + 5261821042279220321036999746346900717107895012894353289951489320917708733388530368251182473743527841343292751660664418023250390 + 8824252317744508579970406643025576979363288136493464811540150480851485119103480579103156985795448940762007262203877811330652870 + 3204055616321408250954812676138625194951030184386810613892670161995606664768252471283913135456955545480933087872315934450481826 + 0110599619290339021324056958678493559294456117665436489672772960474962839844256174658530179997209334133515553960451214172384426 + 3123165163841681474367010429491835679876709672710839983993762107872490425945162980229932665274102783110995818120564672709048084 + 2232035395926446390712487234338471590552947684994788621710474575654186707905435367680711475885293815543060949577152083169955046 + 3350028292251658928286123588620947938740352179851517866242963626384508167950485172272074373493999323206780786225244298185666999 + 4138239667749081340443940138823062129167164095346506708209137890234837357780622504863833649209158347489730999565991588612008781 + 4664217286110698633018092758084011823559493288270590581425742146586929149871453186482768470820080489858199024057046533515257475 + 1359038127174952081563588721035499113638671173404164924825530484539148472501653910385502837523160916070082537168043390775386612 + 1436923728210391122200372504366645991744778858443244990595402772009992024820412617754275410349299293608939703285522116131987750 + 7070475686255460177418547021473687579971194688396164244442299931146128832803904423667313289561781005593542663645306028982529133 + 8234121263247251924212841508107137520536152642698580769661242285329043039771966387613256643214231439403217580461965950616775878 + 5413104246474816660429811639531866004425878342745986000581091374331764631199000564830359002609727849512990017018293163945873976 + 9271235506027321498393346844536657245544343198147802739604119444238511848559098921026630558834845589124777635275843923942487146 + 6915026105020117228571904488841353205308577369931061433915716936274811913573096342546878245443525669417786920642396110509919680 + 6739657651695868636149376334284237799146008295879768907577994879004415279621922483186516644311320818173589692203657526672858471 + 9876510782436209693056682744986249105883882516043932138260023370268816469981968622627487020614107433825722570906101692145161092 + 8947476576936475757290736092762279169953016586726757242391235235637432154172158901821960951603571049760362400377076037216546585 + 2735502157822565784279289258228694712999190257163908804541511707522385665999422960150232894155188313507493238330302410605425296 + 7940101946087505879550405973067848188833812225296523952905032878875050817047074123446017999571197850004230072472112763344801201 + 6857142063692961406887982913011490273637829211932192499375592176104274764580285681098203860236999583984675192011342612589287803 + 2211465020826460764614937570329924717346527293528447660776999654426823206473097384092520163892337570587601913303602876478051786 + 5272016532080322083507311689593741698084734458418980219100525429302190098183573551213250917695957795596851135451614813138939428 + 5194225250639639525068156399214932189538746207985167145356511964074580667075083175359149568969997574350520456153735083289658446 + 1455560636188297319680331471565963722123437735473357325582592487841750254758281060767877781711667628353861132757458093517522296 + 9590937580052253974622159164858580322392765535712215396895455529996073185392085906968002802221878982904887664044332656986715431 + 9536212991471446618363328764237863492326635377747715439634427901843465449556160996406079848698687609807559175166455209276718369 + 0962150554158891455114948237812845566152678283675857088563676954226626094608713709080121062121158536561703886898127526222898762 + 8414892749163551177217490205399965970236826061221918459810953818518538232318451456451553658102845761329243527433596909757880804 + 9825158812532083534774503272169600063323718458433952873310136391419269694767849055513012348666684447456130828029837154887287827 + 4062509382360859964541627147185929761392475832974190883249337770970320052156457280268514718326951417528373787461693447362886601 + 9802384514195519930363615938594105163103928246792737359775050266251933928460657553568168049147890604569802307087230082628479583 + 5935332407364708394968146809867463424837289762388992341535259500067286459397511377634976747563308326968703921946360640378185893 + 4569961338778055670213869684862788995924625160473819440389284613604453202763523485241482845106528449769880720371645531620509281 + 4202560683681703431369153262516802980502196714639887848169937613326674387122996761898343353693436995583214395894151975156893071 + 5332713363776927366695888962587179393484799105075109946348286416315933464459810857879632369155531524704654845441581407617245460 + 1504145331569763505220832523847632508529957830567158287689592530569297300966404712183597770247546234814056520028432048220079902 + 1149483717724666058290549158624685899733135096369862966589441778195807957291623190196664952975922610237417399523101511538417768 + 0036082673459241242094083136368293175771615652653244493296672289353318399016588588663275146926170769838811055155231491519921092 + 2671555423322348703897548437846131134228893160392027737396758641632859270434645917320325207654186499204544521705733245689882718 + 2041837354468721403869880661989984614132154115011011100068745419042193490192096797533733270459341389726436281948139045659902298 + 6287265676207191576589342058985373273830354712920659876843903556929428288343172794038913384089049546744993546672999661244015504 + 7671119447680097893124176344032941210873441607294204020878536819662836852561652631058964593184756766213107639235733279668108014 + 1503597944873319896726432783506968518844581130482208284211813252594573116879179483819354129815885419312761420721174077013349076 + 2090575099698794920755209276799477214063322134870825766478922887601572992873375806104725864045048652936083491870937541080699093 + 4276983494146036588052551210478424032928358829122542012906258904015903858342990969060460111480318597431250609578131562003677515 + 9113189915457840484343399644582165727880755692052210886524470220995792925869536099894161015143779391596346691130912281801612173 + 9319631208845800137369253760266414764140198516858735371828537522929558300406662683159046086394078157278265484925694452296859315 + 8349237034176302850857262350204638637311808275176159745110236526981407472953488387189243977498778789698586980560479570319641349 + 4582085067641332005668306046922050438876194786256238539902378554139808224133740244623740910175342259941720827473284689401445459 + 7345697903120299815105938454414060402797077914470248272961589951135290709800128402376384567445478103311791196342258909767408438 + 1687450542289596593441156541948105976556022804241843599203672068561696047317558154471118174352593930389361496742548511304322359 + 6498489819476221747377877067530863799486747795199009866503783070729160667495759546595972752749803505545796148381282603736838562 + 1116947692218975950285800049524721556053629253858269322416639882955425601685355611062823222776368062359326543474366782696365362 + 1876190167722031024686917347027779070009896358771654643412669083054810506078866218417271851286420021860907338434817211204686529 + 7526344148737332091666585836660697055361931941977353720336283268157952341498338628673162826343734542380046878989163995116270895 + 0881257474139601407433704222324056930283355591807454770810061687372318085122818010133000433045729252354366007849932042280735696 + 5414676249451280636930231638752958380804768673433252210159619334608464253621441055450445428123593855381938626029786836437726558 + 1472864902858611995686957469529408189014561042091105708978737612763064100403995245584630738467933358860436751349270719679653915 + 4154741684647123464440327863242393005522818718477064168160551024239993656696764829360125195215986845682299044548790324197334138 + 3620127277527314655388754016922253350206555973782560191527034271929722748456430219013528002841930398470078939445946816067765376 + 1722243978849829693580351795930973604730338879610427564825410468950337347468265193351290232895574144876817631258161159766300943 + 7560827667474386459711757237346751568066838129529407855307314365209698298457841298119589066095648716960974765231576411494919727 + 8647954673176727645450541867878958992452684388452058871232181090099976607265059152633077058376469186824930991444056731009872982 + 2534991973200933430036026714058825873362205723979737750638944916727241098322793656977758591967127159597583155643556576943448135 + 7155096296084695428953865082662825849460303226866978634425536379072621988021237204615220061198468810868414563936757985215986294 + 0328355158636181420325206501518296045012302259181045466662110690600154986730477840865756276397313811576274178347247630894639601 + 6488666618858920723988680761139802965152715427776544103393791345032803457282545151397254870010332315293514763142030945537580212 + 8490792796508337321795619849060108983218521200268617175020002271232501077412217793566906763151880182142093233096870432790215644 + 6497520222357920618391446425720257029473583117356819552842063897560547456381395533477059429635070000008137772848031720176668971 + 8337012837324253697188573699623123203170708166950795276999966009577648906818828342730326847639721034032786616971040641824194318 + 8936005757600971054320025253057644372313238443033194219596927715787049581460393528422411161050154583706800554645719354006707835 + 4215727593152764210346931899527305466845340439034432649923099270817579403876601746194619933095404333412889852431784452755466843 + 2088097487158522551752685495115047141137278634729729587648195891955992392424399063377394353752520259570862609415201408164480501 + 3544474831228092443689968228780611679861586419457086393251353177701671796943515744580842421181721325756988105402798156643588821 + 9778536795257051681439799124663145890473401144931092912457976024515106053860305458288529123695426810921506064347775651216836501 + 8629179794286699832017474082041208054529672919556607496647432513709724969762646139135868191228785586347557306843431128687158014 + 7106456703557605702232569911033196736598272397024373712296482733842097318351505429979256730289847489156750506335880609744614597 + 9660558924487542734143121356331540689398560467085012517453390341732092436780513934245365179678624863881161450471818695381011735 + 3612453516034902143796136205048511802780802772294479133906585232123112871839607661282061340027850740910859483338299107807956460 + 7138724118583930096084405139356471004624454913317962414308274669136174812224878197906201370412577330455805945128690650516949333 + 1730291821726950196206552159924266720782365385611242853448279354949948923432277012453511172303822029259754519038931979427529263 + 0548575047242616318508715072515332204278272517306960109310804996719916332590161894788700070468159978743034429043329057033741956 + 6780889499085964528861899269034340070621419803779139024411147795371750105312955245739852543595775978340360773771494478163557276 + 8779458235824687171901362922249920581085853186181780124486013927395708657432957030172044779093473433280766667409407392636463029 + 6492579411705822845905066201120652601308459859010659739650561022388466983198156117882306744218369432413488854001765063909641296 + 8476320260631331607201248389753502857961661494677170435281685503191366884817616726638971291309647117085069726218509290967362859 + 0810139343653776833125734038676243930878414416044335363929863448842581458674823745747264416650503948061405425537368655356993636 + 5246772266327550199529567399996744188644213516458735587639817991224447177904904043235549503266714688854194981790228117033924563 + 5461999291173972450770635507697104176866762020802521790899644748842731393628432841194003711839701487245460386154522697276378209 + 5508101058683508523829079387008807816663732920071304290119836347773461806818814318630035261732455767269492882409702742637950576 + 4599609444549117705097045766405200220153090927581307100167391516722145681413981100426906534790499705750570830947858845925010025 + 1009651634984508835728715571045793550385433404603846489058904184111368085059460823145504327889561854662565906194985160507019989 + 9357881999324778923494272780697498659881414033472270442304085245770043338219929173021287371666801815069695486701740310076529915 + 4608279080766236606674170110085478654830337635040537744779366742642067739517988003498779451425063495418123468371481260706586708 + 2700839483986172436829409192485873721128692643705335631914640430691426436305173498220746572777225402080014675196382731227699368 + 0086136702746607717078625347234495013215002090165872533540039551264212687781885399476155438281141614343873696580481400589706298 + 1705902722746414058890369373242227296762941970919549616605978259694120130539911344963309277369189903126883321693536398430654697 + 5704737347400443449757566987270236468633966314353505101478851263083176174429030344023607680553018559157482487272502931014168203 + 0929253853547791644998906236759598501768018124990991199353184644473283908513254590068607924929473380232470364424573291631346278 + 7114456427076321654054593005258016944651062956332800845969220254804995756234489111294820165405880256529733135691041245584370134 + 8553075127747556822577563288536391683930679292906640525736392953226223500696613649419343205087984527799731174525862937043354377 + 7195787380049689624114711568372766827743368052980829823446372539589421589808988393401756593651612425875577606936738214349475949 + 0181544697505469142362834711903740140759734959010974977126438624042186356553593244884210506676336566524109269413687671228874205 + 2896686735795141476730158554607522934103668703053995570782216706155323744964613382384967846986182100960586040580173953854307263 + 0286768549279297394586785263108063892918942908459235186623403809969114153282154910435594392237358132752498428484045697160025994 + 5955615832427009939764606346259378692931215536161617155986791397037887173705219219646647075071165536665651942885935717666403172 + 4276536421804556864922554676992233459439755861177568827029918375612999063128068548901725736512083925758415949098712083242055096 + 1725062474106111957956927114735687646594918046204634711666975260667778901437761819647914937715436330233142512856404865653199627 + 1291532637755334170692403451392823323540177224847012033326608939686606026939972956526341007272336243309559194347525857345975521 + 4741600004754011316928740091902596508371266808717732973936254941000335221943249074812743110404969466723162046697491974991225004 + 9085942759791031775731739206062635146158396893656161608173687371708987211298821225045306367484626014700868922039873009889166761 + 2541340395518961317950998826785729636172355473248648132541946680948357368185423797382627281741493372551999786014593359188997484 + 5815863362546532185070737662568520327034674676319716730206859041401224197894669598892125005912741187360523778711460345399659500 + 5019261584110255017064950229895215051849707546749811603776445037494938571872346104053773024040213974077890562979334359709174595 + 8333959703819799129975411673347762248495046754138982930023526377690018754531518740079491735091275401960400702618787889510076010 + 4581333314409607030057543494344952121287231730028937956224706941567517833092451729648212810249480493474654543033507398453170912 + 7852221502784071535646166335599143402394637641678513241517161191111016811759837825114453186940577300367319815188600287295217212 + 2010730508881189649006207896145313350898015140508068016693226343978406558747353752836658017965545008809220423091595161424950648 + 0496642867065050893136545829132837570390366632826974250747266589629788809643453838849392317508541173149110672931572489980731531 + 5044656574615736195246481865299114510211631762807229391764826087155637720268154669986339615396192306621947657967460512382581862 + 3895441416167225879629472693046552479446299590678533650004819143386099678646479751244788463147638567925169013110241886917506841 + 2313203706796269432481996570645174678020808456857425673026366797683548661197668493887407113195800476443548512276825541513285096 + 8842881585797604763305986235159142379357301472286513544030211227645270193019240287343188528847284806872333232004379253392212209 + 2688409746134847438143178885250323822851284371547861492401669288415720100963691981973327453125586959600245064339903637953701615 + 2157845883601129857682095395770985605599007238545319703595004924079346833281510603116153010794429037127659368861617341676777914 + 4401447994414721274888256152671021736338924549726141907269816501834171190194745666679544881448528084111510223352357146390678748 + 1598441987414496519030297478102458680201205753852279934039229453001433839642149793337137629917651258040708764206181523433254292 + 8502235049697025555092849971402076674867464110183607528142090872909056796241616598564935589465706229822069262366265937628292137 + 0055816249709410284431305701461181450452686881595061600026629505373443676670339321519731346337868758756244867546936430600344835 + 2653221234894262976174352794968903515069018957828772393070009300269049849197795885320787480595346792949215526978359438371233230 + 2573198395480105527983836130766181207518943018866225650015829519188519988960108721260257064720088842555685468531102293009893766 + 7692694226464861550196190446675400547348832497307906496613188251375658889565533214610868096123194257835553142178169804139054021 + 7725637998171173785445603097719118044612631181543666841703322233562489202164880099839601175940461517268783567897496005081890093 + 1623476912740353658966890439792885600281612076194740147557413318421891935617196959684345685434629547787219047616918564873155095 + 7025393340892141498709286165315521796432685307146924561201314330411100254047950443336104515273461423562157427134079178986568513 + 3037051173501455568382307906695636378996155638857317043809314274578391987572790382804869815651855972786188467330565714827922500 + 4074893387854201023525918388726764794855730871461446351512218023803177488574497502040250654764531910469820302411970861290475346 + 4505685142400586418253034395353236203805450253479017801928704774791824048811941055335303586560686324885362705510247805420001343 + 3089154219080968310703760534064569831009505236913263817236675143668487294264949278958590434251398242365729091805726174530517140 + 0036394729791915199963247134854987262729782792900430729405932713576759938708525288045097625035200406357341027793528833641758308 + 6352067888617175431411674423431768301646476262241768575619045274936408735985350498083851711439785845206739316196883719103192098 + 4796246905383107193048562525408958439687461541231738438567101188983088993969984494129981508412118318349184613817013959589269737 + 6278309646817389075935268193490507135536415367887824086765490270943493340352420279233033265958209197334685770879485799469719026 + 6501644826983757753799478095020135205854302975462551896895597291920140799672078608383168757287535179491461326280401680688209269 + 6878526040144420355891683769364803589616260114471471935609824723068550467740012749917856656207461894693384857525476785223522600 + 9913533038664755944016342494625355616351591218888135528544319832829890186060691211822484503271002284261557646472978467535245524 + 6548210843247451049422320528853823425570998217119732063096360026534131251690098102596630502775298567714836475115745947762170767 + 8887884056401989307352068428168695321737823154308274924885994114161224059109503941221400198439058269599476104839310697936760947 + 1499621302434101869959148741723191678491689696644090274728115214408462354277075304721665902694379966811617179086736989510478453 + 4472180192689505631132593579798684787021607827033405644669077356547531106428251322335834054519860462918400592332567647993370324 + 9048351300356674084399149618697303904545693491523593398209411550081390607196236295352104843258693200555492607047645055200473684 + 3904033119579621911938196032662442953927339169769049079015529114126726770405396769752836907821633197786728940414757447592836029 + 5698177775039384194905994353296325732870874582783505440992449252246418852133705888017732270642203555475460239299507823556669568 + 4584762886535479770675275444567493237009137069030861149601485784515963297935895153471843170037858613325007001549210631837023209 + 2986230798529869904729567059889517914570160421964137879893497645563877292347055745496295096825111567999357916375574494934291205 + 7206470066816931559279891084092643447735267681920960477832257393262206090265312234429580381825327805715755696980240563671249333 + 4975196191021868367044398019078519059684387790904063324517862970957096304027938042892083911602143438683752393325035772333502998 + 1316065614559478287404397163400580119624302865064035828659428240183667221604845265166461282189820016614382937134407772850983969 + 6172722824726265969836224691170018753182037736393837492582066024393428721754417142086323296047227886511163988288746175386143366 + 3150098340574634288363424590978979671688129464997330011306067549875063142531548626552657667362582081599069751262734236839198246 + 7320831408674583797739325661435931815687746601771458516299735930183747747803369077854960129285952199586802721391111341133770000 + 9781649076575876416834626425635920411598588075542620127671675851163249442163030188821293485762987388143543674662920406406559708 + 5939935563329383384304248329695829758747483676028520127505271048590567171170009956748249750276404393523654234793402435394531559 + 0252668408043754647206021991183069125065854666835585971567158743285135342908676173306885768974453965943775589652707957703958897 + 6941205372351396701250517551254482102589310971175662401605631499693168133844709297036538928165453987035113124871313193061665449 + 9276802658913609967848115344605249848453532699908586062377147315012593156326148344297014110306443933718879254374138651819351013 + 9358073205389217401007942156414789371666731131537345827743121944929460937083473364444624266082970336996459723671391030112788573 + 1765411908158890001229050208942988203575712050271091972655376675898080722954958732806828573013490785204118792568609729781493352 + 2380302146221749454886974990613671789801805162408638634096879268990438108120689272991357553079627023448340790990962415597084280 + 4048096687228528057040549427950909321059124104059954691594133361792928522598487445722858314871353602305792037504518403367795101 + 8791402885580812697264727719699410880547796108771833960539902147827417638408675493518018213254819498104814348795878620396366601 + 0903924261354725492168290232167217374559865613331033632981304605379493456181688182582298294804821827770454840207003173905889439 + 2319227785834038175693137220680318778454701304164120192954225359327542167556566637258412033259709183354710843065358146305555525 + 8673917622829080548174920911891769587355766435165634787328419281721579009044997104872530471989859299305155593643127267879722422 + 6682290955279007939673997760490906289041187907827046608623932479656002087546101920096135789193088482019418559812270396482968185 + 2423495240985101912282160197226440146044901932777702865325863608790152621900419953459804469566930950992382020196553029673452779 + 3436610407681610128962456711300906610774647139359864663150800708313215865508716982334525964257676579485350065609743793059790523 + 8492723526317024179966715344536215615681812917282255110526575184184812878258269018344255337700911624857617809339928700208173945 + 3637336636381056356070802698487403636259922727330027710606038599582455818066875278487848716217844022297313070587219989978367370 + 0060775392327016214743079646392570709223503152196217613938079763344036433088567530057235155273916070612559581478927578508356337 + 2980025169096765222953776328674278356394573802596587538549701911336821174109269755308129020228887624742741743790423872778133411 + 4050821812671715448039700197323622949979651733365312936187264385591443824448095216098907529899820693216629857601750862463957125 + 3142033473651787251598564785166706147991399595143208797800693772522221250290172822723884818192653997830457442015732513857367482 + 2434227934816021841461320189923052035591521089170168079786149675686974463633607305584810474242944486308070058500812306124076610 + 7715099107942733927512136192299373968619398158672679676087995950860231222104112656659877314698556942502196127845551909712373108 + 4069114461731658732633727592893010579600135097271095735648535688306732518715682620335083055144068477571815102417990371455419096 + 4513648336048758526599148974167943082379478315281923441623546714332454634302169701041016212788185513022911448815223921787570792 + 3624469067047527512170727298754069896031789622645772484827952155406739967506695954077541651367850929296976343602998185574427928 + 7941267068022945446692718780586230511573764935339043083147537297266971720289420223564631007244922385010298582167405543731618295 + 6806852318072988521804655880278600099719660787055120319799397720389095148995402664025461591174050670273042539667806005860061500 + 7207008027571345636661751333090766740919387017591058445443344334627123396031143577924484316316865139392646603641126628696936857 + 3077564139261564206167503001531356981773542928052096642681673223984499732941393025220000573381152245673838328811500670802459159 + 0948542799001533682410297780373013799791748346265940949566539377367731087302452174028989049580452869089162990037685957268273937 + 0880681561126138584261480022891283215404751141789014380796409952816321543905013512146286826522138659411899727000462608467450535 + 5880091566261256557011783504868257620770129211977999169370084785384096209807922714348396458806443353193445034311369641072095970 + 0556656033549253864960039890721015883335372132680590369609602226419085993403091634173432095151442616233244407104672122152816903 + 0104165883408627525444104591380562545622183558159751831249938218150151310276941351661814981521482974647621742382874619909936820 + 7313501231477817301767451446702735705428503662442130539627888646852578831768325107739301527824363969429357121983438884878755269 + 4393819179422351389843662394835319603450398553466130430331252873486799616761474948216299677793061438633632338236018231007238273 + 7068094772817742176160590443426997804722265949259567119852638283512544860402755698118178658952516755701578554245375512654131546 + 1929058509678608173068953824208364147161581285515961193245483567752314654578018433833005722739540799467152027333949229966280869 + 6336730057716861143854645697201406300653307680945816167555425942108475384088151314617817926634797063108952284581676269870141278 + 6513049997339587705695549544072595339278305253913271901919825663866146612507671581432953692087570028664604274026412331620371074 + 8287494858287111672511595795429201499531492727612182441663719617940686643391436311349735908431637719847434127985592417043341276 + 3683439281027866311263196237695664936547654237370870765012602749829825808040000867227133823847412406422822451359747985192576292 + 8080745720999988790691750589159999510681935221965279452806039652949988754070864815196625235801191787296756531552141564212907151 + 7193959478339407643118308465039555507133342674876808586706138734909756613087265895500010160295176435656450676824231321652261709 + 0364925287385399527025737739685585498448664221812361858587254459582955070942164513804426958941634994463722930608065187062143205 + 1510248350334956246451724384468817066713416535078509857129529545180481755289335535116009464206553367625156566677354615817653859 + 7881465671702288772143540937915254400157725015862757578041600213873551218117006116952755764443062859739372284691117745149958234 + 9088672142145404730278835893039966187590126325943635642412358143475145374782213403246198035026788070070178049812453881844272867 + 0338668401687420146135473027030982411204915710337406365921420685513130184588295184291465724202435316806267038332889397443572598 + 0839432579664022013756612378573508309364105293988945101718659897497738253028464952712017100629220365209543091962896609529479679 + 3205960596777307708890129013560513946330763313564335478005273643120628824046289255031118424365183741647820073945909472936879735 + 4620269579622752421433383654982653678424583328146692271652411473449919421964392617935515652881545262048907644967697133592449864 + 4910971218311134291321139032124590602851436712963785978946343853100496072075735946195731359706831946181264874128557978861454843 + 1011713617018211148846555458691095625992954032111035185714620653734574566700313717404927859717431081627049246861417661324499234 + 5786110524543942705885896839017534087003537095772880970962648591315518710892525409209474091669813346069319857029093908507508520 + 8853954861830714292944628596393329384568570114810794672937003168548384708307820733820193722197605410037476744326684584534487320 + 8506177470614128104032179365484641505802789779285846461790237297261018747968281039195118146388862647365824837138881138267868859 + 0627387322960768524871037409484459085875896325439489116621528742302285368082254073124593119410595219290194886865353532781155425 + 6809698357496328576273024691628485594217747112697681983376999200098136183929376787562599199562809870612840417370015973807170130 + 4180345838072561608049345847198586105129570485513244519517878528919531649387592676465860801665435795014078048815567745274248672 + 3354246532695167434429089502120887783749962531689888071529106417054905309204892456124468634666345233412562908228212778433482865 + 8025350198646920310690370174859009390241456508358264258699021020277939851249666503547743318751810595431556900870080845029269395 + 5024287042925036023658377259430412863334903203075207016434236014370755084100466996153432751138550920390967655897565334875107985 + 5140055633415509862050689677756134057716739901647883241169162784527852235725792016297971735177502489661133426961482215258022336 + 8037402896490266221826083726250897311919802495381754225581047474087034884706618427848292889662240224463663278752931604522244404 + 7043755425948194930791058610151488175614282166409617670305934153837246327320668633959913213103337798602482509159766659520973014 + 8270324793209592396753604357772106280615543278837901728489074421806486555551552367821526140160754356205673704266414947144922428 + 1799358966488711764366695558613904123247231097498677269788824167860157320461004934898696811210735916673092405907643647942161633 + 2879051334510139198581358891368404052755328890835533066541217913121822938905792625249238474950146832344471977043224365781135389 + 4792241156268785166424579695585412116561708898561202729978503519790831983242726846466172154727854320602695467825448826562117055 + 6892572380716177090374320438112277052543379149328749706362112028296715205065873069869487739216648881329625482801871208985853567 + 6373214964682547847971295488976163394711102004330268920420740567984995588029489900437674583804505907280376076761512694288533949 + 5155665472119733684583254908202345934203146938766729952819115305923223221786312083916415057710647121628060022705929366547804604 + 4979219068691159117673733260174579718275355270622127824048810725346461586407079827993239800649367405496829848031012026874839047 + 5453326819721439241285068650662264327283806902040744362117833297041970217611203752467289267570303110513926750426867300123044678 + 0552826491452886926336136137608744868267813981244854176639767832954709406334434073383918878421433694185303125198608436174948723 + 8232804838617139276458679276053642834353480357742672915996943482707728711707722990226821986645110256211853787080947091570985448 + 4530019597199416503606666321373773776661468897805635174486648284631882284913728030703703554479870389738113486662451982640555230 + 7993338222145807140991352100542338400006637591961344296816299971822252698512532704506078851263452743784059409504687946969377470 + 7050536882923788373466054136459774772814292349043369279413441771827357318562815124739087054575308713882488227553010491099772197 + 6089909596225409017825449105685851204483516303044569069782656841637982677940745207225513250507661349031619934115869792030545534 + 5623878938475449105483656355950820776480123283684344289877071474158657289092937164564108821983834915760732145489786160801928029 + 4816804046415869731980026155380698391293302660706933603124933543082802974288753245590234004708950597141938648083597306991959548 + 6285742091945356496670113754904503990748375484181907762641311090270050878330341468974330973619534202556739616012441626266016429 + 9943182264167678058972498083665971330560261159232616995578303066019814909746442924781284268163340228187122534568268386331093065 + 7152421562633124939028810156815250340969816324770306713467508016775028986746579511353296216202084745909078793312626258806625843 + 1270211232086431110376182218366306020098067244906289836262668331857252429211967620796216066094322098532350592071668917821894836 + 3845983140880841145716906938062904326623489852177531923802141898083667738472813358868563811996856141869924840103531518902763682 + 6718003149619307421590918630236184183948486678786725981990313301354204177947073223184765980604578217913950986068011309908008603 + 0928467335337181093723613708048071495790652643180583079182628211576154222901059273081503840088736880283912228917857747961420216 + 2166551801482676965109266503314605693500879290753119500152110927158165273225738493344045059814681043424105403563256277265130147 + 5602984870377735940956944951929383106107020907201382858387070933315397423879633043403789726957228735509198228676824257307906832 + 4033785332705686886894233935205324983504447579271074658738235607798108047836471901273736322254888901735575902110174004577938609 + 3402493343952267342344754443371491773245869528553143427384549726736187617570093360565939837511071410896535571400200988988962479 + 0467384270228802505542012448307525976842449031499613137353277852822620338697586513075361354863064717799164245330603052561106892 + 8842259346260183856170976867586760896719736933276441816021638614978497367736310097708762890208045248689587229972592272876387473 + 3259167318440772369838882122021007960375389506141034220872992638686407702750133638151910546511598120704345383522282582904780462 + 5442641858108090041720094339574637116216554948307838544047344475741751117118100567565238848037532377180455225898883679663375089 + 9577142779120614628627441392665993338561362305904130927688924256501300629907368310744468665785794738752761659537261334710214003 + 8036648554081009787955952496618722107214483438085877494384608581966978660817589075759692849806559360759821555215575625537328994 + 6018332837847583031691963477349319171451400074031373390713717042745436212897138228273237021196246257873177739985799453366628180 + 2105213797394649680881845019293842601907281739434203168302170068885354441461289080251599722778415734193180238772976142195797481 + 8846734820754645249343903444980443492288225807913782286509632765370978666435328327850741457922220028478728899676269184885886857 + 6241211337754447826883159708571545245319208827655835686933251362672810423079630739434073408653288828495537708526658804579257936 + 6272761641480084516721023070052621557056643754854336674557368573875689625068313256900499409409105292963555938180247719262631692 + 3370472297661265053196085477234369632895929368519546792630928565306505801718550038387422423219452220411081683199640562587649457 + 3951837878713231474233482132735598466639480024677257398672432796607337555329635538613813318615303256000562507502749357845826125 + 4701181391450803850270234592090970559917694412710413114961034587689766035663731463069166460549538653431143701866309605231883521 + 5130066101866721176356898240445132440597653755333619647577387320361484004480200635865792415170670027337193740214918631143418262 + 0808586953125247209833845490228639118624854066699258124848785165048528440583631961380212929557758370252911013779599196305478822 + 5521493745858166529682225371969453760228060851280399420192708176554476472315839318021751905690807649055065100259488774569707365 + 6158697507308922777896716663452883986126333631244914987739404979553039259206951208801722656773710392910263349735278566679339104 + 5235852402635719195587338866742022182421541295397761869128302452896058848115769056351269147058952464962337808384290518791915445 + 1541410356265877277120453080537595028913680044162125110791583969590059857305994592466475393255534238742387386696685456308459612 + 0685998205305456113478494375669069867507303172663122574416432766684294168665147860680796606372059541989820238442687325132846277 + 1106867923762001975234815885590982053876420748926951108789589029118783643675464846081587064829483161231369554788911064379449191 + 5812396650186976221479400172298188629572727898176974211003232401377793666992976058114854815038333629709686365618467427463150786 + 1384329026943982531591592399085803625354634016228493888015194258739954993856952956641410330220082208258103940975869674221124275 + 0959625394390538490258630101489160874897384983747423071388118372125410613424612801559234232776779480366009970965890340120701045 + 2667599636961907870724269931710369308622554291093494631427897956168577372077593727180133140549717498300507170013965255252092132 + 1737339475235603869117715688789198413446311276950893765017909814539886259628403094769733766342691082854440546058895772248646612 + 9197218961185262852748275379196855788331061390003979168135259363646749693751540875250641291188297420332987544882702271806564544 + 5155345846357272505381130365306178806560153732924148036950818502559878423925856638459435711194956693467002588044226649914787035 + 0339515088331009475687588955523954567747189933073011102332237830656095392839856108022616789694653613303860633782147528467869258 + 0130375935586298049775383191407798098669127243484570035128574481514435908283974501169023065679639597582504503336586846159045241 + 7077631278309415202815413204154287337150040264985085284229097360757947744868068694211304208527582045828778373828218901884299318 + 9750268301116713110151838109753966293343621088077855224277949045570521139532153236249008822916991091102238861514323117478408697 + 7155195645472829181908341253643812659814915997068241585467987778740169901860636348467280424257966646686476472265113081410661304 + 3489215851493494198992712587668351276298911212514851702684901497030382245009336388185220072052801963314343348536393431861793824 + 7433750102437336219240711853055477575713689475760799540383502439038522399381791672647025184537779822386053913810580122038174879 + 3818754166719135070632269620576055650986227950584996452818776818068696309115722467830916362575260788613336625118633863774586835 + 2178221238069038687341161131798367556148830622561463128345189400786005116148867892392990638096974925106944221425159061603022670 + 5524790379877915422325982255364820388029995625235481186060304010456803568052174332647747736403777805245458180638361448671813038 + 2561932270943099179760490101865479784716200934807733561691561384108933097340199742932516818080682737612322848740218966854945307 + 9080116601255117121383041648878380955264484146894062161454022932953200141179550531168588724355886537447858132714146647197563370 + 5582470235237288151308759910566681678927176948236130886004032182125845977161600117740547183580925791449145036400529238606663420 + 7837033717084727015977259234033008100455368360038870286352550514822219714510463917848677542164460976523276256801252857727025894 + 7130094419267655355009949375142847444276972876916939298289507233195397404513990497114810662137361054915518609388753530456478940 + 5388394232615483120266638817714522427995662494049561316381620397442848359037023023824190702655956805505137789130807808295750670 + 7728487145979981298300914926600023112696314252375455071809186812868701327870915067718357028716612327551252066278398582389353164 + 7289773656445897637637801900198614044295973498998341687324987147175709042706190580765940871231724558042584698396691392833921161 + 8657047381454227627618374146397069336202044856822409754902332810974380485722671719214725867693990943072348305834409116868276317 + 2768386266640115552548464265203598491327266098674766891714414339959283543826573869249667218521183972556730897770799418342118136 + 8189160219232646049490114563802577964294955901129433201250836705921020927053769046687178122894793267915461627258608458791264898 + 0219476902780453916709467789696795567878369111867867605857135264741583700268708214119151342234570678050700247598575853332533925 + 1642635008587172832360657829315478456525706956941480551250122576528755981779071461911390584857611720174162647873804473942063599 + 4967685799379026281672422049403080588839491839093762962697369896023527084701530700159221622072624944257435732610627292851813751 + 2044450251147619884660437582513822729870849508689036347657931033634388064328200140554626737296767003665386040440053850111272335 + 9965191238699562685527207327106427173242624391995490667681457409129351701642801367806048618652102824703936861574242876103982267 + 8167136500949575593721265813173669081199030452059803613088300447991271804667292549385675921231605005292459008477827396828396980 + 6509840801282604124983554742769070687886591529251914833953844029743868619125159895774188014042708540332420119945175514865123729 + 3692321786307153306613998657737637076488435978265420180472674598878806315670458550057067811482012301407908299677656750462270208 + 3553454561634700149917505664871758279230385607072819176680565522193204640320948453398810380708601224770333475704117532694153974 + 9739801831118688634434296635463933483606562392700839399728340475392493400599816097076262424865867680957927823749646379318466788 + 8207485786494651396331129651303688013258032982874538569357681541288542572016965208057337584986821728683984473782485195031290559 + 8109594698571552972881573904540885927360173123269475341745160895931951290769944326526035760450300948152494775976334153020903866 + 1739268973385061826289687149889229189956753685868472054090051279828873221786295847959246538258862203254463138510475016160891729 + 6472588945675080220223551738194925153786626106262423384260557370130433634861152559973124770729011313810073811203315002214957767 + 6317904094534761856637133735479679945651270156668746266850573869850630241143818143990553888552953747865302101114447970138765661 + 6050111904910844217007312990287283030132792651432799525258590083326102644255354794948740529248987597130140253327270495396985608 + 7218279207220544832644649289313013019030346375149234023654949206605352146548635130815666273562950986058561700625454917451118233 + 4591089295985815819108775507988478501559092837715809067331448086286924500664248339776158516774620654659269297333948779421651033 + 0402389695369287676425439165311946884646996933164719659142031175373351707836712648952147263228223229642458870791042562919539663 + 1663280408606348818705021370639699925355411336760403455952690546859354756234316710656534265824067538349235703012760994218438928 + 7331947252166763395452202287514396143003916184577374680861816449247026988630652041781591100537950521820855164931956884346869156 + 0167992341341885278124354492799177573677966259864026035120911925009272011711402759093945175436356249669782240856162554344304896 + 4307297970448548637044676901410933338328417297377294558704310254387943692431491233869228400552419559003867252598836554809147959 + 0400912691036342469718967629054695345164844205186330491298158594966799688436822836744333087245877645780438275466738783338029984 + 1522719795609161172147875781283157496792619720043728981895906145341666050986634594495047649741152246939806507306609930123284981 + 2105358148148398274033567712304765375367909977448660123752729616799410712586037852322616433905738649313626209308187391551045434 + 8184050603718152729487919051152176341217780682835043432591401578282222377677030156609712538101741280977544353648960619498088312 + 9780539921497865045552480951265192490326869876857256607893887668594821322177012473373977135212994227092237257692716960309499930 + 8387530951877561556746885813088050059098237284649866946622347108029066952894002584214015925808803683837814966224683534722188788 + 0980315065961365338422640630321175434205379462185984915822930473041804521924781482514510231643402826027992447752984590090815631 + 8885215984427616592965846360943654237762984211426187791836287528989189066470173789608783423601639354776027707428728361921725733 + 1713545761488733797112097100438352878478186093850974631628293903780866218943733017611561596620119895299713346283509695880279900 + 7056694123692100328413045552536384469910897094450012862955826233283495356986105417266885152765210669772149818027501922143072697 + 5044288331991180937483810266252299436099022518584143328384527105505463981298174129945339074070183868941494344473296478243433481 + 4945558387028214187495664309036767910507538072289226775563326183770144119596728765797237537898375774364456608274929793323186859 + 2322622760682958787774419794236441627708513520567224931868094563846705540632720743482044172976408519449985880794628778392723979 + 7704734167762682724779119792543440260650654515136102295412021984201525761889238911775278953009856036983484297176809989345351898 + 7538438504892134535588424111693601136717057553968849287415515571796218046474942306436018172239215803280193264125771352664266396 + 7105221455394922182238669063185805229847494225913363125711170315190206996126469146603174629254473614090501455991736786538113046 + 8157168667432314271904818365481089200297683424381896431649087725330131885687876217074390326660020019876852812089717929283102567 + 5370154297245853419804188360942032243192631168128880436140877705786486797146832449934263947276552080089455965696884234934971523 + 8611893045023888017310198960086212752413461499017699656702018998940525757023063840379418108573223175879013713671744193748767015 + 1169024393509843272061563781622978325016779395605303924999369153283788827391502842037817134058668089767959752756676201396896441 + 7712715405049463369575317556974267677998279848759269048895603544096481338768211601218741510541248300317436674252540127015114391 + 4834430831243295519098671812863396000922057166207709070811235493720931115916983299692520931163380069504267039634742271991229413 + 9287385557045725218161176454965763264083042136444478713449129334549410452033352200798030615759042237027156709457224173930955024 + 9440754327156472541302944326043902553561785824204549770748860453197398189036670911169331773914895138408417009555757899645501252 + 5832453847611197719596117303718224745254716796559500451686231076822545459079358621425609803998655831572289152307921157534370594 + 6716617297863540993457906819123068181321563782640587142663699479729095230755403564453694626863314955875318305864016967285927449 + 6751752585208130882471772146338918033811645841373896388668212294917320582400645793013617832138799866544853495551795042553770974 + 7292062075462511235154219336433250111030971448383048960076039173673865773457243289124490997622252180509835724029497464904686356 + 1703189532838988444479300672213603786659157307392869303094005510273480520540799882625565441527626460538592793551679614793917597 + 5131469474921792991086626550504407821816558283404370799177646663722782715758886649389166252871185413421418269585717891891693033 + 7009640276492618793739187876608008054508113875022453329081433650929497189681068056166559133270910556458288747450052550799593778 + 3775026817449250262071158797005661647517869545017156045641434181332078515755353689003930497030264487465467676524742489128433074 + 9510101337115987091584562788637829217924129844325702143952753831115106454935897717213086048464400730491846668741988349250815009 + 0460642398157894924642248578767274436367563791950971068099635643161955689433389352445513881354534070645863359289997626236597102 + 7422701275758347504612869999447090197900987293675125648746188541872170309069628366658720207642452150511782301406643296921604925 + 5722148742542704368310731836532013521833785510008023772247459847917061172721772791747731176316362682231389997934194900072780568 + 6833294401022288062004523032063979096666714062815023108654665205678873446818506366372748896978903704125253114795333767006805633 + 0409503844899480726742485372066289542014116663615248040053134473634302073503009858583019797024883588714394669118201212140331049 + 0801167094699960082079962007695468661043658656967418331551197267388919434693010620339366679098731235659707521841235334772751876 + 6325143950028159251006278830542343903327924750282184108026273734472327418765244935721260982532015689685569244807990908472766627 + 7594072557268049752783928609937336033485545218183637235406635759394992632389014311377829965838907592318760198667367240484412343 + 5995370105199099659966025879437447340499996959986818273399469349454086733538293008250823125200112169460372394345464200255398128 + 0278006855752348475839798168839058164956107248521078548181749550904031782397298429598863198195066959241173235250539525076363890 + 2434406818995447305231609382502170967538696884871023912846712870860599713914006479152902091530717543673744437190057705732209450 + 2049303158709878586595288112356673888760379702189055053773161541139894881284696826212357934526729889089168985110486922861784281 + 1480496657855804936389615128385812000095228481966854328817796490269872553734151219601055960998715934877799282526137718284428232 + 8638224569717329657108787802886111345753795000064618991042853502960039658407299390014418474102137277340588865538873397922966731 + 2915504391345921079597753766165614369426311302871553494239227907927104755401277811135239511652090480469130728548314080193845714 + 4662543498990058418814498281187250236958894998429926084397929019382124044722273292092351973221932689481754974738766719140738353 + 4190409245555651289372817877351684664080842342410487693494611165285252514427042631380484145603968868053004939443493512729765220 + 0119636369629430093021488300230179969441757666478935315483114992540843688913867607317956666306088259979412209337113112892142162 + 0522344915049743379719646407210766405374162220565183535557053495876729008927029380341012939110046953015244548503515867668213581 + 5545277258914067549098676802369675716209629211229823278440028400844384130766676038181293025311537464968008032689589725571813893 + 7241917831784954432887951874113610869422570389407469506150472467208362227227524708480496950010505902724279188045395824562149045 + 4536217193131427845613009167815485956442321803951137596941709381463070724725318338865720453796245623311051568325407640234609643 + 4950000863730017668562367944404823933355943718044346155630933481082791520987136962663882167172001786426520967022022083855046918 + 9948462347102121864710644896101448735320408682918327475914042821856145185407258575043429392954988610306816855047216892742882375 + 7607463192368539597117886391111127498537601742711656094819081284338644518509840706151881140781291037342960935079170415736099697 + 8170547034180787962131392617751093115453333934584190242119875787080041916215989194964046994229463391170868877473670939015394600 + 4967067863801616048208692428984726982425267929231942089387972467090049190181520316912402532109719978404281158192349591335918000 + 0182827511598856652325488782019351042712700704721955971553105284410000877214479216605042256842199795133210940783113951447780445 + 2845448586343352856456977029480170139895515001400772533947791028664521178270989590999530566461508232129548565121491303912378773 + 3186958087525040737796735368369363073980409705399259078085185801788329795473492605756831924612159181775569516279264645527914405 + 3736227582287369825938099577236266512057139246043733096797986415476742434871074557767615701953628932757311718425644125724233706 + 7173052386737821682078985950554267597062731307233678638341260916391599502956775154905191238402444341035490900454688563799626952 + 5147641961470238255748645042116320141678230506441721302812017771332190399762353180889095100320685446894708468194573746305094928 + 3469096230652662675602711465325424276546888133056279141284661309882996606616677713056958440903862720614419241163546636652676601 + 4000176045790898594283018168562878609386243501149259496688481941480198035420169390431588952838073985685288362095448469635565752 + 9472291341301030094187025146867336563674988987757598438413852630025766068250538948297399599973328446303590662904124689712678759 + 5558918453683884045568116648619640982031099812596210893142179251292478971547413993326289821580230193948481450670535256195029562 + 4928975689440726890177460501590676962108712941853309133182477027909307432937071388936253714931106477057738446899643424898539007 + 8940244387920877438974129853648880036120882337129881652544245505645048735775452951748876363983239868801033134946650378020657016 + 3701058033103724656733182793045707161803086804756890720227008032425755334349001190669627279911430274518624636020186433616060892 + 5795048614649402340472644254299779685615196268626556186825992241948964494636129874107575230767378691185971658847979564205979820 + 1236133846548113964258787812605512858795064801453710507748252434757524711761598464790831987938492943750974650361247007836117825 + 8985069765244610015917016588371467517920803422724008738355002305222843175513547415525425623310272808519127269635589538855868669 + 4866637881580384758530553032050127301271010383021829168699459836736308865544704254424297016793922754172114529453114659796809124 + 3421197137282279783180092595776656118340512425979400729754872785822827951114365899638513626864234673281733350488813180030409671 + 6116540261589173059806435182727298140303534088364505375974117730218290182662177594123794279119735348291936701406861588485281875 + 0383388028538445842643371054045990749985217056001543711456417105050188186522673179186319252532355654228417953034579705914850138 + 3589398737652268493665223622209314271095213796466114005222254738357264490629049957974234088293478306962011737255628545244120278 + 9242006644961491221804556688452952473719954034253935879343918188942010496090705258446852742963029458182305909452754390287793730 + 8783068031607497439341603800503578168008017096526972920750091440007773022446775696934539156855822636256531074692478856955931965 + 8800823547223548709312492609422799167744315137636030763502283934241170303284109496261288800964950861563894408561284405190045969 + 0236871653896771373931349637525093015261721424149322538581449425146949187109336492808412768678305259961228548229258526615055933 + 6808296006076261647807027264924130647898638203490518417736498838185026931804266322409312178542687977048973852811639981510309567 + 6711783212313531503601350937924384067635440627869411288664439772524317458074685185346606914709019186196743715338064452022403271 + 1329461726620692353133812940387503225279782302791789101276394351197294472993751698133198738485236134603208512597461992464092534 + 7712409812790062450698418919781788475967301395142101015147156004348821394973951402124816517835984222889123201533407163528809483 + 8878866193884252627688867520926767781102452754391877549372235240772045942305940402248699505448319900090404392151869967674502128 + 2483008370299951549301955588790277512316664972307031593695383033586616221934522732614016251454351893271188672805879216575868904 + 8930668992950485150931537517355790279447532793020359504907584544928499659083716918240980733762266979363328381222043500384239731 + 5449783313063957701679502215046202754515996947849788011011244404372242125949053935941173427778943061308870747330558976279745268 + 0087442866677315281344307628368254568290685263159851300491709072441620656219856549470063530059686910247545618397733080267966459 + 4275923776467144475919672663054261638444876359385278313589184049205522647886045588220547740175271213225571694335593813888699266 + 5631076970562565479284442184748121529273149320713280238168313146627141356684124916604998541431548094125068927278902251637629771 + 4049873854233479495273404123122985718709224211298472591495302249456292201698069758048348513785824572699432884088465158829077277 + 6601450724720706904135791943277181797939378581152182984849501639363583354753791712537234399122836156611327530479415218232099189 + 5823047280117680731777259023254262177630139266484401163220777646941723211983561493087099972956890435877152661438838138706007958 + 3871525096685339470645850417153350859644241363604522957863652066029739101996436761253594694922069548250943637910124220796682359 + 3789021225120290908842849945791566951268040039302726617891236371450848884685584694857899475642048623621033883942963333740640913 + 3413392907322042998743788130668642581010260731658079311951196515199970920919298587850590756579979416052745401954692899254629962 + 1834576186290812892686277778078188491493029363265052305832102758282145333131211542287672262899869561233857209736661910966320185 + 8640618069436548861856298762841794920426604496493168277782652390652529026370866518863711574378563335650089395301480857411365309 + 1062855694706861343683613721473054277513151272875708166067829305351279095564881057460121748427296483260938003342506900294399166 + 6708351271129793412643921214770696882147428525507519544681246954889801321262715754608536636546303081680171501901796848282715773 + 8170065360748835664225539865399039511547738151434626699419911223518847738407528346693417347838281049824633463358386526323379557 + 9773283803239608948889044323843524447778250704201869489766199362127854167469574262448141201863158740882252497005327174568985690 + 9629170341829493159540502281159419978757497174339132063688621315745991750554750919122418499757801567167615195540686775308036772 + 6813737486648360157997154949184994770910737848857708594705159108226498818076724620595499835896899658135344576077658527954169440 + 4916163367448740109143119472115171909713176429892100499193749017654102572161123098799425438195950481418848253249246794538567213 + 1943648585194380435794184207380836831419456414164714608475465257187830071751668999365832434059345210749956754565801799757863175 + 3687162724713568040156043932976576841434569787909011626375244300886516755159434297033774573216110685196819615175124148320455479 + 3344419757198679638351706919063941845054040199124828713172593196435249592482470220242606177271518431150127043364815791934444495 + 1400008065520008098162065199768125759577818782918099045365313282741980846275621548204708560469294053250492025107214712766610441 + 4165080021198705915210786508550601653226551217888163799551833017968067846988341804528031533804959471453060256667445828562593413 + 0316539921143167379344751397929218943090424282667061717675506492829683232765044382831375540458280475310930354270466628024378573 + 4617204749069035253813713597661824629929473681227979210717594546338035842018470292109616982725985026372103084242143325201934501 + 7628437040946835252535863570081482725836702391432238382009021257963849956941583278276159017021059243802411805222128391491555532 + 7118276592277047948538579672067937116293934455417400255981648387252807293008272125197089405857447395662820745517911550198420495 + 4817641036360381588057889324736649206689772293316553388319983835732003282890192751493367420760022776216834345866178180918425947 + 4046762929816361002114402224273088310438847474234192226897299571581711857975564268312621600137920668387355607049886008638057179 + 9349209580226030857313156556379575691164723527464611358492523658913876021766102463374095835678962118324213355237312840525047153 + 4458386832215216090846608267034928117933000209670619365236847239547649406543272314067052926849866069213065858041288568227157782 + 0323889725674406704675299432615839196837602006707700866051572397447613281818928460518366859474985370527579091269025122957262918 + 8693066533952054034279975214015256982660363796184125831239795876267900616583623647519579472331003311428117914837252346650454796 + 6978896914173575690746678387000060698232734806725458177123404206650082946025871125219582890983005045333389163168584620102734094 + 0208343185195645077429621338459120990032615146936965171481121547620265509203707449471143882951101626839387108073423291107985197 + 3806694565547588080124701297594558579857621291153844744163973871845300036486064506978169189349641947450555475680771354116721127 + 7571370673293744335868791633492268450482890329783462471218711903016708619390949407758233183647172103050542587791975330523548939 + 6895867004702083992837053115350359081392183348123057432804437516085126480426796559419343457573809103554769814374422319272987621 + 0493741336702343083547043049060106406621621423866156744878463280624931631638757753907480473151395705318815364246326098575320029 + 6546610394497897246218305493409122075422636049647756434404729742804710870898441487104017723846320578576625101570540009682146545 + 1011863982645118776769923031005075048502898177517353081584252680645039932448249490068383719149012492191034530578466311073324350 + 0940022141946663679361628444591959010381878575634668757912852707910261260983582304441366347012174417975464831931140858093450475 + 0648068206853955526969735294213923796512233785864528730934169006767896899020079186828212231303729771906306615698951701782896040 + 7705404267837637281673906483600597132329707232579985805240515664780686649377686946124141035632716982723408330472426681691722063 + 5719449931034079305356439666263973565128713593058013796099786122163872295053911196817120195135137786906005302955333296169099953 + 1565007759742421563846584208111412785562612780177121771600395311757381072903942514964351796547320888609281738762831301074727155 + 4840914538717807330571774867536594427640229999158918266573255879619306849868398528582717693006558964074770743956975947230605506 + 8434170706163547151705112191666162854461320116071520338539133193324696905732424568076770881016026396766250345270611437134977029 + 7078829392513262023910437193357139649522860536333445198136202621793588265321546711781743395796073320028953300954811115494631443 + 0358109781392845465184944557313417160881340633391419971812545527651450314512749202620144080637491419201752326439158460989691315 + 6502021443239860929638929077452949976769441697009577432157105021271893283919677666379901876413440307841861569738215346309784385 + 3775582600443257869423701993595504734055924868316007937741523410145241997102735147790121190918364977637486443176097526249923371 + 4637116062887697972788560169232687166734847960365006931173635513798426534363094553967229788862861423059133919581108100325100963 + 7530945856385218994386045042760138610248296085030904585153248074916348965900743636913197206787899808540051760130445456596005975 + 0082651589864980975976353455996961471089119847766125021188045871260940417581575204228376995886410553255809049908515562710519369 + 1760176651046607404619158827695196639809040360410321347276093208667279377323033464221881041272072298115933348047136279306992189 + 4449900653089574942697877619922022124081013931968320543380925350254859461377805018823478776678186127822712476112142520129506611 + 5360537273314488942383696459647239094488670283840872805432523968819547360255856276619301822761467290415157270983258323381158842 + 4069470180647648022724489031315390330623675246416531426538288357194889582860078070141817901349890459635960185352818352346101741 + 7844251807909360860529020528005655952345376045413861757127236316061244993838373872852044455049706576181912407467785016013363013 + 9052782242469623627138305243693885375972159761715793565717369599576257075617300500868041008633881912456191819467065232604757474 + 6257367548773919654525538912712606831341580701967173140576682703453195979358288347264315572356542410824096892368844905848969800 + 0225531033632269859821449136659749178099595609866207288912288428688139123199517309089785003185562015618879502978274246919977195 + 3412420395378666741269488926730591786905587902546167052955793049551854045851796515140844301739953615780488764468845360750173095 + 5314569125098157310473890637519564038989130593324658307078574903372187794019987998391252363359372204089006276213106238012887639 + 6663953749875926737127213800088216077686383881272422931892106536521390323291590624983492836817664288184016273391511477345251544 + 8638673096407867791116469531963581105938614830552680798696429006418115851082700139624263097469936097502648484256024821946642846 + 3261638416472717635495620507090713763983290274773473746283045337514051847664087913092670813304318998742601034170158553214610079 + 8880759198069479182867513797991706527425937623927208476182273090404608783390855357409578977746370113730628533384722500327769010 + 7964841863629197861004282115308229708980836184692237168958174288698996726561927516939282475998327300490824455643829853959878546 + 4078550144875137620442196894251820235783690433882002285566789090860837373159507997956136455505729693351610325429624900264497493 + 6050282912476085926950954499140111563620447106769829012752567207785593165136710295523078591701424407957863045561973215300362256 + 7166661176552788865443610475451627720514979209097163741564119254519710530732032781304320231265321064373366029789454524964576034 + 5731838949398822830420671258681703806386818639376155723888774861742977966282701086517327314375297715355669245126118723701881276 + 1224558805186365369295742263213010659311742471260411491616914473284160243356280450620150570408750609913288411042993040473195864 + 3965363040687291139829734658431286318462224708522925124414942719604612215357576250193871596416258769483377169469309016314582237 + 6893425774786606424591335564336597467021697313261577560777519605605111465025332099784940659090512446671447989183060023172745349 + 4463023117754025492704298169088346276715292811942385607520313996627188228077675005968319409041724080200894220147117291796736469 + 2838367610734769148543248796176416656292040941138404572575878998139182976355595776291061040689581132913463002164503763638521768 + 3585007037968899533646050958305472231296473689572926896126127396786068936357337467731293075452760614111507010520769025993887156 + 3025256134722351463444782906552873128386686368275305328178049328442606382059696387241124580313700815579068965097895955058791706 + 4888785355196252887855666442682481926655016587897905441501499624695729356509071382797002137717002280304447105900656692938689937 + 7373767636755443505506466024295128010399690845976961083809222125377563226037530095320414396885247587842781981216438439176626761 + 1467040097296217610154727986310524824930119662672041177376733844872215017687323322767179584613934704188382812120901100084067248 + 0055261010703792927114582278798343530536332871891286962151403775103518820096790537756954678439988840466572934380472009105374277 + 8745186553258777370952969850546252235196298235316976663904366268611878480055244838332857644576178557847556193922108941720480963 + 7310291886872239579954842039199219595404202222951474277713284211951970030467647252785199038918806323250107496561396165925992981 + 0269739665100112200470147709926216131752562563116766321854129961314938822821859829783043904077776487245854331065090150597583869 + 6022034598022521394602277250974332652859372516801989113143038045232940829875622476147452690929605127893923207935810728978176813 + 8336719184987758081413476270877983896287998313373933528191759149653154025750363065606417948489184358633308380877845477894994394 + 2211461131853873156810302948765499385999974459433061226146423964769287619911252503115962272972255899290410107199334224556606196 + 1402532784763926313823670409002705225482185592078872442217786835593632982577282903273472588503956076522785281354947952227775013 + 4429564170373891691353053299293858952840011672714332817264920331107567378250030393312486800497701640449816183190591793478209061 + 6696515680454660415306312055092012435204898424655900246268144415272389485588150485707845045690614308427142660270754614963190500 + 2858971388307084324374434247865554208042477256400063151868591675576690659860039137955754547923321131572573666015058716528677560 + 8082431519645786853787074095747644469767343409908775777981556502295146873300678603062293673505033125364497124824045616025095406 + 7796338540952910648733467788030865929612271961440794230689497348772551503718356824778119200166125356293580937006896521596909494 + 6623286777262305838866280436574493459341503722464731387299068764367690003490556552997864648359791608273875942027789979081747901 + 2820762823681177751588883983434913077317012385982082727245344446265775140411273692313089468167013918322825570599659499017461253 + 8261747834117161824733335000918969440857899686470868022119901936951959497914248555296472517607486195543086996762943719289544222 + 9801799673583374329577712601117604429044210658931033348348701101269055569381455391166077387776701104476767458640618577366620088 + 4812671524372167827325442166901095131227009588677251478248615586184246419258110774327904940522040756539440861199193515869861850 + 8664636186261176234317788607818904273283245654628256017166703040583397980518196864696741148650137946657712844496351414683354360 + 9233785042626900594870398424394786589093845861107111076865742457098507103631392813148996022790966610376381301013746723765671101 + 5599585345939628248728616861490756773613146232759270658252490655694524473642364799716984131253156192355158951050342077829511934 + 1018115413367504225955575347257464735373797464835594482025360169817251469418319729479090655145106287600720398462808509722342523 + 6277929810316831402715379663360019513470321307271888286707156176722601290897267704973159272389968049881611196311224142002818283 + 3935507653397356468132051961271044279593473480413318195705016813924079917284710536189206698836513833423232062305170527285530270 + 5930541214728728710514258849354991541204981028873011695299038161284051747700208580498162480391834623057628739847088944321070540 + 2131178112490366896971016249779880442716420462976316622931349965957507940779710818286842266030393060843328131735676772739856028 + 5339433698747921036431228649318038784378241814872129036313002907877189828316605458939009159662654429547906907634851960924867766 + 2725144295031618884966653121214453016640389429569724950019640175004023672074204183536974715285043574870846234625695507751624691 + 1101023040899658835128880208200979236233784480432079242348382094125974376887755928733596001730428491870299057160651502141598807 + 7529805201863368482438225714843876867695794742159176187308623091428831090441762886002331398279108448588579520003248961018841987 + 8520639531359520492110038481387012497220545183327686786319255787574425654228049283708164761318908288816634942299623177967850311 + 6808287068903794688768313922352685578188040716704660250946776133077382541811421559714303292759615754217647905753791800896114429 + 5661937959933192849164004778980526700005624355990312125795014118394734147334017327033918908976463421944496702296931260093163478 + 6866390898079223822127023182717821447021210719486206672090868302561371850042810557962915762631762160188811564644765871940463260 + 1983784957124576912722518060888269293020694751991232003856484645400501387457614453894654158242083061986108255912461168024044362 + 5023757063288290577909452112558045920010016969071712896564748738667312129264760935144195712725562634643903560619975222875598092 + 0140266427651227095088902077296483470532188392053269670883135265668245606745264278532552540957167938303029227319042084398428852 + 7212818706985477890259174108784143029357600406814727037979412733984989889987109358055090912357026404921211609781959966663957665 + 3885309358663398776897062600124335478996053317484403001725157655044282776168453835403175508740651996708988152698983678588345737 + 3549561496006579864153172902480324325137781423364931522958523431287424861594425297230970169266435951937028485126756644018421959 + 2100522734881499893473520957404272588614489603694208305341205355969403603944823313607027770883562580199458807047182736184431355 + 3558566826776678787162145637003470985297896846344237649664211727912542844807936273529611661291547660198761650362176216275159276 + 1697273051970401823436818435327916444246809126780823246257873146180484087471375537086616586114897794676638646530157453530809297 + 1877141731822379123458355749374949833686834219493808460922026220049948042459289931477172440353720942293259692771867444391010663 + 0596114677690135744062023310258035439858771664427542203238516588128327906442218908975480077474481540939986337760369812161668739 + 7140350695399428116941903267710113882542083290951701275369344655927910523637037185426739245384522097331905044898640671070017500 + 7453482207139204385313210256702640687353020750058344407280878423180101848431141829884177527114462939147014281506261604724365378 + 5747051408867537658614820169384534962462911220360124367460201651929905485919878430356918185750947336103425001412723806012420037 + 7672418158298677361496394053891368709542765466425399242228084774006250993472472890952527381058062695609973430135097018848485375 + 2721910797057123953879416244095325096151158592383520642643416351496904866623597785985406941433201519864328401275343395705908857 + 0642983563496035432630122777955167888076028823131047975325063367604577001605053104073667764503079932854743114362110563627584697 + 1737450520589955785122525243234607141022634008326290553045379074437558301788691892914015378729774742647378096844792864200227145 + 8049477947243449894011256046326611511617306926576503154750985615770186729781372043096871431456514521234719945343529143211616132 + 4060930164560164022219102032312173710730634459253495956116881900466752536260684001258460015562183214690371015163609148581576715 + 4339672054138260157605312889148304084301210593319661500758836115820325521753635857005220500312010112221791048318710925629489360 + 9098118884517110952549620567550824645268745886275953112452963794466205654973301959016969502644339312155829940467386423970146851 + 2030422710629305679756784568188030405053813130034967510951876362126306529129246017456183221963883892572064857246348841309902207 + 4014325197777088687588337561652558142332091500654763031260105487352116429628561906919380099545877339112314250562226830515084041 + 3366554959465306038343578751837494403196208574534790117389855546409717054044483042532146409499847066640874035730246190276785027 + 7784874865116514506998867941821004659533959527747303526874272093224628939120659783314979799979608075209344316698881835617720838 + 6440603777916554902557821762272317634207749152011454338456295029524399535728380230269435936275288518444494136138485427687743672 + 3697767429372731488197371169546304182440802429138205900920907076873491237616407487249087243231746614255961699354564621444166710 + 1737116215657118949418096366707426664676852506304031637797388892083081543972250240515279155087924413491083737598642466601038186 + 5943501997584026886556269657780895221836455524956899348998644491412008841758015117023754182242908647650511196372757530427844200 + 7126098691386230123347928604422159107062602585844839531380975985325229120484080904014468470157441597070403077589128617082084491 + 0277414078111008949169676840880976444791578133697866086476338429943906280786246925904505101785927908752510981120731146336711732 + 5011921703942318242688882518650473013576715256957336272842712546671709676486379489552317943731327342059730625728957322661925103 + 0879272542563908841343149899911945430473689164183260890378649854294324088836226655479509126988786763035689227450447066454969580 + 3635797692910230406460094517526461454920959082159212413377990917407487877377494660930246389887432321322711771671714018210018244 + 5496909568572645176488382324921312621177838539677336553279411765862833091060541060811106495286938550448561214644311877956532326 + 1372848285800862888898722477263959718622329488994306400315469392140836614515990231729283982778367781183582185203884353672168533 + 6002585963544294141850925971586001726265376264686412361898087738304610666926697454083310088708743790359728974336913706461189057 + 9544994601782264143680659072037087516325897282651078850550946582804440990613134903404213391711941451230258293606634693846961977 + 4294296739368718314807261871407488388139897913896057193551518458028526780686105950168593279489650803151515173510050942218207014 + 4440222769538547178501749374936219442687195706297985586916321673062155148432380676822216859833618467359812508595764374585042802 + 7090291929148830504311787542972555491835675686001439326827409601590115100758667523079283454747571560861565934370463671494879471 + 6306207613636744929606340131323412825985507087453258431275338612289333774848983021189785244607159387364635876091430264215902551 + 6978625947059991073203270373760209952614062079324674488242868605448441131389947105750784088354616643566884781392969415722350013 + 6876895254868693830649346298281314621651851243964761424180528331393082774872122268180557991527876049313013835528942921722633863 + 7994555257251266617368145187318488777925218911343096210380569645729516845387191015748935661281511118325824054860678678241487526 + 0561712487759666786219959935849355827031795611802441457990195006279656115907452353501575006228849649556626967066612451740817401 + 3065700444272921097020103095032561392189274167240364636985217260309148382438375007728649942200430100798750588348282135626863041 + 6418290958339960432209597429802884987767056126860829761197583897408153172039938420304452769552704862796110442336483929988890230 + 8411149220304441269312528476234638082926201849344380193272700895522547783655344727512614476846755120115181365390739989354909216 + 0361827006206843386504436443633849307138803846456656207910374387223474485947474439419270873842802147250905121223284959187002960 + 4561901942869500550331725452244098638243866570298342595884556094097612128702524209824571526031229091793929079092201659156014426 + 2569784663225002575851412395224946857021846888745089626571792624047307039913201999491767773809090290291368272189546699726924662 + 6874345054057523806453164208085928558404937408086499251394158950058605789150302667994062909598865360566447853006716951800116507 + 1806892347177795837940597487685027448543886249836281858785204813002880073746279096873385938335081449362375954555853598273582800 + 7280197984136582079744511307894765629896405494228558457447110951049222331477610433641974978714281803792968381573777298819652746 + 1797088044067027854938520030542484156979879022746379761147066454374087806486473993175758842146367406488679492927645706548068169 + 7653106688789014002295870215309142445613718219291306854675259348422471093504331308963443794325054200760084750801107789128152322 + 9003923022817082834921721240788410357242843286036977355497738812382673303415071169601837346379966066053060156517838544048108090 + 8927903196351477482460887787174517966173931425526452434853205934174795153124436599267973662874006233354646357728472499860554504 + 3649137050137288600334652169002894564926317935052375328874723351133720379648102007752831671041946276927861278960706248758820299 + 7881676548153486303936365019720006418330263108526672450012829414081940012783530554845066547004930367871816825750941800388750747 + 5617499751970255706526710234532717339068075364068621300856559435412791685014748892438638038434662792832126729610856601828058978 + 3609505162338640897172019393757051075698357002384746777463891780931828353562474692966266497051217520058712600221078906316845512 + 4218942164849049619324701770389240864171286359070468568203895572380950389773235867347931266228357895243861158024586703415416725 + 3286877811857113758575603255834974713137243819997694752214133530728139390482439967896436662426005413536915227299430206070281748 + 2197090522718698504657769582076344098155286933671656794750871593655253531647336100969432683359373204499872727545324036411875127 + 9266329520011965890398156813860326403682885444460637962832683571266360623432333340007962893574859386016733773045469648300215724 + 9360218780816808197711206028145267393233058010562551036732947883280144516446467977991400621686114194941533328336858706301853920 + 7975466727102526807928730597288066888928449183473417942716701022737828267407136547666947638756923213101355014521544864295487342 + 5529807372773853881156331115996145600478892095295063408262502214227819442322854320893250029815358897498644974831455098851752144 + 5217677466571168103885153319146030362086428120742099054171064034691470505077333070394007756131235288630142015715989289401952345 + 3238751872112411965525172279795754140090657968922574492232135102357083597107656178253770512768121887161690539858563177051498031 + 0621143235328817027584926551312004300826256116914067938452329926333908173348351478521275486940271058902772821984682443421901374 + 8675029994765542582556780936437230200725353322681947577235834861538086815882331325782379515826004655685444830286018743065534290 + 9009226484124905023296329465126310425464799999137557622919308471018246198151834136297559364600044830857980861753679005100073906 + 4026810600660421971978121050945152770853655639964897333811108395111596792046176724058242259398267547036042717629901672105588823 + 1701174760060091817941457573061071686086097383906657079983926029247083644956175901708832562604741667581501354921250883246878076 + 9360121868675405580012858168094642670756925814930958722345840360155035939830719501362830202256115680429221284715437831407183230 + 7627384360887381611002122676157337577850291681707758128451482725333215128574377639863228270429176470896652784523071172226399208 + 5924717495388805188609979501739528551778957144375491268555383034743525334962407264117945701829683575948250702090310348063964292 + 7285038571762987494406954123411340680613165769286304746181220668099890216085869650378284432589286853709759806525223094629118994 + 9108371459503424585162428035918267612861106220506440110173672498423384456764491877643881942033565719022603374698498258614890281 + 2119544835856779238923121210216240209691871364625727861760840643200609817224777039142791222829730821468075117365482012776292615 + 0287625006985324113383256843550124431381565006783532108722669073077586017057966762263289920449445173729525567088605286164318499 + 3802234646726929017573814267132203009806257343348973659561216577528599490870752429375293883854127262090614163544620710283467000 + 7574267833171812189998339587827378487203820258567218738257171370030553714438406356225807045913475052445364294909346459733645424 + 7057209974818106332836072380332490777736818456915022774135091028181738711236811811377666386715288877847647340595585098875240481 + 9197215476954479756497624010576859326493604058234153493216522641384431342823687635555610194191608220091909666730522341780147856 + 1119537820044774998504706322100346395055393450296026673688711639572331613882591716507869222690391102545737433635859812821586270 + 2028121903848368987212538442391618102128444213522329584551212886903253244685970973210284229639689302832127513289597893485709871 + 1139101840913818162477340055623563542434178020287614160741421605723686784042526943742745792272929328869556547712709877327596063 + 9107408768006237961652791681788083610784715577214377191666576416371990600318918309907846332307177843177765073709224406749447169 + 6733725726008450978073741092474719053157935773438091672305982444490248804288080650618594239161482780330596854243463318510550141 + 4618707611170337857871421415147893285747404164961249246066409955331826510336908541776726066361511390478520619795261534651528646 + 0029871423726184455790317017373341560382122160829511677232857909382425970016570928985722750518023888742942482674353399294113016 + 5851677764630543407742209257890179166834894877003624901201481696534056706522332095998210032002750686323425734736641298781343895 + 9906317458124808949504199178481097664951999312281141056844360268819241235749855328929404804574246937697891911753442746410513511 + 0301178939436270473741478421267690206733306236983147974561800903978683929049444127508643906957999471564453966363638317098479091 + 5695590670680910148994003236516725327853434675592633044599651978504490768012904279502213144296250305384458215615813612885360699 + 1739488113025246606429350291878905105006718514335177675021282668693092738324431010591942084632165356255063331639570681777622822 + 0452464599884896996261376953519588463160916217402746423924422154683861260191652961898971705302933158251417160490178433853439776 + 4496351983750730650624656965901956261109512227868877661440793378743454026849129576683511149685514643006637302234104714172349199 + 0650873766138283576167959756442091757660353703079228843249388294567585567331488037468607523624545996431350612623181744202876623 + 9217884841612782253645748182653936757610046223059439143748083525756745987386187135434504743166765496977544377259895573270803669 + 5233343431863155649799928568730055354198316775389815272387174921789883067246402571006054994197016258947251698092729387460016002 + 6222471188835586754619063338314127078684770466144889169048987130424673328124774962008878054843463980934491177848530073946295466 + 6092983987521059016788973113331515120050882840886284842856803861355854867424082016223127983920367739842939341557083529339357539 + 9152847423135593002663232861455632334026991039822394086654099188131348343461957860123922177650787602787823148319677335222779269 + 0688837540315420699495154888659745629289164825587079409113672585691726485783954257060693018031835646491154074592682796993759642 + 1560331745546205131052821650865965767504353088368099838110467887791087910699782310016063819056506494246788726522788847044002972 + 9843063757395851013539217226262322774482770252168515327930783086524549572291277963238718919614771432829552926078930464389873382 + 5165503350814374626462147517304790280393184056104578516266158383058163824599464967401146483647756651293496532192439439145458877 + 3334882919381143165661074051363092147447735703148534066554968559573383084492917940343234309775642206678952812922080261015609561 + 4150090892422827778476783958648862075260361082863595155851728025658354185826522324370827070485157038772970922137249416500335139 + 2270729610239360993359408455484013545432335012129825782822705159183112780581412024925958595707332590452541348227573704213342055 + 8812698543571227460191878467610741003808872140196791243938096775905061169632652370417102797369863591037024610630210903737953654 + 4650850571724314687005845773201562588529522607481288290365062000530992710204626283641702861862037299641210309359904939817933700 + 1541143632255817063903213640253364698002930217355939377060114361273809860644552941254027110592936933650281526566113066201345129 + 4904443218069061051090074486584977672087200091073688866301081198367118241651115030647481869824608967401802054144740280994709964 + 6714819600988123781424031251846423957142678675252652218273564424036686308763026328451858255344930462603371376203101104448466961 + 9509079835837547622180222314290215064732353288206452347849664411672496172109171750484558066698591320017336090478613367662057930 + 4411722606999341112288605914814611482715323396030160357274723566603030739104369997016486251468461541345322418772128759607222696 + 2948183785699572384084816055776039138878581148811752092336317365102276231176457487558011884744609026187961229782054619496985034 + 6425095624545385534119498681567553265889108179726785664829530547971892685921754372850536788921833807429343926950424016846919855 + 3908326069100657803588698889883675042505627231337237747168653314558267673583632726264839565017058848634863075879312565153073799 + 0321367266050720934662774520376532661682212427124263069420126600109509081952403933716651001460064949865799766176759028464538738 + 9741038058065551330442704073919666652946527397570055939551345839830820648016177629571594906346803356773604688620184511211636838 + 5025402557710775296650014515224591309232698067998266520271098024189399721692010614452489061642157793190304607388980065831660161 + 3865371756663396962706440110406172511579502225888432146828231479035598172810500698253040173626514931478221885791112009689705108 + 2972286823839979161832311952971045738890113686974537517223372452946515286365656547601871718080007574659696313592727664057554794 + 3671238913457833340723922452738592109309375009714705044237276003225833183922594035143870946960395880735557105535062577056078657 + 5639824224660978396027300014663032753936090244783494976851962014859592152013834741021570506331633866559318037963618148063022083 + 9565507482964988994686034476299289689477300610763650942914931588839058915298408270882723496065586551944274748829842524532900569 + 2950174215698554483745941905548644387438215825109435969023495189379067472134512077000118600012988374494816155364721054534508820 + 9518525904194943790633186346738672276318778362232864095452323156494968062204689793145701834333799109246633884847638921045253621 + 6777489268860937675801194897856962853781999286279373198884776447439334574892992495036091872659389999472183722596570197112840487 + 6940178173947556103657708676822035069381549630078448878860057242455764188710473335746627500154960475546070307022636234086868814 + 9329686102999304427635999138246997518586345169303923543680994865014159368545564362656579126189568984209672180187596509411904289 + 8400290546843033015441275084455799605870040808860666105081155326036596425585507607789010815662662324838353003534213828215099749 + 6262731155067666934829202231823905666280056341904107277513506385716411353609764416145090669300953084810469016331307248958077392 + 0982572667217714967858091868055542854621721843072461742877828288780619596753823464439165581485796328231801786913442847252641526 + 4848655976411335420584575046674979122655105315200347515565901735274063028061587092460808297171218521824980966675211293241764354 + 2938658446761945214970070404972488238286005305727629688975307477962234711112158327154676636619409638849544823620779316735831746 + 9233723105727772276287999774922758635916582468201648663126732610340191585232715185516172590941978497752196971596838962424314214 + 0715690795433694724565717518703035300373548926507910938888351542625042732566820561320308097626791527666632661894798286702091403 + 4964320219506572216963601199129841376254539941692757336784083929771858734782219556315822673159169808692321828354292775097642159 + 0335559611733921504268377474272853207366325430567729920137620204884173222566965027114331948190426982554186105784631841860371363 + 8033508558384267940900957170710292773682470738089554833769290979485707252598489360936633550982291403202103393568639544279214517 + 9104033203529399347159766145704434677301867369574628242547881760927798205454869510642633732888078982477565192220841911379788216 + 7987660031763621257245807669247102344394837687835695594169011679441270384265326170270019240149525684618010449694008041756350062 + 8151902440733357075969965129856431003770185569733670086864031515027203169324745948550070082363039150127359144961399154724592013 + 3790327961179853157835883754649149214290489479319422066362773172577179735157530589191336297098156970651227770438081844185734307 + 0727046673630137406560803707058042940068228879956058420026237531511228698088255979495039662974032046384364026969019919437568764 + 4204578688546460366354226690592321231974552743860907666913839079477111780605991648504857092410645662298682793993079551732419876 + 3756294405429570395559614676089322871628319405115443082409818445213875343993774082306018456892013141571878129826624772129903802 + 1915879655542608031603048228973067523323417771894628549592585367737979812887089684899398996853836990904295238545782994463736003 + 1862917064901509743356712523964887969381684280627429777002084722985720739317294453681605121270099743339673719320682461749376518 + 5235629358000506017419756442938714321316730985284287276160530781176188912088650998156658168743552720877268116184356043543445755 + 9443882656574676998601479646029201608533720364834332155558897088411735201080867283586900504743773546108777074700728937687647870 + 1677493272605889337983961765432999426943110889282768474699096119469883217687878946342929523139815961885455260346054616901453447 + 9942749715588817104901581207188857800673119328816832808571244811062495461360073125883981969697016073423707659358263862951164461 + 7589849154636259255662987558451236625196817855393407896633655975124730683842916268495164065502043203437031707489979618651602416 + 4877537573726160052953215845080536556910640218250727320033197474127755187683283945624270057808449225177808596236183681916214308 + 6307674309759482316304083895463219733480617515657742063182272951154632706337489064696789783685482205360435876431996285794642684 + 8643739931017169670588941204387320679922643218218094561807636190505893287798227669018730741719908408353128973453099243266062517 + 9595878873331613803340153742041195527735780444717553915355354609332848505998881213100337678158719821578770031967558080136888152 + 9826258075448305567391906666815695574763625260042694682673443923778013491658161518721464450500242508138338760627120693213553580 + 5553946281220024617384962807582191448987025563460515052097885240434443584003120884005027893320006209592895012188176773812824397 + 5351207991648894581591662853877103686069327469518295438143903554689747912914341445196157967066587607931175822601224101946313543 + 4718020971952950496510335972370616351651238578779144226177776993578212091520634237018822715136461197024637982739115303152147863 + 9502456279815158271330961578383078627663170821879138142148906444928946168505151984176109046790336568113096829851051335078064246 + 6953240969636903319954311768057533966261755313567448194782711138760563765547507739230406557393058730942539222575666804143511119 + 2069936646276438376676948110321617772893399556260252358509335079746651069969820285929369016951090713864814429938558082689945968 + 1521371174145731236232976467624651809029170086344894245707746268123154057519935873219521049882236870962226595226944947282873198 + 7819821085451992801895188229558460134173236266804505398682944828070031878272264470195089873005628963880175293100970223151449714 + 5581893838568192200692899357118035029378571475716773858918510887575125236858310172913692992079179964473799145336381338174573764 + 4769245956084317711076182507252518842194925936437279722455907758875435914157274173921143663890367325067229935879996805150485626 + 3134946076248319258593699700301770098983689499295660906642311982752703674969335911328913636983282731424392564971128071529792186 + 4653454953851844259383149899336223085116998954459207141602572224661191223836954928657358541085552778110770329785385935394034672 + 1848527104180913477755119395683294511819189869818050532796513348646616780772576901429766012659310230873210004958312011164035296 + 2958092156871189322732011639055425235756904126336215793291675441374713359747361020499385226744232860514052551561041374928704972 + 2212834863497329670476581032210400927271310708293108228424935554688407632484416285274174812931270321948680850009808218617859705 + 5759858970411718249018834966145654061840913712087092866138009251429104683711023685469060131756225674409696442152891897372343886 + 9744590632172501257249804338242668855862458498369585009073080663432870189779358421204658237236159348444067179731646552147785093 + 1487302286960634890703793800583916358993694233181958170067964772301899115902690629049952516027344747956086526751455372742400915 + 8338876525824289493587802849949027999302785007312125533604872964433845704867828931952315117389601715858805797176205231916978863 + 9771708561966315440823738672686475996359300091791133612159610896088743156170335643885163215910168604808694162494306049091846493 + 4260246980990607411798428730055796631495823134395302589335824515261468702425017396399121744052394058025204383900792732372609031 + 9971700068769073722960546542881880186840993544233005529300285659415785115249158554970710339057479784757811267863305208596232681 + 2366740530644754206054437467535946438364093779279894170145358386159026725061074970741778654202207224942319105808241561149108640 + 2131299570746273126264570482316141085118510380774029845237350007337531371596475771574171940133305454244596824947855809667756017 + 5149174518393308544163272712602730988826876495407743839625377436405836969824290538418225557277170446225596736304939253815552458 + 4121823510749511107366436348094783330267428964699228112245771169272372131739184081655990835742337126629817378548166241761588650 + 7681892302838328396599913751062470874471102029977403036886581893796472818466025775981658918091981433719370508505357431231485600 + 4066251794397726082230815863792863498887502338665772599923859722198014368910671442996024261604600584351270667582157099044750647 + 2453319243126941865196218141928398513931210505017908632678271906294188175528244273588712226403525451579574075491526959814201424 + 2165992720884571403675858895697135732268260556618466022757708781513389984131289376166641651464163701439701648503883511692095752 + 0809953098069693344801057772787094818934098518685172639722513866511171301116371082267224802273430384579466957516125344869179896 + 5481982401939122614289521472353637017126771394148320518526784723238206085981641590886685015768028048372274104457267692145673344 + 2306442226244080959840391166046824665212018683995806330612693877379188175903847065416666586796553782166003940513860649019698449 + 7839622245401117642004314710277578314230150041129278793586315748881510113272583096733556513373523207978534603403670731996254473 + 8688617881383905361473235374450468814839809922748795968256897565635364988983320676159901781893744135189821124712699202769736139 + 4654535121453878305432208653573696687720659331945282280482164376466643366264403854440410004602377849435849425047260830549050573 + 5901354141130553186089991532215523080159611047438619487077531580624462005235622602720033994742060589665151566143947383285531360 + 4404189049080879563477017517544794830939312853525609682809863259313640891722874703005379977055110211171023836236430564193209703 + 7229494566794585131912570254848123871703487763830158261455284479338860024826943524410960337002804517176829321597236274083343832 + 3895863444104818475102160062282466733057017625695711453552783055209411033854956586687106898952724582542873871156820426292736090 + 8900114835631317986947314833806014993742344316565623294563018259706162592235301529753004421871816938486470617127313453996556895 + 0571759514976034692556387423658377978720336611483511537576020419517170544073326612329641870061597096528288442406290336718658618 + 5351965547349291678130305501394296379111242594063885471825143788366715324130022316640730177505334429253870301505302005277723169 + 3916717817342560503418340716556896773392571317597234277462755462162266315055085507027881148045053452399408688937434362014420860 + 1395787899840181514485743703752177228078579014380638280483962491760489212783979634460850686798659390084425828810746413759168217 + 2135670387347630269927889910568863392759999570308499518950101510541542088393000686133918165399672601047703855590903413630319231 + 5402756885639965603367270976348755948712799599490635951531639604227412641095043036804481527401401591963544493042050777198305908 + 8529853370862945970036024025436607369800687358272778049961830381455619066198750162208786259673987188349784621840620855238037708 + 0287160171661419657676846666977667625410411272514035315874978763125830094141664498713238305106795904657260444752711842879767089 + 2429466318667908141926838367968922957966923427083942277132655834855250930739506120606993470384477050842837546690187842884625651 + 0859078343456062742869073421013869747003592646292364644445549193378529859368317830004107789688729965524376290149979489394466571 + 8035239664854439337661491633430612363668270550373199092404545748888325504908156365529288450637845828980854077097067322982777549 + 3141023341289995552305686646515529412648513395018325323202158482204644747543553961230472458295893311161675174437937559470576749 + 0847147233703839410907356117466248368234947493218430919253855840473886381053247491509943700747999091387943188137392889875056078 + 9027561924408681103294230082697546064172946790782404069187548612190839473120786175725940158419889526634026805571973842865999326 + 0264435567708660940819192568711718952454625290701063992984178907184987617554072919582117061061638475508286749372288750484810591 + 3758876219081855315432362136232140221117526750802434000370402808679995451358803624973049460963970344708478212627401394392324314 + 0737438132749076462394577606428117744360361527711020670066707010174337101948368515240770186600234895342764130573542724774509423 + 9073624026312594849755836859839861773390790206872160912057185754009883091290659157623485315161215679742322663821620022079418138 + 9512292856680689427009039672717710424584681275009917377139164236516131951125126982668253717705356666975977684408510117347264524 + 1614244135791303269397434529358056292497647554306953362312956458703923199969180084694524758403500654442416064508250070732846804 + 2519174085201627296034372830011366838603028175377849633378995386798621551863828217907888881997187873208215147973680227021049086 + 1003834843003895903348617625671797354229539053440753237068065646834526921585552402882071062806329627104734866652786788079565348 + 9629790405359972301542148043545627855421437234097522244411526361848299030888697549739412058687417924390455152178947938956747613 + 1220334555078453153775416863741025226449115088431256895031662080047877074330240958104951191074477627437218425259277775462127879 + 5330046177874455391020429152325102772616525806909792370732670726443060748075990477694277944732782581654693994482617923050984272 + 3673634429035216620140695806733909073383802026068407079504394523147664262305135669486209989893714484828370038683949845972371071 + 3708115456116104837959577481370904415573625213784335620684326306607428751455492651914598239687297810388689807875911114963544682 + 6275078866641136241403805509431449819259498303907303571719921144438991991012377399643498948247855847742996423485083104296357966 + 4819771171509939007698439213480827086866218725106376148904562704537146213203839362150271333692094168029380425896012121918182027 + 2363813324380838896838697582331955348538206296702138518105826516120031079298034769024454364560040544650658193748994518844922761 + 3584004325313624962617797426518359904557846265454464840046448902633251444504148633006804302389871871448461320891471777760471406 + 7015140209188781023966520963877943044151556490498938297548114159848752913311985584190436463500622710986698476383835553548754022 + 1839528400463687701674829536257273749291910270980698644016289075485436646251865330303505791679775487148849253452040305315948402 + 3145765566550173415234672570838174821210069239627979798684879235063388281638855085067234894023172727303768990495108093511731814 + 1483336663514861984292197260930161194717688304395281475857151745194230301582456092278030099203677396095385627051965960418965869 + 2854504524032911241727059077016541586716790096641727786446371669834231656716324311341476302384390592511402123780357675520817756 + 1896892000036214095213174483595939108751482199845439848320000109938495152786801921343185996467957081886861283697079441114823751 + 1013835470696140967938560803552257866025556771879993212750495494783316985507407134125075415195171213975980403552113090097922014 + 7515529295471634503543767654884408021479006972212507337901526368761975637401627838535557010674676502841359449244736451534979277 + 6386148785910089568558317754358991974549956833481352102962872492406026696207774586778061183616357702706148878186924821100084521 + 0786007793408177523760641643227040330556706874975301831960943949711205745890553620154847773954039608277686547389729917607939287 + 6601065186724585869718286730900507361468222773067014813540248318802263981782312642062065066278538284353552795463948608367617264 + 8710458632884006689061619016115234211820116439477889276589203755014121466655765492211482958675286327074722685854832241409593748 + 9721061962175462432000129864627652688757814948302475172688435098625740068901878583888711851475071264973226898929358873311316683 + 4174366427344989068552152924708427538956427143878190827546384412926545762544478791156448578168011030464548344644597978114749995 + 7360922452061081711320164728509310349083463549987726136205083770590452623618881507969241810844776231293351721107321616807591790 + 2550845118266461695500217220306235111000226441822451555820123914245682646337932826709632824811050296875427929721177340139400066 + 0537242786569134793043366211458572528023713869510543400208763370329672141795438795279424345734151680580842314157723144187850297 + 3691971167907808375655388036762185591921761050859435693988855587355710680373549562866421201047569372572737260475884900803372055 + 1007691946206878968978529598838997374929069152901229662680626003917658157134099448777326028788327501120348629153653344792265032 + 6789665338488546383152814125714262232923477122140534949024472459646083579525928155625268840134301323030935772657800235228310313 + 4868298684968408834649240926318299142611007662477773878693177513443928825272512719998804017438032952107625783388477428012876908 + 4309202213419885445857524725380221565049288409243087159437144931986513177158450201360308556789291053726105045930369784581421376 + 4918602058560708246713982614793257938660065153424340512931090185661823200932451770267967499779255156975310512692435013776152000 + 1110183674703280644653992907629380068789930715341891132020648458097673681456412608084277373854376969813158591776142390000280900 + 0445144418946628205657456424237128264942955311965086380583598212294732021966933151948426543613378750502788733253601313302851775 + 2374366628960975291734051077636704217339955444337088817734748627762386830985963672836557693273405067738105684469127912825361938 + 2027506449534260776940737096467772483868296281393345078755987162674894542324936567113913899614190563606092238595769318736510014 + 4601609459626193748838141934701193459914056226332390088463312165368986927729066528661188656389710831973546586554245180984726395 + 8820641417137341791284188339243013012221967809583302454529489453970560570507033795822714618813232104921926392983794422966946716 + 0917599289793082450351085959141123440985146982836878988204562375158569611940037966919396385952791842444219407364739497415459949 + 9477416265026706394163032606799526520617258416558453349947010427060666346412817629143427886670549081801335758913070396959720115 + 0666704035859146354165211453275694040361967505403921624893044875089069215309652369723945012113209887458307287755360555234673115 + 0255440161315757825615697585801039525106439960924827488627325282298838888854341592966844608858745754258454784788330547612148950 + 0874980077738428750262349348089941932765130462263947980854368723919615602845763694707934084120416138718231554631967803081258409 + 8981164868907222146030105839525610946849494940635627162577865021292617220051659027789888586435753051650333546661672096178778980 + 2620946901150871449077949420947077759285135192780733116251997439655441528374111538899479815498280668657556929167956071921060805 + 9030260608320606358567118378046750979991657572292125217943471649264668431650823749458443029769965695844134676138947512285494656 + 7911546964476705302214543959264572361084543166660831362636246720337948370592526588629297565497381903059061404007654352003582699 + 8922075574627020723499343655693848239182605712427393497956424335482790840429881008002039906918138130808630673506435738463196394 + 1030007563952008786387120762737476786971644512140825923263748032598127575949995761019498818566016398257609354069772389656925099 + 4044422726596923902940860834745051450250943536191821985629944194928632102239101274072099618807513448554296724965250996986364924 + 2354577685813636309146827729776859816069210424412883327405297035176569137490665953223528983078628177275666747947529655966331575 + 5477299131598928984485290428357889109417137134680518227595002407302611193611761790018230013945563583265000510580955975339191446 + 1619521324601562573756521193045609645344126519940152032470378539517720502293336186421186366939997498341179560168270447355950110 + 4230306307869293075421899272149696843537151044956328729562855283491975528896006550623263787552206307775364239158496535813468780 + 1611641802461249957884380478543784809385839965522996094364642447223105495756896318541934272292804367584843894271046287233761298 + 1709756805199283313621618096481348781674012787506990084789188511001769795898381723775624988249883268986469361054705514036409475 + 4042054305280705588082843156563390558519428096353822906407664058875561059644605482196547535261726903242582076817607377960964154 + 4253860999746516433043460107715275174182573491654972680242324213294530205657678192111601960601634649905585928529798955700154076 + 6676179068384501343541631038132044675296273720164020679619589492139981245074167783663095317254579357724910508792547067262588017 + 6293884180622784793929874980896521285454501177558249542530377203281315652064795385736617567836645686619617679168909645709168097 + 7743521550856066318163410468235782415369091035062393314878499152138458241235674642599783367386177248502506902767835896501146443 + 0483794093371674252980588779386498050198274197464907995529503130294921702208337296889908183028360175355797035085155032755797134 + 7360019231801705667141478490298073274830800662389220682649304818227754575701335947775670426238672520023046096705399683924718657 + 1560373958818879850684156471739380073353650802319300382801718291634025935869130174150899754981641558303334317282125650661935271 + 5092493350585336373714086054348812631829949972662091014907535609939068169965945723736778889287001972766703372105697934518100296 + 4734257102525392916687039288087104774233931626636454683584533774360103845888157407165794111547584642769928525653912147278806542 + 8822290823497972283964354496248019949369662678090787983018405519062148805449317563743875081526769207312318307346979280704726453 + 8280283626279949899078861531461602097441638970306234787225062938541682486544091938804453769368426982357391305981842832099966845 + 2217356720554468128605404764499852161966456502338368106620715847133295711653095826628517163144372167241765382757784888551945323 + 3293984824292108860635484259719926152739335450946748798660592468126259449417195090268999500256639254414418461654750409028017288 + 1675306289991237206693384004427250238261655808453706438418460194044272886240166511333039026240609926117492662156547022216935277 + 3798683710262055280473341604637975853707715733359848491914615475081846941708688479067522988710484836724298291195075742855018190 + 4581874216800089134728449476207100847781237572690983431502108191722970308605570690039979318708286697553630513952137757229594209 + 9413803628857147469961583711007745023208883952507321209502032469098964348049914806057645578293300641835023243516073565578336233 + 3421265017714445796604621284137835957308268098924387669789495349357687107880833828961898545436375036341306978848338980923182467 + 9343222636188028392447876071807038373006670961664292112334770077234449906744690005047749541517081971030139237186089097495754677 + 3197112368581263984569948101844452284212008325999133835851189833940770803601768180655910037983634430639371254776873860967944989 + 7762428156063656052457140048976461668407455298961839410706956245596539166362271685772723545123147978715000469199290892122691240 + 4878440976953031234401260269958754462435834653516282136155912652234992770322924693740152133726104201502258366755195941397981349 + 5410566039278422394352444668313290032035427902945347706947962717669034134093986739640503933965401015646443482046077453432046184 + 4739388878693555231586220110918786353416678121114400297535390976972658914130824675010539898056712966138526147925359029678913230 + 5886358316255011245098615464017615182438190446564591019394412368509357681569397482568515821423340665852760995420364289038278484 + 6311541503127681976206070117236931568310981280275285971795790489631417369196648946460067342315632515195328396495936094906795027 + 8224055001487992245066819015245704964683485501844381492046566836373072408682020849321689488337660828971885175876650163928646965 + 0254578793821590283140178222280457619069765363934967602749676534057099985483967828656474230988014165618526645571684624945648693 + 0109665916508637725280874977575865530242997110923401414431409335639376452646452851515568924163798404754643876369338378812431753 + 1218315801760060263870530314784967603071899867258461326183988209146000243519324558810891158838383484826158948667409186010480817 + 7903203377696988414945216232421892536173370183150633896237853253925354364816894136252089105545529048726749085139508534886223860 + 8148078797101770523716078377874332667044042558325146665083596936734559299430024125955358519934955785765198216278595449870598677 + 1116539363983086722722201448783346777178486858969772190694450961667734803002682120934093453206868817575132463247817949468716367 + 1637275206589839665316460804048412011573846372603155744795091025936193454883889805228527990919468358500076576823231506244498699 + 0027621847956067398935694606560509614067216464874695482321462823676120479915649013012054108931749591716879497574932046754706928 + 4550965358813639986179681154209780873107404530149950214180601478806568724333935291072801881538682786052141302073521529721130768 + 1636835808005913985865949033373364692120504151732972595493618693947796782831116462924175961942781719381911750675622713009187832 + 8144555119970713260660826605512619993205968791014438812251863090080817574324870955751027471809521051989383021792494139844493682 + 1585931821612292754292414253292528827165768965683611240737666722015320896218326640019860760530517054982970340862863680710846055 + 6536681595996347954437568694119184759342070677456835801973881107420392523103849305532249049602562479138323295711575175876515640 + 3486443061013741439479986438866229511864021882422370923187276377158037668029544320414759066219016776345013936686773434186071692 + 8652668214037751054395752355562459984977103091936105931037362668574357365575540736744748684242434859190554622399068882473374610 + 8580093375714553964201167764812992676992679093090175449230495342109288752328986692009639151993677096258635370756684860954291469 + 9964866699458956436463452444822527184213143978744043079921280767307287341419726065990023057954791661193301961189038570454182768 + 5099791381798674690627429376704901489902412978407791536768610182213492340739402802196624950327768967894658802241237435134810216 + 2644824029820305111520479567245295948221720974051912855629977767969256584700072624737697630748957013069006968156707232150642177 + 4694014156265815259320275858444952794733981468869946419687206201356067556770447737925027827372686022309398793525531551762030508 + 0692322520193661664579545021783669513925271024381519716157761278129858733071273401229450196329877841294994307214799190419756421 + 2529925924690763185785959066401191385349387731434107358942442763904987402826148766868356311114428295259838898928666272489020921 + 2079494677073945124622995106365273958525412410850501502163733379133554803716983972906533166904636077433873959124786425510691812 + 5600448283577862312179623155268824754692832396408303848264207707120544301021495705368104362648456117090809527815889327217546635 + 2343977389207774815138566905589371213682572216665369482458860895527700507201800331270809726620829481769123927780354816652809008 + 3857604203317914309286408408516621032904248756858927009945259813983765983907916658284682954733130678932128039594166445571290526 + 7783506576165023166951251072092917407173251744876214934915430447355544209919802690055207660666887916247859978935839016078615261 + 7480703460843227445195199879222716960672528809567298037159358077924188280933697924269515298429095424116709060884750185401083226 + 8717064476124069485152260308142874514219920880901182710267169211713742088964956637523570820108183570127357202528608391772392065 + 0183762641286324428853776063863402233453633712505217167155150999046272831538702513532943824820006210590058738974696140094824531 + 9112496681140545311761452054846654072950289614507391281868179377997604366151409215985425553727631766796511079991043874131555557 + 4848466672408480575274846878733482332783913190570793476048801496992752228173129813319287139570412963303092066006377899503587208 + 2004264846825219154033402067536124920004600149381068226608766267724446119288301005499297409144197426544971420258082942394022997 + 0140320078386067723015618497818762945156815014583969278200840575341177014900417018827299383394638626203285185921061940008032865 + 5962478195492396384491797383201234602669716423445444477699550016949258636112731978273213688262995924599283114955724957765374843 + 8311990015515249068920407871121923281094596878515199867380540740586492915851905851867276732161963585489156521545932776243150499 + 4592710682075197276504754152068206668838563346968654451648904363538719952128821973082368544846718432978965867108316589932428817 + 3552163482893373255049569753046229304178905562057146740570805257427023711941189943044300807285165026750415508222049580394911287 + 4596021173135544782173915901528349195173147664807647330846216356295629295015969380040305219923049284417801673254103299322068397 + 3943524404368165203936926893260166313850279802117822440456770151714171409778904837544726372346574716859663114202887576413543801 + 2969116285326615235890680734637608834483184611588075027596448992877129841445196831709848480423954210927050978003235143506132046 + 0153071245386120635128957595884412738484038627307517440237760302728984006580096280602129668935036883924996553872412205753013658 + 5621357475787817996023091217050008449865559719579810787563038126520104376758261418798236153692393962370203265309058313384060120 + 5031974571476436448786217419749048851015183003367752606459920605017140928435866977820091890996541266633748940714886983142086133 + 4562696779266374687250665129144508120768763103068669726719903362264420017240549417302081941962780048493798236161080017811934325 + 4744441027688831600256636793504579543928756869184371127623452884135869811364793667736493944686083992892480103958881983194171487 + 3993112528998853349337977120649249691278774025202103634228484270608254195748299845801769708524194520077695532568068092195962254 + 2329576931503118880223192095103946522402558163495818627264589763485690044385772668639064805859345298816707780560479994433943363 + 3218849814933855133187785331003935806771232881004238706522431511966088657254108552621744793383328388740747036182217129765309790 + 7924052825089429554499360417535494167874442982520963688982831955472793462543386236218475310833559387701937594241052466519691317 + 3120730387098471204669336934308519377296835486747153400369971745719675185172869103202802955453713945706425356726081359191431362 + 5436861304614177525957519069526164638577548380287496823470807113570761415650401959363470580496567502232543408020661206474053266 + 3120249944908567907826123413136257067078494146549111473184473022022655595636232845880738387277254397911665634549126629364411401 + 4035843002062617386757564723259476788690970258752656414372739557004284974159497458955655696811845766981760932359601002427208626 + 0779143969819344348002577455948300927630939121921547040685880544649850641595729872650264658050333293212488609440422250520307515 + 1460705203029148369614787086632962281691805758071437499284040866802949156450922963941143029043912074471289441815938231327288667 + 1549240739672667607945860219999638499322190035348564953406860715951588472937396572245559080251322668950418605324345241657646723 + 6681600989234088565629106267156100053645378516406056877177467623317919074902879430656553383602319342476881970725454244483233156 + 0192568263169645194866570376494013537343370202553601755904593727729559768993904298684689230055250228064310566719259142616384584 + 2226698070135175270997371657677443976168753242911675302780266617573092075405498205119010526964247236701457645067756244640039560 + 2411523124866541301070099168413071292074360672744530325093983003307829914552999628543032410966968534244029432252498124255869721 + 2032148958117324274615176859919802414958436537913396718375158773684001583339324493639015775574550405787223527127839505198335838 + 7873829779466960857655228261450384972633464601331098096364008012962199690499598210503782863578580915221775299630382906076523471 + 1033617798236208613493443460691499481184470043787180389655899698166528830636916915480716417683921961582857940369278335021557721 + 3570877773431086041166388678403654768190776468384892784896107473099172280071916265352211077124176187206981633533447143541466428 + 9162337956051462461244081308639454192982414597589520706270659960902459420484545944118766172576927213645046647438580806130370976 + 1679386001024741318115842266812215689927333532837813069949968390429571894735964678235628716093113797167330012932695772923859921 + 8804168783787089493714870963570663419696958001331927763315516123670935571014222651056237882407840332672169785104960709919825245 + 0497455776366854139775882322268590872937081090128717394425875756408043314452495438785765312873239203328867278937236653265323056 + 6042409906538241575209979144212026252259767618647784026916367882392586982801406891358315499203056053321982052638011533498889270 + 5665573721287635790869699668106163302621832934471963587290594671222971786422361537494624465628017639194877871599798228379718225 + 7432584741479817366719910925645646541846360875945358928938495570674893693392242341873215005147647843928108951666723535877703443 + 9626429137239096178611195842928172193314671253797016055524388530347610194243157336306488458466944807366840872517364192307199510 + 8872554743012955139567705170988677634651238832225827058388116110755496007697973600003490415480515644505946637930188314840631970 + 3992491991103767989877164315291928453885661238942961179632807297112992978760631966972677658662459086278724019257889314597469958 + 6669007755891601840756776309575869340114031142955328946684465711503263349456097268207290469828978418533272473362080110971119500 + 8033630970428066315841260643530102154382783569132687157611513276699429626479061706898110708339849619210276811595853043955446869 + 9768070537230217029438684537825935225327148348372819431279340284261370618005491965480298943126300044774337991256135794900355667 + 3657498279192720768668603975934793465689868735015232170607621866439453389115795388712792645934981304662545764256708338815562273 + 4841652997648921227154354900004136760485517640549167386012657306424618486993618255961405066483542868908453734101505226047480448 + 4390654153631921147807124887078770782524389315313338172327932505555766712042126014521672948387933863420403298182271156860089870 + 3083699675349781049946715849913203260143681249018875435801318149856990157414011015651215483550403032096067120964528627647289771 + 8136660832504574374548878451558509361941048418373428464399511971079202695299106137651197289051575362091446283996841312766684810 + 3676236989934685487277460614965631287879882167402767160319121856718994264197563392677953816932994293095294646864998371569945650 + 3049112960977618674809680978004704430920799039334511606915199457270782728770389854739859266964607398443304578468934206463864162 + 4020319901840360451062762075624924661391286802372025413278593393390727656336661248466535685907382226627976102440776444559861524 + 0166268182450996578449973258577137477283861283683233635300267518223499975003192269667287508860009509128730943175015750710725727 + 1027094337033962463834235326303117245639527702316027545974140882034976571260270032549979726479017186330571896766878727628563084 + 3735720519280562035416027535373646170800608954405500868661244053278717672230128154298018261865339340499855937060742071802179228 + 4620909442780453001381207438741771581539126274686674694429903202199824281873555557550181182902700089108021432193493732079872184 + 9458342180011256500005493355500078007350011604607303307732963471459637499551951642174991940916434214889720629725398539493831562 + 1757418742866953045608344774690257090125548479597625280633090790836185148048976878560947512134108931123436802430288121604450838 + 3439908217353866705662826605127180864607977834354266960510252404933627640585873170058624018410480482791416937234522273135497031 + 2172788248827330880258621512418568877495834091216163584166603056260778255791670347944634914745463656259805211952460022859276063 + 7062821874356395565274839950114991325558841496177484931811683058289009845398038339874364587482418953564120109998982642304471400 + 3698346712015383293895452263862425925615594845734737899372976339855075694671913339207356770288208509103055437248670557197975416 + 5731723926926739876475885511154531945948200793682997616742493659519964588297814245753251250515716831733713917292045440536017047 + 2326213034490494256432217527368652272393723129996987975280491971552239548286262875444742346718137588580994530639159848308302488 + 9664053981063208567695237243202681506536792559295775868533828506782791916794818915656227027388965683683700700077078525885858163 + 5667625010472277345606381058073451841188387271842197689932469281333817846476853011214737420944488058943262260113307982047560323 + 0376867635943376210756229949512175221086640268169558374511241311647850185329038766762763270981601390818540680562189733654333764 + 4491518223112590691196826611428935302844272864063278173063473168207705976253698032183297470010465109985370388667131449602003018 + 8802699827748011182168113988637297474486522040228085650948530427329245143454181410142916723537434758973564869412497956238710891 + 0653015424586307910784932154517633495234468902775642895621562573878654050393509111804824221865060266482583193591594511748836623 + 4094703884414114132180304529532880233548615595688135936066808466092184620343793991343848249436804401054149903884653644876865628 + 2718370374189505315521628763517179672356494682994180239553818915110898807872150301279550476267769560111595428023012737770277809 + 0983429088572418894311039932871928790123994971756838750348015397853262244219489154464202472581023076365814977799205726076421849 + 2244581657719291754700709306659618001196719303854922152332583798578459941542447742263613733064435246505660395020395510382351759 + 2371191845917148718985406337649548363315059193935226677398831831786300690640380203874437098924585872141781137278459673035181084 + 6868095538827304671263059227883616117642085424440799227282508929248920781388666797060697845611588551792908329555898460456707821 + 1192043306305230972108032344493739345654505538181410336224627870081996078504793311999388842368948858806146981869977786056189228 + 1263564157432629856155576816827336520937607635620996781728277895852539790604285849253279394716497232033008275892868545867382681 + 2337190119883945387644191032300914026172189976929618448527119917727894462635110227775485639758673866947701176216601761844984677 + 1541725580846818676211322948610609824222332361334426723507920844056410476870968277509960759021044456134551342168799278225221031 + 5808026746515835625867232790523509089624770846326913802756163972740615072842822135746471264238978131846218179577994033108366459 + 7209194492748333961784669338759539252535168061991620450390411453076684475148292681430958283119646863377618784660018401847206388 + 8164592842234101218973444204368622348477154717654721601252474279965258123105673927507866232148031414671644959483263113289777725 + 9536506697075295060127905565119738004002490249111193299408907722018709064690369235720344207608369516256550493184611556526526774 + 4560017960261564009218990204461419858845480963206874732488142599183336196461705771053123771553268404282868440226650446328616213 + 0784979620602852570679351917990832385632423349482355239911158425540111723754138128518596135522138872178079847769857439148437200 + 3065506422221326046922349934844525141835749289303921189806839691414799095653902814723672937020068076690809012734952484971091424 + 7531639556490305149862508189711238391327019426642515502558468392326082589336113833462268524671249515158066960751008937821736410 + 6252414527138677204351141055246475557495876614593229376289610072418141564580640343324426668169327302426458833085549654617933468 + 8091658367794443766667336494599463493723421496560610375457662742614878721712215614199388402972271203457264117746009414601292472 + 4908066830822438120188614160836549308604180994779262747990121233555704249867768081188552478880193430879502515548138613493765732 + 5079293880539371206967935767115987717076965982796395512686484284292191272158775216705810765026584234552773076439527278292069704 + 5164216628992440501162199298685532131413675395537593848742057924552014924010292705113677909421661221880801679108009584398377793 + 4121418969859257717214261444608216079650826208617995799712962734646420115576080668425510442736110574190180643945326397724337600 + 9884581544962427545759780318699856274991305713483502351242287264905051143111943618139482715140793163760250713362251924403750737 + 5001181429052612807248790060512136898354370778167327719757330132811615985502470639866207141577372460429670627788129417134404406 + 6178770653157619944192283152223652702640541977712224400210339303510432403323032560310805508239002669348396267104479169736023331 + 1565506146888751623012576320991779119855864177643274705087893960131150916233068282254723459661688282729513190349028463435804527 + 6845488200397241399013882436401994250911820745822241059508913459645459567274421896167243282273985655453126249904632199335837792 + 6040683797579452107027216845343063524780614029426886935760791257030864245182939630838108471908303610357161096840181118609152193 + 5867358422344899058837359139467062379239965703229659786120062948805736192330007221916713426793575162507137089954539396331620247 + 9120519760679588392286105798236021559061854045122019266108300186277736886734969411204978788065566311792204801446141473355188648 + 9729762487738362702158800023376627553944314549674371461896299198497056817939283617350417487984379973531521250384859390378780952 + 5278728682099899168824382639886768910340224230494671557124611921288793461227571446099109231672351187529971910075105296077357641 + 1730149007222759960804235202582288759192771252526372328644840575023003569331571124411309306137954892577214909905859437364845514 + 6359722384817229880817656694157685568966235098606153131789136445509767178564237103959982917552413501317717319150118113725281168 + 8331881891680259180368288807257087972744816443005083134263401722243486734946708091896751081947017218318643507133088446490502898 + 1564672123742228001093857696640500357335628593848961899541997547484403147074041514838330205353223636545525633021798226061157975 + 7577934224848992516208537526305362086756191009198436224096722971843979917310448903629548517759776409320845391838217575441202030 + 5842023675100545856824292093806577194777854067803726567456782139496624136800515010149246416535077787552986449619329516458032493 + 0373167808153255052885634740314278397690578953752487856466779556596486994777425942109945709709335720717497273570846620327341193 + 5952530704523306889233492671665454303269886039975987299656234612350738474857467451882170147036566336312226535534145167519693735 + 9607859559588540690534618223279700864577721437927651039992456828233467681820892987538385235563873550538138831743319323285816092 + 1624406727909111147099641441681559414299104318980440722709754783222151032344202663364762643657625463452804121615256537142718557 + 4340315496406729909696728430969897055002939519672286841554008064322610667892226345008617230358420658804502966997298469146129669 + 0210625023915241926959138868143886129423564883883556915150345946486026490910420790564346970440390087533686122782420012907572301 + 4721491005031549006749404748103949153294842924575427991607317267682247725581223721840333859898813958860082395329629494670433269 + 8089333321693829301610669436388430107322213493559809633043551047784093889175488034859221042528763690657356439399119706918708269 + 0081737607011167672164816311361636636595718748621290008823635691873373600228901339494989909273621908199424676593460415730887285 + 4160520455923507310701763781457568843470746581847988497318956296776248312754405407533119008905656107514741346097573287623338123 + 5386718227154603611476662828982111704301478482540378612558078862521675877095588029121004214011721936617184276464093409939658461 + 1979208081789258362592059412017416272899419903367802069424612928998858612300695288310086571610845555893261171864325093713786916 + 7319139333841813731995304531194319105663469219744020376897814143833856662869242932535917521586466923358318419175396557400347006 + 5043921771833079685531325825310432807800223715751775658072562091646020835717475241682115604301178255769370561929846716138929898 + 5795009540103191080406839616053879828656176434583781287476876321448232920090228345539065457933826027880057345811966575002039185 + 8576153060956850521311077608763009793771506275720974549550420722202837108735329754654396372138014747847396055096136010954168085 + 0509043015950572569270166347532451603412568949379675617083809175396443490772874366901432037667793377607725671409709046037414839 + 5757807520296047868933446233650750653295440658940733452331643306076758589809542688132352958487696630197185077693771148210415488 + 3493366273573202706880963127674882710949035853748406509260478202136097703296547394474710548706092731416204930859887260446245253 + 1707539941222225775800658254639655291940922607284340086831234164821348634212665200587884346716985605251686416602230060503804746 + 7119373075229566064030462457605177717171013246215489918839015056056006164706313041702800263980277171617607329962257981016326162 + 6663813052725497188713444974040320318581428866821251405183260930030389032259911879414867761739508256774997369921307923003380224 + 8543233997255243697045277479565692227756699494957952164631865806868110331658332715068585534381871375140656787606232565908699795 + 1127161017080656837915924804407883971278108801828959672411183897706979458144168384325785293840525608900932906069101189576035960 + 7746884054099676741518894156142307630763897600710799726835033615686726465390861737711082117067758069961050536090277623500309130 + 5637631551447663652036022243883777403508274485804348060822361386569981574710776219228289288499523332852532323527986372935987772 + 4799128874055082677319044677884361786887526377254867769810507962743180135340211433750487850964619355570684078365963703331785531 + 0073682589254914802156389462761084682583678912826358978335933715271645287806405047356166648799977142475160038979372628423949010 + 5037559719886724670132444119093240447382541873564218599313650731701908225623880448841585926824993839038111972019595929993742491 + 3846935441857871521862191302228658206156991884533871767438656661539104499878809823997230034119838267962065754111334791148146756 + 1506245754838722163589450414720903186576980445131544657545019758753225527419416112605350003805887953770147934624442363883801265 + 7711965724693431682894274811945992120534708309601562503539815868676726704850890815034768784240539682384600476706665486329906626 + 5956050270087533659778978762952993742209890928275529257391035690977242967921950083594415755279086778292240063613624273000623384 + 5061387982251874414971585573609892535056862802605728035065909921406395624271235709374930413322182966464210152496167481038893673 + 7793264955081367428964822852138933334974506780923885826935088471472828950440677885279984646325294353993045156334916727728658382 + 1917731844388737433964393775321834810791126648863902100900130682254900663770885502300591056044829585219310561565900983432788348 + 3993621103753371559559083065225969001381490024230870158740460349214225265354617541796726739208926003200650331011617584531364466 + 6446975200293349558151403162258385505474942322796455463090381985898884153879810666921247678344495019592171989327800934238087607 + 1116773012813841761179870425820266292137052144431441290909627977940969824030291459806507439794936788928214828707352139273391574 + 6029232735235425403035383736905446200540026716844974571516139411975848154720481565143793111521425975198184192780712740114138327 + 3438200310045736349450654856319455355471806503450945057852390828051199118282010495739738213447341204668213941183921897766832892 + 9512957847613586351781261772535091586107882959218997758350989715296118346024725200133884012765597340862400507624462524830866480 + 9478843365776113648646455826476363854336443473601804016310466451767185956320296981753166811182992550179769973329037834636002638 + 1745421142947154461000688129964181745046963595109768527672990383210124171587972151958957748633651595231193536560491908213623383 + 8381825139460307549572877031135183947681591383140425137518397676071788098018785187454915609863724531998066262732015118963304139 + 9818630925621801216199389879103728134389152002296761687336537102178195168590959317811012194485775439363610537061412149495648268 + 5576817033233193054333141148999572966012541792116109714940451926593836005748304065707002129553500879663495665687664101078961830 + 4255249811578737819490016920102133439336759727576849642889727534022902117660385461887412305323198051682727105599743797538768483 + 5664318936157823403995526721241574938566862585452228404066914834889748254113822291330168260243598542768358287033612921584775608 + 0493408359374626915181620402845179233550927620380852963377274566085358451742815682206366209318504599243115355217504587070160767 + 5099926458337087971802835525020183140934847289656680603935783200084783016975906879446974951582977123093907468193624294378414602 + 4993211036037539293757401608261712055642333911428904305517543773653002323722539705273891988338327482438288308063770111207012273 + 8875724448927612453412899117913683062983270974383158999932195926949387111141855398745328636343443301765332909049991525667183004 + 6179446485196106673286301271613059516541037127280321853066460858041150601008945716021915010720764523897185471929927560029444239 + 7849437984569538042541347312104898444874295714765888754190517892771505925662567504469022216257045253341087785885957187833718309 + 9972288762936380366686950714951282499790474803745721728891585856096753079311064364081796195123806475478622506713826868777638697 + 5194143783169339034131894869316961917794611019135131983101366014715857076410377619181633332553598229324447853163042312520962414 + 7850854551539305001687198329060780010579189214774936469033426991594801002823836027328068965959941131816419243666581830678041716 + 2062179831972241107526467338284038440066567441767013516710832064119073030278681905009991848241324570216334414105094116172288746 + 4795251857046503954973485018229646234695366724410250031504983138843493652944866619750102836093665932368212191653037534272918686 + 1825362974498797050137125577095725107017850998954189361286965048355333973664280494182300562942448127524039989758648090694962142 + 7512994410145549835156679857014752505125401506747737470958447208937721056830032278112608932324610937928836512547690813007773206 + 4386958625254464154906642431853347789932184826155599439488217117827733831342079710541861559451261895702289359997911170346503767 + 9160582845194443225222601665399912946931088757458941216770145834719498890068834370787508728005299127862046720974369218083539582 + 4881031377785621947067985825999914746359269429111016243690638440462655472434228579718379181809439967478754245522265321625889814 + 7583391301685587265357562950095622866121830355803288828241373074939869852539741493888550714334780322503664271906152272539287229 + 3706056275918240737054417094100085374094932331005897520832184041773254725650156202489186855782648043533132404772816727073155235 + 8593562217884076811451277453364735377701544569033315203869164836320799479709306444027657854268527295924524538225997862678112859 + 4570537859634341717395527618756161556420569519217630387646444203036568601265546935410843254883517475649241288633895824882290087 + 1279603976070610116464640212199310166444520867245963242449012132718994226744403248200981139871780434324112903659101791778621066 + 8744850384566117283317344846157583437411072049976031321951124766354609384768681179440522110424899002915456603055956128713981139 + 2086242661312485180876173221212851654741063402662853918748324706267356051777749583559232529239969008936507197332763290031477120 + 5741215520375853751719868036345389495144698592395029595732821924732143612679143914116460149908254801423378398341400612840255578 + 3112678009802694849286559093313827681147182296039209347542924704088172807791962585025279313952354773038812296501897230865202710 + 2464335074070148432312036647984428094369519448454963043288725321796755075626414550577697084871002645789785381682654641241100283 + 4946700365473689782081952042866282556327651210752194953923594323433725250140138447685850292340132652464859222629234697220377811 + 4116813834263078090553178959891950239969717708797371397856902146227502290357214553371450093318491311749632101080525636146301695 + 2152016442288947698443136330933042135184223974200115803798042702098262975256411368585240157169341361695851434355296732786801088 + 9469700239580500443632308541309983452163906017765379912144038775472527920834490565234287360219977902823838503195349727039831496 + 2028576502159755428471922748239092215954614499408923132851493814161260002491760119779606365853853991681827617094579573055586297 + 3640678920108595929213187711839271941417061119448282180155978731064884982006841462863880420761509974612500984423805360525276222 + 9057118337335912039094779552592972943649024122835147704439083152493402341167911887606112405528052285968546122798145084807566159 + 4304613049097528789015322647077710992450848025235239429386820053371823148160964657760192249248892087179211556970604610852657330 + 1245963067779593226119382101475675796217312455063935339967592594066075071514347181089457321147516518204553844378465193273590500 + 3560863140415397624008978961463819965678362699058645101497391867248986869781266285523093686811424022579360460735505488281520907 + 2803810314481228865478572362393166113955034570401397318410902932552817985751479490450351950758398971928389088057335245044158094 + 6904347745025056517093981246275608711548205826384671869194152526627350920208727208140128575295910227390194690418706771705356517 + 6784445719916791606648643520294851397681933118673503958741728387886357271190905065762821681465016058740202568162846967243295973 + 1820495748778970925066926664077661706850366307799032827973753165199895444172414611070770446635902894354703969177838887030507999 + 0792366480532040444153327711554056488308633552915589047332411364711058132183546270866868018652349880999177379420796287072716088 + 2231884404962985945388134094475613555762253572694848559208422137166239633417739879274457716224035685193748560132590653034477542 + 9227302311116220471908055555125965124068362598930072116668063472712158786276348904469695948132587468164071579543544049342283942 + 9611661683770276849635190630772488322125598419492636769106569145188958898006930644639421498885045868655337164693651551682789719 + 8113170194159795409724804157277970216585110875118496676005194638884485314135820103479833056690555003499859437927213123666961409 + 6776248629614262117061005539488708741664752240716973399951870993215840911122617246729216135676971155075389185544568368200715006 + 8136621653681348621828391620654330376833126244814473075974634681828022721817501734663865372891778488609175456672709780494092424 + 7509035477896901683836806362847630551058479464889625032860924968434340014421918549778761662492676219077042005549667470710873708 + 2649270641258444022173705146602820338815565069036316996296828717613516424116147690610506944602495068800321856748967379303431711 + 5231537094318273489411666006633698888790246462698166129109823556983405782712006150780252324827311704109848150151626541203089319 + 5293239066624699492800648051071066181862007268310279648019183315312315154420858012591159812489763989269552995744386956174038764 + 5180720261104219765835445462051189983679962609760132661239453035110340712611783326617205712026077627868902275865901764502746369 + 4450386186789754245435591998462910276602998139642701382886884245787698610667584456364442583085157908011542453439257529663938908 + 5226947020891494666123742174916211157087031239651884379910014927950876644487562604700114503798045681730239237952766587287565756 + 3462320891328376981719619778327669975981463699579856289946252639770341221258397441894692753073255239973756891174514808164393544 + 9266128730309970612623389424292152551017956433451773715730990286170012828117563840968654996015507568606746254308032751484010172 + 9555122523637838569715536561794279389081447703619598960381475663155959964617699927258813445644496349054324074619586132556815203 + 5221901221258703935673357600398356681976947446424967337708716326590353253394660639230448040100077013280765926948098493319213488 + 7738313289310543436800301466124075949448435224583670124694327098481119456888840896351512543815188557251685118660772588456625224 + 6115002819234894874533900222654850689485882307323315708374429887345170183105778321445910604513739852020875884337203588872923125 + 4481043241227156956639553841037732426965917364470043436075190174090995043087977394594850901991029121373900633832712403510778230 + 1122190232976475343331179295988355035324572960682589565916578492624347219825791452145522290660285362795514899273106419997278153 + 1419535386080392454227188259532485710914908620105317213100011817889875764632911121751593887025644393163109071422951719422847110 + 4026612711274029089236246041114948354793310083266181854689070097597525414068795108775947050469531123122537281180760454160254035 + 2729212202223251132035733428110959851887971832113712091873626429082924950281013969697115103891338579818898846568239238607918122 + 3944336153317752913161793886424178237035722936447760222478425805766217641600209813232221230340238786982394323446453582721990048 + 7389193916919980057221104426235427350670234767999865432553198312811347361703697530913350075859737082487587469312736993623735804 + 3544483515704686277538264527506961791275819582201516681389283444580314635355964056417380225809498367162186604237676145482322561 + 8044600252747925830317760868421526571377975782889497428302869692743382713250361972424374300944696385157823203594995989063758674 + 3762181316198228161833937930845505733610147834846550265056669736693282801787541130363631664735877621678425882651996823896571197 + 4895759837384473598984792357851123553619562828621778670882704444499813426092540279529447104250292800981220546692084253328082420 + 4664284555514464728238600094152484535233997991752935740228264651440639886242409459644164822259574135218995760166441434144147387 + 3498021732532747332097779512063273078194846290742584872890698856916194513341236677884416300942002054144602101645686192153654576 + 8855689629475186087358536061769600329981635356231999344927571715122048450556630571843667383074529954198709235538731487573715687 + 0984316998018946399866843104618259659452795653432490384229487374720689309493558506727485555071518696965289338830868013877431679 + 0444954460337393289812378506420855357215741077375742703669752012654590715324153275679920752247842054109194186158654335712157841 + 2806861505564373354176276173563926841713871053400626160801979041772088503472612997224598155147542728678254353573523697935567654 + 6201924274245126686318859488923564788418058568530778365444195042057133158737326264356888205129275667061366349202778458019010774 + 2825177079603097543301363195546845866777243546459927001122927276132658961336248692066215766333309788747162494346240324193946246 + 7328522607444197904276536531669234484641234327006749709725328245867037809150903161226855351918234564454937188245329779811527397 + 1625377992337069927288579727970280388115743434164021261444485502332859966787759877144357204976585729746356637542057830900380879 + 4756314028565636147037500545330319143265189233753100563686689461353510356901840785161069243491300815016067752040583292254841464 + 0425017333645387838654294817531355494569985613245897735076448718279104158222119913920255342054852667882224523660815046839280651 + 9062897569747184612738179958208393387812077029581124581459197624411283206076395360970022007778409057996215320186949888642491834 + 2577588591174250273899408593063983438617592453792302359558473005206418002455294336176016723332413815891373160708758731967049062 + 3790766334026767123109787766877375184100806711868340730414046922950551256206928850545228229670325982658231736019892656930961551 + 5274543406306956723055597804421123472449821052046299950205504470231963135543548703265039753201973863356153745730092781664650899 + 1020617263114480064430348590768589835423732129147820366131428529210137664442462332795234431300140813802687903923031421483099298 + 3305606503022918455845722586154193433226668761115620627747430416848925633688922763380741392673785175993422375485098655310345526 + 2853130953848078288453311632699255400113689129756388559283548184844635112023417531659479267970268571040812683475165664822794180 + 2783222167931397034746003825257822695087707764404029816076797619920932960124572983887919479900468345097640119343412470086673322 + 5063459185940735886394343828328918625032505938760162817991123725871771735016474675217009872180054875341819281047070252038306775 + 0743585397605286027482664572990290216960312219499687628442325704541075906118067163819053997876546874075941147761887253181403133 + 6865060056069818696891296915545023370983419980885799857058396262667622091719201948407642987224698259796247084724028705854417594 + 5103827826152310417357275607217586307830343393236258610369278200854730301259212109525027296782910788706655437239982908254923137 + 2959652192735329005701145454769790852470342092444456431448859896236135922540005403226570654335981197446157556763871319983952696 + 0906069491801564153648838254163601062811138002404571553190646376754817601328289018602749191681199089353060650264442584766903530 + 3785962322135501816792718661619323345882587573641791662855806452191640690223489872037123172150522718319643946771618053874607301 + 2342704599377336428681571005102144288192803466969307063516540780329331225964749753260124769353818714585772490856102378132713276 + 4346236542835966635872778222659462346707942811767870117146806978169322604045750387880280187005012616459999816635343308178563646 + 2604219260434304257671433967264369756269802345023491459538543248359901859356108205297353830910989444923284454022447613985397264 + 1822281949178892000423296707942037651472365683251029280064728588016134363373058610506594311454908111460545368768742973357987311 + 2329670499086760430314104242828210716854904379725565610986919473143807393666799098016719544449077169306161547903571473642324181 + 8934928646320239275117990276319738648757543739070170895539210951333884142223117539519009532014319073300363829125825739466521964 + 5363386211310899141728954217940413318460520197666536176317994465965648033515827854532405714333529319178360920611572195490491843 + 6452281693971710923703852296775814957821367584399432406445144322839651572894248840082293918339020670715780310479909368596480688 + 6791949317913799774656284904153563675547018432823443924016298235065082832647707880299401729868016947630432394689913082273372425 + 2712968598557679357916581334926350397464524640833937031346811806334561647348253048938805411658427143226876519485429485016393766 + 3501555543617126115194082213265703065410803089224710636262686284845574699295863975355551722711478618786950261560124771603773061 + 4778106677024357003045486275897639115668057170330533010873096634039731123238801834051871842868704307554039712015191582514954442 + 5218459195255301650149970279364690486331464065970810654696223977244841051824600951397161627678662117382548039349844217280375193 + 6369806374093253248520031657537241583648618465123745039819043766572718344368140639003289414418211436811709774570097952888487167 + 3212569840247911007598018387084803647762488058555511319640016886915147136497977845568137947542869347226726490373484609221240787 + 8115733543956480787117884715874295702599005706164646884593210924736152784838359510894224199377258864940900115663844969555460182 + 2035968818201814843503316301816877369650620471604903993852843829395302301918155158237168629501277731356144310878037185323999107 + 7016895419441126229181619830275636225832821520441765441532992753638148826237793875874434736200782222141244213180375828740996801 + 5879711152250078980107885067914386728437059276590755707069830533352692084569773933300266007591174281283361187767672358396078896 + 2103537195144138796197574043874859185879649977538344432422677102393984939164145250471907596342652013494773096173424264207508962 + 0637450827987698515011845992398093937196147180755217329303542644463406470700019971836100495535322254679390620873420862364850762 + 2242509562912546291760696517385259786276250406593124098460913531494124669973775469757781521279236307631066606896102762073078153 + 8737688554624301439839538446862017884613896797755819281023174101498754986747558403862071766932594675733495440363990431783540137 + 3643542527592425148722339107873667468772709136145667446671572809454163340131116640859776867285040887038441378816294697995941474 + 4072206008606547388536544456067257224875289444010744788037863160664893445070574937489602184055019861155649531412106370948013649 + 6183624181311379076807905566573341779391313360549851142539899794930473883081910943750299100861533261211231956101452244671916467 + 4790552691647255291761946345206897704211085378644313837821311423673070233392146600975258580259558879486034230540380014801626096 + 8493966397430159495762611418791059378501633459275242578770822154956094389019127421733416568122031957966837378624113082091125501 + 0539497663700011903785013114734351822728368447618541431249895153026462750771721023669565811790420914410370442390790070707245463 + 2527965030066432300857015457970368291786471653036513592059650961230415181073725654607900007084498257528783224577191374901431098 + 5466092963804647249090725375187844347347973252108137441562290526430827908072841935677879142427224945383497721669674256500195118 + 9408447458584058076150017650238543964665522204847767119461148283020725314993208318241105785737923682521127890161621980525163933 + 7752816476751548314213662757572297632611588857400086488089795605852388674435780461993562784936271707018785480608983595358835686 + 1627393802741824989025898363620676709684659912421866285079664625171969200262501658717867654051389804050637814037774619076628490 + 9122449665202107140311875578301366613855230050319765976709818479408721612162782387682958793989254712472790259401394162587792903 + 9264559273820216137804057886666471549044481178190332632113699758788705141611700544482989913381964978281793867160157791927781162 + 7442806842403069859300613325533104981898816922110133255013384334075830779759933886533885733793824024671542171085144755776119332 + 7374346360629846250873248611855740390376331086859870274251856769041575442564535703086946429812945653348220186072122845016274001 + 8100158244663714389704533217051390472696914158612218153906542802690978033894796544874039962095788720080152937661496672600961913 + 8620241055478925684985952252838411836616234675852362577897905957450930653087681187667293254151875334644179085362678160756183911 + 7978254875299875225763061871403474457110245655385719997304830996169804380424203018555208820048813202142753962116252594621406974 + 1364681806031729655441460904058555518845771287158086951978113218142925356256811479736849256168552051145501834683683179144053582 + 2064837061784377038174422796078941972546986123715738128334902017019689407784830561790843652346745495974010607663653352384636987 + 9087616048769273749416367719522093035127707930211676277159029972485006678648961483209994033836189245748110099847024086616545737 + 2425064383233144306141397196556964739088709046393835346029594675076399505634895487000914867003535813058158157320486332684663652 + 3641097021982425901903299759975001000185954507785071466003606303822049570876073457705939373716255467071337231807741213874106729 + 2074354309025181421785407070622306037112442163872375219312465679573739444271473076859615411141496918260111756219972558400237414 + 9209218175245343776137887607783882100053568632353169828579551734386860768832081473967959877027533280331064368843953279403791000 + 7265829914895705780556070716875430476662014009364335116363868273301526498001345684876869560767489114942311375190271613882803603 + 9073891388696315073189212242611726526377243973277573301675482213008892303352424672983354043608654230919446999369674504952411077 + 2313808555572186833151976371065120343070868637724954931470642187595688232146689299510744666262728998553432846824564736716304195 + 3769895001051711590090397709284289543423142627611293076964116196325536683515731394758243179761144577336943990391686351744541117 + 1964012423430274286597296893918822905314758106425920575603004465793377045724816176059995632780349523671266024041147016652652055 + 0559141307894322726836380567121144490621939523042182901839217710526781776038951549469639294413748250130589664480237146063632821 + 2784427615240187672159066907559581170138189996990499287132279332580644422377771338142338877270406145886924306247277891647319839 + 2650622840124168882146785089864582520075975814107450314378337065910303739372347881027629224527453006767239445485125470798573294 + 3280112665923668502905138798645913537592166171499662307256909576761808318862002890184471250591748083711310397550032446473077789 + 4839123297739060737950671029462682374736375690549900393153725695518603231578972526440776594614418742798429193873047497505681792 + 2160244025080490634108186799676843921536142621408043650219395075800794132235618687434126288996783749492148526728267890467762275 + 1151778651927614305188542555589072273825319471951036866487051470913760762080070986450018226884129812856690672034368570260461972 + 9126667808863381235489349849691246557114377306076458702232805159967351257175416964221955677360994319567614203175199799743819984 + 2789442446232943685597991603590204183390799819475475321518636276804097467590827293001641282750302064255269776064371623832516088 + 9048597881455099698450226466082784483581892839976853703691711348479752784919013613635237082895964344395914096977829703979539035 + 8807651873851261763689740610852384724724967281185663138373836249447037268804159569417135422054907833329936731832253007919797504 + 9682114913920055259992108818897312911322686928213632559659016546514207889796765657343025470035022686294498921433293889021982807 + 8817906539189722113102359692407543788732651010055394962852526688290033541790486992705883840600079101359528027208567808930305163 + 9801041923433800395009066327257582729179435202758752590945790035180893649947139262456916818609204478389874916889421571462394032 + 7712450051093466464431798727528046026835894856944238434402423528849559439733559946888997104896406027931037956349309616326923736 + 7381318701427430852131274547674285844624653982181746045743742319196948480723763005752758284784444958915729789741525394299696626 + 8012218598270213765952492120607042939337977067878086380794314818747633639449994732495580724511274417714861329582888877331906442 + 2523903559053376560461999356914800460953183047966595580074070441846526092785101396532452282664986312641571216344907286853277587 + 1243980803716723402043316042450038929890705999070870015541470833748745344879737850504389676782666386423839519311757255510240006 + 0284528532586136580475966266604417479884520212063362364900502892825693493079279816397630592037794996982087214380723458893748385 + 8491272727902175551882935376152929301347887913314101691264776996119552678466629354884721510455050616404890619695271496162337915 + 4545341965713318896843475698632445949069586135305533687841423447686352614650216106958803696792920165610566274323872801678178779 + 8253568664915132158211550322533453124118327929548882623091786963905677622475126883200587876894319717512008420758223683547396925 + 4320222323998014931144025979173468123790086139354433220062005544015035220976182446830891814234515809043692298378909223491021578 + 6069959232219660879097232566121384126364624848136634056377125102029351039021829959177114631501219753707218086851316623762802248 + 1243816089430429483661271140945607300465854350055161784219266668283907250544685294916674983006906835039612884905549454140955379 + 2940117682598404016293743763452820571055836767681621549318648097809089905651411870200800086998457828557152804031061902717793951 + 0887454608619720066585775426385076124950271424460822511049331848391671487328356192926497422819817241814088663154002962024098217 + 9444111199203225196678001748854632792810817288744330344130819478809411416720197937516411714390009340089903953898652786438479523 + 7598508564858904067093707855688285940754985295788676773297431147947757643127210193954685014018553421494459901761944702436530765 + 5554085843289054481441810390185341385291272744398367506999297552891321596456006697431455499740285520112057597547672427356435569 + 0013578994633080338189924814677511395910036898885609486453589361725442884886155382037285922038189976648035996103250646536792347 + 1883418355117695192895288397176362340054382375638457044029914555409870529840507997093953867543753807297378240486101911704147190 + 2990020394219301141282427939313186733000711509741075546302432127423255702951507832353089573401235669455023017949653420450062207 + 8315834094959817998047438269545055161942585493293325815723771181252407447320553420868080424394122133699301368250012158017016770 + 9114429395330391270070591803725103499827663830583921855069504046749255370339126443177002479229837662039928889147633055859281868 + 0939693955047378469672103416236905988750384823305338476710533963327706820167318110473623797427088982971507090747733464699600155 + 8097749323633489883895572126941411948413387610953411492455863784508332803867377054591645781447379503035057961144435257072818355 + 9192774536491861553570480071143726445650506118482951514380572367117987602662371433431531020944047345411439555055616659122572444 + 2538272673224446791161100046059076794348690288664907501420986291128393194698926073716590796828226666658940692534781574652080599 + 2296719356672708630298340102476096286223198315529342168688227248665999468122934752834636542066357602969267253948955801596039200 + 6907553929212877794229661239340340054507529389112502857484240836627584226292443778415389852020999685448069205241033372399261985 + 6092552080660661596415004237982747843962036754844362941207857067711980933061648692291784758051313128780610506614569982941900763 + 6594390851938570829005416110125258734178056235062424322731777215369780823020661620803238711218728587137816612075854867828598400 + 2369696331217866566447853409278304508453286888356285386844080814982619783652943626843027594633000036437577975836948042581832383 + 0948885007237584172710171695745820012612068700229335944852613395850206862454317862915465465928827325249777743488489409096560811 + 5495911603990067019527969794975740716100732404562122420639048240417867412633964511077857983711654955131598842753406211465747911 + 5938576990907415666730959973171116867930776870120598849297289380213982472240243585128799882672536952585668000017332908127868142 + 0055033948608802263653030525631019632385167453147504582749896613855370979829552517051177850239757173815628192095505002356755838 + 1575006377951552426189315697593571157901434403253801500948115475871805154047796850271348643125694619380221648554282326550822126 + 5246972276283601394823321357823533983734860648197127606415601325852813899044500843947933650765212255657169653289842270182408561 + 2963795283400693969427927841410518920229478373496996799858803689356286312942605835353285929732637824507016592351551689198434905 + 4524116354075005325609861714463374588743076763717669989113993414649241279740839454455938573607498636902929162122468763846383424 + 2179849115762842803410844590988059861418931490923531363860515702620355825744742928541840867928398829472206209785674120570623101 + 1132410047750617625576007081275570045071771592714539836172004355577617397790511943990307565673693827096029990088810389666652957 + 3079203667265148591706387956264742397674809071114000619637965798572137055721279282178439992636758230593462657176883252897846130 + 5344900606236775949063632708480760988922321343844454792539062870953446557548709705912512202634518627191679599405320534739710674 + 4862620838291477498931509821859436769537924979388766030614053473312195673928520927507333262772931790461823017698325114264269689 + 0377879474949535999373402143435358728101597553950835828260875850446040578864121150552326559433858342085551900119266465442357108 + 4145382952202338626169521528905963930174893641795335885386219002691641231007259917968036502863440853204735639598211642320126801 + 0053580536687636415170048134719028636721663473814357492351910729926031799390889508364212752500797332425619171871273560570543315 + 8050888999124989277531284920879308536986968026163965044507397321505480674446271580916011349473678101309289578265591746813517726 + 9127557909914237400136577868957543371638044740008283166851799275961511059368672159330761617818453900045874047935222126146402161 + 4101481561011635460925901510238481810190290058999387022386961480571796642806735909558855831574016730200955930521599776711652022 + 7452149234766310409197279968867850647491580237728049077688692166936015804308350068889158066597960097627065379539367797830770392 + 6879895654050303365324517468233477011666079944449521630351405739029720149442284020545119121309386081120398471736260643772075320 + 5115668578180735659993042798673877885823921120201277569914715190894516855160960884928665814998466370463245773786729580361126788 + 8473676321663825127148201234179810956242584805477442480418075610556509294721684997709018216961441699698479559880791844442850980 + 2548233794760268816189190401306088756408880212519056730724214290704225280819394151931727397286420914387903845669497115561372625 + 3358354482836700948199493625980064917823071542164808097350543961229800125334834517703864655364546055166975880935305435123088821 + 4029969129548193511513014303632741396672093205336941776475040363815521979058565558783096959704099250216961508907068930707743800 + 1178228259948098596059380680409565881553234195364086559565498076952409655440130991639052974945372324956190156780171629355058755 + 3717169015464986627001032179838523927735142460855957466743630432390818286505306791995379349323709241837876168544133279436428880 + 0351514453291951960472553858319673428002898082287147987459621016579844258976392337653325512601241626465492005157367458123795393 + 9131757913676253650480410533013952331883655576543674109012844727933443442812463625615079052305206439748070329783436962037461924 + 2344960044770585240104572826430912626099098553793285442582298302002106108601045902079657749391794040816491373923940544837370962 + 9188063701594180602103941124399234673973525989100931802175158910488942922514429931243842291939057260146437903218286048586526737 + 3095726475590315515951883606439041451987645791724176078005404488548116509110488969805623639698399122683827452715501916665020036 + 3403203657780121846439527513421356719526606981096988845264774034545984754667811956286997210908649753612024363260420418331459837 + 6454363503953069085653959466382547762654112282647446898596667543948487517796676159860624750118940186171824534509979950086899125 + 5534857215488234005757824538224541774649888325359087056984429790126545819871211147018201409980430263764262297169187413523924493 + 9520167452539794941218775260774423444492261204451489938948286717754151689428746487424118400020813014135629700319029471552190487 + 7649753857278617517384047446362214242830920706961544783469693002591616096695611398984815665331683937899607935227857197308530722 + 7670636468635321903676766861271780561993826318676409654225250617146887843176296360469702345236373355189175304203166464435492803 + 5456942248296553684603690989598415553795292969337585462669697131930121000520692716176831920728412650435826182698878423955991084 + 2896202227362420166816298936702205787111522693592087473120377589659651412246131193859654870409149102874068068052947526362484606 + 6206499177988103420772046456006763763163890633653756586913836205106440292257489426046140931638490258992453397047593430476263734 + 8271727426541847240045919975482895895407596972876222349935866226855009736203327632117757403576107132386631830517560425145954967 + 4982163925157138555939635994371164500846077564198212229817459032427881591645290463697023178851238007473163893076170963474781460 + 5340106261127351887331618946742533731988940154583287036382074049074320856289664772105865760586792346984849386692407381048942810 + 8539587910802062328556477423232706345676834247983911515809748455837801552264721412722228887311117555317778442883915233779797479 + 1727978384302123967727306531882414560603798977850417620003458650086712045078303090511550979287673387880893466154163854646269635 + 3674694578655904749986580598395421685146833662087197374056652325798896836233778806349388223093547068287833955056912724333066803 + 2847637229990901535043145484946473452323017593046078412652932709449735113175295374406245481235052704111601101677970510368326922 + 2791471564967916436181421827384161108238141389611296884460017859614820709694863977807620407661790121758211278587753750388535470 + 1311682212671438808292446213587823526675524926735249896308087156166254699859676499961522597030531906137578453887072208144785351 + 8861987970713845651946125749765842589051394459161283498525078704659636051445265425124710568264660637581231331333166906616781773 + 3433773030784699549858220921642631039795495279596839707512577767723632096893086622754554818674187555230885034907077860457028892 + 0456580053379968368017945695164763479833506838952019851181545387562584359601036032261663315698690958554540494006314322814695152 + 0089934480486704619783110767294727013349926542271497056296250118282426029001430520413060977864809649544418723152448749796245164 + 6374218433638081986774399897692332350976246009622586461188714603950733284096247572024844313234627483374886751903785440297788166 + 1964624071497448806005939877571581081852368682713329198774704389508439970356078811686024907131424792844471710419031994307710495 + 0920647722499203428391025133284362175932945797352824069655533852410541721344987923656955005597638885921881748026281505225146701 + 3234051414875467310335184839402728147911090604477636334326355603404083470772369446633927746336105082555084803709873030579813182 + 0797776807854225896647327655002411099428092825155001834564019066984990634531216819521296497699004639732085677368728818595315930 + 7917485162442064658421046487728607879599371289976088757626588362451318559683586821768061531908102225442474938214076282479553260 + 3281219759953705660325535461460598775637270570011648848817233301493712654518786509665608881437564458093540417006933366539835720 + 1421309961668710980725741781573712344943061720229290458895090456489735933725778071381711038599743236066437961925604705889777444 + 5346018484213473348778149540609702140487404833149084935132956734625173249282732560039608351835971014828152667004296001672327334 + 7640982015534543149522949001287972675835062998825649759593191032854308472369740597155188057572429051521288244481472576347709112 + 9082197142126709759172581677046792938596869866773476159806997279087695007866672568094682918889951065921351285356324461616422296 + 1936662836367636814393593918150500159197921407091608653457518897602784067757706017281722377124420704953813373267377728149707235 + 6165532554189463034890275736530147346375384892741034329027227244542906540148716547806611470041759808947343102903725834811540237 + 9921590940060069893953324679767980790622906014798953371116800849894891003273141853411016879477894602450403366892842855960933978 + 7315523767557595011955152358473653019805790165086637876204849356737581570450280098237545014539966107468231674446113357850428012 + 0791096311925956512226765013630421811573099687378388596324590465120594475232654312603704526616319090075205150090415360289991719 + 6209585520294606187513003055352209151687938901113926217849214203137326771247519247105616300171713950372822794825746012319922943 + 9070419207282434237195104895273960005868745134822958234433238365905514670266360172103212277318139495451964580465731804042546085 + 0338167338157532972668177758079386489083653270128069387600686406564818006155678752863600080494279043355117187180589834925431100 + 6075857929007054805987361298779916735419742025429402324367885856941288459616727309405216361897524393233989298288583563658786859 + 8295608945048628864124667559446303925571884604451666719475562297491635918267804843940029802361638899118153382320671609177821037 + 2582167131471095203583988388775565537112236568527071226697464466863969482609071992299656322827744545682290545625251014139439495 + 6711594101773826530320065101211025715415340393938808536071030195055575879765597974028194836866850448633781263352118203830334159 + 1911464166497757327229347266491166768994040887477045432967042061773419808596553435219059712816623298485611786304164577509711093 + 3950559965553312195375204426888631697136007142008473612408896359608938295800221018496826509159015008898585495437881710932385623 + 9874188189105976892158996129334251306053998794609627074731940358792016931428037315501950874633599120688188498035110487709165641 + 4173410887164627415991784444779118017795312676797160939963018529923226506062126935003504945358174169319649592822030532548902364 + 8585536437904001642599877592181317351676828771494354438414987542591562928890147892012194379909967644778402105597291718886776458 + 3150820435297838229930820366686733000243384455249980345366643081949584071763731857162948259797374460060553393333323596509856155 + 2746510308210106138913961915766655928022321725147254596535903741506128248245569457512888067134893515592196316478265340857967148 + 6054837822399734332369250046782008884610626357811684106025662192613352002782118381922758419491552146516596733810475017566505975 + 6253444244691352274570036070483313882748278795425532524034702609588633374333913295809727607310412619066512211586460777396607177 + 3167935626890486882612342937895694862011472784369829386553959207681859657350791878067764914715082125859929851130735487337849909 + 5973912099248621614115761320919410184939653960557823675647875630413749948258747675478750350454945866579601771984960798194388016 + 9736525221109913891380740014791803647462175891768280453619965529263318350088005137408675181210618289125588737889391858187625884 + 5353369021308107059796622691343010568879776199002760578714065302617216068310095438159704609241785014319825155619864292170880710 + 0495180914933316707105009248960814921465681956792191416760665299694180526760284922837494706424443747428740900047510907222820027 + 4261167178860446527279234457781216359164057184535569399549566971774741437839602392078186827336187328588770123788484074481402098 + 3638667122645479534954458961543608733857643210245423464371257036918768143627288762652953247716922315676522443004771243444008790 + 3924515546743559568892457871009003770852048769643235894176832052809028875813896140562020415910166599360845331504914716199418304 + 9539930208848580218543922990732130838884473458954810662182599563214576790823089949536669626168272941913640024171496275351316441 + 6014586121604715045014833563011298445249992633905973084716393755263990314978408352185626630254184110544304520462563363100889663 + 1480056209827971737404379030390423810733649879094610502529510552900145205746169635070607870308190199905737823014183804945008242 + 0269907341608215559877018486447313197581053179139277368261940240899846162645640750726730556726252880111678045833842135360488520 + 9452683639389882051701960541518755636274003173728067144992243393027569642308110984514593826650393132965688544590683455796310124 + 7380252617100440281579567534384005518334110526934315682916800234325208500512344342386934373532140277510905603770493859349394883 + 1640841298979540048287075269187639921568678590871873233480612103263772909669941767642148108401983790040311768132667513845995891 + 0797228841202589730512673576721011566549518209931565777081305309555092032097475454967752699515363312040210695622598933787975405 + 8668051227922162902176856358741680893763627061240389531754672702747011947735221029021238076999742096989024601711374129582948446 + 1940517877834907351003862153234670764674347412348064152632718218140233582465116935278604919054339813155764852687263384383689198 + 1258507121750424356317899666874328759136117897322624713333775442411946490404548479399911860814088039900005338783292400154353212 + 3215026566497194921100428678498475477212368831513037002482731701747625115899231609161962690257412946823057745227816040916263135 + 5553936624046126710513840693074241292678003250027162357678547764315313001417556750343221645935609713903330012474781806462752509 + 0087160096352464233135718030584278086059148140723626725159134239250134423251753319043440628036779710209805517160099782393064078 + 9318218498563579335348341700906218700126032521018782542069807548617891695409073329049001835630809969460708500370067751685336992 + 4208076385552541906663566236770990347477457147392506695455104977958316161334777343709329582406111068678972797895379263213969728 + 6469519015224118923867472889765223881558607274601638396572334489644055785283085612422941306760043896876352796674858662547224493 + 7581545382840053688960159322695550231110088020621219817091426507061324686155465441741816208389678694769740607167732243171488972 + 4513458865704194161496940570841680853750653077515467382681747134693802486964790650970100691348806372555667204130083389487834234 + 8611747863343669889389552604708894518837779002018609033906535124466043777729170830388281007572831090596749539330676454829092268 + 2614980773184238784409092097541705502166871511835967598046040179529035245968990886914099394023190993075959231506769917989928255 + 5078404017663690714097396036195442424905417384596337491669874839339606038090162958546298191413554764614281624619030688715839038 + 2641999347004416078674706237266340276545528202969242926658631976187485588763571283416465910176657402769591804490385811120607894 + 1022069138109039758566977843736614783843237277066124548095396035264485535383579339344672494958836028783883577568562124831488748 + 5036220302308126851203910148295691777409108647096999242270479109438402097077523126876642469999412297820631461204592271671208573 + 3765990012871705693020962224239694872611037068970786438641717866334183625110030788667653078611800346467240202316395411589819234 + 3782933301188992583378339987527190128332463154672014687853873904582770103495961273158433396887983077621367280840979561172209874 + 3749199929332536186794255922364823419316096604597225233951718116228041916547239168206812159635533832324993459328359641335851160 + 0949078067861678051433564861906686233060038981581529250289577929864989790385982845786299381823508035058298434160670694386088772 + 8589603171909191258961043702444348933790044242468360895051180975009846570524502293795875915077460542906777905339916008769533025 + 4696790001285278712597004232911565273828035212555295118585512821803987256554356248161862945364958160311031123882054615472804301 + 2136763839544335242427199077661794515629181187002289822787279783807001282765862055208820154228904904403489678312786030757766407 + 9614871264207972090235920749815254428999808582182551807788105640461738443833466880592889986393806973211194934814261892282034345 + 1053682892737737957362804191027861071649489484546703968499730625323764928679998205513025454613668271807284174919717885935584552 + 0107677739834015517323287238318659939175109001778305487593186279160892671682768468572465735391214037913879126299875773890935302 + 1453192783717188719965961795655288342172822178539274975297334507529484119848624649135862288188339473719284880061285948938876451 + 1104549929363155396273207050870222760506597442331198500643525825130190102095717730285667006432704158844993996831311067931052472 + 0828794534801481162296313627002145147495573308897739685396596733882610495059540555269595443659894160127867987587635803471525887 + 9824022973580621392509031573913634949593512565298787398230994893915219176490569710003371534856099636970419816555736516423169506 + 9878869772576948330900142931880528301401489012367453237909670821957956278129934157555287021598067976133621454184066239649408611 + 9449658706952732276667554753119961137301412966671524990966931464264571223338509226807775956572226631814170860570478467598493299 + 6650524655470467246688640367290038855618731841663664529545949374735107916410687959478366394614227095766286594581538618985047713 + 6086084723895749993359399578577946854255073324766404400181960974843071723540051597517023301307855898898894953430083847202358708 + 4753978848939024247917094291054930385042551054372444060172056724142258138979831515270370976027807892767076899036493276499539268 + 4888375835344223898032733332908158386194226863203069893727606532739301723911436149446573440019514355993413403576684311443713663 + 8296174705195869577823179373277139184472357378750746123040139737885926265459733919518384739329034183096218738593256149149459218 + 8744604285228489074099091055498838353604537087151030264581202847750393201247650508352763633370859358894270796201667489608183108 + 4803757550419070833057341387873914307394706611793081307683075761521436160450412298883575182283341357874191269212976379223012176 + 4435149804710266828206094765772134040146772381477199506975830561360349698395986931196641173574221626045221904844792851097031410 + 0140901477445628979104022134212056527853288372076077175566962012356161842830489257088195443545165486451856025672191097292162212 + 0064993358872969642733510540028442337052528489493327308542431944612538748472046808937048692371405185247438306806803215040744971 + 5863180250517768423942955033295423284494978569038179153339219650484893674393537942959738721683811008504606623434622402463074587 + 1057835094428515977317637880823368056821605598124838652727786262421298250352722448869673429472764531868054225289565474229567344 + 3983238067434669068143443350182793359210352492378691479389127933138449974060689160199725860332928925347596191014918077016053014 + 9909206404814481317875154662284644158413522012241871567063512207157398398808577747347614035401411443650498361772558269985219726 + 7744531085141281581884696688318667987388073192993652661160923279555067568241657394706279105517300977887168465546838484164576246 + 9611748410338839797298552575152326071882814435353560145135335186607329942289657269580962404267932188572721339477733166705898691 + 7946378873728294158344802516673294879896454520313415594420541327407109273815189756012820920103635963852069701484919842956064247 + 4874591841062298195410390631359369161750834793590724525846541010552709961171248502344146476896644307714211419632056930049968152 + 0852013636597020207693222771451991722621240083418836922565030460173149090294177983564964216327697927947088353859239269055188074 + 2400549504774664967997419613371907388057256285629514767888950107220270166626488534296499500671373046737811115964349503266901011 + 7846949189277918675793279134349974486913260503583373441600579959916070999842932572749268240452265295033063113981992389359199980 + 1807261813286492446582855762770791231541210822077548388510880369998042947014204967053843960432445968862263380028288322991265906 + 2762645433260880544005259370505499891003063278739034550726117946384596067905756389481622864019774830490639904899687312014368603 + 0877598939078117695418432932115534755404639291467885726434445252435059379183430846339103652602297046524638381772417363883263654 + 8359730049870608112690328069372460928467332597727838745244400830648941526818883943362511766258737811338084111308530830389543560 + 2410247474136168092178004494614768123474893065682802068994067272461583528237284734448787471492174143726629957921201303786784836 + 3419244084207146670255645738668183101897287707313517219103923810981141387894446864639750358126083692639837682548305250192071549 + 3436195357834369331471914469743643722462664355231433520254139779344070714371148189113613561574794491575113019678653016828154505 + 4439128393642435861391888228862161582205771186938296499633571218847225435482241772976029740807151825694346388408247223423817081 + 4171338859609192030035030504936231948955422469935021643277709598491047020926862755743386040228384976638566676326191183360208322 + 3510862362886970176404175491659583359746924395962009940383204211293131363439339555697993521569537948812781342292800263161257581 + 5726969821251892647951678196842942528264097032325730950425154233756415408461741348237674984518538018983212811201588754756679009 + 4778823499024627173529601893322692810338013854983738107737211008580929848242105038076828712411467725165215358148210018424891037 + 1496776225022474894349628318466731097093204838845621769757160832213029122420309244726997275518899114578190401052089674878889558 + 2150627813505105989559012023523240177523105542484058646465606833626398767902073791909228024464129808047176621447241995834760361 + 6052017973982660323612282677894938232580284277106494794233888932365369180563831962638387127741187828046331415436706723759407894 + 5180894648613337149931873741726031450761346316713499884971063033267583243155357639761188673059015634957451632776491096066497095 + 7359097724129074389636668836328680896804756391700054500433769926703593431467797993796585602417512809374217324038244052246360155 + 0320127339112689809171849857331267778192107524355671645529083978652864384633410979534318842451250352236642968028403645196181521 + 4118883887076525329129847815663385510560303081843081502700312066224535446821931779450723308317216723461024137619749777688133771 + 6860925861993428345905718490095572908986315074234835981417267582301259888782018674341030424958141289788351602467046638469818924 + 0143824935249223588362256342022083873670928848969341583470612068807101099916137780686058304339569283167254333748135808339800772 + 9845042645815548051061661959342234028016893229602886364367950621055704775648720419681077874002883738984453187494339471937282961 + 6185757617018491828131168967624272567910874050935111978401025105754755523134728391834040088198125315748002405260114662632225537 + 0001356522238346600683651153474644012974963965580249070955634679932657691126596449770936543341015260416997826513343646145044283 + 4828874167962259991499503673600129164632862005208870245173240873585329607224314026307889603968799682624300985376989091014318333 + 4168596789573195113960639290119776051474016854378309232971533989042184885619296187870057410925857690307120789952188315701548184 + 7815816015467871136014863206025674274535612873638378381437080759117487117954420502148760971346576864484963796596882357424854163 + 7278776070084196458814159988413439534481041061939764299982929635630954177993909110795537307351830954498765311432170571984412940 + 4866643127910829515007652463394937334032003939291631862785106424516937511685939908344347334073225050202328398177347110978277589 + 8801678473026832588217149008639268101698714830248585119117348101801713106570301483277093069752495633755950440945309944552577536 + 9617526174545226424763055218268088790352736241937230497521917254797890205799826169553805927031554132395993133419267021828416925 + 0588595739388380595646159745519694245103070425108579498054959496392270944865180508024017295767451162258748775694293117545535076 + 8702772928743292051022384687311462236447455075709507160040356608423402093661525464261088741775321017969842598962589897299430978 + 6237136476697160214138655273076686746008630927947783830802379210660809805387482347921808311217785296709410669748246476297410657 + 4956721962293257951828094615247811594706401567441027963919853253912294488061757086648296894406025064932611868738979275806148213 + 9236140986639524620047147846000572917224921424609362686790157846221057427556655153843449488971368941339909014048314921826442675 + 5366378038534835924469785482056822213525701444985254633404597205774596447015868437597513680309327466710395924280351223623339183 + 9261759487436784234076954133371789265925256106206142125748755816777807349896143234487553341181444300315188799020606387261852065 + 6449231339989879656134113568400091770993505914272783860814830316499113207580889761456971111735531955653301180535329421263128180 + 9593132987957417462820592468596242875901632353771559986709766159903387546786798526051530972235857175987208754226458183961092508 + 7166010270941368051527588903270384190676373547534758318035208065713808112773649467017099455130795910402044915843292687098488409 + 1937469715418217414858420673158652244798733546985659728265347906685952080207655697652213278741491999837300249957163250199620558 + 8228542398195856592161847035652366519403982135370687548941385579105164032051119406009514327346290711302155896619001736994882959 + 3637688922930586118891425546901071630399830689323382607140358997300211646909715463890915726479319114588493474688432142961034974 + 3846092487931514115420051603659542019430636869539365331821500084544038227936250365288930517356505814134292254191756084661422225 + 7491630641568207270697424777290522332626816338241009039782131614678232351819731901409187134000842000166738975995925878926795417 + 7070750968877352578247753117115107850387026880348329157736320326010941179590211312594408978595708610843851283204781916328035469 + 9579425490712849875219973084577346692279033275981940434988363957383909743141776369454560267346747976256694629456374012164182136 + 5715566001611830336152118124700907641876141203182109095013901373890817946278609009427237417191831719001170380251629245333691467 + 3777911831700858846402803605902436628175309291503492499557547037759922326055839219601687167716391664999501580752878380637519910 + 2345655297190543682328955031766959976133728834616422943753268441547260728586436316967787919247613972239277147037959837372479832 + 1264917138428370036605146743753527478105136932962495735773676134552135849746496312485051160777893753074748519890909181403083444 + 1019752269689676763134331558096188560591351764633604225395078892173960817806638672836991960044167937282088675278982806967963563 + 1646009447412568269213391779579827953653829284427738902923460839464242874336523939561058096952551188341759036552715805796071087 + 4514073980834947668053426086988984219335479873558292410478690803080693664498437799009591988658726439726875547569087833595254435 + 9375888306479510358575648650751703046541164954438171217850843228076528589259852655316343249086105052230853543970799873699798265 + 0497165101239642555970983822927664186264700494353584434852254137560612395432178721562325965038387864052788810184396252265391565 + 9637587742861000445296706995627451301787108835157787393998256171661400401789319408568582769562951011299994449045177879050273430 + 2769638085862574311449284998834663396793439445498698446119611616703979283028314824805123683773362437290195603306996434216889157 + 9746240352274295235857973544138134283682808329702423798784675201114018293748073782256043515882634590777226313897991318556273667 + 4701746730536780180098002090253702648694901490740529266632381315672027202981413355374788940709298520432491519903507229198264330 + 8070148149525433117389602780506057744721609297582112109576333690538110175139908485162827329907610365996630627743121137187293998 + 5104791573207818901442004558359267736381147580646586301522698902268860041597652832411905302035950359208853670857974818287006889 + 8341316079342584982610662915730694074266548963632208359785240542883719157226848170269734749166834340935627403531307648991671361 + 0980972555646214322144321439065894684434469993258702669138171566031352957356377641038155398195278908409758982420498643103410893 + 4371601001168990355540734973104369357289155288304862691393888938344400557230712070949783924178880475136899894295722616103660902 + 2650480054074532640486048424756932242389804525662345983096982594522899748828272298964877383316038674083325253436014966605240140 + 3856519566975050055663208955514019483009113366052382153385562181732228724721105677879336134186949728875130780075511950816508916 + 8078373724394599222427487550133729616625008462045077201670397039714132392823230257154531053190372696559721189464062559107218427 + 5533555275076610788085420797340154399319379967237990930040901555785674670104205199936906742420190549652702261090687000720033243 + 6220111323366364001766649253557628713894497231901067623752708357435827393686138195041002675760831950319558894058730884453262921 + 2672277003207147557184524907281442713352109540367339513087567600977008089227949901291846746947778742548425956666175882640922513 + 1341364992092721464190832131115386139839119999152547728030982443332120739263533376607896512917871745789498861904805336640005368 + 7658494769549719799407250503812834345058648333149043237321838262779633765459673785919568562329102220327192186018538985265090758 + 9891469225677893167626557199385256479464450147340948798817312917938176509424351376822942297600700655298360387396846679746727135 + 5585419624514115780086956162546737430419445855772977848266264876064891998070796161296726855803937113862539594644902156882096859 + 9369735292641205270247208512449851304357935258980017450069350537303506725253901558161348011161752800022469320895146408450548005 + 0250792460158595347750598522833094847081172052676835161342784300572879217498951077354750791561533069799550859447965317570533329 + 2215924262194811929293333565918894008757945953561673129802085846175034801490539407544733104736094736753035909391436637603434211 + 3003828547025999647155773214469770001753156334255534694689533941988376812539304881256890976599139258146884644045613614613975749 + 6800289970404751783592624836999186310592737935219914459902710041374388930994677919752362443845898391179354567028930335795630336 + 8505759963363966237797610984127231223565214326257640335015223496586184791131912377414208061741646388077399037761412502229212389 + 2367769534630970786705110465175915418118488516256049569042500049966228999665875815493320452276993289094558376973109778079159470 + 6740493910513290939463082366133739451516673396242163998658427933891438988618879026121788841470475041492666218138874169322768351 + 0357303411110414929271994301686020384849443986791255124503432672170825267728337655437754688169388290097504447359015466216468554 + 8192240142847884347063706580178899765888936207019662263339819670804657575316021484690040614562949295841542317355852873318646994 + 6622263158780477778507038872483270954479088649415292887077869603719840994025710565546888311161500807362774885446004022146890733 + 5176307819234962298055575706826929453118700498832781969398229886642207165799263179818071674130902753482145042794765741675062383 + 2751302275326116756435072977812989216925193208517438463427139377868288067976273977283764655073728859395428187073500573181560080 + 1845833119022235738677681522695682631533441089840982284202257527507809093077654733824218731845673599302802574363126193666185391 + 3166900131346963127277355530406427740614776135936937104096485949875917688047955787215898240293170537866227146364747857832752126 + 4669645223062976703005533676266421855057200556768903274559944244985743499257659816488004923631139517399183550005987669212203452 + 6297157628559223790562907965128004350109267209905657347407682698178194211365899319173140023292544735908289515011446104226422300 + 8502054721545809152280155719799579471628904200160322267901551608506906168294064129630324866997658363940456422902104004108177137 + 8611455694956943077268590839116881863962149614279260195002902444128093061737269752861412765172102748566330731758569318211290162 + 2118077432186424807711637317365270035214176328074110410477259086405158562676552653953649314850972984909614735542131768665131395 + 9130318975369645829745860603018652270421321400871933193989890358079853776989047665775272263249474986926107253991947206182591757 + 4325629926598371530112760898633445089584186304063488458578614511450976053503391266403574144006236271752461276059535144816112805 + 9310962691558816998084824217608875970240851404516558899699931821439837002656912679683111747809512293159335274051955163666587739 + 3902386789985655245291475443305453851903636698632422663873769701394003436882941095444088054500028643416504275287739285414766428 + 6731684059779922460344447840778233714899809573570342484286950672469381242333715669289828470432847009362616600780028432025743033 + 2276600041430073716292091375271727222342465787797822281415644677410001912257463959430983836963509288786612692459635796134586826 + 9782224784159961526251458006646854715817922665126779115397720973464372703397941849152840323345005890646175543131277561028472366 + 6526167561528291467123805366888888939086346365110568387291388627679455761130295567840390067905361907699677554800553539940686367 + 5318634933920742765367288875699774586510799452591417236786364826083325845867157040527831875773026806940962750032015566117391953 + 7493598975572064199793468603272146721884132503560554819191261369489899329392181449153306365084506335645635211479940033483680033 + 5666857577286998209607341637144223997808492861427974015972123407497307671199006287616123632355515817115708130939568369663610192 + 1205647133800994070282776117664323692713443344045889466640364601504907846992739340462456897562574412472399343745023522153250853 + 3330319212199788930516095800858918371890861157149091660451404495244272634139073531985568539542425087248882661841548689414190274 + 9339962909966865014181214015249254327772461905399600921043142492498857240896128334661531817157722725029302364254696461600120855 + 0275915123664954327692393323944686811113159039391999178218124646929218008261416648150717574114279175738099624550954907847794987 + 7571438595941848638134927452374529897917662628583906227103605014116793319790628080501185855732090732338304609688113595225239617 + 9130230309512350610529542991215174872450882806867068241227281773112095423160023040208987280292016395893990306260033588936149291 + 3745658203217218584383948667226718968580182712181973947156555599253392240064780457939033740602796118129681262618905670233538489 + 4412418271808065273371380680584774737632471892264742468899650839254371362867805781616736426407895133489629389395846145646724319 + 8489210495984684333844268191310832723383161085211929007986759567690696951893569242504292424131665261321552489038411809330750578 + 6574010925786704765333558400961864682658986685222505394734228960816617397028634600968531515638569668302469579752350128387282475 + 7078834237219808682337835724461339925697109440081470255808977861161896407485691000442893960515108700590859410043250399284457162 + 6826005017559754965121660973424054878627050600950197534543970583792709158920574211453104472613133226055927030752116724686804441 + 3714997658728942284217722016417944347609973564690519305766123183125986230197933675112901682033357194516255841107152642532141304 + 1057671755594723253182271537993425618933500230542903348744403011513962182314508888904498037845069539547674219152154472098348463 + 4167698979868847784276420293320039606112408368549434641654634849595716003611837153708427260322734964264330233981684490094968636 + 5842205187892994596332543353231430273153910962730263311288493948447613898642287416656513718409931065308355871917064045665758537 + 9483067464396684153711784947324331651250593602460374159868530726671454450164268258494437853338327466263116015842104260460184775 + 9918327983152500807062535153855232542858746567492036007943220587038833257219577445237712255513226337182088357385642452970244677 + 7796979178949646284046620756567408638628381588842960380640158418933607236535455721736245193350129856456748190582611676103108397 + 7474868470568488770868160856619425486013084529184753412392811134951027143914884376770407337322922148422893409126222728159404831 + 4025970172900887552972543571216650363430374550536726543515591505239084581125341961497432836939375430662456975979411649814396281 + 1376673671354389313333179969625064091561856231653660770117134131024861451548997992193443491241771601133879416546391689721119253 + 7812382563778834433247309068407407067582779720037171842393136498269365501469642413788690972515921121053433102407538535462479581 + 9706575053071949026852790205126415890557321745536935615519559505631029223517371185086529237733348358256190743027438758336144576 + 9006414531022472111125196202814342278375571427110180645405421603811535358205031055882679708681076022342218218061708622772715466 + 7014411937404524372862470846165036293398376604107823885481595132489354330681978934995519374885800444029796119672180751145597990 + 2217635875626883098820646597303117864519547801664674186453314965253480085119898512655154794357106383983041271503641895125251110 + 3512252235837181461231288315033867607629725036297297118913502488196313074376766607719647753171764776345290627421411392489636355 + 9367329989873888631983207743830247822211335192876356701620415814984875713241717521999471919347104942898869901044085358319426464 + 3886932632919049176756333953836633255259101098478704964812325499313834184343270599669768380535271527046781188364512125103089728 + 9085400532850996923140563913725057699601728324308946983801623506065312434754540522710960789580013319731801582815683477412184104 + 0482120489559053393661539069411739064074531226478250805786509477678364657275374151794004014104036094940006833641747026194721664 + 6223030054108461763808112515000136243498515799834948548188322786124370768805042850586372228996897524679407164853720521651414447 + 2045659821087414454414430804224189873085215197748925231475200893842348103097879724089151789730563882183249354356129862099874841 + 1315828776287414001746118239879779806183081196189658013775774856212674965726153082362347461854112895332344854176341904165597409 + 1213515137476784596057537684608135941219538557595828609988436459029859804112595309586038750020095414785054256852539919216535980 + 4484140865975650257767631970278524142097436320367062170812973468859967284286099661751054315067110058820945519136720185944895374 + 7742692644036659798892433853855040190699363942257261289132684570773772398269153067661790938476854192452194252168071064023197248 + 0852041937859186893599452942342756186406516322350714595377388609314520833365297395472603829432190992959559426685189491282347057 + 5433185143289951693194250541689460837628217616946850778491455755537650206858581434235195035172795441448516354831307931147174885 + 0450942348007827481803050062279398301950579282155758680606572572109484512358059858330484516434220157350961537316843651345720503 + 4380803663067690067136823238680695720389449212682650668097530448778728543739620300359368766106338322729357455486494754904098461 + 3264642960305581246967575470210497486665490038206044077023048630121578302316138939937893860519106763145890200076403810118822241 + 7107639168089983991587862527040150737165433796689810859573435301169366192576251898692883826389304101824844158348543802249127582 + 0669598166832510431109943775944521732861864105283325341271770704933734103372804558821648326293865298432780241079718755089452707 + 3568107971104085428061715527742724933050823192969880425640410593395489624255402189258495659521212800172822796344882503818407485 + 4194972547530169348356862971069263077075953903800152306693089832494384056021498593498576727061441507427007792270872575143948044 + 1172788991936383893646302947517752222941032857029795292428946787677455477081292410506859204482638074930525197495818984377516119 + 8708727404823062734669585099177621030117278743659596151369099005394128728746425149879168020045121622056893025422397438542352826 + 5536557575335193916360622332260209029723091397745281648820143235533928946294383911963312581783465260511469849131842805230470062 + 9799128949323644060685917638538635211442541566486657515013727896653746677089071768007544683389875228688476415065723679786222857 + 5615573863935839938823973115950563644124889855629743447770458847381603667537087961954383608440966294356327727154342428403717584 + 6135719365304945156195903748702135001035781887797234160617684449358873860897697192990886253607384422197173334101390229305548708 + 7355386834242660296627412137907269283682869702323709426719706244145140528071269497974044139621935732608883353990706800769609401 + 4117824188478783409286690916041542923147052848706784080198351893505523979781915688089182588499549735693880215954821551279637108 + 4670168752285459430877011145545186817108898834243886734027847064654587388165854257852169040893626949216503073312235415138548138 + 8311486748387427946913806861679281620866414231742557923760474181682196182819449180979395793050862114181314437692082443568986323 + 8048322367949325657177291617359572925594555792044926031542356556453504106573058251613848469630469333674263842694166478603019606 + 2241419420107086119951172130953831261301246015464350985640311185360710868324911647982596380951605647282292847958812174415734380 + 0207875370509633314857109554449234589264638078127939118196136645009058962335018366740029205503954796978369681506112588271652726 + 5224125202089733016629542238144949897132285324338195131993745529968240465385054246763922445031407439625787648928055552616882109 + 2793536617404132317781661381899391556171029177272445009604125493001682989300317084296686416290208482553512764370697922889547543 + 8188433691033017668731418898412943576673580084814405684350547059200277266867531820522833168888834691511550304066275553413432816 + 6069781060072723977215798057681530374205235352090719032425665651313169145801463663003622748057443073337332287692516062915866474 + 0991144941963456299854456491439712458220412985735998277280486665724362417204461793739331274746630407706323572187551658131522029 + 1128985384630705817449509424373236680198643102398192723995214101875334517122923435752591437827690137749416921444994412824571229 + 0933149859869844034267514737213635247382994476023098139584524288805316943149032915781109345152673212416893459588048333327424649 + 8431499800476711779747358632413776057189971388402676768615975922425552726845845057116844980552680355154340958763735731899549226 + 8999746969039035522234132566990886859367771300359825363759150761208120895977530444860283076544729935781975800213516901282765869 + 8578384564148446021966192696855640744733543364607326875346561423047230035981121889907856300901288650704791837601613641976512860 + 4782737185453902550739147496508870329447551421595794641391271174654998339963075546317914475664543351090858707240517793471880344 + 0532832780888888968522715514533732512924561999915854959906252640056974250958067417634581049729155174966017949852499049433553005 + 1013570953208696598838952288133824762193269724513979589866416713036164401176767184475902330276700096926543877198993766233942302 + 1558731482683686439823710758826362624215320659618968974586082717778992330445630506757688512508423035162517304559268454636939287 + 0350643207571320038261933704850349754594287810435189119965241800581118358691680807766625340717143030794170306528880710869836401 + 7542021244067320014248296046012617744009265286583021536650506535157160764351137973007620114482584140630719966828687210278471738 + 3972594767241483050839240086921327315906881022442251582254034730627668558044239515436332898375100074941146541911588915186647677 + 0697122022586499143860386882839929813751234590790881003673047769341255221587898768035294711863803910391010620206350075218304635 + 0915512582808181894140392610882201933416172227163788895549745243551406730258634514282881847090763083210060265428731131498145196 + 1501512625884967191270103224021116637844888067197984181082849059840793925774486252348044423174920237439188586936474269289045183 + 9546757728181045784907692074408445085975750656689918729547020741600264958315888287557582915125013916814828453001978125724956413 + 3762013269830490722798916645093224443451891592652341999436840113601558507630551284115296518475712532341410529593546552381421688 + 0535075660768315265313017230395001783344059304089071262026544062275821507449160749765605530180854702975356649517426392492153632 + 4462229922158652059017569592409947967925255644154395071833612619360534506981545280294824268624971434641426791536487863590137885 + 4122860079882835156235088149203967906043976190683635109983922591971046404170885166646247578979128875141127938069850765269247014 + 1129866849265718274907637855113066201183196338524085201233097892015346569822121339489136356302467977157281536251430774161642528 + 4989929495806193845801738597980701228751796772240750395477795189154079611747433960930484756810247462060407330702869333431213592 + 2584408285550889731205066850550890247663800179003073740079409662955268984464235081016863796902152306425169108972643255331837648 + 1846495490902027499953838660575831876113795963871581292212984733841932116361051031722680807069640515568611052917719380714508500 + 4730368154761060853591867016650935034777443474265562879400822197268954342492544791524055284219250660710445080227842874954141063 + 2999165237216316240588784731941187402326266210523501276042349025855852110771327522344504598981978041650966736224822421754899433 + 2237345937661408885897695793709671176319094949111986436639240560063478917538944076082940836147591761497957719533329126550091001 + 7598999755791735199200904311392506066249434460145555306422386713523721542555336766166589674039359217816140532997872100172694264 + 6085462229902194135463330821695657542854346332891821785703935541518889566865952336969577854576497261635473651422862788436766766 + 9330926718781006335569837395334762725138935227106710853342363931868717426383038886351253414292607302835343171708502682390162568 + 2759725885383603903963134803626246023341697535265756560586925977858745569648871684971845885034365173610581864076735566479105747 + 1316975221277998480665738247654385735782940591833339656446094875845628844928541054371377477189441032462815404076598890156931227 + 5084047857098057061549088214576495134500797236087647217879151791731034614882352668503598335757353547259171118367223224526235321 + 0797097525215466425082977546510079918770199122108187284931098479825643355771575695825936128687263528517399780086601002282738464 + 5882108977367740469432474363253310136350409797015594231680654761034810033039280285322415385168502267113255563957206593967018787 + 3765499022319437900072126982943230712423709856742749800481145115762174065774560039072882469409389283337021169962653600686979665 + 4601581997618072107980461792417647044978305789885381659804666757198975786036139854382381412304035407153678163339829269303413079 + 4804720639771780250811522331538529037693400650190090078194406321327819886301852415216493527923345326577327202798642624789731981 + 1262413264233591997549583133381940611046336903584987787247990058376502498817637376736904140547566821566316367905947287384644751 + 5776817509537024183629053964111738625804577685331848301319393405578215972673272833105126341165662081776587402862223607527237841 + 3028857137505052452119497280084550108942293030946862851209526606327291674235480503744471700882929025765105260116471991605614081 + 9340100683840148792620022922546803909003134351687693370396127613819896251128556322124687119185535407506368947843781106277912265 + 5837860085277971472343245356960717599185735265281223333386501908378356024658012834775741482445665420888316355875215276412206400 + 1493889817668204302273257693995210600140074382228307911629842034054862116792315868260039297702147104111933826341459504324514560 + 4753667010660505615221578575743422389046538837003732162433830910088895626144829160559920876420293005201234062697339903600869729 + 6354021869352141987691776069755076073591529011311969753213483772524805097648788519425735403544963778868397356812064242294599252 + 3007002284988957442402223796792807680185699679494949671140500739304141518373349678385232543712822588498429151363366914067465545 + 8768505870421737992314357883218463757749966400771061631074878673057982116800200818694276568644501192730861238043718483873582182 + 2517111306024948547742611078204983908881805478217286398022649611447119014425201196572509914583877236045184752832586045682283149 + 1376425079937583047628837215348969478849396716756967260659465804416943561566523910593617918317955498182529845524570831173841723 + 1739036166752846450279902298627287438597800774942709861167238037011909085160508767640035085875297386568223167138576660874567993 + 2749444684052418908020211162253183694144723421354516311236418763218072849726536005435788876083510665834462678112083821685346156 + 4979778261313034734593447279308534789267778320343662336147199781647935359075816167778411424508493052174895307203375091235720947 + 7206632108909493796814807157234843620292819404196257674170712616419318834035027854762640349933755746419728237290445935893359476 + 7972523340752476063451026561953128800722191374241698295085331249527419993680680244353440653002242129183827478637542127263140061 + 6106361246560664390746249407209413785337414934577733325155578012914242942249188259728108681483189855141297703781608717770284437 + 2459983080689617774602481236618573771655193699359105459132425259318658958293509205828433466503731104595644550263940782605577596 + 7182234637562052669040625972588934688697821675314146092726738283785184154736418695256280074985786382718815935852352072100348316 + 6798709996334119952629721938215622401513286500076236957073743607147857811179119661766817565585334251822559283874472847953361475 + 8077368484549177973605286548826253514295310845993496549862916394171225254015547467894554807332772219846678815481086218479850253 + 1557723569466563274008492657223419903746768944164337126986375831639044695750746490501676088871281694494821017358352031765251392 + 3419994305802489285895038983304368890483549511884971605938842543322203428568381657097437964153561863023468226697072309642108698 + 3155924019915150179568158859379848450337436841515789553391587979303261228659176045375192003213895824215877498665997186076059865 + 2999137472267175701076913261675494050812219217526275916261893447733447516002165559492227300890776947227359067981526656072673696 + 8601098495166116027734424221556221472614130194797807299983947972112789211510616421380969053402247170620773625487954585201101683 + 3246912051329707460282887222043348831157339566467828142441386949856139091307353393247884498427787480035549002968948796358423112 + 1150576199110861158548115562719716941558388002376600504843363323295796185489468606412792484061811432762347078760084900402466948 + 4752997880608034066503743367113742314926769742881109939696550927489876774818149369014784149716022391683583701555271412269098049 + 4122947315189371954201913791790379829165934721428116210038908501041491200253464990161405881080768468552171131345401309484164251 + 2900730978305956981781132350165898118101889333020350831669690402919195278513062935410969054110767363793161548411520509850489790 + 6317140142444713262780353377445709754525526526100220931420853524029521161445026020859823577131205174501439000115119816705181410 + 4499991523210057790779337069784661258008182657881453125037535965670105347302421579889956188914279278573529309721593121892469205 + 5508146256593369763940336135259800659809619929794178470062048041370071430831208645554427627646035391559292722312680898801625334 + 1648967526716449029810215023304697906807519889979105852637730516484206305531886474058371893246706713362439898050285759339179316 + 3759482577410685684593596493926547017312369150876917333521714609230709447558843397643743851645851153700140054595127571231949538 + 3562024855350127743440468170916592187245116700044293261821848456699166330596624128415577062851344089770503995251522564366175797 + 8477766635255068732724822778949890633417123111391309938080502220545229819981424955190249946666498348138015162432180329219887241 + 8326147305998052694691664218432203744648063166741259109591553998325744681167769329433557902221338261010505326465825260282053606 + 1089081066369978288230079958586716934294819087031912657105656191281125863299636207713663767265987214971817617524167760055475985 + 5956659161052521449892118359418646820302358805073751690270525811449427458601574354728795417080178749838253936083489079736869589 + 4756040554221482987126925729358987605986625930694194674956898248814661136244491613548633391179640626903451535330197156879634503 + 5269657254348772763363513450959859105237330221730828709908803147787150002260299247932869706456162552333441429917744946610133738 + 5165094570822740809419687589443353580562603424278039485215120717937567901150913213688361129548604982677760158365547321585786532 + 5721986004191270987440236388972839714531938869537328769699467486823118683325371541953906389947764104960444262942308606574783420 + 0825423274999976416479179163665065444342056794814403615470874263539258759123358841581177125724615901000777617590704389294753780 + 6742419699812742131364238655136167729098672287631443854160975671169256136755724718145831652290376122821890697634805848496276496 + 3900848450956356316829187800619138955746586281240305331127062820418337136267131988611645101253214320267600642044789378308027813 + 7768142101816225544376840102775693516634889161775441232950103285109025549587962218777853283361116377890977393111956211092720773 + 8166062372469258701826599477785259752674604446062893635372304334593302933414637458058589360745838888558751703330971096452276811 + 2564850420537564339701047323195837094030546459418840734199428562634836997313660393990033302759129375346102025176996197579767609 + 8872870135828449673289983810960029335233706075121561262257287764860415827304140209641297619500143080704997500176861691643727930 + 3523914550868909381989245660265536145050317774721868915147125702074806836551953216452075481799528663908105214114354861340552001 + 1593559589951778598427586959614078571783195940556392469576085221648989891950185568932203712798348499019366215767685195049047391 + 3677450698912939130282894253043150590674429032380702463421683822229640128060377145549638924052619130706857319423374607432012118 + 3201722283329551818782298921051193764095244804825793425784091160773607662095205922340014721050275267634431286245410339294369403 + 2407761928636596422414810603411396624762992445889584536298033386878386163466235099237586521069756385945437909851885956052776101 + 4551892967264629771755662186507262378960508623998075765778878560332855343021946501189553259398537769291592769103084773248272732 + 9106997275950792264693136508466046590049216555344492329753333502148103978681698340982507624277442543719542272924397318970160593 + 5003643337652703728951291818235842005801228735393820041591928726474748137284662169580644065969190131576241311478203049648965040 + 8986752392715741495979561841249049222033021019539768600866686767034142327899022898431650915325022449300084738502689817549514938 + 9360763437700859982761849014720209991738148978736994931574590369983794309597034958260372656270656787930070334337332515206838552 + 4451175037964641122624713478708404279076794770827862704532161639277525181767823672699083856308324336587319988741595847500500923 + 3042463864865181170367979354550819973787820266099597727415684485159423697903917044701020373206808416942704276522208882269559354 + 3048080200899219985092787175219925954199186801590258882778436766885446862979938621696230463254471930200991285622531815432909506 + 4494465194385245878424876179842789271630946260267264275467756829223006003558035998437034034758226419782837401641627699056717218 + 4254906820448949384513753027180628971432660348348526219339979967375196656324459448972917993637121707012531419527163028051764969 + 5795056709264059459045347065077313003930925374715251843125468051992798115117609874425243624614071216341941951333443769594712905 + 9786422961702175763231201440570153261798473160575498751716552119467779736203318520988291431980397558340560735449110931384906041 + 4425505790631864513694023511858116075339628625002969403915799344384754821079679161200533710912237340094421570796695940926114650 + 7558163384552078162151051048460153091046870543482529259775071328325205703384361917997334121827387863984861026567298429845774499 + 7024151222382954834390823993921385978213128615164507102313528814208567079688499912070171914927156859122712993045849060653099070 + 9429307166946990362134229731057708239430020956417601592711428461279614801214510176796114831132813782448589275144006367262952407 + 6718941975166588281116323921210724119843734085559061091993083658912394337924185488399990441930203011310984521684045028699686488 + 1289068200800732284238439423123562064066343303384293220311845805205731603115472146721163687728630207002750751276592100892794448 + 5346713601139175262412572458619231213504622828349869740030359059521925593845499598173510818770588358689016443776827808183107359 + 0509643523301353915236067697449265692352443278187907371809463832094767055096167823904552345535023947977150405485951950799761287 + 0296312146861071422545805752124301678869184550494728174693762162879350214577985621448093757895707899661121270041521839117379026 + 8409726864010205799722565483699810469720898682668219634727965108320651761711145638969114309423068089263623838477654883333920986 + 0701982653061769206880551891091640218809670563459796391962611157072335109465122237619770084725609181414534082646884976727487576 + 3526106930335563839568672131933814040405238902124634964052890265269753914225841472646860370300002991439661062411618062909298184 + 5489284594499017553239845981638823575689673477128445661568350850251951827238826810782941625211567718831490113495662231409070347 + 0761858518186015339779421490664354210470217380607247145985104277374945800693689645130689632481933731656998223732805590077884069 + 9539065740290512427091282228814664586680546652097563995149483899551962642839270109575078586841792310434801955703204357001468021 + 8203312934682104375075307914019684558657139598128081066927393125488596174624606696359883862043330061635166484866461998328167370 + 0125977272761404461319903866680344397363067561278546743044165247263103505646656505183679223334371532724158953424891372755170794 + 6917119468055808943262561786048361427010843965462318965409483983665658166958859076133376429071237660115286920877219457193653148 + 2210582961962854397595552344204221218872408837841098089244290975638461916790216426889841183579823514753626176299268639366257142 + 6938938279494808076759108059141376006848614180404742864748925105751439953802762622388768762467629341123548099684486115445621424 + 8751508911757378238494838354486964489105407120238937324611137021997266296685725619021335556120419627792798600024754767811910130 + 8942964732151281745754352094851080075271176779020939272053185795856508342400932987956154784656391491859464794187568016580758549 + 7093803490558017110343856896961686184727738060163871518042243290379067462803909424058805017311424240997471204900355661374314140 + 1566736119124005628798032033275204642554171747963659618881718232992872787295516246973812659316873285663747257448232242034285446 + 6562507237663679024109994426672469847713139656813945226527911495634070212834050520202668179078431355382392103665110926728808163 + 7163337093376914471075674332970801236470473885515009415164064219689152465011362048740380213961234696943727976782304542628115287 + 3743855222420028553131853842508021542825305338712873483864679766747424043976484573734764155416545908654414383080932700776375519 + 7834242892295013548785979422302177591758705851513681511359120504187140172485698646885346881713211672798953029529425679446990175 + 4633893183134377338289855331963450809211760110920084232081216223646405738494934518180959043407239414117561447413964700328518217 + 5433662660787097930154056128793373805525457327147412372094936236754711564146018693671222546348461125048100620268398154557791577 + 5116486674264823893675387799935762509658389400995246436075653037631158518006706329179420693907432583221559739906432889568752110 + 1646689708083793966601961846963380825939768409816872372745312253381435289673316700861369097472435861788080748455563750632269991 + 2394913678196583770021969391869849166343366172108313828891776494450171319520427070741615104344197304147604907461161478146821535 + 6970220265997137270733854244424832298730380713169130932100655564124041223879414671509531965328454187192449944156019761861229509 + 9043786409994994408835814038392730289274231805044666470305971162880140578631950679277309655392115372566040718447348800220519568 + 0260472202194716089247619131312603168906540268723365507831041804698080034582459501938467511494620080710391206340388730610940838 + 7326118518322238969330571001468796819573761190336351214992854388628577544497438052708919701742914513344327189122670316147267946 + 6390506784888882547755768957113718192319906860888999507544967824165514074944084153555022322181782516106164395236293833936377054 + 5714641021392941796626276072711028884736425391454865594302431453743809683815572479844749782164523410744380979378894640742103628 + 6367297859579910614284261237130263461592389581599593438725404642412171244089574507753692124870352648825973497683300706972608091 + 6528879643690843406788232137812536357500339309765626622435903074816275044864634059559694905228929605192781404349845940406623980 + 6885914653705063359510874305420852766939519431522048421204491529430787666838710231728773489324489696476746687650429532899868255 + 4233440617969212981294448839630057962261459110072028596849512767604956758310477460111261843845740348872559542671712436710774055 + 1508618282454022497140169566835479909506224026572100667557407598641042136865104440157420255694196211078208396396117860451776365 + 1507239834904105526832362883413042406464314583874137343256081467177503191240584039921334732134114272817444512404536172921303844 + 1462051089737008115697275867129401567569051007638125298802754342170903145796642346081652330045536281219892265708368809837219879 + 0453685864744973901237027525243434738854537803039815016737120599127474654581496567442710142699846446910049480896669404203340348 + 9346689990227089014642019407223078337725269644715473933462904642091284492249290308972584444368741981346317066840314608857364424 + 3692842182371137943388889815198380579665396475153546930512504814795832691928659417816231253704717088404598973194431677726441667 + 2526815319204901006066476270701860537782781626529137506566276977867530476935375522834441559090476111355166836264357254224488482 + 7009126058180938597916312502300245038383750490075362057823728327394777642420436778059817272275806207554818391187127829756177915 + 5110816584935888048243109800031765306763187568267294316288420157299418121619714954580527036028226556975389796598626288986624596 + 4019814997533165299992337612192568036796309043358811887855691200355299547444919142751489527995336846485123932685995757878474429 + 6005599839728025790953582536623365308961400544193243119538823245141014368431208016452105852057876883877763572171550179791872562 + 2500356597670124887859667877622171934055903916486360738831160634956448169247221568037938498171280531058898708454833291828495747 + 3109569215216409575065435532987897643346725582420896049058159554867798859087403090846590114662541568279219050551516019161353868 + 6185483127396494726368946515385004646852626975268477683334752638226219119476553266373574505398051454753329418244962919295715945 + 5344724458607009080560091971792387153222793929070066348570583467465266923727598378490443838259560132593811322661974372369019403 + 8458407692595863178782843772482279508788218196221474525584418608306184633515880367399229446502766746947115360332883675953446527 + 3121980707768424272697486172479450164639268792099956499632892432254994295106673987928794494946432347077043928557939886000171261 + 0577050269924549664323393933836052936324274196559262739026908246179444460993650264121746529145829029909925451248158087279201429 + 1182711132849414035693613289891027291528838438771406387710865605582990490514444755922132927296236610194750925496351082081251878 + 2109102647103389955876851996958955042517697886815050668367645651505615553003883543425993431580868653965842109551601532047774323 + 0249085151080461985544466651926919056622702235431604488689367549402288274733008707563604434799848038664792491456040962095929365 + 7278999875589390549123015596410656975040860435505974009899756364318118677742869501641184521884257988494124371969275324199080350 + 2143525889485226056728303512644071737922673006177865168448238248795782597126416756968158704999395137061079007456174899879867776 + 5408947704672811574519430929617541968994408425732774912564950806181733784295540418756875998713610000715279835936333399272549796 + 0046618750251923685648324487668060245166359869535034556031423916249395766390348943983259976779662337330101459084587467420377611 + 6066406518226332392745642377882173038406100184159399300600456331777383902825125059202230966872433187523955621780460854740743440 + 8412271363530715396852912523334867927661153444730211881314493834485030033457029175684264387115709617680689679312093978999879040 + 9657869183165570826073481937962858496613310115706782423102371799566041214554100144472536538085009196821977429400245149738069576 + 0816241320499554734167424446072196247447636657341202004109886635882777290094614656786148313850718338218604613751038747577375251 + 9117319836426478794488912868694112364734778843674655117850629082666869083673489067903986091210347641126774671760575626609401765 + 1008118532396406153376026525242599592034858556342525818569312902010080131834952260460690347206525525021427489641699256115948329 + 9403478796471636735520877378951136546880804020374976748551718084257630575582778549740221982719791953968237118454633169542490322 + 1286802823239946142833722240859834876694232965252258418975725767245437772637447581851118844815831626565504328510567619469003430 + 8292609187732000353612944093829468343729520826414837631688769850723905562968822078612443055462285102551209743540366646373935564 + 6195307285792520347832027057354006551256656817339152300843201008404344101735346974655890347210090580920518304844457209111402489 + 6224596631460367862650134161563558944936031773882670339156933695467888462978309028912902276648283451994600576418116774756356786 + 5472438323418087607827579818345851863545677098783823512135936630219825008658803838212318120192887213931109375285743757983871070 + 3462295993623789324823077363153428519235539388072977171154971504655245868325675529422838022778549930317329461099449011610221962 + 5200838592621585186795894021330350557903923860725207306860907835414568816984390887997385942459848064357524983387010427408109850 + 3373256185275744974070989354450321389766066372305525693275351316959271980719451196548752519719437550201627682282540860722912254 + 5801613469773755028551251430496692677302091408721986707132740326731209806971448849117149983546378567141073671063743582525928527 + 3697803453226110613863663691507092125649804560354539788548901908917360870034087584677937779281144785927759366742473292064354073 + 9963717672138768910209602639579145502161357030053667109664830302862052329208650435316813897369377235565986275115675225384254363 + 6761344873607397157287860030945733938977023836366529156220217899463330627464716487783276767734588772780285540219618726811099276 + 2472361254288850026102274317845905290678407546967989656293686796378605109224367092391377532276351514638630925654015471910946545 + 6893284960359512924679289275759756168128756913637757439682764283483027618435659261867805209746618113123871290501000298928987223 + 4604230631532001258913408929361874112508575772563457725381109205712576762498230243782724863115387239822706836827854691589225919 + 6353180226120522335706585585655463329450214403091956830465201717296254555917557791034667593584676865134148740185250129625269812 + 7681527901091326113048786722462348325784769942754780702258059604458735745233803955056030921585788629283445553041509260093245352 + 7309220586489676352977698261496440058970947266199089765873965038198042811288461602506269407874212537834374031596895817266480252 + 5671380781713371554805278200673327258182545730441250958579106569242653773093761570049297046722445961242199585137608405012572007 + 7828486850550976212754252064205756489990487555478160661135559387233240543781534504267534308047400112433806739577979094229507603 + 1735652617764383585639984486995149658650155492118012228612717608699086389981358293860866276067465797190676060353147557719908880 + 5809608466540093565672420660893504333126497209645992122475383330847359820073574627113129012380682929130905963299348891171922548 + 5002869804918377770158242860178234038771989441187910348213084777623351555039769099812484337067510542127104020429900993982081671 + 7709207109088318832932845793851072838104821066587277352066221192004565750065851231562111055731251503571280787745188052871173891 + 1300675988020851714469995143129598445432183378365444739669948446307812357058373524561004834384315759687175675721550162755500065 + 2986343436898030807360652672895860427883496016032784149587776588259863806298337541233639409877580883769111783951961729854269967 + 1601823981755766290542611869833989750039385604668769648848238807861573337182702195579127745245081404264493592362053024115769418 + 4107102716492675980158632893016973041072334043127798725365792088221597132425309628489541173280546793641323966773146909247868755 + 3819683658930608253697914654878640066261793324512623727802178114862630064529284630973855427311675132424529284212748792990550668 + 0736093271588205855246000014782826243591602482151161574269309829561758900770381929089531747951679154943426373942743857678907201 + 2579391599623221851200754933465381040789651168701188912204464482208095449667962715138795642341183881460864419304811104815352329 + 7570162647614550188694961496075537449438462429576197619766568228578156257291119319362788331980002153009584790725962518357588642 + 2867301400919047583578998934993306274019943104502333712247027666654628326692485228040996686989047207277332133939435024962426111 + 2800118335388070264161106773949228910777957160444174345990380796529948251126974186339060998840435346432168006747571320370538154 + 4476893884627071583698402476874552862205711529686822374264860104226019597554331616506435529408791452032863624032022777509172662 + 2387360521387922188586138212711962601419570169405135474539424296757638201501368935895796012267512214174579198583111876438042196 + 3207944223864976640314026742675529342045001292563111065130367748865114709153385711357232421423093197866403543774881366812947410 + 3024015733350974607130082705448223007580421749047845265584744661269361681112069541859763264352543531462633691003101294808859592 + 1169692162436061367720119759930066692678060291627161481443668541634202666603165593913992477700731194838349007676531720171279849 + 2751165267818731079924541076614810221037738242037928099580658966017244137214097278777683446450716576425458106456674343770827281 + 0396856995901845858069688500739423611458585131275613789773338642449531843526049135797567793850609374983112677866381777610197584 + 1531087534395262206112602286543697479767208631357778942636385138053327121554947922895001619615466561594121066079313165604153569 + 2093692637556395792176696765614996657813671032355821221008345920651772816571893227375691474134293122057079026746734194976675858 + 6656377492316720744820927448196522955924434793647944766092359157144753759050894426200065451501628415477521405487862719508590906 + 8342026934212011048128231645702815266555959471653323962526192450377377432253217447538860983839942343996469379287531744331673799 + 6119650763732836889688973448048471041648065382987440098529987344461076331072134069257926150018448979279801859696456939951283072 + 3364756734455969829310248048507921203362218977909063710162344883654504743601191459570909322659994691353369156210663856657262211 + 1878353636597017372001364702577584897453891661198546393569651046602221858825228640216854117340540870937305588763063713204215566 + 7246416818039080901692045886943289879346943533530756863194707455582283075691686089441132581902594229725501704594144338085541945 + 8508829844172609725721048474190455937918008659794137613216237230265268215971845365542440688734702896182248548131537748110574617 + 9749837159931616345230389269791318525672049015765330922830030005687071010042562156668767526231766645728311230400611546831340883 + 1042438692813477410787838927504883371438184111986343392632454033632895691282059130126453347410816312739668264804223203706756562 + 6361009275683200524885847104957823290376975509915625274519396770442677593644815139040216252662268629183385844801360269251220612 + 2229763646114181877287927118379174699532585850694835097303121614336315830870465640665166803477820913104310061050902102789844598 + 0133060603914382154852269620976632642294770629603193082836985616373167078617561223317446714275063351779922957184196466970884767 + 5219496051735919324804049698971068904312201333312370591154056704186542719979874616042547422134608890139798422893654424476506469 + 5309445174646633737921041425428020908437429638540244462052129439971214228921839562115695079069371301404828066341916732725724068 + 1929599109824380789046935363381838679112048207357698712063450869013602851026654755608800829647182811384855047709407638244169874 + 8711156655539521674331213489806723157012020673218852893220562275184063123762927470825532953422135931696172529627131694897868313 + 9146092529763359061139625016856546857269473202244951373230403084240273596615596144680054956193346943461881907308435567570589732 + 4427806006379233157431109769793014446131865605460452718401487086503103098553754737499082181376863362004474070049162679495304786 + 9908319411586467759323529251895892937674894302534759585448543523471481019079407250526711177578259561097423457479183321229451626 + 1131371780154610377491766557592293428206914537775417828678921143427727968850975607814254333398412178045797967112746828184963972 + 7463947060005178881443883529993444944563705484864960478232839522887114302507061077267547873033859704180182478601068253214443547 + 6363654733262110562720880713693267188885990129857236073837004378034866347649760844198517835526780984480422568814264124396245788 + 7422184144089713717140409869475766686474514248637954570906655127051840364408955207306296810118720773449322716315645914875117890 + 0847277505961582786741295462154437342373825998662718119420520873688904858163025326891259732777158377960920534957757187301680750 + 7127332835591365255818677928303920688285753363566564622227243735455708574607542891965353908456436608550001451776173990862992161 + 3829054399301597187964270168808949938169540225900414534726047012413120885338161369990845308813286961059592718025627205221770817 + 8092148297686870086401035932812080011392424084497972356658952923082172309746025699168011915919281009722984056602687718337362402 + 3027398748877048907651150695381083835937725004446873842854430149618594741819924214123640276762016797602129360641044263480412772 + 3710143070992584709931252199044234825397803955966283897640299886246679348943101389030142066287790993761176511866201467864299707 + 8525777612726675246376342834401281272453399310074719106459898269090225065025922311415205451670630902470074176854745326883762644 + 8262544278833799829033118364917993352082125138925496717970983928091600634758984244372250880458595883955890831596406628913521186 + 6897853799297275638235876552327431216883341950745982036695977282177864189708565950522537254131161076036929940837531981536512451 + 3213748658129585636531039879081929302798794268346651462737129452506002968774313717689240477017446831448952135158407313634350442 + 2055874845167569647361541785365745319937172123917988776868257061731415878495755011208403654576322652419771761741735204486134128 + 1873586980474608471307789365974467503495691071252149719435658541818854563735190343177059527503193288117651496365565656653307241 + 4168177432498780914163093904219938645313613562804544457122557236850377399062589146156364240794704626265205228184552480787389528 + 6002548119488363978641919486071068284491204688921592270835983882131004647117906646204653024128798598225163921424999116659512574 + 2157407327085931030684434640191280950835140906873052295703366686157391470840100604628128222870118102675339834080247719766902753 + 9516075696286688385617312294770633537786940805769023218236327039881513937432194699645278901401806327344576080861704678059497048 + 6871189362548323056223946109945917378776965980493422695153032621053464957232674797346887230723234348508681395275248458966927875 + 9336780663866116286377027773514857490216582712388958421219481975628619943979311778012113187699153459212550397452631591800634557 + 1884225357321516913996913776484184458840279457439252830670922733976854064570789902403772321837879511792814698370553104269506613 + 4608342183802630938543364752477985342180204673563980704638103829760160093636516325877632052705116775395863314477370432360214625 + 3293602222611238360052445923968119215574068058661794694301159396049393023879006675439325347420522015724464971518661959121953285 + 8043528468318108109054413534510021714964009352370382732039845180887830146914560592175998791412497342760924247174793888155615218 + 9953136600515251517270114445026178472065320103271749951560132315486968402879259134348096557033081980214662985678737805295776016 + 2082425869735558279582276249486763021868424618618158613101945224876744522204200404218768513612549469324132911065247448884834161 + 2715300790048270780472694746992029478410340286154036701148546125752257415749783382221561686531788228065371707859970836437758369 + 6586934570724918966767618089617174929582836792685611937969070528242452974277966964414407164887044841543253218406757856518905749 + 6701113102105341541135759678684819193668388121785636742894877294681466156143067331027856246686661690573758062813040020779144644 + 8573371736029851148801112116958518768083768805313811181481300256743484459392633904102235738743377368774016975057841718194084994 + 0319902874585606893329741100525933056084182554392753427931707044407179198386674603799910970919558297811591565044725137884178871 + 3211448717893811033719443147078575334620516368575812396883003880411447512133976398395409888756416803178312866623025053382610669 + 4561353382089346913344316837392847914820218419836561651969690056195804908190155708078402986544580149409461279682788447362287221 + 6541324108089851136771616890125941444979071358059045831564141967544312392874032082755961068514362364886944531733042486972382351 + 1947537457345366294923388536623305727166280503481566200274732091551547741549840732121496504900782994752246247415294786133670139 + 2790662270964346469038082957923935596601670431239525874522807293008957620170868585946546458722568195100218646703049798761457890 + 7207291855021167963306163201383620528292099344156171536132565162121580753163039591601562538194503052311054883261440201088776719 + 7081508994123346370534091387062163390235318525916429277771533969354167555829004274478142845946719915110847480617275074050516329 + 3008933084371763781228021375479207498806120584984898188493731541257384657224732160257247009445015469067201744844463068899016846 + 3400853085115213814503196501389761175483359326430453738990669485692964833263969136641748087708764716019323095274097377414065683 + 3262060508094820191682139681063256834961825192399541866597766579614721818676700322392895466758698832928065782064894903472978312 + 9760920512587884215163543988536526156574865982745337953096380337326849623081010538502752692990846114093305595114511445577198415 + 4534258782640418619628264506406504403447005968106774436451122846867047076694261073542029684272737494317052196031968617018760037 + 0005723042928179923030772189645554654702738582913437716383318676665447081003973531059059732707456286646505439805283337167567513 + 6867755898727425848664558154624878031288945357600827739272457697556698844756274091214882872082839937589030308224565293706216309 + 3727537228724168866963116807318580861851195574160478712150379828696545006021644250770529425526279645439265900826286791538135930 + 3153997389799559939607422587882124977791743840140703583207584629133167628782910497529520542920062933572958127405711490497737856 + 9067474435390875739488758031979945416769209293461704806750415570467527973320692921500611307072408238071671039355350126215323195 + 3397087786775809367683818985726713074834263187298828458889483102002512283284602983872325517586754239568315454503146853407356331 + 1156217453455804570907455838506537271360924924818686966590633031323668379608702859282734283827376245634390166587981939981633250 + 3412106433453184147582934702569648764561354607002098617356742259624760387826342970038831595863063739528564750876654025034114351 + 9541719290749487737141992118412804491779799111981476193385533300689670528815189491502637221085072487226634588032661043056759668 + 2892064967147629869694614423619676513067951679311770744515022309616589783655846699918308471661872732172650395986258940991120106 + 5144184865919978928920815222171229181997238748998964019938552954342118630154574987629428918689878418879411760377091395290416344 + 6885105521575830610256425097707534533542028808834255387318107287078639558846084308180272966744285679093270081574095013341117481 + 0825712842225983699546990461215024477130525988490880256409773994103713908818390693122587907689102651005737105310805023272218302 + 5661584786775396459681434880691492087318430940497979741425101788956553140338175653002561188152737818909816437963790481976018401 + 2333796064755969606150287094100220527676969430567702969130345130599373183629780646448254004373148786027781444947828389799036231 + 2370159800594514645060430450080996614777495906387714719376787944968432214762676658329959973122495250133837956302119421564977403 + 8812738504000258149359611948440268119800977088619535948947126735318099451090706379617772423943777604512120621890539370786597632 + 1363253012488373680482054568974446439190725621429231276569324135313694462859720454323916583978487818838914751980359776090418942 + 5309412448985837938866251311974802939648013868273488976753659392241870912692861488024484868367836148433592247524575436350374927 + 9969514974899115014452925807661936280550953879875740514792224284344537632692977097082883985126798768022555743127429841568583436 + 9127480468310694537875735497900079126170848463529624094796935948030072227221587835070990509651876620138981087391650544865276910 + 0663274772751898865701481848764433338510687274568588217413099134231887382122648096865873338497066278774094796953376828006000126 + 2223991886894820013487780739895880221686260123953688255289857284508367990146047269272253817887508457566736245360372546074724620 + 9022913659536358863270572069247332195356175380482645548420742634480093147625717187780842180713151897503373416116801897541549813 + 0040126272697263557284035143648280938089213881029883862911870694532327995219687847437429389232425351493591671711796587562791256 + 4017430425461987380494086228031466897556783584467938250558585791601061306591861372175583299944343371927286490389555179774602318 + 7872955211264709896492762009841470583148357109101357998512705454425930076065324016499469004837167664624659717653859578461687235 + 9667310959423600740682018043806968632350609113790915003388710593533872466670325086871976600837835610439552558719613595783702236 + 5280944927395295859052540423240381366808883628148042644568662154130067762884915257137995873057791352572012021048384019627522811 + 6995106927652578556591681036413486142384921333996800868230237202393167717311762878194321699747706337864446498735182883503516810 + 4894127087101054059360113153040095596503789486674685811347198640008673703554343464924312512011781208631600506972544379180978661 + 3653914862578195810106428140030210938175294156340298752901536901851573154592330206774109827394766622168822827213223926407598523 + 1752287994131637967328932739154812431240663561508299992489581255396838237199970478414918524473397520840434054432691053868383392 + 4475254299662836002489198880413157763837585826054191105485073144949660180125415108179810953128183235091235263489809711965370068 + 5618413924400018858280428271296438533254641173714166471746748160577329614446433367969692047250196643164558060988866789634419083 + 1976673569829377798715474066924169354140929130742194843186922903877261219583485904128878654906618865153383966440192899927641018 + 8533161119710252096705226091491715680664590252842043928311396400578644885931777054299394359376613317844464091496561469756448904 + 8685184190096699452877940339075889148354699442923532123110999704074604303853725375307368452619373244845552599196580274471194639 + 9829578543429362536437207266353476212156141077734490396691958840205815483098775874456262295189398128556239354143693110486242701 + 9970409655619169147931181826146996933740442172396548865369872311637351974239103479278809874040155159335694067867509786798916993 + 8934739229131395268686186934227620999682967502345755750450754377980375485746895673108969778424574385778481433357869228670933712 + 6403853140387575318798294898252560753364466868740386419346298915926350400035543680556378607221479519818692502368546406996064171 + 1053081251212324305626596587814428006013451031378599825941680949090154726066128761151070261252589982556578267160212779194125716 + 2889755089191961889036525987804900491217472837363091046321293846058934856253393138783914577483067599584740608242898988136077107 + 3871240659195668412257855781781704566864660291767024614816347476774763467463583115867939922590382680508695307915014840948963808 + 2822134512303137695995007841922537885648949227095598324952993245073100048846948118672641286579492473549786447729014913418849577 + 7115799710686817026544023974604506965289044028358314166807497671714007777434113787389629694840769613243261303424414900494011898 + 7392257640112536311638754807439431161718219269700164766558394503991923942217206220355994391249150834799995352874004008637120732 + 1738169836253384974782709569139552429502554327170357536474522232448622509720551967534903770682965229229310748674655279819812001 + 1013488426299593714852536878758330763717657950972685023529624029812092380027913386862035092137102088651474613519196497838916967 + 2365712331332348797178741500614741133803176085015200716152828860157706088237891249512432828832383523202673780925247731837609823 + 8343543339820274706718254393402391405027365642281414672601521735599554959777377014041823630157212633295524276413560148004499161 + 6041268421639300061742794731401962219148955309257726102832738599350862047986714418077392903665425072627420761149419742624568473 + 5903163798089327161860705456299199357142261228683379549747158444438483324626130181126533716219751215937033507622299908730009529 + 0388816251038799487192843352437014500990877413652618253793690269472286848421450299377527429839922951807455986611893857644960410 + 6747097789593097432933016398117542211434597285816625911203020562919342940284869769635598001370921459163969583961849156409633978 + 6058253598655377264266980145151402530578841715801191174134703632064724433621375404185347776838645447066321662228541280092856110 + 8706460045506764337863851824656889505997963004840404222919355019179623835893581428684583324979366713626899343900308968866457307 + 7217115588869155277775561876870949020701337732105962145058144137569073157203270186719489063643062743100706189008644101702506879 + 2134117466607949382162669449831544904500037626615605917490932121868589822502449721652777432598078974018800021624932345792700743 + 8772537472143251033025302537735317107162425743475413816038506301465925279856675607449722802889718409431120703912286958510209941 + 4868004080038983558128526716248086993854257004538122139718459319434617070817759239833696965506062568522567601751636677225399970 + 5772707421791629107161650375371738241195109244751411366251362152446624847548801413381446956815082676765934768156267696685640257 + 3337783332137332131442737895629161974159375156476294489620941247396447219121871778030180022268049183913926389862808328015747496 + 2718665162373177306261228085712460052227574664675638031209424855973371465310593845908878207798419801473033533102851536608498988 + 8594650062259102571664509669089099570629940328720500583665382040942904077679708565306833479512196713193874213822763114277561821 + 7763922398020531727099680865423760176807414153322182938644853758445162559723450312367220101572741122819976006288279862925391533 + 0609418074163954317311535425632639460543917210847556877142776065667429208580080239400632276304974925905306867007809952150307911 + 6324798067968629831501975773028726696101515750158909358262168518496428350181893495977033603403728917956907772455104980623840611 + 3585603421384321409739580272281986370246357840985885096013164036482124665391931947880815558360671475167152552411643258730493458 + 6674212278514790724079384829207583320586965949581600859999150201711417012504831581096750857003895316139028753798041233239967350 + 0724838602272073110730847467620546382405164306488489590470927625949743749910925230346070277479842393578994351426637786933239473 + 9758486324598916254826474547605389356962763994905059896268073096288839687527478615702716618454224618511400537520151578922366430 + 0912492025822760544865884599694514920137845684369437041888556762598262707248611887100015044910247510922363893211117566916277207 + 4970896832680655065722060515676245073680441413700428191825160119923053062012241474629435368642857468208602093702394160800952368 + 0401643954061460061469538963715677841733067884978557675498904356226239814257513498478706711931106662782912959490144875688684392 + 6427801429230014330280067244320390813250002494116054667882575684276220510978170909405937360209445943389405620264406898441269151 + 4513961131947927648793953864754056606418638015682203461287515973198501950396575668694970608763112445843545620657603445132209084 + 5756001157040952762796856519600056686459818285012859365932754153307811718432937457957972840218047257233193928872388202493970468 + 5745171294650962698731398420701143198082563097452816181021021324846599968746630383827244381072653879098831871344995918422668994 + 3440697357810684087609635992103602934958412129332726402190737073092334237927797275626663021730679412659760103153021222137031354 + 2561873488408007135940986273685629006346887762950502897998328704241551747655409051903344700915847431066705228403387636950645457 + 6677547618819900422307650673816956131536670246263056210725538571359966918216630406962626983531012334568659195035619701341684239 + 2420112802529724475156900639848021386946999992189525298915178531829794178899375316321752347503745229384277622075513609101448077 + 0978966580118766906719339709431650123507257526495690738543102142511117335171869720713914484644191091368983835287599510980274549 + 7253035688826486175835885694607345249760996565501754434755643707038772708239856393717371875268895624588946691881982666455004955 + 1229157575767360965832607989363181678043448764770403987112238108580504462888836301106969202711436540526584606392030520555629817 + 4303800215068042550679859587110369621335305905151798020996167677493237088394878180209234115765088470219122388293468346691575131 + 7160108019683761926270404198160152789263213718306724711634865022789627807005870451606075994736870542860235641292939358601690892 + 1281304446363067443221484815128597038007892955460785907630142069752866701460026126386319238710932447939095864553352289508365136 + 0314065667002957866858488765937097697311458242916562733459459218151551894102884025238852720369894804551004088501646041028776937 + 6071040163745909418176019453877965601147459065352750105116872007917183143758403418504559900007858465882670700927317278238845262 + 2057864431401330101261675645065867887669270980722933655585800822914522258771084932227437807465603988558837727049424395413086192 + 0838403065062402417019069366493917705353727605973078124319419683057212743574597310780151384502291168595626908520023754345467963 + 5237595147390251950945857498093768496867490339391087595954081288707206848402637964670896124834883491892023218043300933428536303 + 9038575918527245239784697127935511565993493329345587370301152888215360283868124687096008034911588337723498130857892917083893566 + 4326309213195337889918560482484162052931169753291241688638438611871045719430309380350737659700684663483713556511824284273648934 + 4109675537859830665204217999322330504340383531423575355281348688917399955785319877102842092110480808916641344634371327017518067 + 5976571379562477291805315122658077767583602698526304594638663614898936945525476463455648126285604724437435096863798048639029149 + 6805684460338235182637901097297785029718931952225347991353757161498388530429639352729227333463916470311358261242265252454882149 + 3713554069757475756235174202220726685159145970448234073615786797869189321230621988473892723703610057245772568034893831333824268 + 6384329807418457095553971699330059290079181553384702995369891469896964859336812164228972258241580918221240870171611342340166996 + 4238496467737330476039022845048701321182330582443048269767680094107459509184801830653831569366411726902088279531793681281083241 + 1389317145760821195180078109186551396173257466092123382087137757380977821227017398905747777928583603397479220222412134551964141 + 4172433396133877482307354312025003410197620920424049031355359918529883398507939057731022302176139038905017200234464598134643926 + 3776455852500808911518410528880591214453698534859661007977301367112639128608957724121376845610991533136565527742397972171004531 + 2169236758277228509207094221732914621136016542832442557119974462763405873279434363734315812872035133971702886820591857401769365 + 0469858184126033613406108887661308724723319896168974862654713098974773391394034562612379275030863451007736429954454094411166680 + 6170337864185847270755623945219598905895923685556701346236877669819713556924060508835912462997027984549870490684576221788467996 + 2684567926478205893568909529013411584469062508988939792621227026970772272619563307265559984083650571137624804538833124458965412 + 1535835911469765914801129303385752847166878267150358870063623206823946840223186885612380869419340578863726545596738437580294661 + 1159345796279619020659424502037780228138063084481952522217422192474814460650570150288813492963026126513178935693001157815213888 + 4115255308469968312956667592729481570942886979872098274544235236610800153069537830562688683755471055934166523033112817689423559 + 9188936491751459321231439471707842349428821745374698747871010980962280880750506886802895843191246598782044554283344177438872823 + 8347722755763795357915434510354216096329858917788023158970394599943300789945002208151468416849121549451743359325575523192943247 + 0386458822265636778073946364464754663546374429692132747455551460488109624863176490317455770854516391720009905789081791014745242 + 5441057113825577288143510443291415701276478572336349873718556812697918623782132025707841689574266907977935843620901112527314879 + 0138974051576176017602134330816942995720273624834286549509110307443436271222852721817459586302582019304440451903755250893098006 + 8714580715983710618302573323538613568787984646210126690769977327196476888780472811559022322326994280966501214045283109750894159 + 1238724204438864658817267118920298143255297575901621515081809762078906592560699017605054545611366055292052387838303773046414151 + 2117880548683675747162798543936995265803158300313026522266732130084089973850929862579530307924250791678839458713648131052866542 + 8688866589649054666206289287368847639201089110726068276561807440633436849032550737263946103998593920752309241137169715090564726 + 7992366978913349109203408811669845313806318145335482602504586472079577960741456598112230859758567892658655917499886892820156294 + 9269289344377943028314943737975747440225464454099585770665233191895455121597963497469457088101021828673050970000696324467074275 + 2620213720505096912466481021388401048520027588680889621938076715558063059090115474427731634806419367474059903683493740456083416 + 0419258099585668206386510983923399175364308512576355916179825772896253917529784626455469847416203745543857585138629447495124687 + 4926957394763419387802807256844093371043881188012601196274750577103452141865582262123425456983325248975618318937642166941469448 + 7745531482212763608085822252151342022701776876422939982991937310338710298056659311711100694774221511805463875602371671771107991 + 7622297042918195524581284988624821755976081656742322232878212092814401063399047757727446586120047765852193643525978220488403806 + 7694553355731009082341963145016321622315287166497298675517840848325124707270827181601834343475566034855078916693975601380159131 + 5691081048224248376219969516692299552551684485812747394911625377626308622713328149116932634160209525550974738125918251287523859 + 0467965216958213222976523551707473542482226303543330237484038813545187688169900375790194437313184877958505335015185533760569003 + 9313388170020500404223350587859029392425277844920011385363704844190916888907282100497715918895587428711392085764058004531043856 + 4805593106127448601646584342013400666164278454947086863410933724954207481882298946080783397578430480735942749099815836074939980 + 5829488935963766897295398693976065473334615080031996490066697080972996155867227149556928263586779745098746381741955988476480256 + 5145688238158921108920160861540066499070337742408273263858244236306539277333029376512623358171655471201632148566471544471879593 + 9921214229435926996318797357630113668084683534980450540625624914828693276400997437801995497337699991160179152196384869788686202 + 5452970283364847951628816855350106161884215992345914720345452469417460755112437907196741570679787585797744951997013243245883760 + 5291067302501955637725509930308800308821879902449540996764882569862895237545484938003965194362900224359317192536398128214213941 + 6161982577027434530385173942460521391267875161999821213546453369930955209737128453903802184733420666743600784696394324963677611 + 7259796660195828763104609417030954701404550411856256961919298349416990278446333820166279192694569999689157318159650815071786127 + 1409252775006780923895660512761218733793242701073753044161926851887250329246949307610371367921483913476091276544943910212219648 + 2024883815854805620725646102396569531338296559295702755514936293184048845778213281077499032309766928238274933799920207837132838 + 8210747670883127249029109720500900846638073842072735692712299242482036224417598293305373767651397688387681839834164347629159924 + 6849912340362293051521285112884702937904971535989594393302698489020568178389718625627324020502329354706893589619173731210032692 + 7043789553739208010357759707009160597258827438739048435319844873364203025319025627611147486361041079291073784131340379802864271 + 5630517567000455573262321447961724157507366377593234074637396775521413915860857523966422306759381837353927621547514858375348648 + 3907374620037626404876010563369584978900791842626728009855287567645993864184962785602670934980414501849977057712840353440946698 + 4146385141059123870591051497280881668008298341992956096236493101498703482256305064373982480667690632647788868461225656591267014 + 1968850563894509480587740368883124473858275653505054105229249423142559298770511499954927552803754424222038587228379761857441343 + 3593066522032907759239532950409720855609763959255411331452747381650146615224156577229227092417969990679672022642682488460230666 + 4777284684581020086703554379926122352924845140673649610422757744893763657846499512591483929572896919893136740342514388775709356 + 3278001195584405224574340518455727489287475412287946187833805383833415237459010850315390550944653852931708140442412147400013062 + 4193626826135963841422031213601650476649922753686929704940497664287967482680127644394472418039840709944058706759350270065888771 + 0496707764123239353916969348556102234417341754509205481354601177831190831135133718891421262586922485229955848858284322651713550 + 2364211115463126546765721277139380044647678205497997698025656179147544409871931320460204274120159204240964415234469912669043171 + 8252385686403049790333736390573303996823129984313927885511658858105668489196273816414521496403236288238282761677474764476093781 + 1249545053006377773498004690990118213356171931577992909398589918937522320753583797192061779831406344206481621920250152295078939 + 3709843278222111715104072968292537550135689257500851260250849491755576197121702408117922267107801447424437466479647604658838505 + 9854374828488017805142065771759506637983062326803172669751646781389776006196509659848336558123328010610366919010236885546271093 + 4449279473317813512456203547757437510023295240020059908269371826627596476653671730054696042131496333128833416321765418914320719 + 3406255777740484368806154865989716577772954696365667763046622581695081667791363935783289021366520297269972594689838903064379670 + 3971992965532938884360604600128828768832371480402617473079458005449743185395881312301575878592825423836990732749119210579499565 + 4964414428994770524920627355735483099389790803639808833122768311697123316450497548024460387672711368021069867385676748771138907 + 7272947208705814863061836555172890754692453812368615959884812383294177521377885043762530023437311935454983526848574910569784985 + 9715236460972266941105456775641088939352379849288420663874812734503948765928906653066695278788734445614220395365589281481052985 + 2219149571492569121653088856413977750911860290899252411873082297287513781665034941515671551141663335672214686872998009233611673 + 3252445083210515790502427230581525204628936179674886617751355536540130374691771589975236704266655393863956951833668294842751553 + 1066643170812591610511115847160870442604844517253754311969780356590045310298592533473063715395834561034249527692096332630663031 + 6094678693574789972643719059293336351890222699519292906160704354339193005774875964485745420773135852897610846364640226020416376 + 0078821325017540745977661794444919031229533952549930041702337654768594140134838827623154832919375367293846998623573154781662214 + 7359805369711475680734455906157477769170543397898162106347663466476684547058977605857152935135397794083854436364067424905370520 + 9053319467618246985715935346228519691376765059011804822695041370567668817595587435020117179808441224160004516561911764361051760 + 5279785887324494559284533174001913906340668600486179364934683183133265522486775587610826495582037876134991475823478304604306409 + 3941979376926208894324337577802341103192284179207690346815460983649049917703085665853453770292030524017689837132097566609313622 + 0874696648882529341619751279943169854047021416531564941329234495433297775450795376776860235960754121606226960482122943806912723 + 4403142549129181418798689888112583174439363438245360666469436690361242515845002333293117928704700704567851599171947638983428803 + 3086178172887575667595570158882926151846562563832038255451988723965663322118638716096644911129577785347672668155756960077259260 + 7016060211620447349613366392265953857687262706207804671997611538526738050334785125634177152240160503249217159499633364839660140 + 5489512175142718110444335510020717260552562939322469369407097546446468340557730058147393474938996409762845800786386613781180803 + 5316893398694618358236834304108186582233111640280225864142166804368748966281116139163914774116490280764125236118841244780654205 + 7528194334785274348270807743401184076977359005808989097790847628594537909545137710117536079654129720175240043680499382931315617 + 9670385576675265565821666921824539041489513174876467496206200652157451658908879498586135223489695875901066307973744711118179562 + 9293554881752014067237144247792025493783429506129044867060712220683356640982811741139549073541449462843252209357539966735713385 + 4766042719100373229390546845449462827735583320023428894346366740071025652090167656518273656932135482003817661060458673642777968 + 6301526335239349282461856549816100522037177673330915447520746670914149246304276129215650553527297720437502141660843474787824161 + 8981954968443818080133345527259601739419841565729583936192031325311804839597158161812415269217752774138988523259895019553556494 + 1375817110090726843596408461202879175175450080051006863993971804570798947994555625585878024069026053117840656838335462247825434 + 2951238989342425774096587516368372195370856662387116086488893532196578602234813604266303300411633704142608233959411992656817117 + 1078366109359744038481314864313226318060249081213275603047710120330297564750748020015170091244280923403487005151336327967793644 + 2590644710984063836471814396137903631095128763841800600303330827770204519245855428525596893191150792386804495821205935562805056 + 7587927489845850917488079723623306056569190541982982580007185500509384196528055437763768159799054085157690272308144066104571631 + 2716691447638059359782976991714931875589838509515317643963169052633209626064370311932621633892908726622398410656122098501462508 + 2187341550744516068766043103052788709422923668066123030675357066234501008353745371362353282261896383609682551818558419836467474 + 6386821883063127753430057004971408049021180273353275003607608462963509731380707112452702494852068512020333193164120541304971821 + 6414619855917522699462290111082170337250489881403447602549155371621815281167692543542521085921503446688385053019234090686216914 + 1514251753750908058132963706101498627247758343884090328099690893144318542740931341743091728225255850843917610568152776796003007 + 0586747600603620622562637108763020672642036425806055677095355709416205188154703219135342081900691181922293308472380603914641966 + 6943882703466448671671347942866066071729197097929636191832480851465967168936588557508460013143074231989501890259153468168582090 + 5106944931177904690443492972535629421878279108027478056702348421231814228319595001969285380236108675594104178148223368821682505 + 1013423077468134180344202453328649263556597230333389978398486618230751510288831048067335293062077986298410020248356624260186784 + 9609742549854821633067526470397698241682366743287992123678759953855431672859515457048320102063982700799641338555460645670603233 + 7227510683690963888209842085118318517866633639207568611885740247627869030070367221673493120062595703412511430540635725690733531 + 4166904720216643652362019185541125336279973971095473810174484610634739482031555699998920445667293351815342116856019765913024721 + 0204685598907595748165591866024787377707833163733227729761204199756529370097242687722444149797918578951904826714174399654373078 + 0029695243252514591043935308120948291772608227171634548103690625246068887952914933102467669452782090604646361027594958463008648 + 0606043910237689889945195721316745105694059044358961433889516172023390307325162841023925000976730946622777686367139699337140288 + 6532770425227279669614506342121365572660042996371513972011473090716295756052824631404973053818570282987235859556502147507091296 + 5784383703297394066201455976072965897350946662861440804630035111722516300582625065762906422553404492330383168345359661866546635 + 7755352359361297136322168309187217709956128684689901207140385336402261861792474715981622821266358097679527860080999492143093132 + 1766368206837633471921145548103904997241216165904015409300725066451342178028580494490424756975699571333186681161146526160888637 + 6435676017243653308531673583521916536301571057843651379516536378840317706213255198563089909258098489728121633860286779010828363 + 4431604721944445862183599288814310892377084499055111017374193726585680550914726436314439993180521094601524845475777232173548652 + 8838913044786662722923315829866963645973025803566829523066407753524509752981118743428995908031509623037684132020735808440759714 + 6831533201518779101708294838185079163952906812726056828622166710833228863087344104415454342957894082410432960146722394394312810 + 0026750412265305432804678135281250107474394107101163961158631241381326874456825116424953228542574854725058161235809819422717951 + 0530095666016377728309821374273950714947770494099333703734720428753672558560341529622248519497385032763976784920070775745998492 + 9988103492323582802831123529566020729884479858348071107686123450154590877464099472518837056085048970237891379355375854402767816 + 5730632914573233372640655739395224654373166501801926999740491530052469701082483441902155873112176686047852502749353152358488650 + 2570177044053910045946498496953083595646140791798652856797075918041625426521730745013108556438270557756261535076617672897082024 + 8070822196216776547306746987791806776779912117872036753101249436897151550298686891155685227497724326515850755173992122017730073 + 8834834453446142095731369167693716173639921382555584546233080228430284169771661090869805523170856183199180807458939980812347666 + 3374034628848110181967055896853894757362330956181597331342944383294532319770922905892283292682026888125967189041997170645906930 + 2816796708896328193169753615809284330192400628212014852560752820595983573685822703155361815716715825780349446395688288981323009 + 7068534005360767613192042797492589713014221879034298952445175191916602695770589539510033643533276163270684273301159972772079846 + 0851847960381648176955810985408204753982844887706344041815181406997985867444440863020286602964269777581948956459433973575818007 + 7244153065545137632239977736639101263396745129055793110973443976621943425823784182900120559207556057714294191011934647831514642 + 6220112071917364308442903062123692544853904143920646475613405698807838684964691297033599042267911174717943845099876701146499041 + 1997737579617455507368079950355247973464185824287192636611840482334933626092039322468638416062106707636638684831343949569888001 + 9056473674062962705649948566947590595122246493016055906506275120659977645801864949778640366697230510631836906881678697914437413 + 9851293934933351435860731679561845700615460829332071112719063019501427379839759911846192375852475742108532990355637732868083608 + 1981670764831163220456625777162284911174669042984422665330847096514572430663915704539930674009046717718308791910081803605092076 + 1436167228645743999726495063433059497403336540806399989879727825522625780324646087140141119024144101040594738802339934675234494 + 4511331339256646611464785947970006064997210981736418145964184001849876673693526718038480153571548117761471182638795979792615062 + 1795579829237064976093578272496505322533909223281608272636931019121795380635442871500788593701642237770643966129586714071750006 + 2259558543726883196265093171148297545202455060457641437680621020678468079454735539167389894892674876922877875836968284903103240 + 5190322659532635977759442475453937445078305277952610411039017125942798503797185204729242079034555967093953206391753749025286545 + 3346586896166410527904055884469771043579999692960199777847808583456813215611676699557144873569764821207184084966272170201919310 + 8492812746065013433267691323002027533207826063607337577540310499920611687417123621076705455447051576454279273880574231655581484 + 7963980271743134112154087260650334248257065896933807620141668762775373128572470229135441642876072741306062133796013873900656717 + 7155588355012012778870617504567123068873574015355543463865010611682540901252618661459039457810933495173848721472502301449759789 + 6250342428228956319030041026630301654869718238658413832351916020529083012909954188736775565330222063260635143292678318707172682 + 6306362489099506339243174369018743275045301435603437084640257826344578993743886263071878533536813315686531934206065891475930962 + 7256078764576049009416184871748648772794832357694303718710674780587401830972226331756569564368514137449167545781329158975242668 + 5137011302637382277771122596368810380574982751431852882121643844964841634725254405565914232138014950212916177841984286676442765 + 0130766950573613943351861223297588274240988343477886895038747758639966388317215304568124673651393253970716618528199527580176531 + 6359126988671940758748887099156058290162393017636744749307547677028026325587696225823070273928497980385751428178855356190336058 + 1262747164602205208071416052898259778064629199619315166088744120423992672210748461774575909144208599043872184758764391922991513 + 1637777143251220955861291729128344859755814246044289400356284088474702731048933137147907743901585132956196475715784684303014662 + 2779656199507816022148661387875419531355613321583333187996164541556836852609250800638246651009398874732599973734012124894691052 + 7354320128684821812105410562348993616339745664287363950112497961551242247169256027249678322546929448755022227225938009677843721 + 8972855810687812606653074585753478301824708270260970161604946179349054120962204468271996990113102973342165999101606421899608935 + 2427496334389700886512192278170872300796174251105207296701976843139085003204747190192754643836301630137058164840301068688355227 + 3959418860712955101125551436177454788270598656333682307048221492143694319890230219738438292220497263359673419823698673057872078 + 3013408623490314068776627587135426768753482653895410991590323095157887499728772798489129923069618646593123822639438579269538635 + 1908216328408109211109195709992731650405613610224189255235529994289098765621895894667201782074632616819297670322225038809119550 + 0817943537763128333901984566290468707429051150902489063403888015248830107015875323502758058360302496764604163625874755344905059 + 7334562477121670573355518606105354751505482715112941146764597746549856497547302376364513456936736713783904762299121613461158516 + 5283407076162674672773440443861453333470684691925760891504089347363035836279580135355221825821573398468104182485287843330909617 + 7205284306122028970211792875328746564733992888131805747056055043004240391649557442465694153748887961289838987106491544764907052 + 2500872325568857502281229098611844366313487869502518915819858430987626410127129066096878146872919622682973073559229804271266907 + 8295782206872660046903141337058447164373782585028140797785111578071196136068281762757693333793450310851105370333208052458896958 + 1725889330426145518489875923548346134621897254499345669060138933732620752098808224545684009099318550221718273960774029508377011 + 6086360263760539829227685105382480409473035021789956560069988221518928563686053953426925951987832850158619577369793062706768043 + 4352919017742582830329403068368693550555003865896903349651288061511525716234272382256062983241592888339539171693959034050993111 + 7316775446918119981332285689855871890517757525471516688406003916733927585058269512316355228173253797483394637476145877140830653 + 4449523419101039158408708904430347733804700552814623747680680614331040890499889250979677397459532347731846180044631683772954511 + 8775927277284478472403620186389038850970249719140155845452372844321949705137084066166954690611328982193781479003940799798395822 + 7036309001309751772232372080817838422988947200353430157955341599997125428100524596360021893214442902724490483771053395386266905 + 2526553722458751882973801186174660169500936459737553375965211051557068305755252365586897544315025598670454207459745656417390706 + 2637149880243542713228217652476736046313897745886197441813742086881967480415661410956495847064049122729695529600136287474175290 + 1793795271658672504903869428016853432949018555098626397052181786382888682206907544219009649133780351002110388824693692103301828 + 1084255129975610497399774428514444229695501619744314654316691842636967058501657387850037557822192693461604997872810120193484078 + 1690635325513958119210187262311486075808664902577687177132226261921963946973671413085629761815694454894584772804358916692902290 + 8584983060051303667121308176671074873807110361225378981139031261855126176018462516372607208578426174357538994152717337719252523 + 4278036428830763724403099207458044021754910574858908048715320547117712294990028756794510860977637952837840922253254728458600984 + 7883825345262132475931206135018623229949112586397174487649066363051114417355320278795734783658869193239014023523778761960029033 + 8695026444117478979408146585926902316341504795145288358653821833800650855569985787340203101735816503203866669795526287437002033 + 0245051742430260486282155254132179648064481192529358125651323989892545661828432074084630060930677773108561342125212783387281955 + 1156534912244337917835348237158665382209292463641851049571853921423174805869049378131731211644957860891749912005458383867541676 + 5778772564492822262562399502030821202632651082331648596186198421567114506013473886361019711381249854838415342169443696628858178 + 4018937636066081000726527827443126701548588875106206226537909295887328559668190334839725133746234608966652449462868965060152769 + 8173777546154775498367210355738304841393638757271541666703324260466614672029573295838066643359099243819511379078208545782984277 + 3894531584135582441443997552974471433572355979512626259310899921004753808626563585592085956971397408889173848312206978387162122 + 4249778224435541775834672279093907849532605623442929414275448734738794025759189569362602709330104719867391830325898742293638318 + 5618458472230917207115381643121156657396683440299320861523898119230249426608095966989749077626813445096806473183743262392826169 + 5141443017081978141752639960290174384446691905687453519079674615609648441987212131402698830771368709970102768419122745998384912 + 2946562140012561122001343127839838295167741172616748608003211961781629115805578417306196780198449660660896672943032048541196007 + 3488478058250138575080356458275864826075120035949332139371412714212223138848322951784969631050003335580101622399775487873990978 + 4317860282593236100733831872685638869277432762005042347567404549772458118340256499688632865717895145858533810557576307974444603 + 1928173630042126038543686101259940626688530747112695018229893249219604395612728537717051374474126617790845613836004135628746556 + 6994181584676204860202674587876078621483635083475446039294576324194007589602377577833162510613729896861820149258590200450670657 + 9591153201889299370958865743889668888080847094554165557463441635078117012681280739489741681606506751718013927402701136203548044 + 1780167360508315641369667116901861812842526826720765686979668702075706357523197794146674984683061754983908320058757429657215020 + 4621260027453785113729584439569855185620374311773708057945213037359358758689719104605870656508325190409944963614795797144191442 + 6611412529823091494357371703456481103154272600004279607488151916951301067639113190114505272247774489140541745738078452548556834 + 8106748866753253878302577929999224844368660368702977874939897082451513356653811013795048262545973632043664542271741351318143337 + 0778069182951962287178555694626059563658908945272131830094793792647180018850962827338479100883010796179956428416377824203799082 + 9473023880877077477396337686061036427727779399244945597262198872743579391652952681609513942805826872165303709494805916573728492 + 6294092277154179951451094865452721844277717466377028709711650186357899779470166784063622634966195721705046717157464710442807466 + 5804785796886616339545161571917895816310538794711393196665470438339980915686578699904466139950097093535760550147855823745768311 + 4727439998296384114816286463820007469707513836075275400610242782096499770391027100262738743742494025582717951675320717526395925 + 5770688225429387772370873623458820190254941682623110262393319797303540835367273621810830554446149103975368995431078077876936297 + 2405529175616664747550451981407708416427503988134127731468009719622521436517602196339409678849267725633683568413854707742239684 + 1747116986005191343502956460687122356601160408668274191052227378815062922961362392926820216609198684542476134407735883221896780 + 2662260497987146574078784874203657867733135048405416920171958838688884627100473968981627006284094098910015991752992842055879818 + 7034398681569535649106832499610645350629642323049347631261095876814181084980886779188444300173631359422796869708950194760718387 + 6836733703618557086120703365229061728453720426186389529699692510071571231710123347703658534972106524417884249218380254553097325 + 9819799847270574690752534052463450597318916271469886310284525865231260264874522733678980911253701800076986898602579299994595517 + 9135488779985085378045629972341159746040904128068784460666062698063117787215014912137720162075250475265414449002077183911431414 + 9809851736195297213683107966811862847637535801414773082875296684360754325074703853487298740359726050853338447561139214515571992 + 1029599022890794387902179784268370369360935567144903247409435981421651841889958031240517172069175107596477581973881408689860362 + 7400367259185579353010164869469689488102231791643828135531761198096403804156803391787688285965553218505121457658933398225058406 + 5220283029470788325194233641742163486977117357701064964101876499830666046451739488161844284719262317454589282938926798508893597 + 4856368375624850629404156042966360434746200563963426632219247842217835149470275034357811087591708435161482657165228727592100816 + 6253772836778061529203496032750827006398455227451857109564867169437129073006140463432201664058302222335982176666409479667581160 + 2936456922664809261586171438046311878472513284135606095783748274074803411461233988794425470611010249655925624921046206975885663 + 7903340067868061097623144373319704434575514501755821812557204930865063397777392798291309341112700415633886191910088310537801960 + 5573481392684970852911664492959855735295070104374454536083712417507044706607037494482191236686504544140731669546789850452790174 + 0904993356742978486159542255719565213826027717277534463338027027906360296595539148861118855418724089346480767402189286985762676 + 1005223076106599446960454896515318564456413560395537757983458843931854126284677517864393826744115625918435152244510791809692478 + 2164405990650873094086602365842140190819719314893955030230888932507331906676191911961689961891255808931785984896260979975690681 + 3253727014960636085246150995307788585817654532411113862158610700251523142672098671368947509829930523262641611496136611155754050 + 5927873322526687970315921879739844277763573086829985560339421326548635360045717801382027508629836290928584431149151932663653210 + 4760858192547745555268997678117732829237567270192822266668837972286266876280740550930386549524048812443132805094528566843643923 + 0552200604353097511107833851418517885398565041104987050582967853637644070929822812409158588536557876274185029987107810161351297 + 8488557995995493390642962339468082402922946581115285486581085810242830297673687274512734725802547502660334048415579446341045330 + 5709356062023991965872528242196958896198910586431524813751700975464715731688842846588438403790663597080684309160359805580967928 + 1809180118084899386382440090650505696513340627765123157216132637785703218992306349927445013022757227491085193637218705876572392 + 0750092974015461540416097560544979024242793468547428554110331500932107320102022511854661891492261408877458706999860502548130498 + 6089719190070430700600786193146021409101280174362984471307624705342744373049193769815102419864609660529369826990237068799451547 + 9880823550824400406858764215681272127616403736552454898294728046365136835488231881807123019108941139138735003722461424915329488 + 7529037321181887616470646776506017170053425836736636947752180676382271801340633168596956291990586642144447067879824547939050775 + 0702265125795249993652978449111254341598591409462513412644706330823597010310419837016366205284525093508925291114478065520543206 + 2486005489914656200352331842636430195667576175939710807407359823751196926836356542172998603833007594132689750457318477364742581 + 7540614426291493245957654051180243018629278083258315716499682711339148507426602166172200768552170520220563426401305349960660512 + 2404338617929580850851496148983728094122155851959629735499313721174625488662780908166750428714979229469660586277142190041914098 + 2734970584167413642829413555542927092036718157943315563661250374551603827984602155759774285156429894221533968500275418633637182 + 6560220052859607041833971976550951076186294969188109531953615241005064465315852535875503380591519469842863315620903120851882868 + 4362109461838990069490474891539380133820330011017862518437725479693309451782697543824505868730424985500423739583859994419014638 + 5084805381905175100929792755321577290419383142651436157340596535511027236705949268189435276570853108955493181266234603455114274 + 8408563281709145363110504396918026400160693545535873614031123523353385515760396989543124701606521301192906747319853776998158894 + 2312458699599599230972023213413420672303278131983854442962403875724144311681960596932014490316204359247402654596736629024793653 + 9839221740989926513947745565345687824749236841443758276831531279631822480088615812410461505184335496692743570654981097859767887 + 0148513962240941032376953093608164659349988907238073209903158402845914764726830224719377417036845150993399330628686012123441747 + 5919614485617148484720530134538022911021657584302803306902527053421247675384565988567910916387370777305148589468626006026739483 + 7159664152823325316769176118475149162428707398939203649766531576459678350978394525441052205823105345184421463902500121849981000 + 8288659993085551546441461743163304405139009826361143974328223331967419739647241073571212327801960556484524118468883764120169524 + 2246338306775029095975369446186770386599660011384020498379465046982275031718873753405808637548601707969197710675661519594764281 + 9599700671171430778834023658375047244787074487357323294015535711745803913257607799601446000833932736200689998469969708376723008 + 5081943791810860552689101511523648202214658112058332928346393590013555144813066914194030280115978731407804149764646197662984115 + 8801177359464553557557965020150275317953374369713023241680758235462889780964894972416089799047047809594791811478533742030190073 + 0665429844750818754679057503636454736605371676903157540119156106676570191787583727649819947468340786574584101743147082806534991 + 3657977605543416424987117022654696293608374996078959363230667155054631271871981115488592293902083994811357408917297410729122498 + 1862650934481731910956432936712254764601612734362801048040108459535230079759939514256093409449391542317896091270323008227781776 + 6653398313274972684240408723778161592189390653041468423088421653090661249171357282254451145484842067919237970412388771640682294 + 4059821256052393643115972017853583376641290368154419793622859038067932722073228138326697082834080833163668963795873824307443161 + 4885945116785653293180979216652517189039102100870721593874386070396567484340764036310998065513336640289679790609291581823883333 + 3428604720660372157112193405611757297738411485553283296939642822708738180393410023516446689646065368009275111140421244624003704 + 5562960052258931350563961074454414104687746794788022658055770332756970270739126216170694306943534685894930524814764997593650416 + 3008384543733504706776478261526614225467564069116098586935957253917385357687398588155803265872788670839186222042335779464643037 + 3618994828725096012458832876031499829184389279845891008599618731986280732307102787004526300770299430819579608003697211024173693 + 9217086377524454012913218100708405723232921242597498783314818967648121936298190307693812351239182876627690699979858904402641018 + 6156985750875948360548164905855940506817600324843389599811157633619677210306664432514278405659673075559217581592839918628085400 + 4764772987507938088705673246656764726283775492007659316410580014942504090614797117731679264296150069410102991752421283871178501 + 9088021494611622294962362961658529846402973311983387998125910749644155422299932240783260368601058914444067830424352644504379196 + 7142168355025888186137900382975205885091374237093915396552747486547739152007548268368634296637427030850473757422944218387854757 + 7616183325502874293153395715965826837360328123096242771948215374071981140320994435687149135694129364024023152186261051421982087 + 2832792230789485819847349814552874874835409931161612591863141976920380812857719621635320076324767599038119716738981834869773741 + 2754959867605262800904073710237512445047870616662855713005574347858126481109562377143573312098011061313182520482126994274243272 + 5944572495216446034342198294744331850728989442478427239279385418283344155306850003896073771784045248648249808863649089110085745 + 4935039678346741118281854023639235666178336524231495974905785711915838245296715638301791203620715851604930385744033263165263809 + 7601373980902035512868636064609722029939023536705525076519976556652492714730630698715244783359777077548960439099573621098774644 + 6788103237769355632318040401274560065924878241545893694505228598734431875252964572555463844283713282670737691866931493869606535 + 0416187164312031460323292595651046052380878338516759425813027437945468646970166296000101963391062426079829338723963248745406623 + 0923089990664161924027191610177696764629811421643542437939862866986835556859764272302075103487218202328441244550298063164681875 + 2019867260237068480077811032787819165579411546914115220954604696377168121100888419574969311251245311564544879246746582842436916 + 6868613732260412990938531237301911324073055318005385120355972354500615925738636280898984348888758911483752216818128353784893125 + 4877207978980281193491650735689287510067435635758992016711009033554062927257985428856499572775171602494384045603122508003854191 + 5729531014485818371423575856151555802439384687195667542811436864469460636476071341511650757925855405897036006697261458329928553 + 5460991959983883494783035364470651652782232918135295761659407906592669701830570881217510435070790362298581095301898060905173789 + 7646351028988526172675924552809872541181626761125500157109077472362508995981523449708391893239705562284235588614429905027555758 + 1619134181392874715654091932556140391724453901036282239744719175838602787922700433547863998561669814541630538374359332841359124 + 0642132589359772875036014752032306706353508991088875094683831897858049315214902256977825841683325136398731544129046064024590934 + 8005838235188541103906355513876550842936138467720245485620712847710339766152168792765762537490548824247757795430623230546063661 + 1739498737086961685166983125262113774813358028871712079307291894391835363168962025939984050181882718770421839433587670806624476 + 4755044069459609604971745446900378189205860081010611662569670882836262612421135453240273781870602310532514360568130085933991129 + 7924290416111768289187834903766663006016528601174525638099383915633909474617753311810491476284105443999724682875652267118724896 + 5850681695306617855936614324554272763867627188224507120915540200480120428647332751636414058742508052557803594703673781795569627 + 5161939368398633733681924028671740682293310854421624725144685852406527972897380355105818239535806432392343196805358469063293155 + 8819559114109771559602841216196553885494830284200973490048941610619985614867118986891106961906280843338752508763555675909702206 + 6241566490588598271025864796744098875607062200785043619624462705052447512034382219094774621478633751781359662848610200184361678 + 8704633729839925740538038689681271982506814499991016892558765319948519205733093865854380442216165127136281006009985719211033451 + 5874590475603382790640233559612673482775953839089864470737210616394894296028059828241641608622138456309335058488482647911816483 + 8528577480552717173959823507749229677977069134280953275629509898562844929982109573639706635205828305920402590508711781395835713 + 0089930344552012906619817966789113931607542416094931145768127062728799915073397115668423507229674038044945322045301649766598530 + 0236619236986319774758924493517372212562285619369190213778360087721105343106507409406716723533090029620699768530871602210981580 + 4900295631035231554608058112293217835929574133906243363911069130644679986177379278388410792340109628431007635443781281483062060 + 4988368133324357435318270787600078029431686121284484541827394881261897104701243599451161363480613963194743733844807088688115634 + 5178871803932196297861340370803170767481272576611956494376594793113965439245117335478620700378039639755713637510132362926267306 + 1973846871626730910248052978143950536530975380151232887509932339881071793647054810578672393058114957563604971882394961817835491 + 8978209292630747251522017252062343300917165930874691119490642832557026684811610939173618238354559097444010525631775837097840951 + 8326182506155413337881369137900095820346248710691175947937982923048432643166491650906416257503450243786283464120124419550826667 + 6090914463028322098876359782808759824243499333411218847428154348072847658504046701534863522297418259623151406625685618209367317 + 4253745664431692653592530190665547218310374995530293912340336697232683775175851639464892393461388136647485464789810252552522056 + 9182156878387604674503124667923684369744370052287701241975705851689429509464670883347575783846313229293967680582071694204051095 + 3321006971958449910630372247668837211034782309154572655303854890011708581736868651280877351904031869989741999700057554577154390 + 1273067298313752548096207203603148138418750927315375729523637857281549085842436944573932481003443446922848528006413314412427332 + 1441821872672191871420138772481289303458305298682170739045298765824678050356023853590500427850176428627107627730008396343350473 + 1052326101498218606100898713263447573551827490516947668567656571319040829379674136592743558516074455124317265474909140902458087 + 7834541971992916704455016525869622512851276565353916338983507230882585013003793323808346566693345857527479053033593116284574877 + 6838252895614149905894777313466208709968773989472894570857815422084908815232548928189324969136065895039808122393702760781384523 + 2929303794620328740393974372454877708805842222813897741603177439187185228877406834374147233014054610369299556729412885884560745 + 4370856078387921623155622787671852014805409807299060561419288539719819906697663945124473843579383816264514077377269614977581685 + 3394601383138607507974293429184042736065549935759370359893007688911547744095191909676349245026886870781533913476330551278360831 + 5351259816322765307961191402595778339300322026355376338266384698585109900534462235764152505801492032987502080039176402011160649 + 6015860540766825761905783450339596728965747988413885573654798343784315606643443103943694670901175274103478596479365688106195479 + 9733596316022892971509096088392032363480840038385290255713310540683102401152243848292964926264212842555582110823197263253672828 + 1062515708221923559386659794495097841198809034454364525085442636233669203446069926961726048176600711294973993391741061849180079 + 9806127623797585819585111237146636415904332057123217989550966977692535517011996512651123910136604576120833852264076101548649068 + 0894752723723477938861483316019471992063859736335516787664755140329957520633060255798252299793172160680450787189861312439796670 + 3913142052442456614486902320774033281367626065329089488796925098543116615817296515061149179999137691128957532263158924327442783 + 4918858536678070436088759702284980929577025191565900433342638171236644159755504144947154030057873677997786393398810399270491800 + 8872734106335380929798217774610094691386997739307412068494969134661496618521118209935954632189343140189392135323738890270473225 + 1245647673515237131109490917571703008777281273557596852732435015863930630266628924061119974383584899927931767742330245961719796 + 6852379757973100072309834676038484260260899346508201154263890305770366822928200041404900931901074539015449894481478124870846606 + 5288592940348602075775045536917167753748198797428454287343716300518081003013742004598309648467119358078992444950790157070897622 + 6178224434793312241397484872165819485491096197408141733026367177440768594738187232231600889719889461459739097869779145699996070 + 2192775687835295828387187709692569714086691619295450894879843196267448458847228413092057333128571855124524447189613776196209305 + 6242914540023653075456224110675459930237745861318742551814072907467664681202170417286866153184100097311858010110265935844444511 + 5209497239417620919469741474768380931492201661270471587341653498268177621359803201248700031595849957309397980724999380306103922 + 0556894331856087053327675958304000445533946185075415894264871473185811965493131424842414390488954096468377128994425485984798739 + 0196159676818515225003292466076872625799134390488404188280002687542570342770954127173812843410476595231005479765885421327808255 + 2605242865388848411850848235973559236245406311003883744452617685164124063273300160172061005325886640047067612731170493761853684 + 3723865217540793835273126631505051186346898929963194134815240955269409964826180214819749886514216356192979128714223656587784030 + 1612652380049586827710856241890765244152817303616193799144244842589626119110544403111366867458976947676427002814778923808924618 + 3631721504060950588384351554676808360758437911729833313655406741373502411393332262640744499827573245395519111703225362606878417 + 1363409383247041202382518900846037480203513170344097014906470642027432914804792692599759592956926861572014354287205548305433650 + 9938363167455625445680112095072694438021204263665499289036436205115409602435745285690360330318532747799997172095972559600945294 + 3849224957526742255789376070484796163223388025899309472042686406132560940455845848040737742829859477224469824421878404438255777 + 9153640594267832855398773722288983227094747426234571630063269545219291207342356377829705537624593717193629488670483397161337722 + 4742683466675948276596206085950351177248268507712030644980189541847011659976997997291786802803131893537147312873666734632318013 + 0962031832358588577470495716330583413563622072795533159442347186921867618325791765612531566938977664106322136330634216330706485 + 3562792846227123177501866289549655646263423972314841727623087546398961182987448990222751356418413165373556965561892665216006475 + 0506481362115739578595809306613922949438046074388531145186498774188751322860892046433870735773039483261252104554347599292426213 + 6629076659887419139215806756640799939588104500582964705062365481405718348479866775939471858338157222844571173771380330117254323 + 9427611277124624517129218643055712610406848999072749557192128496185603527876575966140152280783898310639896801498077008734557576 + 4949349263979842274642964286301282439502057095606102606822710846752651420038445554041921101778203644249576817202379962365236644 + 9000537778793090403522534841735088671708809700351632320108127651758914457761194719832533167517277944390073544087779452376879039 + 2179620974987315833763764525622394287879156162214632089232065378247731638836108414730685627306496030775755582279275263164338314 + 9850178620109230660864047257606734366763600031327072575073099542439779650618140023637464021494877439885488556217335419454669846 + 7274436451730146692806124202594474275423757115268107978580315116832524063995327727093500514697813597360878942124695394787220781 + 8077050800020141873083229149343719418506939350096709806686454834234546620350690053797423042331890117409969910833834635664137578 + 4222569085314829230694422189066171115029353200770994620763730497186499678980036529016196644500138184587387164123266827728301061 + 9140763168998745887384781477877234025340780171338591152461030018239430263211801503428946233869503372300942372235304400820946852 + 8437399467538616927457301639250511729312614497619431195080809960619969552298634956256648869707957943168309430154835637684617202 + 9927888920815679261894236713565064562156846670872463967287481642034739020192858148286147625951137420641797396365115772980951219 + 3655403238951645285818609634851118279549531888817205406539748497770277166060720853420241694457643803188820531391415953932633187 + 8096429698574955422724412934129163958768439154851606366794537099440778504483170647334793461803467077456150095540043989710581777 + 2365201968161103470136827409580883843970089911974172408580391996075540014445987053836291636308746569551411995558157351658739831 + 6950345059892537018933018077820506883809089865363951638996552650340293111131388149509355326175519823347067351884531383182623006 + 9729692983578755541105852708900437725294440871971817004794137742625651321002377622365955498287088740364399525852759257372235252 + 4593851734614428386795483124618557640086184414899615960895693770722697765927766996280493365204591488466719654529288305662919475 + 0122479598904859751605583470001521191650223688479671370454989314043303051942287523649808609527628133476925823025842389422672084 + 3056608819600468295745423499468437706122458751753728982506585826980159252966514250379765257256312249132321573973154317443215255 + 1261003464887189939919598811711885508553376196973665253914113359871227784508364309872766800569364687529405313394507842277777341 + 3335595614255964343357224505993110214988297629416503148121404268247459966936550735839779347369294370575468296662036041463516505 + 7279136021331762991558929156754763672783232261635376259854674650491435829901582103560659803340084857348232939069746185793481086 + 7001312755863777334623418958360382433258119385097977803059882470820602915102809159265450380632894446941317444541503087066649605 + 8796169740654134032665098260784549928283316353597416172219489498769356834724310846396610790766934291348253075369200618334478026 + 8802831163686839169667839421840117736653893219551959966388948111069365662007487678001136916755953605936920644573768537311349838 + 9739545132806507773311726139940569054566559814706558048797461242055138311352937387308888484537481230253759123043684421386096698 + 0953084370435253065135920609321712138864781756707944630525539032264477854921495176982483322151742604869890730064964430072465893 + 8563889642871990807691809483723365775240608384031148556634799934500723149755352447233079304887498827996963939978814660785015524 + 4422068594927829463105462477608520539620307156466022889708603842952278355035865136962605151617935839688034493508879959012432457 + 1797597440197984699879058451944014171742351115567915351330880426124733117964473476818687526048324044778050824433512831279314278 + 3544880014006914530017330247894174199038635755809673971423695196336512713364189925640866570283506889971990951009729565756092473 + 7989020444450139152190142450813270776908916050703362005761467814560672206433992898775383186508883181569920382329721780736328572 + 5963607248916565843748383716251646836534350100847190837736559193434644723784998135363197913246364668420334826697708573880522965 + 3263484959293045146013061177283236124170085863131765193651484251463844732711431227375764646336930721004123585223994485289918901 + 0583029668150873954157367992526151571563606918837234329358185868795166989340614129979830550547132857672143145949742222265113600 + 7440572366306644814358767338023644569585694763643144805041668167574800647065193962831865616870056333413559981420227280146948103 + 7295355536699420073390947523011459995035076225978883439577116325646324872851036992256964558891639573786018094493982547872559135 + 7129457262838894246866292831053823350947068553550051302734533231301531811721807950765452389323781067242015285235015915373253500 + 7003661686534989695171145431734885832337556123063280208162395256598378269110597151277334587048349487450140097618803853206266757 + 9082217774055830430004211027285925285344275476747121049534781396260863522010542259349559050699781590339007899734612452403479287 + 3191667292995301649109040619271406402727834137378627737752393244791408796163577067403946973388491815614922007647090321324522320 + 2949712664738909367012483650928320008049914477514031653686312257788502415066119921871956279807885221949190218605724017500310920 + 3169525625766817202209440542641629818384859195018848363928308881901815336912072399651202491194626625193357131514851165636605801 + 7255316665553834762495164950088245569336300767957000036188227515262775800565384194139225891768802813443198621045801692291233140 + 2574872647913296219947966169138393924496399035916640976364671914696565353222749621284958305509352891507065537978150518314618840 + 1953749417768878991833661315137426428652077503145679920658786397955780176167247358992933014357557538701378753423037285649046608 + 4668877807427263578702242652781568611601647436182495270690516771196062145719412914253392449657363828299691513193636571040444936 + 6886803557429783411232920271165325523458164084362409904470754437138270784982746722601116409545759719688367256037780110379647023 + 2300356518881462544550334413932731049376257074071686920169237332025867743966470152553906187385400688773328478685498436856277618 + 3440412356699057087611095963196908710039931495043446625996426055839433344899946522222609944936452224313579344290272586318016202 + 8993953982184479368753437594218699447584551919428710623167603425460525558734552005471227418138809891695708393142992004433396157 + 1641364290874900167201473644758505077028954784718448987507776152112958786620272578580374033281627136838108776465262593788494546 + 7335791534524477898748563122556395894974284747735359153516999217809354333772921832279669823385048414976444462237355621384907691 + 2772845418405555209223672772048928810050444241654554863085813477997024445507615114437302354148041362541497074784257678291599777 + 7178588655224708624898385615582303156928858845044700179599109039474166324676359828675085010955238472718587302252391630153958817 + 7714350463980300266933000010667914572625520828229727411680133017980270989103849220980928606661613727680746076907445089175447948 + 8959804988970943750240542329725780454835670277149205665534383835852603494258686925800889072070906952377561912949333090450610435 + 9127584427822125708186685340454898072189100248623017561567872674357247419856515640720894591586135918230623264124957308938825903 + 8565660274882658423962595807578322116479785809616786494557353542161430392650520437776730973491703217016387298185714704526578560 + 9055899627055835280579204790473134990779700561942294557075688923514759353053304752653692669704340622777026507467115119994712711 + 6401990429555126633982558874714554382951718476795179895512968275571839503381782370343773457772170386412634133151122279458473043 + 0293309378136412704813380987793756861154395548470319616928895806731980671468030021029452883570696897386186564749939824907170573 + 1417717547255789991707004411151265689787923836241613415526707758612724058279277154586299713815047231145490533591839466123670638 + 8468716387126244026336620863493031193083664955579994896168486675960587844522828676215258682659462698160621004514607084416783102 + 1449640886898263771104309544234611139764719954279503593908340282487665393419611852384397377672021450701130079538845214864162053 + 8048887383017701836654298226594900075026630240187365178333016065699848058831083230977644940244574444820285738121188435273257549 + 7734838976170306869973081121181660448148530318134255364556117593964696552501147168845028313551613495459270535042160362667658266 + 1546639029308273692114824601121738207436726090786353640928151613146720401120659236951025944213817893334993036938357931276755092 + 3794363877794105698247622335925064622343924657500773158672876932260234127197098205417204884907008074223982761704004122962430390 + 2332227732674259579606138447783556533770663844706548255581644643545209413054398521429945056259218551425238380035190336407512204 + 2377559578117061565563176922758264522313042429970112963159461355099505172026291216364090521544160711259708331105724128544891227 + 6832428920554567726830569490691102432470549042227057932067103955101428247157515420358182404777567376342028775513115385366928419 + 4241634693879583625259038169292585038330173637743744110426172931636984875802849325805759410994995655688205543970012859415471525 + 4435409455307673255925091284402380740900794676435449835586381572908519616958395334196299914509777009013685912584824599000928046 + 3987500940366892833785739644668889848240740024168650731790637517228616861342434915208852629849188021280517196274460956387434019 + 9025408507685643206458885320228075047871187183125968258455419735129168110055303698970042275578099161589116560991845557669784646 + 3366934559408606275260397226783303207383085083713447307195484607017198247596814686470103165356557218941037264416211493596219700 + 9986983198296827970312097410216841561044999906047830934706495494099795173682393665158233220314878778675703926172446242051213291 + 7327936388263057744394340969867975674336916032235104437222484250956772949755115175068343392125983148796915268153189466560134516 + 4505129238068974615562203042384229709458199180125982048735704933556566236123385106774238252165050271569657572461570289000767894 + 3255121682739504137653843468184029546420570010142268916658213975683507187608005044348538495082520951103601067607492368878206287 + 4806852545996927533787451480123813559737763425204966730971472301392243492249231539770928832609537982396509758149828504617903683 + 3852759316339548366895421554002413138488562983328873969801625973328318967409411308340716647240522981188392227872470754156065273 + 9712297766053304902554018245083167928441148337025924749085910105658941917341095233228980927774840543348243226033787592995988515 + 5229452832882947701986160360761878773430032426431930521890318903440689202842760168592576826646125537090631410703061420763990796 + 9492775501530308620829606600311339640855706549659904872171618766544922435708097161505981598338090549562866490651446857290681656 + 1678808597459616937537502211249586561665053229525645425138896011542471614595178170509581277828163045626690556829964393718215591 + 7053324203154477437019031580603162546890080238913915157646559489429803976541625693989468806549155901365763128179885048681463067 + 8903137465669354155616857417689085085205927330249024040964205952230818210265737328326102255377329508350857922236822007786665553 + 2734904576394968648887628638128862963608976988414917192020797115239688653336018428937106985737003652208275177709699892675605393 + 2387808386702882349280874532643852585858561738093225119093657885192947905905747402618285721157837466909047447734685099503267111 + 4222155360968520550560237616569205752212233789555461181069785768415048417477169723562149137809030351670058489971512620085540222 + 4298243051299268952240909211177826836030583513734437502197104884602882464340255753900393068054947046141922743129752936688868680 + 1061375462364377985228292590232948700810225069864185759076897910654198361668411325978825417457852278989472721657536588031658991 + 3940469338205826791620626804680412258933163753767218044848985297248760060861868407223928680948167632232230076213403901155993516 + 4300489987649264460199719443525675282990880539122997731272161031062934060033770185574543151609533413639501738216215062848675971 + 2177118188977585453528133388279985990921229278769939253605657684059131396416486258985713207176129279519783451725740599907936598 + 5468202247459866994978249422059052436184697608003427416719037990135361500297493876720017894883453685240892163318994013086288251 + 0775391987748089844439257445352687468561143051750745275017026626096588861151466861293340177217020485953364933966278607508804835 + 1628141832107584076506487704333155316297016420320945282094351104594402285535278391969212402643994113779520387919087141691462578 + 4568389047366302665905669107740203378971862242851210284195394536420153604497510004787197852478898999690840962496286253318550921 + 5915870003274717803413556085627698745281531034825477926175968946204463905051355885851004345422507537344854894128229093755738123 + 3106488353902440267975241920861283331388536648597182081274348906670754514090626662608509624737135193693712779860188833406087992 + 7845555194352577902505815561879589158643398041086893321684441920278495085775044919835855368307051779503838399479822915036806084 + 1432352323824143885623247262050454612927281487774810795510104248803405617391180050263987964438216016361064912733157137057008420 + 8930414578064185485247400714821333921221435324501439994244285682760117301820424406392510602828280562393052749013520039103061655 + 3173670884438194788166911165081056822054430147218290866655074231005149200684080014396687574505239932587314443974144267617007284 + 1527450743968461168931869720925121234258369083166801029927251949358618661922498099466741377608784560458426370545741910023312926 + 3234042028371733121222497619662259149254047701278276017559926645765011785573767542697475259020390524937117767929011666715323342 + 4704564242794556338739787095791826301668604024597313082723259898622680965079684337190731792129157208207454560161440807617595099 + 0586578102694447320030978034126807967366576180034644346378206991116172450484663474175770472979363179024738326934451423318607575 + 6711140559239053730606360957739329179929007703740765446432207582934464258439308670322228705839599858462219965901802441668368441 + 8135099406701400995240439771871466473527799329781080913941715241663698683730014850012873125772974693072458542177139084387995864 + 6568179602365017697198231075678811557245910639538778108917663715366214082022315024791477373317009595760696873073681125441512291 + 7907116539452577187506381898980888332568593365733396512784485641208492339371509014105839017197673863709466309379039960962534849 + 4750829188061091962181509528044851805549096285740983094887975885868844208625379458016822827359147295255429793714493083753502809 + 7458122759750053134279494636824383187336514214679539541415555708799139748870593845560799552363619897719534116667792275265497323 + 5164505983084622666859401822913429103147582979952129213026773147211467590148787858747588041796556975884830210299871356341343674 + 3017622046748766474496658478936400050960631692047289817971683454103138868538745678486924385845403439475522996310311537377432294 + 4414433427221551082351019813726625491301604743637648323980649889708459225496111765515476857080238229389480546313915805440388154 + 7128048414711368158025433805098117535633079017719775105234085215317610434688668866637527464933292899758107458405969861125706230 + 3650863400245738680980130673926472854780296246906056457846071189797804208159343552552140320987399388241880735463419185645329289 + 3725491818789741913366698889863185159632846810598378698135320769928269090296785595628838126516727088490704926873118733305049981 + 1156989564178115063843077403158558596361694573121010738084003904783088187504126348616809589260761446819325657369704310082822306 + 3039078554378698516122693013852039986103065748081512292985255853944982748397274910996825923066426171066912792454508578589756672 + 1894849971820554276778681262205130604407309897326530536792905116831412406644096303796353324894146354102174288891383230945427806 + 6519430441043631674771677332934701069341868125297788424647970576482950339536231483156528606063230103167532910086072700422834732 + 5003294909621810744051481544451641763277370208048653102677095428677725528287642449117886584959778219864346164599848968697364087 + 6751096317004399279893854072583230132666460132819591435600170059086840170914605351655306551416965997517899522960511150518237562 + 5960953398400790636904166620422410033200069198453455057858306095484024517953196610901762809189095112424175853725058162186086849 + 2378590573214575182954920757796313474094094261522041549359071498710995391605164191319908953433331128043052410209542459403183882 + 6967512166626834760387377091334566417667045028443096775043889705526174743033818006933449908412813794430186357687977532151972724 + 6459437209781961727829502811704779207375810741393525593812033931653583330049048561114949732748301604240502210577065589268424394 + 5485945220569893838677587873427380906709988368671130490257845675526326075411511740051320570135507392241324306058959038656611327 + 9867804575762976412063217986099462524791020332282964702449941371619543236717809914141667173375719858685004628965511347280443141 + 2110798992334306839358051076527899985588107686694616660268331099137978416904137377280100977825535315137051402200610861241845328 + 0363449860601942956031660094586702469467050513998615147930502263169980700379643465968570908871332692146680759419252634341789329 + 4178175171299653546801324512595807182660716928201014996433033979566075147588628538125142107342090640143892070802843256418010103 + 0456138779092213905930697158012877976499848878257289818896704580464918962127445564050766970246810568260512090191166877529968532 + 5482828669997339487166576516726609979104834674845622909875424783106655102257236764736990686408975204793086071837965911886835119 + 0267535380044835507754251971519271244598217325940244403179333727723642934577686643739339224195755654907218801997476469074206459 + 0065138464529181013506268966674037435955704351830301533242369638335168171139259359713958529701206344946001165594755646272160394 + 9247709545287060822576712084519151900147438436096859182537437687606226004692040127414633767616557761740535046385163645108196795 + 3057714321815816843173779617852754091940306380163712243160807705160943819438940855547343479788687898931661575785126108832716960 + 9533193667848378687611829528479562728893899352573352696025950207316753012731502558223567081292045437196069989946207141541601008 + 2746003049129497733856902406986044430147897422219852413496236136281848127325893646312380454532608491203709112537348345922832907 + 5956088319437370932773128721138395583820924421370173711672367829016504396575639303752597289231640106298414733655039838766441635 + 6180360982212734271044173784836239476693843516863507994881855803639383910953492384867775507310386199169825014966152355545690080 + 3474612962133776522839849256217894365224998226219581308883384099107152737580490415337430321380267679764659802341675603080689884 + 8385214883553973286697705130178868327520836907858212929553123995458539418552809580075802670275820221517432874193060009661810485 + 7635870550202301972338809565930908660230248958179738819097744222123891965883613360999839391218647211336772299291193850385713932 + 0223196991899819000674224598203238140866873922543961390070945675722542943959098310960399662895718004978803705167927661114684329 + 1353039351866220611077365279049149758286033094828313328435837478853295648033377121231092341833142961745552118705722131187887027 + 0630837254454720024736805497864487627874608261900388501662821043624883721807437900259240409899471051510920617085099514167842832 + 1988240186121860008928979530309334258534723646976027619874403865209331775508112215956780097468860667994721263707215073620406836 + 6148969112241707992551262221756342003961909547272415999992255159101022681539848421608837594935060720460495066842999521680449846 + 3457737254497423194650056810264127963010085423288394333781451846227050135758357730754076741230565869445804248143832527389323252 + 9790762908682747953438433738621860423268309500095630988326150834401786630708761812852217486714179905608190957461442085387864531 + 1522476382145618120242675473759696978079648715587754580423057134915914494338656294472760447616089310947302406703031809581038470 + 0171535968526973835184507085581755238300981407341777890096801351412273999921818828858705625413157216884807494772810429053662454 + 8619996360469711195123911341155232797961140155492488752604043466908848244534955186766472286479836154777737654804742176595782417 + 0442287907416054215425872961111123258314536732740500399960690027024024360050777203631279476105577959878524421999307563248792796 + 5348313098484066077132466864776966488466415145151104355092278471837179740560502130988667962911672913331290100002597980514807384 + 6973148695771873711809347394667364106588642004523762177909283034839940053425839430616152779752491636974036365528618662576277264 + 7738896628379276240988497456223829719984420682404133841162697625994660783140799400756439398245883415372300490612168611754778835 + 2968155785628016494964773780830380372616577140688533547628672148913272007307142811840952334174750520152544790354169079912774158 + 6160810488767205184519228782587106677087830138711937806611950216229418417002136640356986986424817853470899640679854298647927259 + 7389645808720792658628388654675620007991152874617887911936239398213102595897949513877377839509375811277492184373982237380291082 + 1922598786894089615133138929724905768857077536113336665514173213408958842847812824030198485744051056380839435865339196791176969 + 2136038443877769241444454895223211664298720250012371885167260344691881420934862218782035849576910341176642258076960704001222187 + 3619101830106431706477720342582912973276053324213930842322321478885278765764844239473581443510550046154371836075105045519367692 + 6632620878175338782391713943229145276164648915620343082760668528508249819030769842115080099804055533615175586509178038716739002 + 6375633941128896351976814553047937414266141967344986676911841486068926852092747499580940682140408121435982416523093436110154753 + 3222139045759943847229548540511800241253979460730316619733573541964096618975921352811299052448712030457862855059140594007137487 + 5542934473211875603591035637674955693033630753758706551752052733350020451305012112157194134893565133530552290159364523539238466 + 9616750069420348886409611437053219761816707838644591613686536212537661191394262393089971240329521480448880783267163369576343597 + 7663178436164222857814082876400941903973450706396969842174499622842764650335956819817450043712545807776915977745377365681672284 + 2935635454175721831517097628434415466056776136240049950596242823574086540015840252558304179235526092054789562977490616481745276 + 2672225222323108279006574534254983148801337991382313626787322270855974712894468368216489102586460739019744587910470428744488347 + 4456074219727400675373619105257416175699861456100136151468602175897841754789156021282927447724373220233266891662271346817093855 + 1945491471112632720796456775261728821202881302996527116048267476118823402662922873934255261349533307722895013671219044843545536 + 3793064262773487395195026532854447589979023796935998929027789654646824047287035198327952786992674028615601422606183219879793442 + 1630579923384492024946757118026605898057464509351571155868933384841116903091820066294965297665314366667361460313869589402652652 + 5439801899827848778232404947415524928188533947410081530624338414230329436826968163987544645598294181482211511249572440955572589 + 9020302797433585342712570197932059030880158484733343798115491391574065623327717092645488738835390428206014044345059915068656197 + 6778633319862050630189473515487955936852231827578947650626369925629640725543661083890077620427798703103241551925751730707081567 + 2865799458475868282589650599779702798567688820803000453419899694057649460056145012638522245118862822941880894081107383763766480 + 9848357801406244621888791600769552120182014301160477310095737436308083268418063998275870777119923015945538580745005505737103338 + 7945415897343252007659617183211493332054610541474762203740026194193724624943127621999433384183901217893204226254420212426063638 + 7076158492133875552332779907935346207685056687613427451355599366014714317865416656614209291512293922523145859007589727797381122 + 9946333250403836274494116934757202951674758307883028448572093526467181950556672615580772027423711017988838817957391185266051907 + 2671612744740733351071730789204383122286756475831821553120581637533315869945628262846596800538216358815764391197830622296989405 + 6992508792590965425974849365498446258624365117468171476061738700582645427331625361075430086525639161565604855405377972628830548 + 1767000101633223839049666007882398066097691088797110243675124836228262533287561681535331091157763899063838214576189418367103407 + 6457110670443987985620843280548984156731527065461755656723700576735027138342545097213504695717743645364185206786138748271882473 + 1596890724976137980689991632152444686110535638170408866300049744279882252913535065665891060859035882361321345023887058337830307 + 3373623078064203672049256820541947607511438489025503639693977760706696248117065715718091918113311545970967574977708709494235026 + 3986923221612406956343410179388036231285096894778891156497956823154793926342464675477516471934158222112337889492119504249964378 + 8383359661494890362436075780531143970408529612575647080037096675346333712031003814298042719987791032534165077846901212886629083 + 1031714454907840175775311491859630739967098843327841882994334085317927475102526174618259645090436553276509976956833748682136561 + 9064443423702201811261101290439334315411997283217810869669829733471939988609585312109817796812433049198581074521140984709783531 + 1643172980645376942250431938106354165389537074459078140489244293256765030797030616074547245248075610258161012282504441637098927 + 1963449744475973480042625489273145165780544076999525577661332442838969621507452441516783367746336168024894911875794707697541031 + 7478540879501049129571343735300770536436533927260315165717247241849652331693508424305277324109605811185754598081962423629189840 + 6683599827684293037220931133813347833193703737280727037200969748489983084498274135581120006138983726589125846483814619896382039 + 1059986341689241962791022654106008362005402932907446471177268388894146241093638783546170660638544503679877547754823916693779241 + 6066567318288101759879455792419222471083652734422111018558539534478864130071102091839803023165372816119391124984955696131849946 + 6509143418752724874347225367749147359005862337831645120532349014908613153135844609402649987007336422813208143055617331460906483 + 3354213199998376189921305928077126664201462525396049040175801721488556837349266500704234038852235700461088952452452884233498199 + 4256488814582093977539133655050527294580364706253926894156976648375809383013472871520377935537449640402956782630405195205364082 + 4477841383190587477839953144802218475017581377483593956131465077901385252056389226406917609350544701283827958845981175691165035 + 9675317500791142255855936241556896374576355116352110763482014692288089584642987642868701466081788634493767773533747361856594926 + 1789275548140948127853887574961649444778475578058016075475638253177323030087374164983465707068923303558558151943477905316462894 + 6521653020185636533316557444077296865023590390333185648729621716717902230175881569862122737390334951189041533339830180227274093 + 2241738740799072036341573074248811436322223477169424669409308388622966605065590062245566692647119962939155999944641570918974529 + 1928105019305194521974392400885274260434232105024551451106931113484210411868649822559924165796213171984543031754090678126105970 + 7223691850432923916423525460668413682740557862272946646859452084367199412001020057846809103738751744440123325432522452656213927 + 3644451389904659220831784890291126628998096321970481352017638587386823902603865110497499248782547323024785254006989249949637036 + 2368125490914853885015667449603549765164883918157991257417554348691174190395500642639268158971914968315411160008374937535704060 + 2009275459811984599922767470947284560232970282990047819179940733002227635796160576632463265974978503386125557611307429312063703 + 5284668210801338637743489600143584813073507148578726973558859500688227447435508050513188287747750741584385175252456997688110085 + 3073679804770516059033436419747376347125944073396261678398209865762812539120718854779696622769273119321506920635555831381282691 + 7090364017219499874566644997354338979508197792775841533060988865177458368657219876491035282278982441665265219245626731000939486 + 0475155794230569303711742143247875808031690475413279208626652350784369479556492756708347931041817323940692567675398118277710202 + 5987347394026084150071478790424131834854554229261815024383846088465079695373324503305612702444122591068763896541604539174335033 + 4436269510455092220918525983424623113381645210225340601560482106077382634781965165780342556554085651205866195116920957396275838 + 3995168889104032757269451494854524514321628575817645123299310077893411388042092201792884422861886303896708749182469953549119697 + 4535001242830034769362884028681925364864771844433940737375296944979919237869503095436572944940055711115231301447509402025904715 + 1800925216578304292056694261819970660613390371844516635237968892926502845404165792819051199273212724458326926182758338001776015 + 5370775490948607047730587515100674887605918594533934598837391246334643161422435117919064366778561014958058716726561922586618810 + 4628995498127197780734498354535034114170874670064085395510892816542000534421254922356138052258209965701576585535292854686090278 + 3177671938008077658853731628156335766651218454783739782004804667103681002183460703859644141290605438413899770795832449230476552 + 3025608055188815266778993615750176656164484757488579062995887277096944086284232725973634996318024169760316516668522315338538984 + 6602875499695059755336245084768806035216324561236127708770615233130804510875618781547430556541215471796577953669434492812681721 + 7882550875891690926234268000498082339514970368440072348061964280285302475222074394484586936518612822244399239424272459493452968 + 5181563270479719492880854609815755784042683606603220498202601700410969538595041484423412424024708099469125521786037119075251369 + 1248580037503075406711823500465872772309344548541150892813671393177549861436277865197182621221456420646870403987260426109411933 + 8643731351640151069976036541617610531794845092323107755413601880551863223421905943669090586959614825141812500194544006658912658 + 9742463384500880801343550699245637258131793581488832729126778269174701627529245091838528797596704702724365423027345604418154777 + 1491976930735419986039574314558277854162840810698202905470921161004472351694186257157283632042119485754805929863758038770286999 + 8776957710513013252382046879914405882388509080000643024892306629178763000752942096488188622280178608686752194263930907107345039 + 7700223390484500013939160057722983340948636861897585123716556883603506625380447610584051517968188462287828774879778811063488262 + 2795184513732482674790613434841545867779716565739406351364662664736206685645328526381352909903916053024580749353932896630696063 + 4740510819037498201511535054658680017511924766740460699058893969064394902765714052038187304179100787141754044221407272788215435 + 0593548885409678785621622325583756109305462458590848222639139506641697602853829884986982801690179238753218240401694408881886033 + 7410128478642788707381845999570686789659413433178313527394929430353749262597920022866973734073910557598880611659693295671936482 + 4050137980096982959463694663632299864309583041246448456720658864445243964035849113054975666938514766051492807225377478267946248 + 9230953430893702870077668677812927912187053690817849571057339797969486866950088035191626753948056471063994773880460982770051756 + 3412034824969056166032815703553100561028200933063775986905919463873509475321843375830242381162225467967586471609115452917543492 + 2276619135566337663226716925555717587888015126203959605452287702197704113342129180746061351411545746680564903503675372305630554 + 0286134594910134037086879568380122070111392862199290853114304309332761209262076794099989915249949904726721530928297666077629849 + 4661032688517145326760870540723245614758880946406315180541283633369882854109153204199703802230512566561461752474068428161370873 + 9985206963338598229560272298952476210547736996017303976951734650959079279082066159408637306110242916656383381032701493580216738 + 5913923322753424774114001206375448829014685918194637698592895629614872898525330558761701771138709572823367430917528581806962699 + 9424883011486160624035588850742276732199499002202807230209412116053419259700106808447590894864084149744926170960405759460241951 + 0111713605391910548623870259046900302961074850779853822097709685279966809633918351283533571183917553534326378996150978977861347 + 1050239621857569309671883851470643478606629045329299864518009651449122046063366124913574153087650803586812245327770871382994089 + 7338464051366649209011968493386794592783056535912533194525947811637756396164788969037121048254365052840678648300844862166030403 + 8244368111563457237764184604100489524090599993135317160344204589670504422777317128963386304474615794833181756194674508984426359 + 6271679168658661069189900053139794326069244916803991726466041535821018909664293827288937825025439753702650278433431356713529954 + 5346852690092871593686894605405997962260976572140748476453131018042391268683407218753909113662935434807662980531252367452071209 + 0705634605741863631683627483540085543041836023190103343436641588904884705166081263630037435630150915106908441737355700766586129 + 2154922713467232816471312647563953292047715226865590918846184574044421063130666383320555928376617359704955430293171097080231031 + 6735370005980738361139146789749484206639522950848455336267649778629028940168072161013843975973729190308856690607301961044761977 + 9897723534911105404785432577277586147477026587182509778621368216939584671433875920453602299697242616307976245807249371547062253 + 3864808728722705732544842322660134226278752025136368637744919793216576700939583871247088670783610602247097814787263304145508390 + 6389663947104499816842871432275844541634180937582381422116532840275365272420061136044394514594368541860114545782560162829849217 + 6461508204689611076377900958964324912439197085219708917353896453831247651446957118893020342996847989755084869372230374673491989 + 8433851389135866749479827490565035784654953912616746305746664585754447284795963325019971006496729330088735987747297399102902166 + 1771497470275815103247219843409878702558703790756432271114114625912471360708464566558219993340028146304118900320024587821960404 + 5976617030473732204037553918438169303047012033263099608437162902327180494837554619833899125897762143660304278719895133912883606 + 7761343244919347585259429796353568917054332343654064758967248953925035366120514799510920191615767532119958355777106600079597516 + 3095394058128591553990850297147880385815415033833458376807751479083131186229720635268920776120415936997418185983635572280182597 + 6753076258298533536576760943150454522971260918131318703703785217592559654671733288977408306810194844570204346184368392179063403 + 6769837756043399718259982003405678775173052005969429887545845745194588303371446514765027612890020128811539282517812340583382742 + 1145447512453860943574015365970108349103036202936884373965378227317332374230149559079576915215507294569467043944303098203606050 + 8331961563901986606916925958427127071602998579210529763507751756811409645017688889813292902535048662887095342609935463489041490 + 9736668802244229960622339427799905563413901438749725163782080129777353814116461004513305940715905434522181472880934497720795747 + 8089231465924779558459413345521275018800849869822143818873965081853887737597561843190118386215028657051186337416427295963183576 + 5419828194392698210106536176184087551774670922454148544855468554475299499312061306599825835773673050247207685913286844665654322 + 2029050617375681673334265164512497368276347055093268045529145666800867914194334235145959975127160210970603920222624846997715913 + 3338289728310358326423356618856438897910927180875153967318427145237491006914876971227986916804404786999082347353908985698677388 + 7003592673799641258705037230618030712653838166741113566125031462959628644295056269826492276245790120809269461415827782914919523 + 7933808111352753578305022191116925704616734794703884497922451694274860316351759525772713769181944674741861315056661705956786856 + 8984597543198443392303548683602615735750098545443867287028649374064105213301110278127297110019939173598045760404284726471910865 + 7750264118815211285409646722851047280505065647360902845736489925465867330208651476223128001763893620074546763783343802324668030 + 7948487261322735741590287466404743224701011374099821413313798593806289098955840277566381979282309078179393391191764372912784048 + 2031963937573607333606298955675833689352959686316425308916957187087489102352532079680910868716368077096336327451835608150057007 + 8744303746009770077282182559273953960324245388355803375849588763883535017206175431068707914836359928021715134879810455899706000 + 5908433402194706392948327209167569206279605516036898586828659659699407482487006764800996251885333845684403771593097852947347762 + 3484375963559500648211146100726353736952008101895174614070329067925003079219669004928157370633196400836866091467437872364498774 + 2081484205640426298611707106538905461885148824043568864528394387116332857339440668358439402474410629912663441714724196706517933 + 3644343088909312558175950443352757850056547896271926536743829402725583986356025290388997593791573353364649376090870755738159871 + 3017618967565343354488657372318982952747583634309941675726567297969538505603943497976312767045820564276791044673865996984930840 + 6755211147212352533715490737391598930938409102322563339784308800982635726297552669891177376792489264858203303571448544969284885 + 7207413969560628720009738274631537646543552986672220301640499255496422838738773705028096119936179105477192211718065255929107570 + 3952347918324244189239309810051132796520311457058379135751168560732193370931728585607246787585935133034431471433154073599431184 + 5948122133173804973271249039138486246462418117000640467153032385374427588683813496957187641107568040808210363510174360369854945 + 6331834561201934486343354906308493614367011264274134644391474781936706762560771237417922164625963715633624786284367782142544668 + 7058988605827353891060874777352863740110376065711990117582066617633614262447752203022541270469488891576938820572417323582324874 + 7650494373012942929901692837674976301695625545739424778268284160337186164992467580080040539595408395037645199431241659430435207 + 8656919176134694488026966726643058582704520649434961668466021566505602068958240292321141423966866142697100141650705135865554164 + 6074242737126300341900975693876422564450176547153341379638414445501488034596312318816964962988094532520846350286682968373824742 + 4534503855120241805255426868718961329975641710164649957599487128347011734954984504486944932371682996864451326051197976215900771 + 6630007989276431575068445405328391722701879448701430734576747641331918162377214794008905979133776103351215776077151862759310804 + 6329412106193202180915032816114091690804553056071102324935636935651606678882718350090015499101515918794964067433252126478982521 + 1507488089191785086302341745012119227252927110062837567351191646939013086128950794430586208439605756178768284242079693463131834 + 5134585587442274519690540303774472196006421738851673713532054649167344075465437753885506375501473079004259777595528824429150142 + 0167920777588082886922742091652852786107461336681294679615598036369318540905949328746327769828031291675250740935570893774610363 + 0038129096989223899832722064059115068115632289006675498997130267266081648211647293457692956590546845542631469315045748487379716 + 2520900382745986244596184110700770194581607346454171538723932383294827821673322365898338493511029865949821494463508742106545267 + 0565722884026288308442559359348206336146522003909225136977382087745807490609842307769964489536237904153503877870475885643050177 + 2879720936866676112852941496983745298612873646677215750883429056007867869583163799946103524454641087004812983861736126233920563 + 2682472400392268500328620582825275316785330033129835929951831594780666869418979561874633816166907302039950903765570878767521214 + 6000673278648346135978034734234778737168645117288730828023574501322757674622590092065551189918194137651428146720102471591456653 + 5327338501961495043879408610895757013526179026139024561532644668711391863557108491473051168562266679950416482721536337117909482 + 5138678303997976985493577927432562758408369467781462054517017307284536794110651849922852301352432225552398279721808418546811336 + 5942090618633537593070786933293193872947689557210874049534803895058142797994756021217906395785182382696435144831868446840701054 + 0805866230785777399683174946303367253262058687100298157860323746012789121984620953083069679370163347105957163924550067110548159 + 4041789012854867563385153833627178486269852350526357948901776390770563029842109776450416321004402898078350462398525384367774030 + 2665510818821145216742821558285899523213916502258403631925403804385199376750878427488901928524046342897043307449003184422505729 + 2048478041171475190266068119919204384149581828382571880806118238802367751477551342088588974943077841775978105590373879036044712 + 2582550167003327483543334770578776146465326561660371559249486818965320307377862762238777770099168908851119806663382875070424505 + 5444680706893164832113072218288281376031594555136022935125966599054561592735752631698479935094668438169179747421550309847079353 + 7876386229779167984882703960774028877296085268097204654180082218579776041301150186998163564389835397054336008319799363495236122 + 3595623959964323543031266473552625582982574960453793645874949571464306599166850005238654688725079784506108930071723727021644099 + 9904805562100105780931661247162991156577135587825115134266116050943890998432158388576995701892214120245792294717827415173723116 + 3198902109416772023345787207073949684308452839612518670096056433197360112721221131290963458888501686457236376124484894557704239 + 1439923839664744053843985184599889045003833780920311682293838839176055898856807867213644378338290067096258257324765963896543835 + 5700918940980369141639579109635400284102047501766736959067637462699617150713985354772825179670276479720622682613542577452843978 + 5832673606644924997743952540484980626339060224968813632527031664879549813855034184500405400404100621140495713672255224298990414 + 7192889419886464319914820529555240869091567523179106161721958129392253172606561099507740238957725006168387598704764060094854671 + 3309479510962185342022955705280901753250343720767822070179996628541199963151640899372621594086084748660799272108092321615608962 + 4880909425016446720046143938905942262706584339160340379312192206890240470343647456683169242925461208146677458242299921836024115 + 9112782389287307875231265914118831295892615090298799256818943475243201711378213965480178556028607894090008691361256922857338305 + 7878997196220126636517126620736341433150726102479409458917297307599211520723041036260833938983460239182766740060701211352201191 + 8683094774314359941970056128495804368612258860699432526379799515947600345795062224586289908023772808639146020665057226162935485 + 9660235891943541046373003698737146580202165968722595524291168751596799140752064994627768069683240083731174671310320210501136516 + 3952299801633659008575843631974719807086212606583728034228268635353770341290150958327244666611228164923899770204672751927925499 + 1681865396625682674685451758504759903079794185779114689381923935911799262023419094458049787998569136087163049641052695527707434 + 7051981372339577512946597699315700689964039969082898958542940125278978182609047860935808672479205043611404976983579300374284797 + 9494276685604001130980581987978951663125638076896908522150813094023439651488500315910058707670482621722763754582892271598798239 + 2297480620143752383199993430862475021936852109466853279971476608874530008450195147642064323768140191491557557914372058492369456 + 3210874548598055876505562103390094444210433165591830328725710043504607452200463576289609058990598342445857989436858490154233543 + 8132507672542987199374049904308113523835831443354290371614453927015873910762212637250354565826616538395197156337073925141693484 + 6828640682510305462478950222772217556425645114511993512248969567524785308290443499084010706135805334321921588360262285590883409 + 2594395457778771868965633838538089838472114546447151674569430202509411063873470113459762471547280714167783037132473173267526307 + 1601839698883476534179701757004074668031433379390884724016658551011492507080285489891017007383477491584644025888213433125759305 + 7523532561560703539946099285117454732843364985652611667389407913314960693543811095755855340427962780551780192610470189512825524 + 0348247544916136977309530119407469259627024645454634138436438519986158560867875479423449700625816301245511994796229708771223160 + 3917296084877555076938742844381232454610347414176454495292235478841999037736204668770470759408859717947445502249268193464913498 + 9942815514474689741504492308012003642347161752400872994567873248383495234578303317585084447735662421098893789187005435875125952 + 7400181919019490047282686705057224403673442901199627215721287263528829739748034312624985655044437343710362758307470148179539661 + 8008829134593470730958751998114225068506458584106597781009501241738039124829892755451932663527484529522803117480503191650035801 + 3220127286757997144992978308357689318213671314902934383221575508818519767526663815112777913873690474000419949051472231014820267 + 1399894109901863236068753449286869832068943284626949416147238270002784106062189067937811371979896380361397172738949505933506481 + 4254902873234171699063619785819122642732788292824537159169433666069361612397840595910726633660384383938078177403483650975568259 + 2209368179438159444309719519784098123505334554409147220881995692904711982790135929098654648473758048308424437091906340638974131 + 8784927854050511928452505266509077489186830632833630361379070849447072741785156478899585449175370978549268898176795868437582718 + 3231975833056135924558298656515294400028803078329218944207863428380011023399283981167261222531969361122301223500410734344217228 + 0958925958615134583645559459986109673563012970906230471133763988818583110841341249599399387466204289301186261815920165156578985 + 1991110694748693828675086932988793084291818416422390423728768580762059411945640551530823790024178761601499474873560699371792162 + 5361696020245404957765470178767621215479647553935020898244576640893571391546565492142211775010405579641149396961911772636411704 + 5933641384834122776049822258585947581244135364908556513226296636775905866481756079367435635748095205281573764949264635941006411 + 5041011491795017405240846374877784042033437774313006536528316953327476960247723830386371163515353865121506304361011426783525735 + 5488997063517475914229301557438267886673740763412117613628897204796477231021684048588313466034859903879245472327441120566103502 + 8530760385580859337137628786690355170400764087907594224462686544107056072485919968752489909254263413225447887894153248109175652 + 6157903578937685041336967794345564722166007100607239958562466608483279980200607600350161886932405833906442195659498278360919430 + 9828873150674702059652960737024831945705458855872859591267757719944168191278626072224244567244295799804168245158850647976515767 + 6733614592966966657616990010769041211313964384427177615958783894640954404002730067938048093833284287697173874637222402450231077 + 0815239310564450548270963278380227549898803833625140660969258768879529883774142739151346026790443492061196604908528916004363340 + 4528891650268490704421594911777184311417838640306057034638291330148034732863406008674812263692977851302665645685305101437279625 + 3233475352967519524983898638596372885741145463145393518228460271054338502613983364910024616107499752355701791207046590492672193 + 1607766030654760272868975035371747266369258074306005268123601506826295532939956628851683606599198929232644016608548496393286833 + 0164998823596400554560038697981327950512161089142533974519294883428101099674224630562022297926592367086936345609705271926077768 + 7913025882622995728679690258052758137385077334095212932668418477051379462440145509778953697224292738907994604706710137743620276 + 5951558921066718365814901585239666946472249768608440652585316569506390348051275814890810652375791805564478189249435436637972574 + 9602716095164159166038408316037910403855288603710934148506742938423062837375851102966449162297207365844156933403348477083451353 + 4627498098319599205600533412615626896664838788638148524473652142820739172777284703948483540298530565794965460580139030303425684 + 1565284739336025065162908150482205331120001945515224141600855715524039864305366369748820024483450351626491054274468986093516231 + 5340418952181086209554963565801571626818882174630725995663438985529129315572417340527118943747399687973820656682726051844769221 + 4320926831481382140838060220194555123790396897025705923345941235597539508677805522059012930976097312217637965288298799051778479 + 0908830534451543414307140854781014820685341080782566962124152921948070095677549807088847640541631088209567823713325266131951427 + 6110373879023562027503964302970937405830359276112650695138428936697834271328145752116000081078410010751317037848623862138058557 + 8822703971093401247422493922044598594234342733457558225718617586744418222085876701060696882821515543129744401944915912235798465 + 6594559520819849307838207390295967732653907650649027886332594421647601798566341345946992510422578734064164433073111139225071621 + 6354737391657731503659719583497860062575481051328877369003533126272128322177145084735337788672157007937391387995919117571678161 + 6945608633872227095639320829071216249131553642307083427955811490415705093929385003029105106248578633207939138356220965510578956 + 8875904572434922005652897358604531384916362396100014485333372047722658292461442588088931849935109173016445065149146280103138497 + 6344250852997852406467930596512109372720069308708153172074632971208643949842907827125891877283714403480777088075917332714430078 + 2141088112696908575603884902935424862191062652660730968192553423838776572288261313561512545353202622522229101786236940604077536 + 5420581455921312988453042096323962394005097705232943223301112814607176607418563604729931333417412031473023307632699354685035657 + 4904931609893963364651740622632458671635349731291306084872673976452365611310080979515796567705432384020374827307261624382593308 + 4292701172515433578998040448234672894273087795215109333668233787741983605782088266764474905796649724673659270602807201042559641 + 0405892711593975173584006410022813365106426354541842020523033260675160988528765885253376470412464249071597201808795790920249321 + 2969506372363457771265917606965665281965775472879910780113511573805868748553670687571273946389007257215130433994049155446244186 + 9422294818781445710760638755747391659377594672815933259737267891227254986222671631563563954141355946614955207418080860505944166 + 0087286626782644309557643177400304492693387991339358406695023215774476540471075851900070969889709559625262772196723374356067617 + 5897279697608188221125456894430238474410213921346239465846675042270793388259552491229704041982502727376305057500585797419096572 + 9629126678093091084216993559586337141715599917690951379809444249525710962700663884823083705316885810747054287541385125785199583 + 7595346119985543253389563272070967517963948640714499895302628870263490256644647992172402145011433583359949875045014139097383990 + 7523156213061115787711878716816595972617134587220608008483487762219572353605120083032766155082751752855610567994430397014253895 + 3701919959515768374982789437891830642750960645657994589236832995980797844253496076657711645006752860088626834982056251575040225 + 0979950855271929320767873941275718754278787090305240807928650242101643623835476811933436063479233606315724201732634520101994785 + 8113983065740845934933526321338302277547952641828910682131706421618856976337728051411744765715349602385454916896966865817502458 + 3541043147303624444017398708391616664010004834339935228226187248791543655458437287589626370079460316930365464946671005586907844 + 6467142906481062672351612846421358624595986748030105764102127849419935691001942740215832120384833855662335231988116688960608695 + 2788530799703761722379561161257911074841314957231380008835616333860526518888348729384930186986891972631716493196919384541563044 + 9960151488910951179842583784111062968107086150565586865326760613018375413860020781154310137687104793480739369654379775885629180 + 5757125618091793590015555342485911625792045336449768530669665131967481618933921507464033442861020327590807013639300157233850794 + 0108561117599044904729443235325450727345789731582292014742872599813512719247096059598721914318005872025916402947088829272312140 + 0248866797650825595958204057508507830807476195084664283762933417519142347075582529326241506715718869000199121666869916905668032 + 8723343677864688450245361288384636252992454056026441166941292835836423200070814147349431308408145782824860695919605646719597656 + 4679974361161727145100641660878503281476844268161393833161261969965276371391589006952925603728082872969549646978882403423923010 + 1471039994683623569789873331804012722815466719684852070254837711074357511238693361592620597284807521864906755820794891745584020 + 0746324287724173135220206601559184495263174825463472438325932765982783597938536871848298666533763661034332204209283999095134727 + 8847622479138729829083277482843135313544249094572861179333595590622772221061675396437819003622647477864448706978670376179646671 + 2102601933270120920559135994545418775337484717153198432612404295706149728016561442479718981277683958181059597372600330224769132 + 1259053282379608711992970881977405077810774056106800273103144031624467658496517236458989974966732962924668833215016485379965273 + 8337096778081104941132624055977594869352911917306275484469902456879306916808789684303864335821138065913931420528939044385046271 + 4299368276599609244497481316123376963837008957992736164808101728168540138407838646916364855310221850303575133697274394091619868 + 2713682765289699129061431150379322274699877403663503040025037596762253721290401208216082436415144118858632156119324419976312546 + 2881609371673910343032291044465003849815028985591391451188131927898325558643746240832264615980161723347980750483187867525894824 + 1267916226042826987257806754004440337824069605413162886825139485042850988829975658205470396562194892003670768255291562747373670 + 9234220033570807048609309912547070817083287541492891357818324994480536846132188820055694019487542207004276192292369053562016777 + 0261127578143197454905032632100124793899615216318941692486325853609952184783830755458121912666549923939667928989436426770649961 + 5323045993412285553048451071174802746049476412795340271320920389475261483664749025686760199917517732942380222819936015551403774 + 9891352074356975839408670998973900071675970495889358565662068888386887973659152279951010618083877084169404988201568384833942255 + 3238050166229051707803832286590198074734858215255713288528844554284335600396367554775218985201346513397387400209397068796825742 + 5728107211476180762511967972657147473012924183544027968479506893336809289253531374220504641466496667214723927677602095165464315 + 9011192930379184487659969643233786997863887173759888022579642343995986799605176120033884333316312893660726740709366636155465721 + 8537171701432226276253255188614622965933151059377811653184802609155191205285178705789524447418786231655055288040171432169049130 + 2707936970837574068569629371931407362409248401030806380356720552870356587923391333211272591561747393382939386843280495661244314 + 1175509422804438381892148322240590701277543376729396595323849510597370466005945680426336918977914561211300792916203174309654171 + 4042805192423544654158411198004453353597731647696727421911837745446359133507547657475484034048732290037678198364742205283336338 + 9337695707833044354501853716373623356235483326284612569311911355595616206369186001725088755459930335959640295675396477063274478 + 5056639209721879485672408789757891131387617511313947970994081160678454602320697412448491839531065552976208944273555314142041880 + 4822378866853898824086257862623541730929040197220702007762078231078349736989651940081080724932828161588263934616036801731107678 + 7042616549110273896023934480613769270956663187245804271172698934235574549161064775406631472230169390486643998381840493803484843 + 4432695989367708020512810012276065008453086786966931783819054126557051679306430656639833606398733688366162720200084451796967553 + 5350105131227057106985599834342048762794186401151883770272342638155104883645396726235498798575148882718582404327490926780130044 + 5764192533929612390344710894456047465905143834205988681215996081613514814903908502795919703880401811242594826105306055481784823 + 3081736917550671392293064759141270028494719167332097201455667940386826052104961288882027240309372922868375595753000121957263246 + 4989894866974583276238356566258521642610551259726323252743986766553600472233437943119765905133915493843897768279428421555764861 + 6801273161353076961494549671635819940275013580673219344227796480147357333556424794612960445706828140206119824948840749240399787 + 1573785648039077385334262023034272384935398204989144292167011651539471971703585283557377107933951650497678725581455181207346698 + 4874698339219730333194095651462069186623435369684882832433815952523247766685863473588031370751632910706819521148264821690235129 + 1745856207579350369947762735836875634021204626000569901414064309006844235664625468595115296405455194740314530759379861609679354 + 1263339035301388606388533163722497011371588322482095769750979879436887231718408664779720990691297703089437248834586600555339842 + 6251850491772376275294393458209471528965471290147918965218220499155230361216164967212789860144972751525815583122397986208096706 + 3484214175754929920259118693783510869997218078047468018854269713219002531566539459352397848678904622285083238008575450746485192 + 5035485477939887603964624838580376893177633857009639663967781579876337080786152281286836780643711497334038142643551235377859312 + 5770990490009748551131841465407612077195558195928231585911499648608018583508169531801015305515399706824738442071885239921251502 + 5505962701249607762425096231287734763141665342862391398728642501706701840207749211087529147723821274132607543767155647569233366 + 9531752996646776228330405381959650186056935054844849148234315573131250892996644098435195362019426286916985576819912113865830014 + 1606555436659451432978242703284043412347220692073799660822918397493666695089541486316957331014765996271479614514099842437809535 + 0289392478723841946498232349165923942701150815142311799644394965419544149980499852640646717021478951519649059011872310248139100 + 5511032978947425845575588456445816057377640214105339473284188761415785249565799756251192934762389301520020016150949209737931857 + 8405804800314504366659749363367231268121943183966514746661384830649579675620136873178912503421474419998605051121952540207826204 + 7505457456876976664571641545260379929258562329503538400546169325488895767917670975295980264182906923671943997046060564087753548 + 1274387949977098682446892314563863257816052408410571422114222854885606494860672338931736657657635104187063013087549529686451859 + 5042755850832972022663213277248439000831269961224227718932272498745376713860758630276016079020855254056636945995345396441383249 + 6344700532270890968181465829707309620564725384105716449055864407328703719779390283415257182087348958918979888739066384714906447 + 2478502268884223599964876320836160710993832544375139942095572555604343446400261859797019349052899588226956407340248510969084412 + 2858479499626608853379284122587510516464864248784114135053508629608620108109543831989223100900685873301894882329747241764687394 + 3516073975240799285196283516667224035786957693305024409405170967493899593072209653378675045399225752043351688237909816464332488 + 7045960591955279992811051225021192695063962021956994060992139199430008815112575669363055918094781304106258599283195179624447775 + 8303548637737456436395221856298882133107004338700669993457647426042442520873552718504789607522324772936205923889075833787877983 + 4528959091848677214793256254827374251508317477836642431769535470979890535339665561280184226951752824749258073794415152803073480 + 1459998553825438645486213601892946519503789985188491129629213533576249295139024141113828276369687768834808863007813942900737363 + 7827507025285847290454033855290419493832906414032145098230761761828468254431382777807611448800062745765313713732689219610038574 + 3538625159483449646940178756166257692080479081424585343862543469052182432934925669284445293824171233112956439604122644220734705 + 8884093066755275809492142335471176239144329953772128474695403479470145379846983260079920680227191033324315471442379828977213518 + 8161874018859891048210600302227335518426279312266158906257386817733776024570411483770025016852705510503728654494429243801612182 + 6746947553453295308964010256393213729923189009745905892535754926116629620973613924884980514744338995975237628963272677038960017 + 2316979912101253225038374374358240155041996499533280966926264100171569427093110935120513047386276224147665309331079377719563345 + 5252039218101191323619349210669314090591183299132043388783600602372822313158646436097466384432429894279310347011205483804258365 + 8849078102378497326534646727789474466302897639756078400720546541976326397706257168948381071970398216623030217390426497155999023 + 3271457271229858454657827770335612567349224212240695221407152662225083082143775459834013524692150107287815992741275927112028076 + 6697268153473360409230969649314429281006253608637773637800129431557004336600687209561833649108523766841818697796052616713524406 + 1264023927267188505910887476294511895228887727108862538027310305679469919872644028196540981088809214448552558389500274219570341 + 2341820289505149961074855375132511787200836031120337305514546465652487797619606591322268017233923749079200060539286691098575276 + 7095345917502068750136490067362248249806291619173145831611517423916491683475780750592775740226681145459237438975249038494918255 + 5854207316691383141245954956380735287065353365324788816174156724268585661703068556010195412645633774843480772404581791184447848 + 5983572806554767884384691619553163176913927916522767085440008009887977162986441335924089064521714048589756802500400756006764546 + 8749074908864079527865640561432569820363365495585933467014689209329639785755338623694144042638210864919006966920756182400308068 + 1488418928276481402385931315882264463640479342727038934158474806015143604448429971536086762337574137961555181782018130291223711 + 7647631250366260770657650732694263292505761395977741171841175592881623563088242488954360090722844918014816525013438918815206919 + 1155451667283610662459850201212152183408308503418856279359708202057227744768180593554527508439246428232801124311275672977637096 + 3703563826897681685685127020250312031591544945988953353941140195645214477592978106315927871524898358121653801020581142274555566 + 0502532594831295067422782714984502485832073390165137849670240378837997996971720348493993863606290066187249274244662460276318689 + 0152755194697776938435286119441290637386200629628199446127743622173851669645911455169432495002024405765718643210153464143701889 + 2562249212763374000591086405147643148598332714850654045728093130807693494090674026473297812238167578278207216049055667059931109 + 1802942091998951751764726262310843905210614073350123667768202638105831131108058708767584753018377136585264570210097378501497188 + 9619747156993809984322106521027559385156110152742577368251988283361064503255508785410345421538190771023025825991060075397692057 + 7975279398046115700291300736456549463218759811012712333893946746580558137896237287869240420636891089058025806023431754219781359 + 4988421426405962855719392598321200928497349040850013918965781094541442225330283536616202634976088463128589329235150833173556905 + 8706200507172140856416642848813849966143817717503023224834106896623433469273328907429832511563972309658830234487588093651045739 + 1804318877742597644565913208808319750885352430439083436497378247283858616368363127977363367800390625897013789449450637875537399 + 6640589174553589654051256599633381120024749952650719727219130629373315456037578535279963334633963259335915488696463449646684320 + 8032272830450718870582856393550555068150335019058461099968557096935808325051772579016403379075019846185741776197086257884683319 + 9863845517847573376326098832507232200317675290516210661300649571154879306959674077908278504743343209243187243262639791806186829 + 8260961262731301702271912238265956345814430445731867024044874570864287595912998480366912356847572447005441275362156399624494941 + 9393142035376317879394642824057024278760474627041377093083443136837548371844421180440200277690935722486852916560800667873141543 + 2707649253179074679795746660619684282278565191941032558500021642302377918384225264159606437430918854686420568233535916210590247 + 3653446714468860199818770176822269463628134871277975181151133360475139855607198727163601307481114241837610243765527921963130342 + 7740886414228885927181817969815506430494309276878003524396743847692333838266397442280441863182363662933711077420022986422070281 + 1048387053761801939044385077721021658809540040018134673396554017098633248966461113346771441179046101247543088625644697892282167 + 8354720955462557218106068480057094392968433715936618376234382444557134795213907950353329761280756136821666440990155365084581402 + 3688937719186699342108738462217437423679733279917547383863629404136782590007047571508080094271518356483515978166149181632884691 + 9910698753207335191315666777695731726998145344199523600464027456153460564479006998462380767579651598842317204792886070420998182 + 9896983218119310999564732404427002821382477892511011450905458994448002735795600011464506066851494867367124445888153203962666112 + 0874480478255387464724872537442210377291532518746867402289144019512477208223281547993390653821697806118478800205575150577662857 + 4918888004811316598554705337363884151483714153627256672377291874950758530975380513235648385297027498654040181963476939202925535 + 2944953053399838723025577285199841577289179795119166022276762443360574684698180143394617215098184693212410119796009072687729739 + 9732016373361334253176297777291060712041712200359193577310902701783613655008446771602140682798342306314527926659629849329119883 + 6451043591004466592393679872228794008130850294984708968342075888842891418002758594861642712850414025146690654543853793479725972 + 3268929657246764345075224814644064768187234583627518324258659649632755014931180023989253455291331973610627056888949488127145955 + 4261926089033087120812284628614836440477048559583788705295941729615760122728002946792084729956587080892613331345225489314812847 + 1986796721026437522158295162217239471552249715846680613750709615232262912940447904521346670150883469709041492285328187488804299 + 6628012528405245613161440847234508491425287943434287101928325272535635664307751412665147263964282878231211570769131706300759265 + 7377088066364420743764402212273540338705138073396342307947494852950818207406971919647576428347904811456431944019834650692515506 + 4705138654618320095006319217530505261916581737627651424491878629844356338877632449493703212698711863106207638016952512058495841 + 3297864919576913522726817303334406976314952205292550373391722910736512885151802773872849953849211298237482028668331950499038336 + 8974669281536290012748118151506739167431258730634523888446083432703773451432089051580445107667501300580071396777438663916505890 + 6676388335245038478835892287014370527286751599266433016127479958260673956274510190770236842963946164980795747343439314929899367 + 9777763357901635768971296015139054097237772494695148781717193551641896481882800982585569826367439263979611639005318235314749057 + 2006174408272512048656262525906502452313110102817338015892638328650570498699472308145823254807565718645774486952361348150134146 + 8820513608849516349458467726176340280776183307750894733331062785346417632047203675211923303269854905166452369376623717371465515 + 0487090344893360730368974812186113379856699749061983876927406730979994152222167896194935782650684486995334925005887216364226178 + 4428212757677682587368912604936275746129828292671231661463255473216528603314371364809318568990891647756504476074694167225494387 + 6438298664776502895176225722692218937876815974395529173364685280466577427859435428997212680686584089016477667080112002827762955 + 5372837358048305432426520203755641518748461432567909426155727245524828496289926253694681592910381964428484012886894327170000564 + 0966786693488185832806410657062413915673905612790978639242251067404941406079608751238017548545457392976940768385484687626020964 + 7081334569477079676309855956739406608641536536529136201573794386634730088085065014162237881535086131012737674806790302926845508 + 3849506256608406770319555639552727023819412680964197246748248202159679944624779483651489821124252171233790787024388338169387126 + 1220350189747959004534763654451835109235619957413590127042747161319131890755258681890420398880573552502186079819673130304226319 + 7793578559294710797103985830517016163667215076322029333261233893714376644214340079810529332625249572639110330515277641165833848 + 3375779071080037456833323971305312807921291040172365572121296035080033198190386403786992644365488916964829938879099337521148544 + 2151885079681150752124200634430960212055491111062153428630936693865872096334814997531820067268121582290646921550422149642030109 + 8613181778258533141158145972750085504588401393903967265445772834337987637418600396630528732934239316047591685154760079805548066 + 6810794208813864500809678470319323448087878028803605043954670396669190693495990898866714597544374154361810960387728955757997027 + 3780694542345726440651447280692129044592214402723296549397501233597057657590741164054767713089063618201384926245188297986421050 + 8252358803202927045538322743598848427122577241918805031148056119515867274399187693181758263084888023518690338982779085780404769 + 2424326538477152923084594002081423911440158206786241827087394911592939363042513317947630468078474296989628062484584400644343448 + 6293560419015354447114147053377323271370974957505862615433195073799026219744354293045028357502721448147460831465672262899873109 + 7387532795839583928982541818961799651808690944192536299119649406867938059084796080728700163640618737891537102681397327040310310 + 8646371766907348023824656340748360066056892200614557523317897955392332090329097835097131487719957799594533173582638863081864212 + 4986100049536290446290958993632891990045407747006838784207732735249166707023914891375926737812449203630774188546578985599909811 + 1084402346707970131458723746814930784514195757804466199671002857316090262762516878154322011683754629425143857675752082486603247 + 8761838577711280264766083372187992430863964477324546898292032760669740251929185543394862067810777754782525582117312630882437464 + 0771509220114585291617227270613376384799093204219724418023916278133523270037263368542243169870229505561283586085433377009674011 + 9820385787390786107677870809083528732710164474423943477332838364565199183957564959608617849089060421328797474250989472544417321 + 7919326323563029775076417955118634250595776343877190502902725431786697484594693383405493496141691115991728752796848704617855725 + 2558255581109821405634179872876958166347174474348761073684217931689004048682704410888017280103004988712033725528911209075578017 + 9160863221896162516421424469589930231499714756713528296148018288586763465400454214603217797926981201646940396481239125062147650 + 9840316514604720267572846195066141632646978531870664811024154364403354983561787177052598257504070314131100093324913554509718449 + 9311775701841172266095504345180054522901312438857477399185382790126084433098439433269362739881218978298243657480689874068996355 + 3022781945908762278768811002699224365141074026805076790548873962428543441756247033480754889441799694147133688175673557083134054 + 5661203741867036406194178717036861247199166773801082533375613708479585773697108277538910907988050442661518792070910621436071059 + 0690138478379736786396005725249615711997663990048585261495921831819669914145515073403200894318211855461357229650824823305525133 + 1751585791160648049215935161043755494836647727651069321059714784747155745680573976254930604344088093264307898664770655705644210 + 7624145261014687805152488774841289678583856425221410365164555890159519557132962343799732888357700797774204345288024762788982261 + 7890710552868121263477187455194185399264846143513087916598365744278210315488246993448630198352186843484020444533061474327432896 + 8206909625120146564482691781469049022430111838502858582644125909195387775957182358764356323550045553074686821737193044914677910 + 8204337650424296695493149708468179951960014630538528111508141341188662936175939750414398867506644825258652647525390439239752201 + 1219359010151342200692679606063626284788399861632782010310804100495631217242235430375489322644648855854345633079496117764048987 + 6653697464408607985860924202927606340854610960203650555980002938739009437996650927711204711526682854187368829518663287620378635 + 9615765538591556297112167827891749863300345638363300995749126057833117511099109253123549891887992882557489784541036449471882403 + 5919028352049694001658038819829671235731815415745829048231249060308117257367536285634944658365311943856716917740139982945041953 + 5779687741861700152585779009366027675558545586949850924189709461217199740749305528005166461978008407813915390937008493360553115 + 5834977903061566139099870190655547716966444068581774636647968617674813198281268006404303675453751976888820043577600761967333881 + 6972326585063978838443446520453713997506879344217941897803906052743968972254016142258731934881056702957790715642228115030783951 + 1362425902796546798395679404782769752464205460307818179674687205006891103510168328363308032810297518997174255427908231022445396 + 1509825900031470252867573280977984303757520410764668672441796612789584482854046983756780462029600563288455226754517497700564660 + 7759844224301976256343546717305935453950775711909213261546888518009701479912670689049983757648821113680742909226880646315005569 + 8295567234561669944338275143058695909726066802894545455268764288094686590468443329734647916141835949923568889966174907115365925 + 8847804451408263609187211738763773284048172606546780028907522556324927271519705281526806470352840988271648499699486513703844773 + 6679160425612818347335886820513491773906491628651444000288856405322740614920289642723221399498209432232637228104522990852837747 + 4111012689294616788593607591102956684483592350971102538317426326909441395344097833084048144520705500574792401000355907792380226 + 8347617047251388711302856164567942061715329050448779661635598992241168749527006373179435024773116055832951174916423963970112173 + 9055087726497472517559694026453105136312139238988721622285684818285622456138820844308772825216777711338810456475617988242424162 + 4197863232696784218000746661193362219301917851338032677667264033511098062281872897803087758355321546501532794013889570222549856 + 6115749894285255554690322957000949336927917916709996337643587065466062558943015944180187981070089004992789679317730749848395116 + 4787717685054333694149897473720745326568218218182852236278365043324649884567032268831086174748464582606382556519285049880278120 + 3971535819215057024510844131306800637142690099398881617684362973207491682213220003762765264571054110883901103595485168757504333 + 3733461701846483183011223494998710865469936261566419212369452729547931045469934427223536598514620405179798084202385746863975487 + 6787515125117652836269017536232648894348703796120091034388135038967463209181552965632410604353037772756879239864709539921500366 + 6197228209653401639582453147092770443022867307115583008238408014093437109999520308757528533277994723967340185717046004119026260 + 0327403058251198538854684801262565688227840370906858688450070334229654311591524491257725374686504434311374381373826709761897189 + 6320800720313217016667089641041343357180293991403820786439200978809209918586099663595021544518755767970175732723433500537775215 + 8586605557740559261081287090127076957830333678084994220662406403052293892606977228772765289631860524156764537528844813070064403 + 8457029064238615286786107279460798384585105993306593540395560420933072225512825677840166549704827482169925869109982598418898944 + 0346460363516674840943211123653705144516811133167773396076974206411386351987012791478690845256647926914987854519697980693850902 + 4071039292859550793054081697582930309815712485519665021072773643984757349601035844973218854642152867868823320985485836576692696 + 3566944195916064023455915853671413519744116499257428302391059795726588226281448949481887857567458305547585518788070366283222643 + 4475630384874509141748841479483575783195093285020751153893790442309506156006253308563119939383816229293457633418322795791651798 + 2534236711768923060748330398823973796625511107263972895904532310389295669901143468746002992855700338033513519817927059960082258 + 3266833442506157497412341209730995861476441931081314990884968759007025722755350805078872002993770048685210269397083340942969079 + 3325013293836474893127556216824859727670678446693115589979109778870903809827936806876988266059842178470200459657153466761585276 + 9339215768239697841992780261560272323641382940735693971437349481277136632058838727826902049882698280374121176916226254815769890 + 0579266322319718076679029381516879866920214093645961826097287139995438556892638562807533592029177968784950961959651824138364712 + 6905593271581094882293836027956049322801541013654133342099776388830151131142904625837046121178740403372359293970069573073460036 + 1334657560229091661514767192486484034874814804158436588838115645203542626667263606421481459341052191296393864355597357106139612 + 8983996484498008491962652081920903788269022697096829121085293173454864230335343930546161539206227982332409686050424799265682960 + 5979943191308039044837616371196377606973368879788064283861010090419804092295381096855027541458106648574572073809903498794247525 + 5748223869403535883463902896159174890497470441638233019825678773597770107171367867175754297335334571074534607008535043181405194 + 8795353535341345876592035589428503364517129250540037247550521782811791666374510791517112671288737422099652323046937343991337828 + 1845836116381331085732349956975527066319503790930145646064646988078457512408200058689118375881261700543344729871472397774510391 + 9908840174753246368222566017712326787176851291551010131314349894185604484963390215007002796394968662213178018411586445058609354 + 3648708782366479438386590662421575557958786432758515733410030956830742717789884410593667200352894830011183921069426063462365103 + 0863636445701114598272155058937842933641739192649108654968863927721554489981493578009581287965498827240184001075889430327826948 + 4493294744917241293353606762738125798775389304371272784848161045309965481110981617696456977856845295663146310544856961560395701 + 5828350063875380289041787243953420472517640405923728557572182762701021146981223831971084235740009591348792854248246191617472390 + 8142911427486019533916938360973756294199899650632305767565787069658787674361642673323286198646595884519076147156672045347769575 + 6919034458315451231488534732525157456948587079445950850088410378838535977516348080551775162637211781455681436512037018188409356 + 4896222628077283599302550538329307529265839416312577475209070966536398530653252477467412899117369638571925172776374288534229909 + 2854126939661606237890723618332733028245947026454912620083338662672080884075389624244778233027185136679702658181696482687520771 + 5486768970237811447646114465006645965128132304833174901323446834886512598955526763233636026886751282286763353050412483339880879 + 9146149867375327619762240148102487012789152939324347118132416925423213349620444217738724989375651879154078406666532230695010261 + 6432289704281535683765846177747137478857199113830933135896448323481180075359182281747819927805855289891296771338965010648932514 + 3498778884149977137993362603088225708342761654666600988476000304267323094698652989046529561743798096047380169014973930605911712 + 1555513950736376520645091335370846495268353191373549111643901821633347913274787967705297774512956543219272395543943905097818713 + 9824515005207942672277682844175672734608049189360837751069564229080983682875340351162730595292836110710458156809584248318311829 + 8644392801319979903321539224060850887494189887888933968978507838319574610389051812420770840579282228222004146980291262806411960 + 7170669714045362254284955377287230002812263383500586848752066007279901210618595185664394253569437180949208007446172620486446640 + 1197418824383226696240145317846075038217263309407432715400718235690780656588433075117078422196797078588171900080472556706089444 + 6058081175983404316870378185108517992309376387807189465675421456144616633676191879370638648087281836756096354696164358804958793 + 7175300097350528879964995120589418404250514397730435804307880003642423238815219743208925752113332762492815676234753855313749687 + 2216821005143022212418811965038884804162533171952178272981773050431225972337066809470007006624527746167477143326209744916009321 + 2874879795494394023670916234680048368860577149936343642623399857065876920729230526286990908222249218870734087284012928821855198 + 4892669237695278094261059350844729450055740052868656916863083244548039117228735586420221099748057054754127348342899320517500476 + 4913533064284953905878883623486045020791418669162484614426142342087782118817607434327885376004285685360966673400518425200903095 + 5236853047264130432207807874987854720636307899392809936830966680235406253508899133299685304059306299982669510153104336419138281 + 2635729217127660380760950574877790788724558832203965184259818062945607402185371541729168619518031385767332811305256686570812707 + 2508693777459660048221434065348386546516873503781056818039736884680690592725066422073878336659156014383855199604525567079024098 + 2527847075125720859307217125972603526269724367871881994978039745425984811500976939283305909268477371136914408464862183620857832 + 0690848798245605847434249059051242459537031098176625887386313497201621005955291382938621297556760277294613833001841927601417783 + 7028637829951952641999762601338035213911204478792655772152455046625599760300329777350980475951284319951538433620056110253564781 + 6305383937871208842219397097772665248616270756493102017303010524320362272253687689906320569651514870191751716750048983549016387 + 2503753802832702119325330648883246982515086513140942076923304514033686102637700160768687271319427097046984664384031053585769263 + 8859227992404387206024381418823288245956367455432601449940099288001162654396819305512052575309088805570615034227083337938687529 + 4650804026596773751781171691707686499798853858855531297662807643678150070418762900082986264876734988853277036828880591174772676 + 9388499761915323706082278918760363181675840316081077581226482199990184463308418161663917171550066696858396843063924348798640785 + 1339519437101345180144205804260788988338143185013195486237509665528555982435461459049630103016492555659996037806521222234571639 + 4775406178328515482958996000719481194780201067828314313954411507309766697327602402398592936844052573242705274081653994583193860 + 3528381321380368083594961454997422094241837847317957074543832643804670074418168234251527826193469648447514505161752970468032251 + 5644398364843284455563221983222109730803753471463129763873997470655511240512635865533704491564823907699160432034740568090163512 + 2019394829622861074339274739867648100223183661088275367604560854273519173101761322314118755022999112270121442893766921444175618 + 1024961245677370458394203192048216519899540056189972652416007572725591801341729111029393594712226889998156435621046992279746041 + 0271013842729391960551828591764938026380238772791709945105208575380084459912538928688891874547881085895537996185248760341022722 + 6443644163751965239785936903668129878996022934136734635016147841655906985263150160687560568016130320940069489352717984945617017 + 3980979401244807308375088961101007696165282732048547089807678715095196311609438432458589671418362252711116197050123998645160718 + 5029882228039159089170628100687054725011048437854579104323727026278151658455314659996721845525056734089399419451901797673293081 + 6285409273407838783004808714400055644398911907669583936293776767386307697838130877184976183405711337976463042849151509723365986 + 3789116449777854153143327216807443418065067164460291516731014023725079965308205893342647719238044202553135045734641879985943779 + 8298817649314977181973643591691453651364965447794449764965615478663842601481733390271221156996231579991946480360911957202482419 + 9923477919534528913583979154285960230181626227828624997322864558028580882337999440750509388244247586570466385544276236851986673 + 6266991152224272268084343794242067444247144028060688211987908624847699372423422643841707689624467016900013832905272766427426840 + 1355067343839251713050029297274635544953158759007585898844352763675665452680269506694090597773786276467200134181329183129591894 + 1203185079814519449730972616794089846681228932967991544425024262788862162483806670387321965112895932667954720701857303315356633 + 3010223406691406448732071777784917670640450961064883921707223591238303897553076936064137492313930301276184114003498965768546700 + 5055662053584872171686392213754554115803665951484341184481678793730256377197108916198950525496472627926989148952673813222574403 + 9135301836957832126464142557708338619444651703425091454666943559384577035607172295502116858050756179608799326777436914985064677 + 7849895476822416074994849352092796372963487124157171056152173017480389097568380804863683908585558640345480249639539155208814003 + 9261731284405809837137712563712141454654064296465941789875748814378776568326711784539691121352690345339673695586510989770974288 + 9504548640513288992288616894826847158596027709105403654435535528958145029279713253496007210603612311147571118952157286120765811 + 3172019293671644099810154685400878900781863310226630973663196219151877477083273521217193649999031944551410361083160211498456657 + 4584835039206895266033291139088493090671186991332152100943013968139485825629047583367832339953098893263224674847060194281239454 + 0086703131238762939716791409510475698044261061184491246815071586146930458568320808697308895974335329174951890370629879266697586 + 4531479959438670471013925537723663881523195629756820131576957595320119441034946472734403049979337927590688920672812290238838992 + 4555784600301091463114748695085394421438230893318590726172334093673394223159678897396878630225087240466235943323892469006400425 + 3181295825258212728965331361945064921751996326740368121061708410146864334211196041567878993280564094949434554682791503673171658 + 0842856419453623298809261289857239402872945556557159985688775020115214582384781860334689651493902766220136835999359515682473907 + 9925790212755349035787540271290598847673187935010889467948737594198142964082798741209190025028872359505393133888993203341623719 + 6881035084279659821037463368291359288972809796102439700962259394869871767171237148065599497261891353342041591198086826562479936 + 3071229176011336182119446125694433597177517266017496957596892485297788477134388949109492032269677674633006492819820954408939636 + 2158505696670981583492100994722239785061126885782859457540392078035784726890160616966602169759722004423370966068470851220475055 + 1608442432121043588281125489656099832629914426535320512741673998725277196703980523715247319219104260826637474643734228192860916 + 4370675331345005605018147797477139808981239675873728794694700612511771169428567641131258023552337644203474230406734637422278712 + 0072859216860622480346667080043679784914202926542586524758456470894276035984569755855670540260788837234221463158700441389231519 + 5908942320852274627106540557811105888610228644494103402263750822407154871367868699882023311506835501899157241704189414346964284 + 1936077419723541310264634055462791796583876957815065743467706393867078774982042343936087382789908364464848533080889495741496533 + 7254584486083999860932338903788745031776193198150907253247533783144266741445178920158676792459480942978555519260352341102863868 + 2324388659990555102109355727630603564463003730580206681960957998377155433799099008210231393030776738444219722412702108302468947 + 9926613338642730749665937063588945780266089547872794933113744630542358661411190558266352099886620858549171525338223571617167711 + 8986318093141580580876428982707764579287478469073583981696234648037808185140269756651566921560785874161230201920488349770275568 + 1902800771331526181562098287158829944843731017880219524960324079005886150803168559590390474829249427791824941894802034999528722 + 3088584384403360990907891602519470935005839028378253171884990772710302832296914348751708792698002306050160936562533914379396209 + 1408310312115069530150233048818331378284637723150482392301602795737916335332815872089409379843010863320155338585218615794879180 + 9677693345069319403701934383954872660888681515065440356051840106884171038792426226463129841417745680354406721408968771559961954 + 4557539513449236642758101806291205473048350296831633561735117237579593752211878576489139742035316348287283326781007355249045447 + 0883189604094854361797387824593448971971447378881204753543909216846733915206018358578418844775503490330084862478510316277108659 + 4392550432502243314906975265564518025479113098902169136391369512817565837562370156090165943691065253900876426946219189578736203 + 8435865573452195078786548417341611434423772217538030617156223901185493595765324312422048299670372764076523094427788078350076588 + 8758192779916285126332006796232045283091922027709795938540004604312898200544114013208612412744965934919541932903174519980041254 + 1905758872835083202758499042134848212716811095613617523820839042848090697442064092232729193928479222578050789364469898951584433 + 2042272602260087723772848808702134767220173723358646135775389214656797340171301999623954978758165595263461874252751080813852370 + 6274949154731112794816216220066048303875986872572001517499070940234617966182507743418989487331756345308613913050407521686762445 + 6252730979488500452149052167583298496816203113490366754560247487872848255355376484138619549701240217905711665471993273764649239 + 2281622687072260169420599936083131206454896277499378500769391609676460024680767553958496006032193910593446808391535507538458599 + 2191010913898494379461759294973512837440625801801770581499807998348601134363013493664904191350527640096566620000395093356134597 + 1660938804470213933500623938584649317535645503810385086838104030744441292813013981381095457570526776722828297499568794267530527 + 0049591878181449823254506571309609592366697654558586847111232650386057621118329999460228856081046031697258812551653592183584022 + 6258688415014551491572224840400910043380364244249549379338382107530054462860121947719561782286604468083436850199239844591653106 + 2286199429292183729722721966817924988059655688863458946473056847154314312282407066615331874808857982581754086039286737461422747 + 9602373046472185399409121350660074121130363291629972502459350277036971026440212505022927430609191673069989761094096992091670991 + 7527879946650183351260678785085159093046180958175365176059942440628342275638429735328061936632746613485734744234236065653841137 + 0853905941635849403951594887838110573652181835969202362039487221504242797299698627659839204874816529447544114385531980406666739 + 8062623009337523311886378539061039298966733017052114071143987228104904834551295397466673191503750551657795489921304516776700376 + 9007862096833941572335165844081198462047136819292917564132567522715598859947138927117299956642745110763969251319858190814717852 + 8138958664951405431541453825461330550794221363483549976099721937150607149588852431715285804748382531904426919820630714135461983 + 2082397885435139903190314072146037819079478576247984221600827812796545457214101194496220097049368103574832514769701472385466387 + 6896832416290927778053721602166743175733725992261187904101998561355457754417056692268681305083190893002118259512241765998122185 + 2636968504609327449982531058224266443456972154252698660084884189652857349507395676672582020179531698016039374573532855093674020 + 1136026577034357822803043248989730467073666295507784903395493121839773911132783532427651934810756742564183961335402101819870313 + 4917099632663820977131969667158301701831087873930909603855469814730542409624643679930249460380846245995843352815176947927777445 + 7319944731827475004706218777611396753968431393783636860295774463198452128755272715443101250558014321901313052738593050746571261 + 1707391395815003284391913583753339859531852184651610466904418403752429242924142601415582143805388089376849781779454300111958363 + 9869108151029888337540428241180238714963181644033868424652184814249832670934245802862990793758097055499023243559198701686575666 + 0187337650771748598070996214382876748717075026419386245187486192182726086987036097255846930650043060886509574171932845313409481 + 6310275245723435456702127325230222604362757109683102954203602714184216564293906952316506569915992137104170152492029578927512300 + 2305363922251604346990506838961419388192179030700159072409204210540634525740072656419492493606787180195424067534096459265589672 + 9014680664163948601215499948895470475969838465633327315676059364457476028555130517706511356929094761498786703750352514595140558 + 9277484889618105650227338993928615130344847104186489285414725102606461111639517477747291575877009412511989063198428666104065406 + 5967555124952181729420151522869271680843682059283488086279627160865021360567069797183031645357984651583784813809428355166017913 + 3607122306789653495447270140672966362274565501229973599229667563911606772081598572491953192767189192005766778789005815828610262 + 2082222249317420567583150769393704141643717042001944511315146960110297197944325284159980684280693676403148609684883994123930097 + 8731372124960991940185405379357412214932260280623846110357067671501251533776628907031655983387403452673941318358548346602760124 + 1976021347697640428375581819297827333264016242688348297392388997119461967525771833238891591593742490277240125530759579876491077 + 6072466888350935400785328899402008544459154165636826625026958037650740601926412225205263947146298128779293383020953022202454362 + 8044034560774166401511114766914479073842481064943729623980836043134237110449322364783254518711575480004977127696613076710220521 + 0564017571074921724777748862479718313010297525498781712387929033234996773668361156592993020275412793744070740135811199115493778 + 8419964042103133610587792208097044601548949029168486670192222439144702607241592021192461521821947279760550828661220709620486303 + 1088814982734131440185884327578226836944316287501836068430921447613687229952034388566585290882851495307655765844223170274340586 + 9005799435401477659962899657617685769970912656575731463413483835844226203192655446200112583102919467583122082891247399200176783 + 1851901588702515045318382295536798092875597244431065042731697266394552848998020859370638943554279437980607960337319274852691748 + 4157648096188098267490705839256314766006302678665206847589272557754575914579199683296869793220703658904894112352768597742132369 + 8723572441033421822131850984144065793127526826673880856427241209325971643349588168485181604003549286943794523645867631822180512 + 9961788999122788832400015923298335447164102572685865228181427272076170219015236471640964326542574283167180040163937092128142732 + 4937228274511747775697611764578391450794749466871545726021901964860582325608076362650424934625277209649989981489750831225970741 + 5984541310271980053712817247539372152339967892775462123252335196274653874061592183413734875908267266920758029830479031847869228 + 3871371830143074933411065987051697909188835376373962685096571028998970101211924718499411402849248202339306457377199877126871389 + 0586547099952007576979285722825771295071780721616176263387445055392095793671230602073249233658371312728279604207471382798903479 + 8923577166944872998618492077791653391106848257807366227129544881151900203904339062941439729248722161475876280041042987870134297 + 6237224656556330445619379055992474217471454724969182529987949872722998015945413515067495314489889032179791415649686011073157477 + 3003735334796840694489912665109880649358659073702150516968523096869480344821929684468744926264579118587187974938771984262183130 + 9005753590334142936036827167253181517255166676962390793299722321456204920350620126047032582007457817410580787154332130609567063 + 6768747081081207028623866855036005032042045118427663709885224327750939144410815093506371403873404919815687844934325487062884410 + 9939375834444884922802271908890569123942112471025359287053666892829043053920922878243233005965596366467035614279935114942794959 + 4228677728256796231027207112191813165638914358249269082781564785198933238543379292199026489661901488181239514397059686005148486 + 9858539705692720243176916548886314393535919032096542151105543882501065636878211469917818253828853172821658378951042353768012326 + 4422150194025015880156761058170304509425792379790006321176948407538912546088068547813798000277530779888405928477531694464231990 + 9405650213736879289008838391184069127301195712710013925801226563743554996233482554161918019454022970208565224871459380574639835 + 9130794172100568378934252595907690555743933712658951585006391044055921485334952756122241280828770097902109351842319381201019204 + 5387985013440379266230518099534711152536460959269911655397255034626367231069408969413762813968064236154692333107664286960252886 + 0837118680763800551465069959598175835527467398611671504215567143391659195926190188250898459493898805547983688580472819756799921 + 3903220661160023222988830014776994424185300024466935537043911148899196047568212527843430862631973366330579525805431481011727438 + 6908486037368642919233388174527626955887348839535505480142124695672332446751550909649591921180619995217291566458925431968029596 + 5922782959375057616516378703156580986104482212435661177276107010237081047649806919032851751263569965116169589560831643100864715 + 9530369870366296156375956282332841862206458152569867266578623568655520592049072587837930649946891321926334502571392866551701600 + 2244120737959672078726164762991283327806243441107419508409939471693616693409630730506528517088302223393878360169050233927904848 + 1173648771365582895309968552846929556758030253414605906336548466169612035971381029462786542081116525705113252983939162686385109 + 3234155840835288921699357747660762996672264982174457829675917923339715647526557875639742064383339589189545825487931401530995501 + 6887665436803180794927923177816956708553785264323074693008344374916559316617894764427215802134641031792988573701240438184249750 + 3839539179042881405914564139952865952209303008409731497507386952470654995467985010268759732897359668659271914262252626200604099 + 3901076984640950131960333781644223983532267536121313347358475229440208418673453842347657506344090138736051557656821297434982077 + 1623302641135870181311409682200177224901019997404700215147219379739297672524540935209651730504196225871915072497095486880839456 + 8525315354478812852093356397223120386907828133392270722811606375757983394361481913342296750609970915686272616757634461450159831 + 1758237483830901977324883248068822612744747099358422855339260889327800667524049577373525949059825015390160043063670312221072626 + 0817646239152869131112173902854770980862701701464607169211772950069653293230684510278012053087035337608494974396015461535406222 + 8646346589715796030816122730522353992998487085588488148264344066530587174128544229529685414458831257128748560990578804587360715 + 4892783957104711928531643465336739867007712821809759300577073458900066680389265377353301997705565938884080611069388312576416304 + 2814927389151100129042633757615682635990656949553591616128856450443418496471442467646240189440950521511107482659253501599167684 + 6135116334119022986012296077975055833220297155080260438551907096128989879928867449175546615606752828933549694825257606317586967 + 7016532424149169529714586507287588315821039767281860867212525388739062009398857291177966375322314074508942295009826535646980545 + 1130704846522761465358987904002837038112315864342341500267273512280490182439691698104185495677754466174462509539951393350430049 + 6239545452060864474289817540605900770875649791603624701849860428246844860967392240963173839859434643202570338001444647069601535 + 2892256768296868079082781775690843873409200886346998104928582896183217369070621962623861890767458984640863725872163427837396161 + 1015987233236680540127175130575507867333440719260832000405122222181144252353002520085749044160442813319007733231316952017735844 + 9207122991749764391450668652103974356514593013095625877412964336676292277200308352297929615022995501002585354045748416214004090 + 5010570807508645991981283973843421015013551379801238469792061968346208698033924105198332080219826873915414042770997813678587105 + 7079764317445013461353198084076807018884451655619023138435629015461147032511308684817994462582990789356614515379970417351047112 + 9725881506883451817378068264565401988152381111185798791532824098438029254469346518084626414715068349480830207550031462251028658 + 1504691090829009028694497048664643697386279163491642380984787314683252474807267403308118309227599112336474348292331546087385709 + 8374045238326514850352601439525770150385106432876360117179641265901618172845807500617241643296725102357385086749024223414320695 + 8751924711372854963768655608131773099674117966941670496696797649406607434691461307943445287152706412809962107879642575743136123 + 0303974873561466480968743445273196900705427451656962370162651211903195479518829395352847623644931113876694882674530035776397562 + 7062275706646629882491960277069009716984996924439240397590784333436313250958554553224460478301293892351431447612983420608299779 + 4021998564670601304459878729468539224393130081394097452696802435298562203672631426231047502881058781296871522825905804208338252 + 6603870763394362689777694406864771464497251023441752146535341971346977029094361489321326128197028616266687437237475295317363781 + 9156020188117437220553660891624641158468448699614504995148457693527457205903178159270764484168386506020072977552224361333700137 + 6800793585132251294965485406539737210356860431874461572263005112556102550605119443415354337340356018964066943951864924412299915 + 9176918467253843792621229869758475550809947953676328982327607776920014653501974832672677357939313552991103607402118582223524673 + 9686597280549256712036750220654564584483912204263497709158167656617008449221355316543489486938189978195357412962551710086697028 + 0388429487175354035020158054103632924527177834523214082900849111108930893956355794346651605160826522047668675831813135358949190 + 4345101694469873179969332042811556018423606297108948984557961826035019597070396285751114257989897953296299318364378614357933290 + 4949793892609892089229851776026934561460317731511255552266868980253783700717106802153694611663582999276204920297363252094371934 + 3674663375108601609896202396621130718019413744942494222052103933540452779973933501106619925311069127219850907767043719608829470 + 2702622493254040904859153876396184987380395898007693621320399251663876437827374821903867019473977298529862021085159803043642262 + 7628804430192406674682789691745692230306369379190920544277057351743344722619473702262372514469670378356778783948762245486971339 + 0209360041654178829792127599208780855624409037374530019447406585398770659754872987726192651460619482209256452092276066423476738 + 4709783672042319775995641852494077105915433063897114034300326610462577068371066683331006070063551265931785531029670403665686700 + 4587667003896460717120912220270889981167563292172474600789871114756272885374551741764032376074283701965139574996577462686971467 + 3848976224442081690472022609003207496720929495444016043645809920259850317579964113261377231461428538754038582648249855596427337 + 6172335672098748490848298205075949543310509985651798361629655073050078700179132155025462638010290501496311312192593367695422649 + 5726384573393389957861087954363684393648224844030047057212547523809090733733447320925926719918185564312722906061784825834541657 + 4665490918503684461998203394016725914244105391374685986007968106627529172068516391306150797382538751326421691707344779240051404 + 2641961236056444783029513171308212582932163735856854734301365261361011265730957017358847540597925397759304056715637265630175924 + 3143119314616534179607705689766936638499515116711864605104806787742064610741185862931157231900890917045797092416341390041404007 + 3447931172643093407899075956016941324761309449689246711224867235309324518097331543836073039264012951510199018054862544697302228 + 1563566785164424421738528286186718541346261171578886688118979569809183215506908080307606078120020216388497864724764057557754295 + 8570889786931244194585660557574434060147391448332058484468219132867607862446662006468299620134301595151046310252336800694251427 + 0217713452224504960721091364387786965013258053103569599886166960333008816549340813042469646283329089138949995982273574974215868 + 5241363057936964400802812697301682184281492778601196784957952838829973528993067785327299171845639921011068758599950934223980914 + 3238619506166339720940794008445086813283016112070588367871958447351766426343723002443074101469688320695818179265745434758910694 + 6296789680362763149161376071869217199662771928863547592423030630832336241218625794010606091635986342053359908043568336874619758 + 5796450483018638379674081988788071939094611782491186354599577562913830254367966241420426194905385522339051453836242132016154075 + 7739106134294761084702741107955615651072406250165155261201936784282832131480551569227393410480076418655073059966098939360374229 + 2971567365547701845803783070635993312664824380381023912535236337973918393748125160984639017693662692774791712740599492208482304 + 2270720904622266004044552929046382853488397030569658054130832432158967100326401536494483965188041727224259066348964879067583812 + 3443273270836744114169351145812281297836105568675664537098362750380900035541986757124762712416133474277811013584828903165701857 + 5742987445704693742780012691654778768416076035850059897986267208927114643299349752186944079949266040605774961616317552910045136 + 1240573283641630694358812830029096031820509750547875205950719721469746524236951030334909216603563649107173637973757255912252238 + 1182181309135378156725140117731218230316055150298076621940456444204177883491865113883523054776801063888819486505485385264913416 + 5069068146388574137237425212952037225400371744975152454660711335647864580574001943714998326035983681508282903233341771279568745 + 8467943310622656536228892538026964919357667642832630682651110048817452858559725652837991052187308635773654812551494387013316194 + 6440134083862480163392226300450457593962112666903507568451147153007397865298280740371802995538252604177619078977124651051346524 + 0537206772933648445348418297957633068071300723364120286017796847418742109018037795201017609886014503958468715621463005263787770 + 3432430202920291906940764640954727327787760258258401409130943189103009317398784374181000619017547537895364515789076658241461815 + 5914935373373404632064261928025631881068410722283620043865276873695737002786518062855969064577740316535280772509182462064465423 + 4663807875203623784262624547123565729447932492414543360035449489544264792983057557527120665531457725601958452570287012086637115 + 0847474551270439717567791117916716520890209772268515126243374020404961236068669964591032312120458856151122774707229179093256702 + 2728583785414355071386563956562688209782901746373262288816864290881579324219562028197868974414398025024344306680144426091625030 + 0910829767068265611067617086376443471268114912189289789288578161296371552096260414590275441364898692653660772972831143055685254 + 6907552020126899986435407709381912657932246467804972165765350364308400598137400904853881086873855469475626923756560878726730206 + 9692227748520363042215131444256441345425607520902904049752565589636006403442938604002826527897011684910364030121356648587505405 + 4764025506989776287250936345001157192241256998927684892678268726606209680040843191546472014984020704327316352200558172668843000 + 0564503985848436331698791790813182963520559967441699554268886929254925633860614440306175833628563304317763920599751129071094309 + 0175566287557279025857970584297243285600759435104151831150200001725607992873593941524916608511725999483859291253760003734973775 + 3039168535120967789573627753936889933310390638519872912077737282540474993630496322839461848810678646381314301370434612679202453 + 5290955424609618789728513231303753525180260090737043547498273247450093929519045624882089783253628274100484171694237532423254859 + 8186844862044986653314802892230697717326617551815053423012041608272398516591496440428962043914698069230013270892802838135287280 + 2942112717174269473287862314996229628874313075502005461595688743732840097634991389852224318945641142059923309434297254976695326 + 2444525231843962298275031069381314438305678331941237253189959661616931936428403908777740475422459580996785256969423138340880864 + 3680179310627154010609137293613898326769365871171324366981855057912989303388559760676270131578093527806064422528032847530674921 + 9355461118722504639190973677696806900807813249020915988601326357024391608006515894656601520223498473406143763133984605551760635 + 2692839783034034225135191314183486878688437669767719161941937422862653760924569831725084821460846216076710658987697058689127356 + 3364076178555288032798058397361297765867389733546080821420688209714329880465424718281983378741966307965647446727248970877582835 + 5097154920011309551648620026419749934729546113147672841385317729841476832905993191729886098778334663461209723905553676387326787 + 7544038203057755483948118938898802083672133837458011190981229303171157034238018580240354203030584798053880317332961525265980136 + 1511152526450600575245224610801100379737911240153008627074626764499468695975779959724757934622234502314480579416277867481722879 + 9208761275469748679977983637248710137550354113725122267268928582906191386758550109656015747293931779066403562806751200098816649 + 2774371960428126935364571996703554555526862912399267217503390978028481995519553561409174881144281743002477593997449474113614320 + 3283118387697337618913008345214573134792212133551845640272542182183565756097005950085429574121104212579366752791246087630740431 + 2251626647794796903046417171601708089033102353726791435541243544024082843362831636356376144988414260766152555993385246920667885 + 4120430579803988192186052185336786436260523534744839109920724061087523726726856003315563861271636470368332064799342319979701963 + 1178460847308168095740461067148790390275190816124283621727277092177096823111400887004927669450338704196432823728793780107282726 + 6147466566392578561700534815888328209861843963585876273190658740165656380640111544922854734365367040797352367883442096872576161 + 0655254149992445465845820920429897376775083347655359252308973271695549200271712623988532809944592500421544522541040542744651771 + 8895306524774577797925949127567789976094837338117657136712633080384090456221881872243825996086082147423517476054977573177854050 + 4943011385246149882784947556915542478920754812582717541224558316858308474902436139789610336015128572291595765038163819815572793 + 0059519490142292292642467486355644357871443222407272677363258010549846343690410511589487255437861629574221414317395258487976995 + 6701428890977392343133134256358135045673673123158832116303929634062094950503008501398110339118434776130231986975400156621462276 + 4809112204042804726404274446015570840535663272343219408139885535879522105193162064034829419212674983141334515042809663864776730 + 3339872236842534294842100648778519220364381792736266281427277880995347117460315427394400908444602067720779504370559025897150525 + 0666515892628240976196163023835072227181720931267205367481763695114784962335391370607825220441784558120081030826294430035145825 + 5990171621923618467399400881105334235398291318764791324436841208478784739274728174080402657482105706012062680090302017358495564 + 5800215155555227538662802534678916888507797284554941341847639680300462071370712985768701847640442454877861723356457893345549450 + 0044372835991682943791367236860846326267985956993372513320157207230356385776345982286545530591945027191940491720657627496371424 + 3896431871159669144163572836324937737933585239956934241358540063356296466656555165061326841756648545874963895216091891197215432 + 1150436121846416639357239779525130732656046114770001886098939931426129354428928259723637803567803101198938817466591948073654097 + 3680333838160206864509221215320873122528703603282455751545397796927467717336094169326962640299653768153008615924472102530867643 + 6770050643269265320774249712789524649226429216132578192388680218997460246361157967129125548877818859824163987287642561738796200 + 5254046150685030619784205850259746232647288005274167276588953501245671262327906633892459399349248665683674586756619925085832749 + 8138659441098017401153449742392984232024716079021347321627336986000612605589176674195767657558188526805373912850372987580206973 + 8191739475819996816485468724355025309335206345790673864079265551398839303546015301031614690697079405116794058344817857751170058 + 5907733664187032783992586304169841870946162957846844623230375351751398150941213221188521406317499729525031329275753209552972135 + 9176007624492506072188440485436086995355405038611315169617103420795642254487038087275622057368505174049950711687063028236514019 + 2054382102455304130470152360854926810408620809647732343016107388521668970316223874173994646760209951211428665814705542349614124 + 6010507266966547829863386841978029050310064720150129583679215294838434102788460967870976228374996605588773396271433676057289822 + 7051841412308687295953020826737760628903413518500966433370038504670238126933304749517485860557144247313921158680957030845329616 + 2360033770199629503223807832521648961131842719239878810835014788911969787608442436353630358920568228223028658040834409931217202 + 8400997693934004696590555410764211165674028575041130093079293183383749718414250933932351869983505392135593326730456694681893830 + 9601966479081797142729057700273038016579775812303462568369987589932810195102540708796028133906200420900692102185183676170434137 + 3162497370959471401670744764602103343725945241209609871641803759642428128312023652491828868062451307296471228615569464816843941 + 8764436487815154921343571706294950245330020417561336192910050884197950522678946771691143370350696790098631293864395203215663546 + 2103973531056753606278933160819590888661208989653023859755262642075600795082475977389553769715231157147229187302967554388198370 + 5511263147464601148510010944839861149087736327442223343582633059022202904665113422199247896714934045390179111585670544907398745 + 6503691628140930095878935309503466424485388886339832328600458315631288162890181616057639363435222140281269282576385033650710680 + 8454254370393439429040009560609022779619788056284224520991161927353411842168395626223590494290282053470410540843450407987926472 + 1336825679355920509182270187363852809609898538144457557442453481966013998014732868105005901821373796606751500831791325616529203 + 5075118330341336536977717509239821947081842843667207368538939749602952519028901304254002381236022047524790390418089280097834547 + 7087002693940685994858725839374363930880942852293359924965925052590869503751762743229260822706873201650092697209849276502693145 + 7306083000612674447155484200177291509744727003567573915026132438684216504412932709214471251820240604475149792423248249870477794 + 1828750345492089414352178700274996717656637631789061874232476374372589026121784200003799632748786969419729627555600483655428983 + 1419038605582900945308948756881180557106644399148478031842482768934058982366460243721966998715761966320233275607842960609086807 + 8995674775072395937621113944922442969450956475559169579744736615353848691595206952225921509080923588771792361528472949801095259 + 8071164393093218807836177998870397618178243287174730595843254576188688725044187468313573761652235487642008727514328298453902298 + 0249472421551084408818726321837167660068433212182140863918498142778473568559604363644028430498972834010437189971676814372359835 + 6326215711122626023900879284642848379045342532983675870120785391214889560676166670449442675798343547201651587376372310330260972 + 7721128349367234491190961548434288775058240627555576639847795303346657927088312538298685663289068965153779510427872075661840307 + 6404054826004851129562529146035965093659305313594131922007840749997852785915480413483418179403471734301385082608331943522033365 + 9733723661694274986939415998932370600151791965983225598026282848806043753357041009447678948117256393500635321688798336983220809 + 3023589135170563869561312040343087996767334919517638058142422305672311345678035221436322642357974773060658747505711133889241231 + 1715152441111565992971519735514891973779991073609482568950260394204089469526267416519043590653468197703445241031998318436540928 + 2571161687670398639649025206286059219618343667065497532146361041751088315806996390315937024865023472982359206847895714744923905 + 5104856285757044366877940768642231044057490201353054349716001939164041109356173546969025877651803874584635636362767779008126317 + 3656921864783698643075571406752016536758441120671704957195627803118074461526120679475816346733176098378409722349965248254591396 + 1131443502066788861338718815939549028179403039813213172777877033453234020243883715396074872970863142546452822669185069959899184 + 3828769910844736669658151259692028871696603091005326667495981150974845310134146991259645265882236097619326183020932698293809389 + 4299190605742357746915386971343055529972124390299804481008342198376182446383261925929177219506772125075974364335839610948010146 + 1147666764087177430198110110312435274731031579695008275499991697667495238558041459480531076474591001063866865437151222907417625 + 3118583599222787818632900781019308738830040805599161996484071877144944130661026998282751748208682924005109173737574254051272267 + 7248376535827628635806240316333585049198937287552863170331727642858039762809709721675292461634836370227092107000659180675306750 + 5306506627623780068062337884640840561088552876565604494700675337745509144650468822636638698294453362040534422173031206225551013 + 4252579308534696009946359817557643262143167696605231236359117810698816646524895198187607892477097108960784373761400944824549798 + 6045449932335488814802338206074710052382801251742328755176048705595171441928353779134497634248965450262069632636038949744898591 + 5048702418591439721957110373280102402968469372594873031440576890966279374555142674908990757259647232567240212811527932452059539 + 6445116473158402926922663638150560761537491240522157144544441504700466911488897981059188305240921784775901100861995605851341634 + 6426302952753103378949324692632848243080208624864503932730319385221633332864218296337728836033257029589381148577572779689079838 + 8323351033213327371073881110283228611521471023685177945561596153462821296338506612181495253533007296541471850977144060198153791 + 8612240193336900124220751825865213792796718254928148410457543169565765686381156512821242185857562689521331372459681870446271120 + 2190046770619246800670427384048126037985607253433475697587520496744179478706647309818755439429545326720329201172200607765064227 + 3736184856673482672738889087427014657874110745468152414492168023597661163943017362999706603380493625843592458433287608755926735 + 4182865681401614720438201427164757077032257161772988732629306857669039790289782177374506368443513627759379215518499475202046737 + 0697566863573366009839193988358046426820897141853585923998497091914817356341676241151406963597520055377063092845547594101697448 + 9770510287164808256026738019695567751276805483623280478598925336381177794945569958800804342768914035606587017994256909693642474 + 7259755154611086941695255874435534803016372667978524879504844920733928636400671846029963027849546724083520281554956394251995619 + 1834558695670914755649864898844629047200426021450454765139131674876570357846943407935142270035129746721137853801869970041785717 + 1163596604514706992103337640896730977362836499853948987124318776421720842943109071494096297915872890046802390417171851693498985 + 6696873506860390067654571204036998680608912603658516851469732917336706912396900863519518863153116679969409193499475151912748965 + 5772630153097284117632752487886616553301227224710840592032831301443809681968538716385350119500103381352429438906070006049324510 + 7255320449590155185339594353774382542901912346562333365165993746566717810379624006716063017965110258762932735063223456498216112 + 6248309487192090873881009634314790029246770378814629258114526635202683322798948006269443152846896870196478753064865917440440787 + 1079237303256511529274839846470858035223497145513826461412560940325017754834231423361883666751693338383865225187216612119160015 + 4861549012935871901840283860561328549067295489644918336638431557892707608901138017599623121810750153111482390969696067122547247 + 2439131148441383234199376711842415663942174805857098114579871600691759196917341291603802573327405138562282722593414751206457843 + 1973359935209045256671529911507316084304214657632392500349841226204006608244837820483129185333807659672251730206136609040933140 + 8184943256874541309753395121370721662620513066937352652876771594490437810449353276322830929392380590748672786848276069239565457 + 3348707026381104836690412750227080237859968000391150025633563394577801401905026748085615086352851413067595432050498561008571529 + 1877075667972855586652155165911443897166143801340467259805712033287524340520335275436517702758812944056177253493418193171478211 + 3774854369590560985587771159245595691913575127970445498501177157738494672527414527162836050852813684096791146417973149365483037 + 6704552131555310027219368793280881514598163193897955852905718685913917573430057096937340959824715120372466589909944315684960960 + 1012314375846207604646749185426484171598374093369935297204972798525329648052886568477644707532784462941904877487489747098535818 + 7985674284714583813663198777955800874049562438949351977791559431711873042288148908962573859023348239888106006645129281470473018 + 9254850687404139400561382825175974131012329412859199274634520950110017567085977669352012785318630525841745235957179742713982397 + 5097303689162257167085390435448404263178199429357071875772715774544733708487138600770119134943129539543347602041901144161660698 + 6953181183113203630678272715731094392489433607360104735402092320971396494926265205286840279679199637087859730680473846380532205 + 7565033230336604389926974822292700950491849340699150720775179860790531037997637976970549940150909535407513425455328335706561853 + 5335368312471755733760541805372968424193070274491865313428788002453279122401760512494622819480016105587606929438634932015824839 + 5559016338160351661853688320039654018084969722536423822579994200012801736919709694310831609907486201946501673508356764142877308 + 7309191546539260723637253628477957548575327772499530308454034050815650925443083418507106015799454347735223841084017225944595226 + 4885590707691548323545253419048477650698836445425272829459034786263150039138385336170173040262385017882023012446601786508537725 + 3159300795992899648874466508404624507417341674483549750138299511054547355595935184376005929821246479521411349307469101710751249 + 2708412392547375974662585574062716099744667256888486220537125770970468132844596575936704205294434437646542619212125911160088350 + 7671842861670510559275736664436986661209239228900436842961873275642777838933287515196746049787877411927981310119576400549956135 + 8080578380146388148902757671260230173280743467984486835312292349158474503715607238743382799824745964056080082925917323860644616 + 2120225379169780135148292573265658608927358543522142151484031366388491618786494744941370627406622031907792989518445311039563243 + 6616422310981362438162790258221845503573731451992162868203601740290116853659138924079987226446597241351646843845278977024986205 + 3662517640661488061073964114703410205367685498808240378692251201166863090113025726146269622096930731719426952075506480919216671 + 4823643457908716999726557603223790753609939423361772712423018042932577115436095139459068730410826645568806300379584835433450946 + 7837676208477360145796134097352072195957133041368812408314333472555459775670645841696822521516557015970698046160780950308863139 + 5015658403765286649459660652152764801017680991103667912937430519322186712931073677796456215078436603241360959178629806771058487 + 9139921128024002577938454673706047243620589115000240242563021016654786832806633509254081676514023612790990852595917560180876986 + 9308821204883025320496874045455981233709125160954382611635568126874562312377547977111739040746530325193651004237373402504537024 + 1600821697316131396065115975797494969376263815891380490449703227459763844691726208596151555303610430036532384862800860173068687 + 1677749011530966588655330008218462556189908006964342216676682876215290543872066380630113889263010720992320394875173725292986311 + 6989579261987669045792589013853182107944124182584456537044269091571439065320682853599165887592383283334586801282099984394392022 + 9970108676029913047954776468886108937529661369633484559390003673582932372797656385704195055160295258401674267521236080828952316 + 3273802761420937902459164150004835781371893878839475301617292925707508874975102558388990001315786419341804043737604037226331752 + 6423865093791333509337877707981916567162340796885934470115945789596479789320653277617641131277451340371426117129794514423620761 + 7417609321834214164793102707841568625675868448913528641242723253295495191476269874558175687931888576975179732585669568870748778 + 5922089337143793314961512325922930026645734559888635155138481555659443901618808201784727019382947895019140665125084159195324704 + 2832300412363246058905063308416630201890917641050411420603351067801736891124820850891397186056454796477918095532199343583413766 + 3842538349880871712437577001398701888177344881522702272474861972439339253087204797211344636084653095826769076765966355059432859 + 9877839498202302366738674681533509411775934456542381162185787945980551914209016996885507489310451917077029188324180322160260432 + 2738878897545393488539641042595991720479279596803533846602159358145022104838297930283221202267258855473584700375502341592186375 + 9062102173051107870783580788794675784912283028909776152369743147402812551267763802726764393893702046520930303504745751378996798 + 1890158543698671287785156969862722836025364759849336645190863408137034806850238192071351320453303572785270717307117565718365448 + 7734822410504169526033583218346170435610106103279145679136488844339942839493180608845290017442034674025577300763459944350044123 + 6105040904995754702216898271414142776115817083443246834852579568391309141621714380298793479424942862844759389997283360409266478 + 8207744090633188685115276563756960203356370566871533095111186389044186232441179082078908516925531610020829064403059153715127765 + 4543411669625489070844963508370766554494552051662899693726257799474616282059274838670819153036396550543481066774790569529843561 + 6679799651036598201198464287278166599830430479287605906552407498711145045497296895091710143423667516678729308766311555682391918 + 9060618446032966067396024483927774799271013972963401931215359008050857228820472502367068320857075813753280582206475097498167537 + 1091834892775689353192772704190529392359261014072163618697328287354942394830079331974933337512857161868992496906607708010073398 + 5364177554337994653512816619520240821994073186844625407311661314696382001907220045017648487411581430791143507856735567122196867 + 0716761726451434192525856251744493844256079661428358229774069510316066898590543756088198375973992063361152435222465923662351366 + 0043075513893517349925411233398957648025096112448548886678072991181902374596438596256297098774636238148028169588473828501924259 + 3228516645884143195864667466124866845099402543607000135666586926382976262509368071827459582454935921975303881150829096536404067 + 4761157693052962556888050028734514069905365690844215214316263823173976897101122538440327270223709317772895230031391498145736860 + 6385041084622772519780334652630409495229736116311103527030831268982936563366735822928512879378203876837625284271193343076105495 + 8825229991999801614347782438381474867852878074358430022437396713162807802543161593009219312576950358519990247724194904234397934 + 7703801976947027234960802861233790319790676821468496141323682139060568458559647230530529267618724263639883376817372167884440632 + 1726382143017323548108870010820096752312836426102452450577004449101845698867822824844060001600494219691513701486376765683162295 + 8567344046439933818792026021934172754782928648841755910876641284145941585066904498876784179002951113808421135227067381608911653 + 2236981696764483162752804813037353468784452076739585261632267090804876266610444767882886160729217192498345880705115733282372008 + 1313046830998564657547840785183730714291004250275503590948256987454019097344722968276149211207582987088443854985798581722550023 + 9063006406664758572850022859344148370428972822517076773683529207252067208935050546823673576957790680951020623419459032466629849 + 7938928170423206022080881849589066531884975323736816185913375521669990715327020849225286810140422793741838143465182856377816749 + 1265756842388175742586708059491362377918488379984875832030848543287918941984050070389106581268802594158962582407355351035627049 + 5900221712437059899622129468224343840497771816212975521659975058333318690798732737341876177817630804815720469182652538833483463 + 5823081639915099173836211725045578069819187508359785075471465778986260818861591546963352470179514396250583548650281488440780418 + 7451048170517299540822354367273854496577812259623792325601325690996083083112151683648900535783537568629739368276233311118065909 + 9084734714613092289461178939653038690130944168935857129538400432419569476969252314501208058863985767404598559353985694589773895 + 6277214607560240011967714168838143750302367595949536752213657372427124984199709048837186130780108450270594932950252051594320147 + 3499572321088417920853211811454866152496225537457554175697449661675274675801653044218258736968600625898775131530277707042339508 + 9914225219653958408220404955503421597988800462882509224240059485399789816322467527449242209991095322026817971575335077154317985 + 5278081500892846628897442768350495212681297210154604830667333056587120720522354514329460517681155334733974540010110756237411297 + 8210591237075811936724693019310304435150990235368637778807792760313222154371335709089813727563208995319466715986861635780866968 + 7932415587435911762210037637958044637519791039364219987373646146500303943912999127265553435145017969397164413915816752545161718 + 5633226031400350789184112011648210881013020831437183038308240362781644283374155015679893305443987813011631237184023671550613020 + 5811978080228290171238069706605813947244025818423549831774560590994763911374360626408512454006214897383037052649605527910939842 + 1578662832737601740265954708879993575835470810729170613732770615041114798158887175252200232752097837948350852301754510131346245 + 6068409444406865116594371496646576550470605636603063539678037419994055698404550683594340710909264161990867009969259182486360989 + 3207255402572128867597708386762297362519921843080894171603067736003753278183424031926979188196805787920726466251458690002582913 + 5008569364534625206093594865389861974491057988729642501378201086357626134901180260883065306275795854872408871966970358994916566 + 5260870280380960692056382943423819321600456629197713258529958092905135072192290151897612011642141070383635146934909632500071674 + 5103943101344555719687493820066438065019249811470335254469779344109290667032018362593087359223818942995619770011635033602760781 + 6090182191502983738438010896590866621707943859659299906860770756177151013807688207972939771298998138528654622092955429850905653 + 1626336772125369872523005387925612023085181385255260458074393235131647700974860337649978590067937668268507156384372177447503498 + 0983088220975640726485831380650348574527016263360984693517646111104451963030529155545125362875373684368744288268392996464031787 + 1886577864886560438915496753180364296870396016073972814584707172757602216484353054194841318491639088652070784986581587056423963 + 5791295955798452846006486957884980659241458306340044696019455166134558465794056766142717707049752847050948964499027310212291201 + 3920118159051788842792018209898781792646763214510193250573669914454162275192491103856842226701566784572791940951044194717542411 + 5568425247114245514540844570366702834465456557122445652286286614869534230920871827766118797945440453053831301603663599611151007 + 9132285049335898106348530191639824752961756612096827245060794650887002292087021431444313048295402370831165699527783501924024187 + 9094264576555332744996979181892440388769625070877328456545115444598432716233979462060670021904359658071557042696819752714761359 + 2624335032983933790947468174067700780434730280286305837296068262033116687738482347338258135450536831314508366201724139587815922 + 8450751384747855334597310320588125802084226440657572189418133991724784364158225409421748567123411489197359560319327166452150553 + 0217315146965805878176534045386582646736519057669936823885725039838691917663928104666774688631639185290691596050519297245051431 + 7940957013433199012061114563562278128253591876081307949974283942244584406336676182042124767131849195077146222822951756668914757 + 6589005956437167623060683298552386150740712051896264556502825752701728084586373026820140301271827258402697782005508526864025995 + 3287288894211530920495178421618385358928209601522908652144815977173646436635300032777312309529559530424309089857544514218168330 + 6097483328468004536631471410495796391660358670051698715076410248502303660016161800128810231929174703618080502422800241933644130 + 2956392224013095847029227680428083425620941588942686433369479814315411693725173853101111802188051631515982053459377355277916857 + 3065681935968907368748287973480293783213808382487086015879418794067438804225330554229750223350574245985145312570124344685276455 + 3489772935059313564818602631010215526615299221297140830316899208960430528821219213991899112889288129943720176337014173173174332 + 4169981630658215328566362976636435099613640630157506404256612156966851420692144492745499377619802506248375541742742014068421649 + 3723697831339666759125999969874386488250045997138226100381868783065151573396084764792101954730971063666073382268822664370648202 + 7695739092394145422409597895972497681500338948172798211529024633083754418602669479252615594701113082363308526566375385313538692 + 0362024243582700927996091721261779876357892824920462321831613846936511858949877169168914710103805138231321626700946199996026230 + 0910370398336603134902288593437904852970471827636244578441003561376156126397047213862430430449454667576391124197185148345471598 + 5028346423876572027639326365391106837855425740087158529449602646500698308039624506892347711322718143846562617911464289132024496 + 9181010776426759091535139982513243227866023899159123168014651495554175929065144279128447458894513674919834462361991122972799428 + 6472902683846165829490192503189706567753176937559527683694767361120216602239730653948099377610225798683453077405631209096231256 + 0512986051426035486790488833906991553793296020140460296126591780195814787329857676072922129878562425136025882880600984983973989 + 8577540121631192413042201337007929873227061283325668352988181356692287167551269236062168964313569524237889901244379824573640154 + 5738145734013901847027973765976787682776812683421111101939034836663608749968365412229382487929512185391212964474327857768911300 + 7562207836356806317921677823535902895646261255973726228824124734902468677105214682457780953879753523764199156291556619449942205 + 6685144408630396033374384521831023348395708816803320958823787110609396335187767019703187308157675845831700883961350733812554544 + 7576609828782901349340272529157644117188745883108516505970478068227119245704450471362770646680973620118556831550370068906691429 + 7387998131808587529731801781598911046784196725282943998624870759033897379214694560999940160160935915403688360574784745832951209 + 6248576464881189569842693329569180599977760906738941622134746107827192298531798906163755685774369390363347404463590563452485459 + 0534570888244129725519284614466994594106901806409139995601464274045789187815608635654309801136434736637205014712781222746921224 + 7852721958335248170761829133326246797700730414740667697834509581576475365734827900004460335634027879413672459976734498386195835 + 5088370360545200433735093090688791665393907039059272593032100436084501418577206986549399579720624028466951070544585214365207165 + 6435187129368614449937580538296933531792687165143536181239511296901417188887649499928950174527974591005214327286330726199831884 + 5864261175041853165789209708620714822361777843032399821785843235985913827357647540975103877312914819841724359018056154229990484 + 1936832320986190570216413377747783409617074645446275675504398782817281167330026961325947267465552277788937638823143961712338389 + 6643014994016028760819796829700070956205113377466899907953033114796754643995517690305975245695734383895488045495784881027449542 + 9277149772110266765516542199009389979979428729803481968242094114554310414335680714665255584623073310801300516821617747378223514 + 5122582985363185134103472499467534154970594419472963412571152321765481331992341844237099548533622925469977982035402603376599366 + 5702039170472823969912601643296899307773750835106819267275831078282467998094066465029472821615682366477091470622470049719032042 + 0671010358945492991105729283517652015315441687350701252921272273957729883415005085140318681745681298665587818639399209287652478 + 8504952151973256765543113775190946452315557877268395630007206112950274261280515123602637574614066439170518948486082023049534264 + 8318785147359309244073883391968368385030412213804815219561275632927036049996919071912768810313118985299449822580618372563128123 + 5447965794084022881336224721150430474622954063445132529997642171980649882452452874371660709010271333178089011623650142945593513 + 7498570392070031176556263724838104407401975655807188803601068318852915004571680712468602581133705435004279673319305506280782318 + 4235251770160613000830130983063100984485301111420207302571915861863284245935054969687285090784775829404258632032504825073887582 + 6407248272722201582954889873840796724288126199508498948167917317499903480984445960848498060154084891463403285778107348687889003 + 4953941330396268815099409977237615027521463257528034758197037642240947224961515275989640733601052280398818164960445717239008728 + 4426630124553142687273205330644281511721380282097626819427510520776002629092574526215543555846304555626987349130475830717662512 + 2679622415503744585776560549326024439456730222065789254179516934309405880579097989297964155354764447981652276792153719461894070 + 6549452078295195952851972101892868752466073329081552637836554870868329745518970415001754631788228704301414087107528862687179382 + 3095714010946058367115405111675588241660359378724218257897889232511664785827286570897205547229279697287663245465265895194075831 + 9805465298621739062011152177896594580714703932025865262409510756369094551491315344002976208292437754134178483455044310999687172 + 5635853083465443752399385809613532628000929554168679920157180193163062291041706935484519604033746044464716659982230583915172977 + 1397085494342438160066950214161726216316797535747161972858218528442291370670389809452231490128596440810108729216233152926963393 + 8718938957831579949398261083744948669476176529513240710990560722588644755296402086806852345746538236347718030640062631744819555 + 9204989031916871283227517942830744003831314993547893753197955379403077174291901637842637655437310798500528596483721526174221178 + 4510621681082500438705444746385938892179962383128718253236867948364044872547102979732643922151263657382171953178711857903512864 + 3434625913079139632847162412927858083774910063803492872036606235419074389757800463882617655159555904544646003283714069095719127 + 9422478480758793975004764634088848124200701219293815383644557399151474644429876593122326476162568364525117348282565684006439054 + 6415412788931044743766779624337137193856769272687596658353208728053926044570228051289974744446738511898266628888688489033821326 + 3857187055764486798882511807937125159502970249818799519647825055901143034107396715341111836431533491237288074873324479254847609 + 1944275217447109672414805304798039892872048551668309961639053276921203694927946551682999672834794575568139407200344761188832584 + 9228691574818073805866351085919567356330517627511140717776424135867621344167516969731782408297076690641510925488519425339786231 + 2831239904815704920016412032913992948413502229392159186483640311971384616648328934218616172408437024641339341534952850417631408 + 7800709599423404547224077175920136421077429331304204846667623312748910375272177983791546978316206296185604509872479031731294077 + 6784795879386865023891006814459422181459242147354385223330262696056730516247499993593952360113613078289229711721789291466201911 + 1558378948527819137236700414103122090944390583763494240148255786716027072401897565958932034145583789267171948650451004479200278 + 5903365269957297061267790413012843976619330012086443873201405355132327717135407147467813950090532723390786355726062359803253439 + 7629287528827946090011668159293077488731123501345393936384022425933097863996545653037874008416991412735073016080615679561676815 + 3237960418959875052085168366152912866396485668534444686608623522780325138572281373258421046475238324527598957994900036953588632 + 9883457218912143598750744649289916045155230666253998012127292069605955397882251577278616463161982956480851083203582599294132885 + 8739605725967415654345383552272209454198363876790394143551885453633595477692847087747048445889713841117432214889427740276964122 + 1808274594398149686259653460592417452536265711085053636183889817336547379067581749366999937190487929782077243956107305394452893 + 2858306534503555758138192142342374976569912519114070071304001216131565171144485590883323767986065555672710513575942087665489357 + 4757258115582473299797872077008431880804766429204591994348523186470015406253571125582684142251809933836340635261386229168816736 + 9918555292750664784762306372865895993392873092492120139178044227677315162874458415577767229742354738329991177067335396671747156 + 9915416169565774505455198608946138326580556663002878103141442158950284935423931276623631554768708518659417736110868144091121408 + 7485024844800932215930566743200643612646843426043824587026297306446562930746643938917961270550045568670866510426684185886721448 + 4920398501344484751530060228048138752162844188260697740262204586350188489261031255952257367650241279996726021255197979400713310 + 0983903945365766675649828378701431579004857069167244696371192650313930100887222144395396003002837274898192175630515559492616368 + 3277569441388072350944394279081011821982637576381780324461779633187405677617459795408379063310477462661505822241372624056397980 + 2796195339856562934096874382820282192099707799004934067504550995736513197478848274092619553245513516215920528915358178045259427 + 3947135872153511247151284668940911981933985156149720562664695031030349744372110088157223178406720212021960705751648342245477823 + 8276198303392861443910819050105767637970397653898744484200995946877348235373325786715347188697829025445506211703973576651655150 + 5882576032689008918318143363475006909501115410116941599853261283394744451901101910507633092078494500214632287815925595536310673 + 7269241743888980922214944937348603959760552838607959592411748713582006971089673926445144319837129979120595791416170081356544964 + 3311215693514569183444297282757452024106434743342415838798070572517431245405339373780763180400593713529558089381582197573125752 + 4556878108283717136754864320383151773421100605854818531410424407658443836201366417280243912680383714161438889747985913112617159 + 3825283938152818066103999819485641639048153915591788440799327104545750772861261496085802570014233362502408220258846139854490942 + 3543037705426699624325696485612282411023745859388735341967646420985563945181345313960301854453402790876180716518598169356488497 + 0055015399759018591540911328290609447855851641187622864276870240973176403939507548117764594583218172186919643238977138111158956 + 2302146157347717928300258596580246250649908644352652697865369736710811431250945078622499892640698932203651495464626034751579299 + 0465216581077322245370388400939469195489616593652097640401043603078806904801413336072374703228412879808024013691780444525050754 + 9151727760868811886689437563229171390965138504950138407176506255752456724326383897323049258585289255126700265024238726662681731 + 0098281899254404044904741984338800905867702052389334861534065540083641450439874866038625038945827791603161398328731872690722059 + 6264530562489216043969280034408943083142765136686187837798682491792210809601751533837187815038112873969767271421029102693650921 + 7670518311894906730059859298650685509520663627502700465860614043829130684092155123515969024766529965326820247830045239762876384 + 1971827918374425559499103800305418434180845901819771222995898394549615763182780848478726307902754377493105414864115497763562067 + 7293146824231836764324358936471102982745003549454252992884038807314576844595566006507289403671236553892547396334547842381936455 + 3707012658412106034610065750021436552038057251146149724375405389299956024255098042568008242870114719254029045709055991603654930 + 4543749521242879802728408392725236169206369176046813175364511678612424177154836269263324760122983569594445005273913013269664551 + 5817700093174352547416009939112502133121085536020612539401905269863944981266637678387919942591042471679114800424206674615903746 + 9928390417067700668674925186060124842260894166668581468768675095262594932684909013159566891337437296287921942274275342136808279 + 1720526807320641693668140417766107453595978158154018754776221360462162393984770342801365549647871062173743896063916005240392253 + 5161802386530577435326894842370519298812054283209695964545050386222673476579184628919106024296128426895608065795872894836272477 + 9269809290510364760281346041981538977140734635535715877861564862122154561230471413453427434440292536928348809500100637413855174 + 0657501300841813074935854851050163894991818276164751987873048063138250805404584707419292446697964047248725308217946641983844311 + 8063478785147013188508380911686106501438761736788881545360437305874844044022285005421389985126661063912349587081288388003345466 + 5080385912620164034274035663131591931589292314684519240800453976434478145811035864455399019210261903984106215732682395895799522 + 0939020059406813121907073513079575778716665344964094359764782266431575550874973231091097656538411338304404129653958312868999842 + 6732798933518323978985303323091966916070134400750942228988862433672654847071015762525448860254590537863809085645618465872667306 + 0427846766351683194895724811056690695837239230026578986973494357639196637007765612283664140977141629336513743191474504552821790 + 3228155682944358310924291228796943417467684350283874136741330013804595358442242749651649995689037646356343539795964269040555905 + 6826145487746532059740843858150338835296508366342272235981293613561407683050389559856243442342524690245207486156018191382164551 + 1327436225221742602074234993619036983345996345216008664910823535986496447271949044534929738194453356131648251656209560053354614 + 0407290886807276555505472513777566509192309345071661761386510676177956004136233159240180697853305064135526857625954524710679122 + 1431829687708285619275876929673787963838663779016128696006658789855078135858492072768308764926825429711165034052613724177837083 + 7028553048202580189681827868563421125284289066186493489485470631057243002992982744971998313406439308961352814738730662842546474 + 1661580089658576037549874036611720164076275368701553799369961428692585978010787204558502174932891500734632543309652429899761996 + 9575856899639421670892327891209797029282817824375074240277705275435359082312316792956844954585652271368228646822716619012170165 + 4690146795978834583378953218274128128954879679834962721495470431115747652300230454490265247933455376976025418712883919785265770 + 4032584676449148273007032590154174755542691092611500872882432669889260868344191769763590664159630537010368972815582431630162563 + 5692592732110530293190433213941741940871216528267789341138499704212959459631375151781937020467215223500973204249438057106028338 + 1541214818072382006149334712979978351719934230083959861254175062060206728245934867359880240685020444293227864055618527079589472 + 1439159705776204064690488345048299759772753492079024651663143703086754589449249599931908249754660757813918172727140178033198709 + 7752381183500066741893133463291861429042158260704598873907314527361438231014952758222297919601552459311683576335125432073345960 + 4158788096315630807867178963280856579732177587633674289101034755608242832707107748491269005626588055241208204418618388578035469 + 1184416032139115028602210049000593619116279959516862765906011705138739437332038056873961010636018153261556031158803924660448426 + 9834587809319862013631879808865489908412831755556199315250744409755028410760389172898604230817719091796600511778684843691064279 + 7878372956127669698977302339079670592653146391325443980293253311254734925614678750486528888944734310378404782150993544089766813 + 4482271911480681906845899905802627519765113355182171607609262740960268207890619067150293516596923655844247586174848972864721468 + 9552003526630991149245651109495761934587784128507108647124483752936558263106644305431230364441437558819641682185001628863763328 + 9406159315820904843204929487522677107941937076263988953382649335050929875295580457118791755887589396355358703932935557257606830 + 2969493527901243167542109903168828628101917337300403325039813279857934939104326409957807201457446262732489661524241158979368142 + 1833967145487476098973136162241392322964264292952490319901422154921305200229075272133864200487657774340560812039475075659326308 + 1445298822625141627089594319278576573094647719202883678449230305616300998398218250958603519589651710614887336894157702428315107 + 8911019753589361230572967964751571906635823516517521975275494263948066958905939807605210390275340148405377313480598158489558111 + 3183749609096747980513864052412964607501407465024842349303716927046134047076464086834827581454812880653390898896534483223922702 + 2047220404370553586495348686661844320582343653984119122227275984849504305399708851775077220602618170548438073982557547603633042 + 5484875538490583169391720574953649919139069950121342298729189319935008363006908499817188567294646844902804708973781249800855552 + 7421001424990409022663446235185073936721530809635245828159482916215742480785440259606637437758227633658889520747280770098045723 + 6510075506635860479703887783619213078585799368504850589990946726994909109916359460180863720392604659818835051505356439580781411 + 0959165291367850253561235537386721365762207442766902579631829064237987397582522884081947056330594794737026301952693630585102680 + 6267281924773054128920399667616892395906931391070201721710734680164804934661829697133693962106573047827000567454860592220102084 + 6351225785373403775734572811446819619019190839393144125015360556285521375890386016901082233720031340998488590003458019399286006 + 8086983669350678861956334882898616321436714400384547300867927315159417274826609618496301870293049853960758679069277021904136960 + 9865037759852510085988938641077600576537641357106366728530348981390205491195956901092388717027996104357442748303975082427786786 + 7507248774842522159480897459767378325396763974897420116495369220388118224704985677597657612836164641593242643705906198310715923 + 6020323897854469493762019753971728667497338537420217765895884555350482562903234559598367966289598307357713584270039680501758042 + 2970682482901424731104641663111768757582340710358846705532647449734646971482108058532929343635001949578504462729212526976463810 + 8406644630764947233594179128313043631264609165757699872474368034583055609364865453910940072958562666156078109884350362008700655 + 9106501316131398908994689175684333822574784889714347654697727209736986308940910431037486363365667132654371414795819563310659169 + 0137910472839714679161637852622472509459014895991142745425159229935069751019575455036034662579025492228994125955644298201357138 + 2263663590472781654218931217059804728469684174302359039764853349702219977113201315914188584584955078222068657185984247622363558 + 5695450824338155861977114741562006985207639935376048162114526556989656274727076392276059583216303897816482298413238883403403632 + 0038975862485843345228895776545691226502347548540923009663654944132545600827380276828701039586345737400863528654887451057233197 + 1285772332269416234665537910079978608222632602148452508934499816027147308767944385913555512454637610386856292966968437445496548 + 1261330191618765210009782014085845073559775965093415001665110717532374517158996315004359428915981278340620344383170562473911188 + 0755483943667647640579099438554263999127548734337936583257964438443463208543269429173892355146856191237124938489437234962714824 + 9129303544439064208938552091032859116474732583566245269345387009587018850752964356086348467165770868170114265169858965115946288 + 7279622065007376862875602615836848329672073134886504804366938182665036461895999032293214820132094992897811456738921945565996030 + 4834236494451378286976564913106384851412866607459667235230175488097172277734513000370973157558689076209485032473704000163914074 + 2906852713508769108670361019771730001144071549164484831831379004788411810506441972725735257048988599402331202363984166872400551 + 4374843284474261559922201408952633150671870157517305411040726961843624607898601648184347808307024923212656070285299487288795732 + 8117441033938778257340076295628604371272466046790715921004843853378457388333862596453687093388500288301007959254642621709441228 + 8336419205482595246714478040728678515920231077940527413442313540990859460129785367310524821300597125039005330560255760446207185 + 3407569957745240672748410048085824476146107644741791845367520753456514888607145322239479922742610070735465164422006326154369011 + 8894279996606564122245246476739025836636961740221798143384506169709797876615015522415620193119156094455114077417058486277270353 + 7131151035004395224877087554662361771017971918239145723682405673667071436258453271309611849685373102636336093172827546720740657 + 8432145665345782054212385521456100690288045272048653500410117161030682916822394178179943934653293870095835416016828701651397729 + 9807379993673315841883406823522043062628694861759093682354411179777001696451399181533177926653740164108712792568617753057780749 + 7552198060883514609633356358462724322863739238474217533806217264897669042731651388657558396154686026363774639912794923252267503 + 6291771443785740732590982981719905524567339994411151615939323485160260431350712239547320702908777027534814334898810771281406391 + 8383725943909858701756050979518960102350055348726092344362770497395426060226252186716626586574811491995835598427931237638307288 + 8507265667315900242180544608612147833573934012185340789193936346356941286917069481442515796977733286907179390046007293777378415 + 8688298391307343027481331662068268845813946664921272848764804887244314914603468930763919183778517730411504413547554154855526591 + 5310568546507610904043747230819248926074837842921381365456929822505503792963441504203788828448597610860322974517666735027993699 + 8190512204618058514563016675739391233696406975567198996502543146118326981238682542313301537034074950744994938638623004424018628 + 5962797353210542352910227068452267455627736914233254078275501019026029219977380762852165264848013890176220808626487330453830607 + 1392715231741123546207682784414187261145744424815836598165304144212321073536110482416294352751979189695534837507189501132643925 + 9547196873348778230662094351866444409683500705986806451682346762409749401895555972393170493498341109191510645940668680160665767 + 9096955810744288162025152776265225979561511052982298941267330985571152782374720461772752985049704669084322641186449467889515212 + 4360617959299125510229120098324080014685874269740158186892010379118371918256414709312045505595343772662619039003425826619680875 + 8242651081630156918805572079983037638369031262141838260427869758050055377235638965872717517504788429694521145838583513263909672 + 4433259455372438105974775408627724880736064277338137893108385178827104479149305047828800826485922049778207824411348676510055718 + 8718825984885049258859271868511156347573558547616835487996237695354831720772501296121171500663173314753159506044722718279173640 + 2709996430110563394535123371054969016136174141380219513450493806426805948941155396288218826477132071568170532718023856256400877 + 4412955918580719390710872526700485018418160226844433869987075876676044792011973789419662798626013873183203506118837233134120481 + 8772819562426148199715932002776622117594716096791960417797687467419822085071157480539482033047913473604918965910085487367720357 + 4625085282706988812822930138218466374524023159847349699030998731244290316248877616127354994943514784160430249591960166158827428 + 3012297335233487487686932791672504848939891571342804916267615897166810277253170819233520663757428230248104405100538854660927429 + 9123919446207336590235297840044149569787830675448852079217813254125078565940555357151112153929694801251132171203795549941163920 + 7476175369012980559938118310990110840174599144325883878065361105628152837782089093135806082805172562067617245231771061838879589 + 4768469919871257284902195592516344833223851928691778696654759047583702848545509080899254152913598427216007302226235522358460750 + 5223927757227044947866784478462919350895723643402842384138354740120256079056226884847266693352002580953694527348195695223607106 + 4705073558122375415417200921965563405533347843275197814453910296613637292816403322858277400213988846375567124674868467361795016 + 4745728385156852832029629080429064757351207656991841817680115495315482039644479548944488439788311653187692817074819840714497361 + 5386314847182104599263810424039609228765878994123179215715094367283327303020988006589792974721368333841513658700314945433634456 + 3685020221252259142980926069027074077129168059113331677771782227727933843623094566219277157186574916058687802285827552124321505 + 0794558617931775588320039074320252238014802597836590634824227249703483529574186006183975509386000848443692647358501225142361167 + 3942679708028160995866607265771564423203677879968679929985370044267348240320617033379072586756373490054605230219409903866795469 + 7536599276764983130315949383875187945686502994166320326189211280377933687730984141460802381512939077916932152569652666724046409 + 0292377825630966235158683241512971091944539929600065707699283877623772501033680549048220288927590692487589517712276010516389098 + 4141777627623117777410741182897322646935774432337593489702909715834793849902052358894916963594941828827118210427424755222982593 + 0263099400776234259640984881940007947968250580544744304077736076557953616095573458814306253535718606350692981623255928091096507 + 0588327094996262431505059042095661828596107333578122924612340170790916991622052806671333685104366780235136494027277232872825498 + 1523246308282008538061408160202517775966824053244715248653671495274650673682535042749033828795099010214859776685551489176975506 + 5811209762314534687747281829159103097186141033482266881873367741901377849867980657673782571505747169485443159028925476795003998 + 9634367858634565656906133482371306765239555613722480562207025106068336976469898723556668691361827599343403798798405762012284113 +

+ + \ No newline at end of file diff --git a/test/testdata/chromium/url/sample2/header.html b/test/testdata/chromium/url/sample2/header.html new file mode 100644 index 00000000..d5e55914 --- /dev/null +++ b/test/testdata/chromium/url/sample2/header.html @@ -0,0 +1,8206 @@ + + + + + +

+ 9254835974458887629672873635789957411886024698554157393849494864228024962939550688297074527198420261051675205999609689838587412 + 7948702662533481896767559573369920938242346354580061545409242090168773727371802699309443935396635866263937828773324526334321892 + 7929250312741837331511829643632683169694074912332726993582394725302853411901337696207186358524323117172520907433878952968176465 + 9486937364148093931718552300016332142708943190856638524388888569011747617956915519539025796115901484762122047712200094207683584 + 0703675740855407318047361595661595146837376373951978537785605481083388906490085533348547865459237835407372374738389274773789264 + 3524314516560200536698529022539598732463389124803873184044464663165630452635665559603483233341839268186056673186867104904449866 + 3388466377320953222057779182433549144340237502432464295061371141084500222833875925546082542869030852833895137466510262849050187 + 2359980877010447170873386178573828860442255448874794721230413368694441497441338856684036949118353204002591974711928301953002372 + 6372613557152801003023836434406997863096739346637849381675791163293956729985652182807911615231198696051411047800847064484769940 + 4555399892730282159333189930818248844009737851281434494736943722577947684829017806688345340403991974811107725657399196027995602 + 3976607710681047393460981746843991626375149576917517874980586155555711990727221948467045177979554215577477183785345135535682148 + 8981224019853812859833307577420310576654838103212699667682513798088777109119729024038590682109547975734687407898816774007038892 + 9017123764104410282402525387418186790830943654104676998756681754083664849203556615995024922746652778319099999725942494552746687 + 4602993085345245279681119328539229356959910969065035141679707233267342542524482900839390718291823532073464112692162110160887576 + 8646564120617234541914353449310981315044240998894442066188871011899825887695202156119273906958004776559173081177243291448706570 + 4866033151494706872899672197703352421058356661105030485577210664650513250767511742264039882291373723618030276740280451621184372 + 9438899492601727676139376045138079061355198567322008270344297244790265795845160675322685239683610065522225253070076549915962270 + 8389935622999431104891971065250599273560270041530059453015141663393829191008304620453278274234791447194116642959854046669653221 + 4390066870930359126190473237338490788280116222078414392005864878004044572924012489353108185972058375678318527434060575546457283 + 0571024164252835918003185534087097269093594036226831977994875139354124615791501602629221816855731144878875700135493432353006251 + 5927821910139360288795697248742701824779517711136895716699422565064551330393130338804982871980774254446227613970394730940420871 + 3742377272014443550088749485134437400845098911378170974616143540710504172620523980130687874417124218036934374655684373965565750 + 1478423915766121994159683752043056020433068572256778826939436280481378432842397489866548450027752963017529841096517341127140258 + 8566764493817154363962092792522076892737665735147823735202597353071978920287229637466345140359899735477359400126088124931881468 + 8940255760337363163978793913265843793885760290540433771518954295210648595347128727773745692808704267887587662204824695198843990 + 0899757006576147578169404543275069681042994730814241204020586377450354179962282687398746645565905502250948590090052580759060254 + 6486974981051360582508378437652320531515639324364424491392656403886587101611394285202791775180181840494403192370521504242888310 + 0832863857962097233772304981176182241414796661234070317886749751979535621508014316193777356696545211120669034308685700669047575 + 1601920560631092775469657814901382577801938745924198963515833985856042317888652481510158158143597978988591350058772254540887509 + 2132235148831014717469033542114409228818750252221985002159849994061876844567039235968616101425307518401162305005282076459564485 + 3749005491254116003221964938075605607977980187695543266859111481060871108661145469674590183816636520815523589998805144183387552 + 3454557776795930937812464849331806246436437524220402821725671887519345824588678830784061509096255092713692879753496348543679698 + 6604711892156464428503873379368266697844691398807542828869396127474509499861163107833096454590997165019449027223124752455672795 + 1464056065563451406292025100441586772081609300298880665395988771146415490692648836974652685280576941091682396423173897267646839 + 0355383165630525414486907132932207574564820206814521900700480593494653392345246480522618317569197186894847097184780188176595384 + 2234714652935409724403164799544553996270776652429105659472464101488105672623286713328942045106946821859926624587221567145826782 + 0309935578008890373154226142294034025862773115052182464935233315361839771441799453095926400038395389556682588458216003237653863 + 1061156071932484650516913321439215405043703716040614962270232640142284681169472791577978618224769535957766957086206741391709970 + 7647351716205014294072195135184469100518783539374945598848168573993875333505334011212625117442647232720744618603822330582078365 + 6190042304849971211815384939288709598033150233044255711655989057889996862762413082297341687788607689416591830790638752880761817 + 3350993967482666602170935703513835999165561197161777938477157925978429670778105685120890113130859239045083522459241247368307415 + 5460081669964922086720150722963115784946235169601550836667474277946931369187925788894576312382075479577915204545165252523196796 + 9483728931707116749644793319165741326903913011722074179317419072713429472369240811255731316334667969479890293999075667048649131 + 3479265891282260862086967904220845208360231245372151218473448305464967324382299780822943482467600298687513476936031155077963601 + 5358607166888753271639287331221882667306965170073890751994864930247242443182503197751744519602399141153643026523167858853130538 + 7454234112327473005509721991333469328638161495819890863131852055720398755713433050343878076412540696773945682790587599473898772 + 1829500286670935139918198012253669665196719074234685642111242009658467409729732638466770339415767564217863874440642300491597266 + 5585497029761221358413402963546931530898077983556347511671398790492531247609197801647309393017719703556474420667077635431137035 + 8446511749461154540070308470454488783535318141900958816289412388611370858697615498746416636102261400237788596935028958347787028 + 3125589335242227429164632721324285385335478344437654660712476162463759322956724441170491898597020350367163787012219584863841888 + 6802337989299969519242898184367047999251583706804577726542893830886334416591927545136810611568115854449708934129157129519681281 + 4502536799805954583144549032621959969753071050956941684132891200046324576389173182566153807220810192479638581311891427849367417 + 6325541021938064574977797529368876421571303611445571554655335842928934553745122110842178236045825160364424732178843094315127909 + 7416551206319999579172591987511489686313571898121634456963111089610744020435972487389528243640299599133169203384400119064268257 + 5942558924368052900576494867848083529988242331335385049200017447913990221665638834941940132033114280719741451021709322013495656 + 3034267296680277379429583962288582457402893052674209528241394670330734634693333770067544918231098413897817493181756172191761769 + 4462568735945386723562623780129364617626340957792264088426814103842409805756856047587770203362285297182877719759239486173167134 + 8181657858983878076788365457679611406051878073922935400724071002626732091440173091689286855430601190105542880854867957669944342 + 1682764258327911438109776589215105175058720345720016147450773913501679216877023673201387960875767306750352156509386560915532694 + 4168453046768399507263930483191895109159119018724369742162771101927944398681984030667327651300421681200981291741743361136642792 + 5961214949092908589726506803431211408890378633711553535211419472586275853572210445315467622414789208830684013971300686277675328 + 9269710543143964341467182430089608998710751826481978504336310277969086698368677287182389959721242273938854619109417313330166529 + 8486459999966843090378171773263091325696386996545517566407679424699279968298703891528397394384066258625248890398189881141241156 + 1449849546688513154852662654151484110306993368687380709636409815697889872688403677017676988174939843342948688833489247136945501 + 3026821425662283243215241228426396875362999466310497066906176240972976192127107346129568606866349374029240104708104443230866441 + 4888599832610923002904596161762304764008702325429097763470366526898011656507069583771589908698710318907474941536590688671464002 + 2187786798670885931014137550230451723811271617853032443909991254363190383287294838940424051082728434647528986018234698035977262 + 4010150476565439429491060857277549534561616385054516756344772776300804281913985317098584407945908254666687113999982299034911916 + 9543106789274635042741853569705907409683466986445551664737067041728196021666244823741197574167419992584104093228192902092720801 + 1102588771206288521669854794170734776396759389699841902844928003578465247527168100807066013305698109312645455547945036883046986 + 3363256734764708042924448420459037705906529627671525144633382899415555101340497992824046104327698365969273385304329013580634534 + 5814024400502542484138080303093675479908925878015957334513036393579080542663814740530799226052633254072603206379019404756963615 + 8568459878266889844587337958272179244147420281407959235700418194754222652142770182396574372220705526302797889629403089542338729 + 8226364273353855713782831639652716359809735693921459950536413341806490125092787610897542413754704628839004798504470781343226879 + 9564108089806303912196187245286576464060313163695650258929860024346682416259472890719900060340274063102211811727469052257146328 + 0723807096388817245239864356681843226170736144832701238842559718295427226555369395998370081796589238415142792914737246512392617 + 4241424816471283201248965000004171003042756134627995493041482479770591013182623840449510466593158465328399081296605282376713554 + 9973513220590332519460381924338347505856779256581376567327469745338170108702340101128824216183825500136464452346025348049667485 + 8383897971629124447860057453350337067099519586684049058435585462779736095630666963739484221218567448740285624710665297561214099 + 9964116268591382706460872763874878534297946361217165257274977145088020502651470013064060961213429959898581048432243027406481577 + 4824315082578790346775943088343852549806522479147355182415674805204204673847884219703487656256651056490611337757236524094938348 + 7062382447597254598729362880233858271292436951748099256624309342834053225940366427538355199347489811241328865453894894705029296 + 9735693411211619628088603452483215272175364970550497151583596541206523461527332458408984429879086514102509879665768932131692226 + 6961688387629152540756216546017259642317857065168508958573052496210655276891659756089714383999813015316305245290357709870563638 + 3863034723721495784723589237391107262786771026496285596990386769945707595340965195448259401890929565886615037974745228156868323 + 3287577904832967842610714371567414265151412481754216777139400930821306278453396427971928947503983582862250196984342590738386627 + 1791128295449101351282899590128118669109794265058849951756999066974826947872800232214872176234126177766951584517353226892319930 + 8805052099840613606036822579273082344123139982418321238213526119536401574939527633217151490658267375799590895845553195225375174 + 1355928510541796297379079857922955866076933929404227257481153317061720856509437585235189609477388103725696248255380889259925943 + 1402201875930840177564779603131963190398447445546273482826943610197406605496467698637182093544726028048446184407465904504733488 + 1834037129267281181848805100644706716446934703366578946950288560270548606368029542736413168537166947783032181537827321728818305 + 2399588088866368871684803227983829485917501647912319399696731866908470118289600881964063135888922021379521028829404789266368968 + 5637489977535077950426899162426475829892339881113388204978816994197921201698140466319573566765752657389499556451516488232245559 + 6112692169213605381302831305889438504096793315962284966459192757358537426473374519814657784899843476819443537896967951107338491 + 7895505461382759098793722523795396339534176000429147383719128841803883949006205025948100090981495836498310874463726230844486437 + 9522042614500829901321795525603265978871144309432521198633117362072879318547949126425751870262081563243482328537146079314556599 + 5093542621599279420676140514142072884094585996707002095359240117940447064308608734332029368110977503867431654445743620282821742 + 2074818355004815481495949283111185240895061522427508730372487670815127557063465146879286952537668866636765956480834805349247418 + 0982616183770170277896101663961256388046096956303414645662042291995673037815635718874781061367093483701372208717092453548930045 + 3197990341408426456860501773717322183556963874016603497159407408857792270849795326742052795163483613191779561704529979153717213 + 0442381165605136382176204027769856937910886725474913822447353042136166362618403395513606165988761350028767809916274534709139581 + 1546533500647539778292217072989397950692244341857345231008319214990106951110301762058019968223873956867021450221558460837271796 + 1089583682950702039719953402978240768135379617758154644301927987331573523265837746123630494418924793748993674977892210713791382 + 2010498095473532597719948269554932451554991652103201520706494302534512806373772862577948592827967992187111665796229241795272327 + 4495947525239030494005205359163320911969546009892986032715554824732415447400580445227801191434206229755544175085033640445463730 + 5799343664533857261737308836915890943267341995945607000250119768647338018370977116150224513412795224930773162810128318361091070 + 2845165641335198012087900200223115487995666447653144922411381435396653532150893427712002942030941647409112450887593516206623257 + 5995936189970345951128332927675055555031225056766626864377451946716279426300206796784320339236602175243416848009874418064376734 + 2751388225971927284674719275737386426623723915170272496656834116124167598744380632642578314683658323664087930294748983479134152 + 4463890675024338744201454760164930410895360686852249316115526602608580347281230566360947860956394767605509297995646286805155429 + 3902535272296902694906404269870261097232828009262961508419387381919670436136425912908116240583462930917866834873246313946702767 + 0171550221706917129701789274673785241823132172160837286626181116666263103300493781986590027327174868610919833041462749008446670 + 1233446436949798212579086729206735034953949556045481891487880919889748751337486349345808929953562851746791383784762700811827813 + 3273320169223863915019571833988285591541029709234409949795661766708317004888223115613777281294607726043777706813741640111212754 + 2476840221289778122524588163601454015024966289209119530584971298419043747426874336591254749329149388984462650479516131162264547 + 8321322112340265706034027413610131445579234122444443539849216325832257070066442940612976748450142222873158683339615189385385401 + 2845301295555610107931163495080379964949955895954082606347174241430747973616106979000794362756653542557197433894470866065773098 + 7002289110540946230118386265586199860767183813803128176222583812066464632835592487506968002253203796340562076570806978606547027 + 0518614265711371822209002835579969441398099868205035333550662371029236766960492501859441092496004547436756442048667962205035734 + 4662742623053069471722274771033535333247780680117662494001501801076484609461801093095512629224389725470873708072969419161134986 + 8879423231727024904174405990021786946862967043559824446453539979244586561718968470449066018656109597862462444251052806647222165 + 2462868109247823087920350263249330583062507248433983310105749602411182363633125913535849740456631462938827755069526554867046297 + 0556317986368239387236732047607114173950737209007825151623731055762898522619516377121452352573813859619423710420648830645140602 + 0693502619716624171936460417629499350461603844160041861287075322351538559343745415528939056080652464222483749575581089457335292 + 4766904028429523888256867990946783862212788485169555738269492360138212802976905819698072914952002888319407814152289904290372830 + 3063149485419553279766015944554584134585112055860455417890621924246024514671960271622075351843821409825893454426591239346175825 + 4138071925467858356596514010874840756148724225545969356853427243328235466057330927837715365449101436095007553412409485033663473 + 1718208277388066697955637942282188804022877425156297722332673824998500535568426990569492133060260476735245935911435663031104540 + 7259896781146483425619092546253937377799155709431757305830799439617510543866635784180461435471514956432054478723110546701399601 + 4212208190748800869765878332993087846354727233690197986460622890272309218632979045510485708917467310543076772888886969650697402 + 5830555875156620379814707898244277917838097196097913596741388644704517369937389656755811401456911697429799824431768975340394565 + 5218384019129708961023696421751573471619498755822698446106554346210228582416782419196987283985815988033363104751364948821321736 + 1511408675805990625863697514171112598891753956197059919478438005392395089087719396999097527167894172833319566356364163919692543 + 6760864061185222844062388472607262118669410742190580800609818458141651702885176634837319000673951554557807668749868767849900633 + 4624693982782044541974663953840367719217355838087352148000020445830027606519679992919499646684217452676557562945022247829061975 + 2885293059896283301736153794239325555898371313303885556968069349802848506212069388120502744705750493536808390340479824477084109 + 4742565846910523167821445663540712005957374896244507720218360942226085109738527921622092099772083368812073433747682045449511884 + 6164131243427554092783794384838205105688550227514505179310025715143470000166045228305059905780171994193190773288044579516190413 + 6196746209214286300600159852801523856096528659384736317041341206058064233216653841144231397934288134905891354902685060365011048 + 5888543435289034798476752259935453803961756168693460157400272434328483248778988626059542292033153708506682448981834226044225475 + 3520105979519175798851693163134966793094384503981145911295918784323346445102768597120762535638265452619900970085082259502423098 + 6023108133594199401032707688284772080067633191011227704160888217224741219472651134131857620995953537078628999627600457859691029 + 7135355737374006279317910328897677569526320656280275576870747086734764513800879537763010892690268998504415888806085447064856828 + 7067645951048993310751362481424429404370974532580270127897680271443323793244595619510531091473812713032955994538657114149409819 + 4429631547566328842887647552139562050329710358137821590185444827892759275367380722401524911377817064992340751082835810723755618 + 7949457580263990600187866192739809055130641391600646169338376355962933757309772135951086682561238922534649604316450790162767470 + 6778696718174528127426896010544648198065903564137512038147927254912585276060875391066341248912566730098691603844487954144583289 + 9567988530970013733492869819764508889770837509952069384446637448211216157716267753953316429209184585653933599673133926099458608 + 3413492966631743395005504952764856687552734825362970605800032693220033767913422924066513158712050177343306017113090503548595910 + 6782760373416377101401788671756172877579108677684185994928623883970442286211028728581037425407354811624955553337741266271223038 + 4228769569080076083693265874897262718489495320015615486943453828550003614854151710616339504422293141400194809493593482338761720 + 1275749976017493214306625272092330580872354604747422498275624636561377503079831465248194508227879655351358840776762816388383155 + 4044611547062276323077587550347056464054608166550263311750875441257836393920920323092209759398994038142599127607649577377981910 + 4521255521824521693676238300467676986666555950395922139641083951517880343036286546664953201729241686129223651162600610883998263 + 4053431348518058012397818472045875672812077824208246071436792077005700411785602017912645840401853632467140385402691379589989961 + 5296228207351306866595027867237475870719440724477597041700391443928732836085081541635185416372585087892465757549359102233343361 + 5753047891155830333399279611743974102446066339908340811693445790222472707295688908858729491663915472040238337620182908302697924 + 1508699849153464593476010736879669905272623521348097908417836104685217230447793112158735284635375208948973376371517941685224649 + 0333224377446486130711894052961084313686306998844675785828086842465862992758130724435712277355911443550657464532883107599718794 + 6835605634916383199967953082993703931572871914916373072477880100548805151438790628235173925034028725412169450381473208146789756 + 5647596797800233744008641095874820885871714922036190240494729749620603436690380840330661337877272707920476284213555812599419547 + 5513261332211064956118510684223202485323331553849116007081552356506786559518794150443263231676076605407451231256028775857402194 + 0513233346964413426058663133294017428893643801135629939987380889256710071523164000264715556002787400893978524476668487881682249 + 2238557041006601823583800792379249859430190860772025645499651325329407777431099926158122243379494002959281894688702064542524790 + 5329597914788889055993063859757359411515855405549076867209561054324585069797183524577493085961561532791013967475565456058906425 + 1727267651465421481105710991587303136944086691165624660300683125601416772368166283177444892976868345022274558919475820725390404 + 9723590243421203442884921434798664645968065479222983928276913077586527562214486087189922112591555037425227530771384194025142882 + 2491150360749458092334991769156796313818947278756674701926505201943095015129003490350920079450451251986198697962197375931585963 + 3288323311745586996701741630221983319300390047571862205264349777484027201608059718085154305903308263735198400749807369566973087 + 1513669962911297058622557295345513797998471626294474435337069062590410594233688469673875484253912558586263976338954760252676149 + 5698941909248281308488717883921117273305117757034931046904729563167368375307728972002962702645828488935279252804415118514787991 + 4226862654077359109954473957002792990601772994320272543965433892756039129932073592057677191275583708907760929447157089919000104 + 5013015202975115790118348806423060224599193301855272198220793587287609415484559416236588999749109103840932649489845113026318936 + 0096212754630289886604076288072412229982106747320501739034720205607227829189554712104511341545586461792092663001971581276075105 + 1400830012525551115910295470153382076377587383792342868236429581401216573706230071139732339253271088253819425521718399148426972 + 8130329129443141149308342972871751834898890054061408002066328617017958243761248655943163660366018684672224076482931610024551435 + 1612470444029502611969134698674683976299405806211129021898957209691274647456212891723004609478869086828079731180673443147282673 + 2207763612557030174078525394691981763423880246207823469307642881721011975478949627177448531469379452033830830547116487954748579 + 8943550014526152971159374128630625318393391528677655228099671641521821415999666028671716937719971706453115362098995997004338463 + 6633791090761145650463177053061879817237525424207069349153087084514135819202898699531517360951263097509259970351913296855368085 + 3253556229437227815840782322932038842610282009077575504105765620857277275220518640524545781112378703944765595787111117088536490 + 3612778048987899240807648365404713381232983899393777316948941796158037305227415310986733359795685540845368139757679718651388721 + 0329656082303032301035960655149116897998069813522388783445067885544697734848160954106786926689147778838221235161040983098545023 + 4949145925422482842946072091038603570358418034882170359973918018079551251028978485799644769497234033416966830413282850538365544 + 9688715528548523732988559882524759509039740049260246259447423254924760566724656561201075170029641287177630144231062011355479091 + 9326655743860681005816798142139776662356020296561383131825601205038606699757827396575776760705487871722516625005501108342115046 + 4862493770761711413231246894538240278199950440029797832691068222332648670966923316771267216815856555063431665762362373752681261 + 7759348913324715341816977430054410931106803880118579894939051307627827449748451051704548335839341424354678283555009009093334643 + 5035504534504599464259968803145065603468459325562475588547886212145426779673200191888479107787688352706387961887120658923163596 + 7064143605981003619608323632499268464142806140873807593464533126484595249138527994250140164063377300752448939069709418760740581 + 3405460804222472492156715297971710492718005664789725902179902462523655008185987881883912400930038752420707768027434069222517179 + 6201754337957471374021641947490208688904315801118730053700597398632018696041671232277781587402859428981324544384470959282694488 + 6581501955752939978682011949909110724289175482558070539947143137365139752819830357605189104362596510417675677952395485738392629 + 5415386438105335984223237131949793153812658394744575126207919072784736846230789712179591745207901814607314375532066326818332653 + 3916132472388884065768704630042622537625667251509691545801542090771247404318802955070620862627476301969800427094218570764969521 + 4673296443835065767694158631727161041961301871016507435883528289555722603890069782368970629525870136617529702747543702356107980 + 3969736866659860369283152300636814307559050510391015595957669034065148689817184431746719346979216411505522453887905503375134993 + 2033209673996359127998948182294581452192221728807476998740417776019537129643269360367751767407520936424856588589036363660084548 + 8920359577043563701436228560312778025314413146903691717334802285060730546542075837699964573276987471415144914980259764316759773 + 3627657012409360919929372833162804983136382545072275729679633045374976939117136265913209976809144657411039862524163682772934353 + 7062667690768603813766580397495981633020198031283191319322060508875443418955017187814158494951274114076243932640382433951906100 + 7089164714588749807180199878456232640504233132283953906601030144605887922753172274055475279148519962245834295034899100856266109 + 6314588522281633268271129575999011547246790816567972537919142521521537511380072338334215014034228037819143744053883142669885047 + 1533466041592069230562893355289214460798489775583299853132986367560533284715718053651634282346811547110422080041794519104713892 + 4512970626101824923414591998781160477443695022763348614143799819070327746195782058463430126505518264262282025424239196981682678 + 0616389983515682792619586855106396642118585620436668809283536133165065564894495800101984339481469054418070569566522216534870046 + 3480404934288007401354060197932800798509063792079011642804930003377191431422069063134440047889535881274567178940747418743011151 + 6923077833597121569133964233884887129884707102983051918568192593065049229148460460606709813558966649828440283419826988551789494 + 7928629618912970441223379654942167876674509009329326197500704752789973531185610595644942798244043453568923441723724834770288101 + 5686916225325175369639383018669733714398867749909229151589872339897763998251848983094518391124033198227341074940345064217565274 + 6976813108342658294069521014494920511978448452850030848500379855545152314960261910035283177013574685072898109220517966532820914 + 1235440485859974578507661524414185881273494203471328032423655298610228309217218895796957468358842309363210353318874365415441005 + 4775757215064448647761305923181381380005564211124254441169985896444461359377488533806177746993363765363744834471832298666899659 + 6549502546484198000053617666533373457701974326516846596770901748191355355442117405686714513545060992856554971022392931918431672 + 7550521620433789157641377352042796699563142807992890238677899811145361588800069593324309664156547033893582449253982866608790396 + 8335832703903786234598337454771069254394148676210696718885661839587950139009136903487221685179093872236368600881697661914186761 + 6081423646547430855633909798819189360248786532594620983774708429259122445948885539867620755942089483824811916664871291112367965 + 6763010129734054857751250818823088329080234337202140258490696882947562857997890963039131549439624749888135285626495741851799125 + 3823814359862336359300824370629334246257087407174522366323576913384874982113357872199582879993086251942490130349296563220714459 + 5201936494493880745125428463676510521663426683417020693977788479860674628237207703884747094987717754212968764024565059007572287 + 5656800692578264688131164439239627529022443380780216659445516384845610830241501827976377913518196568744298647947111534785980646 + 1465035810576162949068709350012676100595272189178329025511241633720229686245517256992739629981296918245960598907587127807526613 + 3498649092457065189914681277177637039326561250640746889454833842625621406771442705555721525931725554548176228818511280348712812 + 1526903631217370487596090586369687092431736602852047414002552907015226570166585529226164536775440508494117144839832365340311216 + 7172800070700446830268660237981558246985408200103623671258540515214258800554645764441093416997150958224932045592907480540349584 + 8145891984169127686107656905169532154735243264685794264058843466267191409417280492627793038318403119617408184518297221316412215 + 3733585102819835157576236492205872180664881259553134950516961350305063296415930019908542524245430548400901559537444244647471710 + 8919107817519795022023748231546623121376187758240479239499900553296636944913506176758776881811178925344276782657634277574411018 + 0087408240115194690559689367771085179492160150159772172117583670772068640711181227707347785373406551286722418977845204918371862 + 4087671496873156369239006050995430210075877655341012369255927938969111714405072240508066221092434986016434496634246773638497705 + 3997764933956408083465951727938645280914517402927065500370134817839436837421504452664821784855528363909858322652715776945384928 + 6358034140171396799781808478643680937510756584505346662094931360684566558016245219693809041873394197337373027746374913052226841 + 3523525169184690915788330052438367441556380178099903982632705234888141866441214930597392851790874812046196446764134474357280196 + 7912390044622498326943727559828557263667260605437809865126129166669886288145038860031004268429510310452514645934110806061259377 + 8350389661397820495902304825219183306686077590455378114318515252557794852940943308375379300282537760761994418165168215848774199 + 4335948571309322083199073879107610257555821153883090762370374143145191005083410872058977433580493717339726072170334542991808382 + 0741068478360850873822704930167309345230781173492590875420659162725013692793497218747184011101436665668426379299561926131540226 + 9684119382210299933488533355753954403421331470099036025961973755235128720357457186896140454721156015369426494838464841418224574 + 2606550410151415944627360045368428365343042196701567415760981599314167562524281114850783881875311867997694821988388783550617647 + 3906118902121264712371873625367711895188485445955724568729752600563482629569914020509331709891753567605376276818895453947988485 + 1946035303735634882855442231649687139100528774921727985325887697840697252312164193587116219630593036960739462878472488751794288 + 7553042934057050700594030020764349497635594011506182646429625749401961796662698874719407015328877341348471848266936805626731614 + 3965083773308342246671432838925759649742042738645731254867213711401607696364783002153346490446057228458139827872431818981641456 + 6290917282609648173484002432007182859707772380995362779354118181323028872604689080381882966273198128487451758287389558544864092 + 5135412345654409193398015818933242323380089276961210614666090376540312839620184116491698184580875294639581135409937430385452967 + 7814752714924949029739912516676992468879575093818117912716084850528773868618697654019734174399226706840162753982136880421595798 + 8344230549785765490790122830425599688553302815508985004520791080241214227127540251939234623642895839337504147995870998311297157 + 1312261536153577576475501063559792340822581967430971162124952202625290357772475691141555237352878643256411801046597748593662978 + 5420113078044378326245454890074054926337548530109656935414953837202844128511917486560998089330806876653700112974245139455110655 + 1446316293204894461498438056975498718142802987046646526458433588790266320884188848067627056955062757523352642280099730639892974 + 8768410207973700878297712434460869178087366365740643368423050061014329802628323539796504787700469737820946806556379851425348409 + 6903484946126406722104799612810275531016737884354336960835748710713062889887930835389522081146458095107803234373499389860789149 + 6113798456809198989364723468291582407592480139088852307707256783165897446795918270682937158869421622443360894104220836046672216 + 1297180429334742843324101908319081257574325368096788573404226330238491288173549545719251363488582787945804486932260991191153289 + 6310060489009039954463983763054135671085760401926391779699811819750329003225671390731075907159344886944959170333579705985011394 + 8928332308562582665591113793712076278529561597438667031252620919756801258278599576959931680328088876910755153375346545987026059 + 6122799394738485298698282219069449469308864175448069521079405422190290510333027132055402559422290946776150886848955390869348557 + 3298127120443406100122108547957183131539174057790900079286455780159808161628252012286085211125545510059619150351442374519647873 + 7895547723969636832110890595697353438517639756208042458909186966958825057542753856885651750056062715953653156961335641588198051 + 7242277604059435612451710438360700839539630420328128639238629662384680381167202360792624305492770524378775130253064094350170239 + 6328910744252096963453975544360333319092492567496656064841933375445672717827688660311871137666274201081402086421470543791139037 + 1263075806974163649200998435369614522606717804984408053096263479824896274273438278637073802016955266073407127338686266295417138 + 3380472791463934939167548524939273036820154830243043930199471181363843017057589926197441097934643398001941245455025305275718778 + 6053039097745341259474392045998222000183392630902077243215225896980913571132934688432219430448989534298905581203790323081204451 + 9398618592749592673582297312578194153271726432191886003886455601016177152460729663034185278967994135744387261240974218700552874 + 5660578626067455796320901716488860867842597868415619043285914590213707161427735661103212503097888685177044222466862770614738888 + 7523554669658437443860955048187147707950298396691077287510802686031319997279006079308577219459278947413769480723164988814047848 + 7728230896579900984081254526628677638403672817908586482917564357430378814260695955826428360637353362697491648099319657648279806 + 1471506063396451021205086178083016198973053283515072407397794280863574093292850961361893442271480652011908263493969049518154719 + 1271663389268841465526530211516124798508874084299647641127612963439336172485890973748223056840291177210000865573662838724859865 + 1558003045612329244947071838328209194658672648215862136590055290358556159847830215232765640226279624286079243381635121169856392 + 5235686772055013347630127336838697764880220575101940207293906989459723943700375632099865606791689918944793971999840022845627855 + 3362608893556970872086765317357229622168187942063554148251194799624231946317410456787560024770536041305554794440402555379048363 + 5400711312343982155393978124014413441498824140561950458826861214386401267011236483424009049988004220217832202185519723172983734 + 4739966966771226209909624912450025675969022747113454805529677743180928548967947375791545038561055048316262023987945828187738406 + 8806383430961455857801815047901978280522034447065757458634887588704123408758546678452281010485610787173222519794754395918755668 + 1313032694820263690081002684124072214508820793025272277314613304407858220279657882431787747545642867929558977205831435007980692 + 3821423807029286765485523471547535800355065560255771366935624333716101960889324812432465967939307158664437101875808531730514686 + 0552828401027435473969844207309352000803571913860014776373394805498998489404828887974801011916107676224063398083299850490285852 + 3252785594630414326772320135663653623232974740345887923006984684749440127689169558676316478796812920656203083787608388272541143 + 0886829100701462879464273672433682081314775699581471366939184918943997271841997863805609882688632845996559926289731733309941773 + 1588621110929737275611330049699746179538000510503020090443485760166202124848757232989323035029655555830280894064603577880623924 + 9460393092105077041540924186306320293949908924617136654677663794806814239207321566509608838781326729111423409256038330560254768 + 2457234134203393682333223194421969884096521962196051357781698196280191186003044231263105047089066125824374037625184294564841726 + 1139020355104202113948476242624526315291276395095210708873598278111336130644448701938653730158050834519082575031500159059606323 + 5508845274116902540996666349891489554638610844733883825695366107090243640688502082955261760220172087743405531646494097110373564 + 6139164128879727447485151113660365410811051772254913947601863445614936478465117644061091010800284725353254306320280311126282508 + 3691867968556520735423213939515627425003649240791159831598564334907098275550400308993911728901273767070664323401959466199812550 + 4385285527314360012494827503644449196670340936661875727271329351754418864846693134514944138823292825239723190822861243721969511 + 3358507325257641984977160116136111658256532073729689685425144586604492783647635836225848095839938544002404873700622644589011676 + 0802250613087293781581129847507424374630865942136402236774163044580066760450481644654868348223850714885941401523519942001370346 + 4033651642172702525694267019009943272304377112789600524789052835595443304754361088227651039992096267114223436584457492049115625 + 1008702122009370555007456522799161340685826326521804374437361823776598365128302875870953921955751574077453333491368066562183540 + 8297016982983877478208126579509560908805708870139177751490524014204560610778740303237644832086788493774257972604784310184677682 + 6595999611158451837934955382339066842486744152636969464066220937412139592293869816659174158028425151865523439443968468476337116 + 8189453034430471397425280708179774110697730501130625090567026833440338110187758034977661201862518966699911402128869207946665922 + 2967301009332385012982602845125958037212145265901920840751275900004234804254302792404413397360100212415586648851954797337031843 + 4621309795646253111797549932297844132545282162620476457572874699573469126157531277320612819758228011208417228396419529928921453 + 8015689409373876308149147646698419734053674168732622753328286778805854267784590171527922720365829353861437404497654095122385810 + 3928532819894452405285805315911246752486216644456327155370715615309647716023031992277092232949890587556921144870096925641170977 + 8706990895052933118940892301863446619427769704201470123344557113277628075518257745853511560735206426541219526593186205677069195 + 9323565048038756996967463636608859147371871703253988562924960678047445864387523330892542610569708364248757858563962167618047606 + 7400110024724615888960177029937719273668926142229826804752461957263527604940620456908940268767529855383328656980509173310228171 + 2961079316835291946492496420673777366632570317335815018560521820389694972648667220189874230520964455139599084822803458488491752 + 2053325276467463411017022059798270225751157375504499399426618848961341529109405849259510473132610506746820731096435354555540869 + 8022085653261752864363248353443911714595466837953116893617432029480864961559617145874891482509931363773686667586008577729590619 + 9511531059462330034969446429670396910393858411286019648142180898913734931062268324002479006487407711948954747504728441451817299 + 2402899664016344765585783952968436864461868976736500943447165022135283244224710415767003722013469693233516880183011359108783628 + 3912070384615994999455640965424049848090544713337811655011624123059617272139004908000480810430015004300019350285545631530421459 + 7040129421344930471792157420616841533490962354840490248534268666426427664847776443733801972606800005209711387678959754783758169 + 4514744752921544867887197341433819468485319076219844212297689345457872671062595496333380534044033301910072934964202067332750929 + 7744301249953061021059801665718252827169031698368805857673827901657376462120738712603816558346872095129968009454819539063410887 + 6694959951385441493938996005094705323326365638007625755937236084671116883434472854253964886004560210329640317017985931432992507 + 9830755088107356428137960573336610521897465624860840691251416368635190221352342520096074021567053917840102300469951496094532646 + 0386151915867137989482068036180096232759486104299898530934407665433761886348452364475713105652919177827149093478062390353337982 + 5026237611119968967543921268886408485214827943839163757065518470886816959612437396882015040264309844556286249899479340530273455 + 3790585606726228419436731177762295480034329918020969162076958086843994331135466429174339242003665276457867681590462499745066166 + 2010072822988771442333707800353630624045735130580706054631404185963369356383377732515576219388977808173711224814572042638811746 + 7799862036041836103498954213010085023304912197271099528776247085017591855736447939941510010043072233516636490128682332435837718 + 5444031310957599380550217779540801553000957068137470959947071825380695799288846148959315246034349773291226461068837384267657314 + 2720831922046271298345192916201975278989464655822747470522487119845175483171802764985807888092086888555468865508558747670561030 + 5037268239030155207644532217893862758398321608270496665238719184860604497280537678204406616537105359104541182047680859111844623 + 4406453518829809819978030558459040108565356220631255519247977687593573153889331324518157228436273334635625807524985686484922311 + 7999885151695902136577261421847256015439589971601084977870060297320803728853045230722764838994142711659330991658042253610623719 + 7149325976325848648664235796296763337498794913699316628172271388813068172391895353748736320858783488531575015143960860926515250 + 9988100123929774124197265328008141820710758495752123486181540545695574140507942678614702580850949656109084164982037643220132234 + 0375655311441060929515636645306301671876166021260474227545267428349070029167644989380583812184485451805574601129180998157634256 + 2128590561140195400524100610776393812855470570049174388092975612532917892277799041074366790055894057834557983976227857050864930 + 3547444389508771568810075527864526064121655767293193457033048336615284399475478737509966968763107403398079684015244980874035979 + 8519927849602061794266560801914694036469483013102023144973737181284943231700919734522079332185384045910178109811932848109276138 + 3567893790780435626536700059643971391023938979188277544418757492427060624484762199641583855650960393640504524655219454811384399 + 1735108417168233650163860054247929680595797171838825452321119827231787146560622246912322232224942016739093046379276365165998295 + 2756695873865903361436041234030623662053438358924238813701743016813195378135003338279782291211315013357508842537428877943825850 + 6550701509812921278785065189524058197762485207459987155095767921276575821627138362297358879947692406013849533700244092475658064 + 1746417294003960060064872265575781963057635907396407260460748957479942537372418296161245217676807862873866767635894044939661427 + 2752800199195253529712854754798642118106991591404644917342058968657791030752834046050164301961614256798982226629143783613672100 + 0156432932446788502003627727688728508740309980174215347673828299641766130526832968939502574943042109833631744090112189289099293 + 3949539215662926707735521667894130134427486982796357220482855624651559957655963754443694394481228836760254413314867991125537370 + 0833694740794893624914563726494064663925162779653035815936273173351045298468454290966312347207985664544908635066940292067018215 + 0068104260838913669470167249521001975928318786418160510709377212045134485178004263296128628173776672447600907854928188803969244 + 5213186606414124173974080816812650470078589656434215381413340547874523982782714789910645183938314140377172417321651847315127943 + 3831079213870153648590263375611549325132489817138611364392701108960231363751036773655982850004119077364131468986709426279928740 + 0816735516514168218608953096598217254388061619583961807831532937684267549690578384517226873045647249368898189499267589557763196 + 7614683199694761607567513771357320522896560891215582525317620218466204798420014498841517198000714225395529432437408592988810647 + 6493791813371800888731383040408467219612486147146096499615909931691397312978653723829961950808111958324158561777510444489457609 + 4673680562966535580522867179325650694242060572148395328716350087210015917993916484085808071728589768362522840828065262726854285 + 9484597285206848463033004828740831651691831183702931423669671299973340807479819361399029066256705512283915649297270684923293120 + 1714285317558703325551063623439102862882087552524008272992080310001454376923262343097189280399813634553559119888320098054640112 + 6878492562141548781762151287184309582512789444294394903670308453724775992147414690794148922865626436020007876554089383158780819 + 9151911784071444893456939300122542765400868095022473582458690303654492910301968711120089416900205538880607052645783814509878005 + 1882377638793327163743947324933816937365677683669086577608915703348630259888777501270806753764247220631643679580537815123548411 + 6272056421434812628524453496821198676269890972424881983781819205395093370536909259477553372703891212584194254740307122112225533 + 9681870026283102041075727337579428100736459914910652574617863758549452931286799490040297351890738617979595875678774646214173033 + 4185695124550535533485860637896723654154834853472854068710912474987668413470803105179616610921355620666097149488574561869489797 + 3333789216162396397679204330436931257560768258425513267401621836728579265694014546537584859527037491359360764924746663506919770 + 2081504393567373511045831331064517139188352171030907247345004840816407938277996907076471099879274974679268216987024065310558333 + 4237450865130692858281322184224268516039222037739605355087614033374925113958908332718451900205100215886486089988991485524969556 + 7929075290163499129098877300162688469599528046726233844196457006510599251899484746828484574667591829570772351512078305736672654 + 9048657921163013454470683806356852138380411128268107788272256300715016144618475970710912738205043728268553865691241054834233600 + 7029431095139361764456603528202380622931434502522594214209499225882330762428652317267948702623321489577844016464692915246359712 + 1105356646640216883904536505154508223476242075189032231521222657818953039915135319911079058876034135094530224254031516149971890 + 9040945596327638323723931073336767619159273652642403035784821558395849500879059623038153539774239738033911626241510146918039749 + 5283073188137753905883236902928531799079492225443087557262624838420087547899455213109577396225125545248301841891417389453351792 + 7168518951278682051937542342148124215459196543677153007216757499379420036959725544058917170458823956258437616459586004329579552 + 5203183504391078070063471026373757432195663011756522268894506479810617330340549685777010011742133881536309636471645529762659089 + 4854999787239813251707701121392165868052289429676407362096901868531485589830231940346048063593475645736706551014468995600111842 + 4955763538748975069385515923948951672972674499411759026560381765340448515748581186486358853253830173480680063909301824002408127 + 9640228631714593257928903905827590703526290377038235443447387587380382054598578561742893844220053769466029427853174638397427339 + 7206862882358947361070854137919196014699723353543071743024301192848154276186984110546320724917862537765542130378492262094573104 + 9132037902884622149627426018038745128067438979528182768862440252858820253995972446342211888009471423051493159698724414795710825 + 4044729478097558603438562691316366082632115863305337165834502683246949426265600257894877978230675496217762990369003197560692400 + 1914819988622085254720645203900712417397542695171367605811941681178792903669629925720096971822910923986744641852805301639652708 + 2489879698662595408916009150319958484334649360641536805110449468835050783501013718256899380316883895243102069697127104742796718 + 4988423693542042725154817443015091705766869067613353141088272355694386531680806067437655514967029170154529196712934789617792274 + 9999952996574987268331116423939940247569869095269736111023291772144901858552922926558494336795934151397996022792048113880115874 + 1453279672186008281192597269984891593458554070326190463606379023362133764652707672957322700161490484448540753367821464532839504 + 8011800610118047251507565848810514239096971840458570325653839372359200258329325658866372171001058138732560340444368314621028592 + 8193050742913890615185212677939019076499475354863399017606329114085259623153218920828787136128272822531407941969673998134066236 + 6165032662878134088891598296730315347615307351518186514382605872591152954913301540364688295560996800081490449469152762525841628 + 6574519924837827479315694440706135165231391744110344384147108151733208482344899812368417803491072197299164648305134049390042783 + 4020778253016163495293946067531529520938183648436344477015365877950549136205835548741134429268197026979922853216037833912140076 + 2560367110629307999607135522026567041549325633921424597293236948045008668100091755427842685667533245402093886980655601060106544 + 8546203408136109675436916166218885966337393842202215612854795887800951672240495314500504099192631873269330473780375743830861472 + 9788815056490265802740571039729926738317636325182129335295512619052159101153870121975439793577984106855088335077085584239297075 + 0607830196004382404188902942190311303589870612777737359147435465863424442529799140567063628056860095478745600686399779891523221 + 6451811221617351847394635729026502559474989696391694472537910902735717543356566711060840045900392940941333171363021277998101010 + 5131780001821762931334985227662541898093578808808129086254438607279239181340438600040947973426848418990057822839591824881359023 + 1781431927220093804299065870243095263893435123368341056371775420733487563878765425465471958566683414339834418118022714155686281 + 7855784526694976383147640552245153733193000678558101047345867400675345449097722230036412101539440443445801673442840764573276547 + 7277064664195765848534013590019916383557749169375559963951776576181466602296914352536749809247940247872302329782226925806468043 + 7192135649991318277247808266477765244997880386860464765070023950465490749600254005312168230797058556941811885358619067264540155 + 7745942254017380214048240376624237449522972214173349323588251697136718540827110673334670762835744617609275818957162829921297194 + 9308025524075793350930587214905796399488049433256186463627589329393236892726854692113712455277309297788479077266643487682416715 + 0884436213404481146144542589017779230742715119840784000653264872459751590076369675379177572780987987657953814990135600852985178 + 3730124530298931373240431341115710398974380360265132276809345755075936226833617497570877144367390338090832665519341170114016004 + 4487614165841966483390809601332500844989818602599615930254525814591372642009685306021109318297597415196166334778397096512192919 + 9738135052767202788355804851260065753666213740432424577877433994081030576175406007197406894692674226624886870624390536370450115 + 4972079333970854412711805268652812255100648740561624233549801666164086630826247751458218621070591048081789263645429911196722042 + 6264477153602121971771346665126521727114186506364463613567938860398188315590497953212091430368302124372365408850328299694402187 + 7096923163132078408222622634338258654575603652287595704602066710353019363339205986259588116309830845020074124235604674290929803 + 8620319232582906151287500817533307221837336344013921731345438451489042597967502976685688377786979657248449082964352894633940456 + 2338290774645460787964275902190755185934483199622353782037807590665967507775691698706742149485822727584225845398159573488959138 + 9690411512559467787285374715845943612220011261976368220307963458032917206195128934924351124238497339947198608551639030163894645 + 2522942273087160899325601687017261599086953489151039944965907240532011926664847298253352884442034273091440472287878013270485552 + 1149024375555901235741559582840384810679491209306220816791833779666244374445454015124428345163452944670223052356961455086641846 + 4911582198911887147216938492382715818668300238279079306283822841054803949022104243393368739761683072273825914099989412306146198 + 9386705286204083264591504191247314048641049210231970001783669995174466309042384199881382505454205575494098905658585266777083412 + 6597181522016787958122306510209743227930379650431716531860926286813430719462209935654406493573792531684209677728726902971780496 + 7454713877871827759953186012939103462107245349313356776395316754209733644734837949073664445059496108161795213098031298387675255 + 8608951097824554197185243937211248657800767047324365682759725200979621123783045604563185385990004228189141941283634284151650878 + 5110742662179788336448957887870922104701629467080657819437644833165127617594897707891497065965495615130086622172410875337801320 + 2393400609667414757827986008711153834467770780863121443973568354701559598965757992398836770293536284505657099974035105460765424 + 5696578078800033701889220099620389665546740070731873354278406253021517777757298261519059116566359233204858968015644380662525991 + 0719487243613892918578289524307174160805716406329931625803050285847534463223682481335815436403441752588538391995273084423051287 + 6507583132575286651290896026205391515246827860101127710478694329951379556419208073957900692792049817183622267407642643093594278 + 1377392380718866307096826670910831948575020464783957275980748872622490677834200043136176315679139636646826582155786548373039619 + 6270395893591295820132189201839068186418319333704429754904087462921395570639063307809781688462251183623162844581418406608429879 + 5043135604579355727135840436265306254474995931628655768285052525690960177800386175175072542969753822246288489006113161219380471 + 2468870042718971405890990067722938578347935929978019468025646064389136067817188723296206441343678326386730657242344326326352583 + 4850753963828793552300794217123706294629474328454245842829452531896699931041364932772984481884556840376569123447688057207356583 + 7057042541510451935323810217032483925746383540989928451101483213770975125680075200108338616874937924879361446516778250185550748 + 0832810498555353548220097752070786325088219810053096162098021215047558250904896030368053916311890910240442204298949146112466005 + 6040761853883330139655359121858985041009457655416978338162675746762113717003221699855200571002086517873586911211646864010901906 + 7256461701161490507120388412005575681572262509069280090655692691681966297281536854053796037221572903258227405845942489932658062 + 8784119159896217889610742272823513831023300901198251714365380671379756902059751391678189474782942687418296669663414454093527211 + 1713004342725426977027637006978967397759795215758374886596544583647960566243025979142738914314172995528789806147213520151545065 + 6148932160477331319836946915602714548850688076504811022908366977684207197869071392739615383347277286078886115107459496844571114 + 2443445647690017845788068401719782165485185661849045242867722200580611203950026796072201135775981201642969396670605705878495845 + 1294371619212953132417647548708472622197636506856370676160451382994700324005284453279834375908065277166478082791508699598722770 + 0053575986014268796134989286247216849523870686352637864684792640382519878279886269694672196689841813884729761559800125789968281 + 4079017492141445585825743793710894771763718871198578437956220555470157513268225528361787107561094227364687598864249537846090985 + 3335615421853085612471428388452383268898317706526014807014690533942186796242785098624189594771605450015209158202436565395838528 + 6313851017796457232684831975868577197008285743175695149676285515896251363246115689779921987378115615609824156064808941150859547 + 2765806218554516717364886537785391971358807028025829434420213828068755277959823238847926003687327479957197440099922200245318093 + 0743837871847609090197592779267491068691643664874076633968061486254606691482824855693172784961663018432092989740850414577990750 + 6025684120312451259686658587433694029989987324349789159690905104220972232002229613273265979326232104213906084669828970966380427 + 6946689887211552778830098495751925653354785324514999092963991842666284889259310987400348941690948665027526678850288865496058905 + 6762732711489921976841952967909655635081188142889946182277259409310226741889437458160117435942945024450654816897944448992096154 + 5422044978529069360644478126257492572807446085424868838210351520631277115650603746786970481265582987466949165123354295111201812 + 4211276624640084315612918421177060204230299421803486633824592006573340606615889580523464227765304350439006450951838160825473751 + 1889210243603037535646067281045805960008570285172891727145769267831573879630019508324069996866828486890146852983707941528252170 + 6433944896458400005722683036542919674416232401927258992043251760109983309622060221449241884161395267285324969554809613236559401 + 5926828496890530602862162152396620975722541268836002211191264684743325984168877494942640619948750726132999624105124012640906283 + 8437529190279374121273890161340277025282882572337700420322280964590810755716568643364840307879983400203857287989101011632690781 + 5802276041061620122710926329386353739806320420710281218622737558209391349689462899753335081329268758815057487656715890733084223 + 8915069186666442083922633115688459542249351209368361689010535548757066038294153139851377020698884275592572198938097053313533421 + 3618393873597153740469607428584632822338908997205070091595456519416863149036488990139674096344263132753025929808588767591996177 + 8414765535715090848046152050822658084473018911692025473276058620384118863100457752482347145023516317250246454398495927754913591 + 4409298010504839698734131748484717641239465901635152376312170896985346043211365815426588368753012122770591860188057761705660735 + 5937603186684235090583457539320837412342393238618817530913846014346149555309319385019839106489932216877734882102311404478731716 + 7896182092904946306296521788524236999972318921384942071102716941043024956484573567729385887708261561271188936395359650621440543 + 9381772394748371157597820184835066654518409316544350915121960781236322808659004922335381181699829103134517372303100027463245782 + 2615260350961768130102419692323579521155005867350775325462551282112894826272075572040191002407099324856614539494210810480930402 + 1838597774381264536500359028476517592435681239463143604712064430411599943084702827260512914320943321785685269655653280527187527 + 6303497221483801786682166005068915785511014637493079986822276972242808097676862236960849777047832121671397043713182928176830651 + 4198254431094795957177601291882860974299955452519675630067202852553365287181631847719984611318356336562220811004590160639271651 + 2089050062014249099555113392986787327862396528284354504971691665000330719435672605372528268724943691397193582081997337212460855 + 8717657741330116057938366732697730717547522872552360477855457981234742653137379848417305649320084599648948083741462795882532206 + 9986804236567371664160082803763334644507241277854017370156980387812678877717978239570818728942909512587707736901227099845780710 + 1187012467446764171881903676699687486363209718049359334271085642494010609014855350532206473984262423560106107436149534409159662 + 2848539362765385732985316450544140366071147981646641820740677994697597799634870260463776941968992688323272637389950097251845343 + 2181340059702615616436136969810778034448257219485660110664564303142589278244498041564775661983269433643752893242421364842071587 + 6511475958145031560867412663572535560224504744829799500512261131519166232318015397419472829178929843115481631831351152969869230 + 5907563295429072630722334129008428981723806690819380400545768764609783317272102244876794754684900328466037092277858030276039049 + 6371121545042724094475375695524854871280733127714683231595927748253222937280791764025222016369882957071507439090065827190758754 + 1326490274618829941454831367643360383905788459550667904893538378442057279259437234426288871318674319032806392619399812416955409 + 2775275011488829091588325070565060813564196841900611728756018532857865700574781000487644896468359788252916194701281784442869238 + 5475404321259151425741175250657761031096608313986258427026901467928877964154516924617882931075782136380173762818340243425882456 + 8098506275539721604499982773326806644420333816118778369209316210417120818431663778002427348509174034183157653013145092651819004 + 3184928471078890543345386093573923680647427432807794321314997911033358058808825224490515008557540951525337845495688169454435522 + 2663993815050031607786993170355950506772886776860845172901406916363156294602197804936561148186445731375733299997098917913770308 + 9652206542382536216286608096098963262843138133196068261154952924480494400928138047212132673039123404498669742532274932056703877 + 0803886057269071094490544437295692503919136095718722047240291609927251689451657849380414877514143018375735518559305335464120670 + 0151936480170888759767939879997438315844081206201757776198680712499035405650084830184555439755477818487911581690050566831394218 + 6229367230673286153903588882341483871782570684557378319370079577894075314574849976163949953230620503498800993353619885098682722 + 0775734990307483598683533921005381003594918538823910337693583925400749988570440308274068133400598419503446320537735625031687287 + 2279164484478563946971740937436182665660391281989609876479617857522997660917074445342075564734477309946731477007826609533166522 + 3758123683039815493345731508244661356741376276550143129350958441510802897891765417564525850067802663207435432004216770694226804 + 5619370786333060777254420771287566622455383721762137194440628363338996839313233289419808657699323597544032060605130001017679348 + 1117350732097568268814555936831091979923626150476679569711035279777989299558634893220687598099570940599334574372587146302188862 + 7465078440908857228369280211059007709404158916443923372217270156208307015594931088483508995735817533317081734115339967063512432 + 0277551433478001259984748926007853394677528181409165584238991766092184666080139589261333280556946872045412337141801061054086949 + 0700754560549557192840941960533883683916477333049889110496053434388836650044089728945956844381845980096615663986249384912038818 + 1729833498846421646108320742580046475400334773592611265395391377127688594599285540845684396076777993728243626683212706942573378 + 4323511472129830807288869567946309250674678068275114664508496611904796208234885435751853338278854135085398181237686024172180393 + 1312943548505486065871582599174831836548648084308970713256187466678464307897110260321658188877464727357499093515658589884692245 + 7139584610276191442567513021000360376560327542398104492743671139951823728316211591532169872633220764756742780779371664542606277 + 8013300125828426771757381146217871760111879193645766888697436656318066675243280906292568248974540959337990973627561398675008197 + 5419373124232954726590126551016645137142696380830673731392642951542537238565961064580394978042654467730915963421765890733361548 + 8922925533382884854249653772799918390864697404746308525228860651400300505857310156341812355891928439789989969029099008533806665 + 0128219411137135309941467559688405403979836275303036131774092714874831957845954239946311223981403764141665925425006138193699503 + 4023035360745761142363755560440975222622652382698883967356728120684964102122995320575139970015373461400690787473496703365503109 + 2193654449177213661881030975620088565679413977376323484863510871705861613106991010472484286534395967108522932664799263272973605 + 1651932770511765948726250021128129739307128956256839990590743197977037091662728274789578774568077274689428101918180304889077378 + 5017924617218629587957879829522315523692604428645809008208520226544692314383658761425382226132125228054011492055441635314272210 + 6749666157481037578188762106676697225815856020636806090419991079970372071289788209874954711658011019178097283297120172931963024 + 3867624578607959056494862536265389313506274108084087969185322137028561490827818437756426384470803080867883480797295503488443754 + 0266755732085811371635896735784706558323514361613693558482118358007540674486152236347627273339110326422500120960164943514979392 + 5851591583094022546650594344855608619956936942520965617453776819147723734709318492888126759979035908706037791854416714517089588 + 7488779820804386679237327683610073367094612676999550051056279635818725821831859618176236859057491859294403215135785905001415728 + 3397867405536078184923760377846341551636533657104459673180071634565287960125731400588939475716477977856211995657191117602660471 + 6368419292461966253403926350187375212915416793685707098775001247308325202429711397391995493844090131420300451991006099818565158 + 3171884061798508018743336874067220372374917564318502076615548912819919624484325005878069566693150527749974672352053137075239471 + 6765298415501192506923578604075674679460732604669110708523132941578157177568853063216936080050749029655642031375231708316371762 + 3941656184595817536876952668926168956461631341364895778129612449325569155094729678326528659230305783051788455638170048468709384 + 9344704062107618220092102502671070488066523904860951808964071896990152691743696929206393427492236495869384495623953241985933433 + 2329954473357680885309244441022618801570174231106127708621760839070677029891079166854592191885991850284207932518637882898896696 + 2253197905988134418498970803242763736997197997987724202146481273276883471048373064146605033007993208986500108914474101742235859 + 4471673346443282932636516218151183887721959139730007987788845685281052854907139082610271978365656275535187015151917676999391516 + 1490454357895502187362105850833658593130025904397280081248261243837433753996643256759896119495710470799362993945917928340275859 + 4187480193910225053682324326478852139878506761849860931936128187212907303727615513834095500089467988300420504891523377586019041 + 2552835341088538861109696869815032626256269959324139802181242249722241877212898021098564840649196902417063584333206994390607317 + 1538928060054617317449920025668989345408124114562616395808759769278572186743963855933221653177548947045222630757626854233433755 + 5185848360760696218717214816135397052477034052026614446970415328439572221368707488898468973353428786860987024947961924953899839 + 2985590716831731870038599668250152561736463733069492744631154471689685148003517537536069537952391933185169671069870236035572482 + 0858819385615354860719000425698572982937868475649379251912477519089804489107469755432874178918458772943168929318750385686530082 + 4333886362870957848081259613648289163828064171655224322239708870842553708643760011978783227657321411272976905508646641961780912 + 2833169683733846355069467452629978104797868384861004576520122658047677739451418977045812632716306848990938028931383957425588061 + 6045777379942977654526927417023844498064089452756699867598470436037381168815462649457696613017471951809000988548875034178737874 + 9160331824383077463591927113486291567227954453778702317129507491730495740733772073822607464672707613182092741352901404225499494 + 2171629178354382148962537134449119312001738349076684871759101972177169632459401670960405086152157843086489006781537667287047896 + 5465718260392150704046827088996611582230320415786650066647900151553492798388495126103785840394545507668150495076747239741124643 + 1419544523318047856148530079232229449051190304992694484547233964026124081035121194889038106213961089629592355710172833338936041 + 5735074574334557161220421706612819925561806730824425800383474349667304718298810588448596848386045836391940535442755152772209476 + 4477743831927353467775816826229193246462805293097367869721250682503407993182691455177890744118461259199550137591872314970843570 + 9614009267031215091375702771630372739884751484563943485109876681877458872527820916316860531787616767154557713108421464243252888 + 5725244451595751926785755645396186934606833650722629688279447836080615920686865486122499155337740847620671316549690747377719416 + 9886724243384291436035548475563689452903302006875551792856774087989888845839795026561561511158603968657727537570783565987096483 + 4338269257625836943750609173139824275314999458619895874921046346622761766613817248643045610302260828228899586867769128173831852 + 1927251435241586742325643335703829021262110618516121300640702167056777723519853174450793473043913595814696522118527504244796457 + 3599578411448167894106533981801012494310659214850381649569414007781396645447499689729938374104814729448345077680781325687345087 + 6129529633831819171439689515282408943585760656344118595138870514119273973014358876594274788901442968142994742135926265337385656 + 2522744449484255252321589542733596606602045925005526885282459116039248444399754430448309551058351839870771919853241700908753171 + 8095397674156020153025647112643503525783203561945051043117484225509753196255050991995918313572389826508756030729780202503607157 + 0514732746209410237098921106270758705122238404358107693018072790601247661147289735400790334022315641411924147791473123654604067 + 2183481353624169330708810250088442996270202852800382852132922090252387617856118236197486397057001588957700864557493511482566082 + 0159554686938426672550427425422201760923684567404107605954807954862252513544057244716697622930133085009155635119267747535809775 + 1603870374074406842079458547774759610733574985005768921583657069449807861035511349884403260777475545081121567326386609338253275 + 2866478551802452645398860404273568244013340206033503958336009745540839717584645607628126532817660071722429335530485083943886111 + 4372806755879104949087031501622642625790498233747556727536449464577828956704936323795941826197457122033168971930280473743209480 + 3510521745467987614604622504324811929598409501462197588604391588467606320835512728358214802216357643065451820237801293132895101 + 8869176817884529359989957422435201680723727230870849702923220814297956988224073755455624237386035731957272496882413670632312027 + 4987041709615070926110617696999725204352784063869478762637421619822949085893727644701242995534552198616152209092394050930669848 + 7400973738218421741284556096408600962957422728138542260382229658265717929340410249216494966480842797114656043729408022372140555 + 5357622280419421430680077268491817179160449030679507850055675685514803114136633487732178706581280425610186327901499849008080553 + 2063614935667238312237638365326101007587181929899519898020565403780654677915752203035463564958973934599571280127628650025231204 + 7510339610097271890758575355760181313472729121504677949019841665976993380277166759244310422659174282752504901557558455360101043 + 6704624590746564335785852066839780043541376118703961641315331313655337920280405840841448353766789935381787637277026193365826955 + 5718584531080420228299782199614112550723022759714938401551695221278973774269123526563402857239118115571007974128747966574892058 + 7406616537246908705363274038771943716880888382315653131428051669734785136535017075892856676521312977758275400592055721561155447 + 8191030503034523458658590430731690106155340044400945735308786298326190302983231623869556707507267012762969572969229893222326020 + 2781627756283482808592633115010135954787388098836449433663074354764942592857302479394320001436105974173300167981736974256889069 + 0749889909665269146510382674032370824445149525831032970035921874308716508078712017288693000420564774687445800320014347768102977 + 9500582955080504298493442003839451470653349230762999448413032412395803444854529134420395637374428892260393652466859653474793248 + 5578683404816116099839255848388989533623282136956100112356341602163894219640627502458957004434668830525937659394378712613593339 + 1328818081682559186294868249152029912791110338139114004470380993085670292745974492137182403037306610656137695392960137614180452 + 9752978688889728250401766859342517990190156836045937377483717028864519242478723992053825465496992411244434140736698055778811865 + 5764034558119091657996034001136138512460220698471156208113839665880299241195462026376651406117658603193270831455055313097779290 + 8887190533917978952783942478895262358255953083684956216049958401478271139454139129915935858174062762845986202401574727546757519 + 9965112384492455902741039666831644918325589401840520355227650968749201419553213336728867559952057316374095495633674649247673155 + 6547477349678905420240149432846633096396537735337479158019850832661246628844505249719392841713290257003652108726047676880419068 + 4709595063724483081528398865202332209399887790016225322294096330311019868576291990108551198704968033034014495019187100300731545 + 3677983555491782274707240632393630038558613476413675438434221141668472183743225033730344641440692723378405837243484642959062746 + 5604991163272359834040422515862505640037839519050818603112192411600677144216422234215431187611787844494127075718764452791848799 + 4854476179924301594123281798645361490338402536310431288082224776520403651635476604940174850365038818289755315902382966023203577 + 0810744335357702561567797304986145218660883831691187353402861163846458499952189536879044115452318681728624510324860015033788398 + 3979771283995380891938289539381044182171976827997056764348788204187193621090041996206584024348644400402675325221299998818648561 + 8560553235856018013965529605400965645682933039991913219712272084018424710938107420465401522172404020985846364794336906931979136 + 4463662321945447989909156167276620401617659159053053338198477063314745749076987397606793494767276193523264007206178167936213596 + 6945045570777520341473278974105523918485559285787445842507870137014286454851350178004328369233461521852484045058748849569462881 + 7175394733133381132769602280613000317015438488548919976504824538838731947546613872200764083627777984989422833194236427886436510 + 6841401583932488101726607361270514543381198032082148492961394207816779730163687527133913837138426969504533356370971942113680465 + 7438297763442758000905394998453798098283316097089007654200747461809281986645383560583766595972712154827834692097585224878349332 + 9365726487547590990433290508632050107564671461069290060500347861396555664994103630437491491318643117772003180597703910105848664 + 6611643426610581687045714856705413399193072506247927181637882082436528718891021527134176567154185837899481317325358321239700678 + 1557904502034099580005949862058754523860889792700842593217321816597173581797908357156234792521428404814333336278006477527454771 + 5551300020237036342120897324580866490216118116991149735001002790662102209629270626643498774459628186650438561401066616780089887 + 6490963755355736580386978526346909059361347064280111211229508805478817906115930155049278075845715671257641653870466615953910939 + 5214778972551839841667874021257601195235129654518890488743898996335333591775608284908553206841411120044347642321931257964395096 + 5963500480745033263837415489981452116756935833729630104233601643805643301868453891208377454731826714298746739883158478178624208 + 8078825488224820778954240186836158374373671746556003072588357835036884385547573916766540198508057742745190671930027702184464479 + 7807519854130748159210155879811678899722270728200599689770154189194726372412310007746266228667023082290285051427818296004435318 + 8849779730758648974379073101178990211676693852201291929217145528640734853429497077571161674011066495817276757324157483849716817 + 3827352998411927949530005101476246283441759897176637008058185334546170312583858564041585383266413483217734023667361663656510262 + 4989459887640993845875939547459055523785574975836774839383442442772727790780196274204446558595371067248953971633261788681833422 + 1430260652446882399259326117845029992780579944482914613560754920430392419419801174119306529200876322246749783122971752437529985 + 1073402550916699040362018956704245437401832452382196705545206547444352132288265525961915924743830388330363555452775455714221746 + 1446616034452999060536906307198084433181209978784238878045014349105221877679941993115397416711191417693894301857690745032510836 + 2955390019036983033546377278387952218996955027373523655965784118029086980123579985775681000785897246210289721704232358897262443 + 1116899333926038276430989136011993311064835969966384464160468735201645112827713375177166600414004561963808951457633980244174631 + 3365167597668328545027411315066184915713562624842225290359331084124729347322094220584503855828183282959730835678676639554531692 + 3703132630286521554741077336255711977522731641435705473997030102644612053700886241315456330580773390018414386585814426113751822 + 9217494111509421272989272558690493322060649433443466464859990829891612802636240902558280843106767641519024486333577210250455758 + 1991150751561946927232491146002439007601543254992434751580119323409611022604175456900099304707614992483865118197257172247468485 + 4718289269042762658615396540607439436267108037664826892947523927247548349191063673761417193077849996352799507438421286155035753 + 3670003174685490297784963434080516316824119943018705327982929605778412196093833118187456471893403114829335230172542023511761918 + 3530299462397538994353624879221057016014513591355266971800473995195599575301873296387357918288523036075230002667564181209941862 + 5652465756063919538830640228613516853681348031923008502389424015416629283480087157633179737963541694567718976270634283296698772 + 0628398273786061322495772855081114777882254155541640367813109541283460927308493462443462004237680494256941289350455650052190389 + 6530923425528750248516830645859529161548508001636146477492907827739674571658452569696309864671893300056851989854105052764500328 + 6377838408857911124605696723808145124469491655188029699697020610066790779133275460162800601521823852930699312176096876169139587 + 0939964825101402137367079294180090650010316165686145129739428563266232844352675969324123159076365905057635263730951535508592474 + 1811804823447992196520518580949056544426238843325335935996032408627339563545875884333166832898448807558706376176980463476019811 + 1853671195949445539340843650229575714750539986544526174232405759132358558190475375028485355385394868549681406717987759935904458 + 0905656451763972780540932190579104438556329939472118207647554428546869843074735432587357981463196272333295652269129883611649971 + 8081235587163561191593283995607470950948702816215035438010567011848029435878836700192088876498542980088266248768136664360732349 + 9048395346539903256416069243232533610069691095414640231288922049229368354092313481960519237230458713935632653201847905841902926 + 3586899375981532151071970206889742452371614510846757239619094223086588901204291404135214382914427118575565088049023826713070734 + 2259183814776114935570816268571424671175423119794189492522671432476564901966405647187984087627618260356094922535155595764746633 + 8775939779211866982932257974707044029673787248018990390269181484731175023868082868637570701885688930003111950730117366747034776 + 7292037040878433775921745075599110933471784681597260046655966261287697859339714368407310137037826533774841074326027111292219013 + 0255740507228750627788675142293353045696200562639503837065555027761345191438643278181859657112500994447007605647817675710357329 + 2976075331061106900800437561657304517961915727589721564040507512613786451696450429048216474153539650176719572123959448008900012 + 3408433706045747990792868143612079234278596536479367304972783738238238625919742682436942402201332632706821698633101418726786131 + 8375660756604324838036937822438189146692980841058943655646096987446498055875487503182581651007976496878268593478897138465125407 + 0302161625788138941756180586844882835162635784547013096553214201480525116709804815394793585124634598219195269074280104207728072 + 4667838900407600665351205946634451166183916253892825653381319301710998507256107777186848085957403008238368100522944303632213848 + 0568234978451633682200113830676859774853569376506354250671989943595147694543341125278943952146653132296950198184251693558754266 + 0837997184654618266464229835853893240382511414642926848175904359357425914225875122515607126936089890130506925127703951001817058 + 7698607971927804322206607636649779969047920064098738740542516881736563449825854806194526365935192809082449412467250570813092077 + 7597321887811111154968364298503454292989382990719881362442172931187037500402048057328677657705369081382090672410230632333022578 + 5702691344767100466202486216169170905325756285673048601355109036801723677816257513289352210067825399512675664902709627155754391 + 9534899164623786842509061739505443727104012615679366121874758009252764781464695793453679090140639672566086270483355150124722338 + 3629599380125790239429932208245186801604452556987851483665390481177058173633973798236252529147955843797090679456499291551397899 + 1654839141753372209578242837530384383897899016697607163271741042796206564645006293555562819243718356635356102675076651792712069 + 0330578183767799422174048823749345411130436371482070584047136107077445803065143356378310883097325525812461948426463818958359831 + 0535837083229949247061916351323305805073161284351843348700635104127671026579915150619625693973299904452300157134992421628495782 + 9135533592025422741289488252334208635046166354163256661447685205945401888767478319569656787569357811074256962118550453119004362 + 9301751134736346294356523345255306657038167822211402293117443464784840025659169376501953957672727051530179579688902595680131766 + 2105969846665539329882900056874716520798786759023512793122449365556804018453805656203040461898429839786920406056455733868681013 + 8994359707951012841246179634189829024194191300675090705148350390247850109295388787831386650321294752877084504137894482370739618 + 9241947230769626839032573755018849701961689378840022528468670515360403514925600595045782712624516468191893178057825723173315417 + 0398704518600034083166938112120280977963993296425790225059839016038745051472686938943167918298644018861694001602670324180907739 + 2829253174521666979009820015551029220993105373115142695444414232286946938928961493390386858301002697320226848958500348592987936 + 4933376341875898717948810316592654389756790528913140902980810511129982071300880573916140408222881362220907631175682400695211957 + 2728405831786952505365442116971677026094675638127255014104635321119617454191227198408175192550442007477181962648595382032863011 + 3335513609023390087365324523236604049358730860336918649941016742564809500323096143070248679219333226141951672644858949079743290 + 2564143013685722767288600853878709769356311565059463598251742499173323941411533573854915762183775988798690410191696639340413240 + 0493448733483595346076056156947860868081377709049727106924154044343435604871736849228001533150906569243527614792377672885378205 + 5757247991130415486385859064419869200094851432494013487858837812428585929428086640566084149796652609672519627454844564932256297 + 4669558478660881121021903646645372020041434507907448258764267056511994202274610206718051374682457426295364768694292186976277202 + 1564360996091464350826834839280932166253903015206256531264131271209638480781609315412345487344374301996139188255108960560840234 + 9176534815648639973257109408451729832095062649822000160147163265683826755303899059727567592934572490764864402347275743547218198 + 1866055495605517210298107031806201932208987305284317169767415130763125409722583393741250961695800822861253047933789380082578910 + 7563809612558319699283127796207634523042191451596228205984495682290513031662522019531400901314878626864267750108819514332947951 + 6013217317646435086018804719571761416592333129643806900438788455325630320446510012694647580590342912656641492584092556696246675 + 0844610636935384963725961540456988648961187114742364338486232200258126457044861826644153851981432318719173242496404738484829592 + 3080829363782082227074488901159023270312983944302028828324523976099006110195688729810726298266450333348633619065288392022236229 + 8005690472921247866581261895577036104640057531331680489329654614207889686295106419176764455962025382611644995861348654828098933 + 8502321967575148172006469677676125932579572402208147927471694132908710196626265784804209764246638587086749717612279459712731943 + 8253507041283227562754413288994720899007749153170225893148651683553291625294974124954074490050789574119491844797138467527966227 + 0130509196073119104402816135401821552059355465255575401457469499625193746950815086568670490180348072693785487568778765124602003 + 0665248124119376664057125582265850335568981888916788294854156077917276025925880496268355143677289608433935345978812154208855268 + 8995137970182597573167629723687168196388018417038021858197249313810312106750976993518701591284371821222304917627037046364482239 + 3380163047424234535936046961259910243886634603953810906816744443879125914109276466757734603864050055610106148478096732039481501 + 0050863632424997195774488430947153709833716798293363139764056905080948883372556055175360309201107604690863026027029304809129018 + 3159045522676282622055741762907017038764983291766901157880220174438440331565498671114637842462602216932285417970008975756029800 + 3552237063449291059014349162828946704972597219745549772402644156576458713144836954411568696563098211658803621586740322438123527 + 8553792749167921622407818214329886287689794104816641507269131593430918574387850051670847355476478466155909359159406347347073422 + 4529077230987714405406119382703861571668341576429308147647968381984164008665288474312273798880569173169482210427510225857144151 + 6873466267196323702969428729542596817149488353193513581368049814798979078196465830515246880993440065883452528995023407220294628 + 3423764900702625807926494346022071251875105005653050523263476206366063134157656968651581937910705560688575444683225925304492434 + 2952113637739291573792177591055762311484591345740602655920022962868733639951191003783483933798477891209504511076833970415208477 + 5918285063915228730571970492875778946493408022023485280196322884176264848374770469091671934052402742006902024842930375953314997 + 0188283754328437589051211543538670804314085522712102214064193375644277314824255259794129098802312806481056628400349306174297818 + 7400374465412082001463306963438819366261869661341067811137716763449961651069723995940239925017934226230532596999220744932707685 + 6210672490680638537370704393760193333970297977253365672997212980801329671424210333810500664050546692669173806880821364438329547 + 0441850655848799432631375117017035628999017015487913470494267041654835295714453029034648907258088418618148803149605119491595378 + 0667709470097778550996561398901373747557627918533058120957567808028277879620594852014529739234370013800886373620787541449928329 + 3125515897530266841998191196333295200100578758020333846745697177799969213733901430202219148194889600422499239512275441137216920 + 5650415027342249979224454839045392096843643602822206652387425455763721764312986203030589819856297909492941454232871627676382600 + 9334860923952422719693805188600329744718934283065130982713900165662458916981874159673444880197331666542991521443060535788337790 + 2260464469972488038180467803562022523783671731570132720326212442908194344858555602668263231905684505806559421525279834670049624 + 7792295078720351079690690721334629651981883246931635344717773193932081371713539221551527543695110154112122644215377568071412160 + 9195473483543180179899660415512485164196998646076213127620507751563271324222304453084630241541418631528227182134165081602418516 + 6107199131518105376224811112336028754695240510430182476876463353393744511821873843541677824666782764783493452855094114804483949 + 4681701662176678506643507046144062278379351438997367570137464357422720669913574736380880061893275748247043675527436431955366100 + 7149553832033242764660394022295041894654956152213899886346680985491273200086975419330405272293533518246991447255727068177450390 + 3655198436587622677364860349928319378663047397528676907239140945275682820405657108502041392682979560846597921188888907265931036 + 6476533442276806500783053564071177712515831376234094631885310570178318133342242810813665266902989059805523937906419013727894188 + 5431372487274298724777517697230193875880937677668764659986523658830811826735084723524757461022654674192380627828684371745612348 + 3820846618376083469895407196241963862417850743410179248545973893510278183277393709562656195366243761330452232662018800107769440 + 2069720833072682115347026542393190511365870201586051736004598121210837565385863777323843786272509797134422300430192141780468920 + 0442031082909423594641218252063553777303614020588281829250848330051744891712248697144729676289337492695365177253047051776547762 + 7268639820077382077506959745238922291525171731315329144119549984484846531136030620064784882237444115815092112452964098100945835 + 9872606636855509027099907122315750101939814965155251567403611737103452272009598076995597635176083234788901670535978209531433759 + 1085327638195333244518594079295886331726523118261222009427508754702667381643585015276186491128806622593525832828640622269002176 + 8000558812466886549021793247340135947691306446427709528028498200426365682563584527832696795214569479985794618339152398807896264 + 6187988847312530289136504030984674599402925257102785831329312431749794271223626066515601194350356075536808657593446997124519277 + 8221593778261506773470868068030158332034878924556789236087379527748372902142937754401272228850387450354124993708739623158789162 + 0522225048132576688432285718958345124544338046135042578516691967468794904627442698787375554323557096004260191198734997094093259 + 2462493092358156921232365706546429643442698260566011347797207644508552329524610339812245114706710736520675636593241151933904714 + 8168806409481440220552654041925492552985114821706878419857282323004033916474011864732600044228285384350058041710798941857144196 + 8456183927145192331984325229219292792322346278563254801756089348717336352552507588302857665733398806159165657708323657950532344 + 7959027432654889449179694030583164431534165468437531025326379868797173494533488353046359898220027884040904102921916878818230634 + 1572671474039612214962772842653777925720919829404267236601529791378862012346769450214240286963754895280462160430824808649254296 + 2713235643749557564532205594282964657763877791499599519104896455051738725475670902079776954156280521778944415643098383791627273 + 6105964254598123007279257593697900824845572590247120355844905046052760198392683039070579501029336629655707492386250995234644336 + 2615762358163929247483738668566291188631481608731204506773561888479176007728316484171079619334578564058039995926257045933155309 + 9915284962226636771930258072321745421222389817234966851925987744510291810977458517680205953227386190750476782698954854970577352 + 5673578687374046860672064496277781044455548859373704110716891640260365042726694184132711815871762240294031220477588483951772686 + 8668728817231201425334885333412781573848400038328099971193361147160493544335456580227648349461318031327984792185171580102807503 + 0169567182553246331404084202997183149669206523460201655479386533242862563036582654644409484005992680312894606697548079677284436 + 2408634459821807360135371085559754639951676453609356475891807606645289547821918227592956096670383760258316085039325249167270345 + 0639753426126492725051857242781368140995333223012553263382165242568922620303770347983405643905206504900791961601071942284936427 + 0871588895354801816598052309754202243843057099627863238724184518284044817748295192358320828895054008513930794283973928514112196 + 9798654324310664456635488952439998180995428408476235283937134417681364575355417817510233366035067348678178856527757300827180944 + 0038123007290989063863175985592778519488056333171045377703085872568160778246582018586168915869948568385646644298618780983546355 + 7869384600764512734048062223566504717806018441987433044570169614606144975153300488119826197625737171672582011169222743563965980 + 6977293818241046999651425289984525444775996710580402650890897413638457082477468109575400763448366802872239506128418904706794072 + 5799904603862986594106662322483455329279349540532965537255861860553280872874108710364305979053889159756036410545175996560632213 + 1905113425852351684154357685504469533745516493501062212340862826870385326709406031686063551224557399310052952422838419329227931 + 7546871961833002037605725905779115533289685288706841277287949763530450546184456445185142124516259820881277398739985868903009290 + 5390552777664596373149764240028438950449670876087502765011571015373476441820757391918243018050536384628502031771242890575429423 + 5602898175403670523511959645093602460733826479169195731008780332981500631244059144423791577718260284080812356359230721779826632 + 0282070388225563293057775488479437333861437827295440192975141284220068554470734762243654683900921775316128776798676828649464561 + 7044919729960370651911034098935618095727733916533962937362197410606374931103363062973825850629444853848346339446960413652519614 + 7923852433886365419446901963455158024361204561948757781294971510735411634498000899993250692952771388573089449720039510778006556 + 6448339128502198442312788117252393804187619178631365039260121533649897690132658417974431016238776431953884429473283621621760928 + 4796673454480093007496675559950785558242785307210144883418877108437084521237518409035829359990440607609053004656855467826840969 + 2539967222010309449705096804270772495367746726394308555148839954759386392982542739753442093370829925036983594533194718249508227 + 5349079635800249074525176724894658939051245265345143033311987922668779171808073614407324686649849960572890952798590407394876104 + 8881074380416317599148271017700792806364855765066986663556628051754736630602571628284291106232498605571402693983906331712030753 + 9874937506608818776772074340810498838067037288381814044995123846119534641571274807743575095446827709625774292925956993651483030 + 1351712538266765203986454072646816009684736475838189392745470191271779327758375268068178391759551780428792430541942252314370156 + 8407859484892460620078868667802179357348492180685724246644370230014476781983275135684947107880402240406891839259873980451085903 + 4906163533191850256268583682454988749837419823578079473319346296433799092047235338380155019552271132115175763259341940167374009 + 0058465924482070913500147064727037054124622100326796664614046484792704959337155884709332716325316023891570424872580884952438266 + 2436800291590505288180953642913700972896437288014085488105811040747638787748114199225450616098949678241069300416404785919318926 + 1934599170792002326313718708164205938810092585230289681773510059324899654472028348104884160918328871998687720554532160558923223 + 2833310668093246151983045850009608661418327316614685260920047242208439507520352050936476946684777115573214252016051709311522733 + 5806306154432125296361988853844471579270461201267503074861984238054921903008010783021332277527690547871326604862832931571535476 + 6953887201338700880983597387777946758689636635028887005208234910693065403037992011989492126099118102129494636864406808581750418 + 8449828487903174265578895543349223421139970247142747092518020699819810023484608128979286359504168816826179123882092074937458466 + 8429190917143583035383484835202769619898592015997875633392860989349020465819040052129531463007708159553740489427112502433350259 + 0015541288911157030703391088218525575081861192862772160417721389983310098584001488671913042391958271599517521875772879817883670 + 8715721723667422477987285388090627370795114420296274720333968016528373376502351404697409435351445641183117232448408900877983999 + 8085119600169893659072473239891529571989304915800525658372770589231187553832358134049724486998092398100951195327740893124363904 + 6825971614998820258858203237294363381385260403003703481866209020749805588161211696398124406863222077112906818160524737133236376 + 4791287439396340287050946270382309108183116290058907007033269789030152170762597022242414148156450382489069745048352057183456698 + 7699407910303700018163871163387977417734630895740976320842794125644044206230844211892365927545147294624099819954065586859396532 + 3131672188768311610064467750350104984282723151135474654890501043106825950749943883966630006426594607652504022624213316206819824 + 2381097970942205624530028578508606408894416081148567879895026246182144217645044116693226312513033539646866882479709987958089969 + 8906558060289356651604127285059333055318644242901255378341192868378040612451560944688746385088366187655524363293058496259834503 + 6045783943499511329380195312503328218913377235931966010737751685331040259612353101709972563764048165640905281453608759750462107 + 2697778235378791219808122722229257971170129904297461026446932149333464400232434190909889478146390656698937276924878791295257123 + 2803907707992452534631676946969649948134841465957319668276815925648168701088565169944440306293458637327427324437179025248962792 + 4731713616143649458304003973798123909714421863335575637937266819992047643342146589405067966192841049385855050988705354679370809 + 5372002945727744156997261317197525282324231196500161732336217784763019914950265863384886596392669097800628799874734609235337063 + 0503789478310331174915570738552836640716185310681333898360502850585012405514745303614418697185463616197057663173866523087604838 + 0675037169916204490298120588020089851962810662807481941976840354009840553886735946987601156791667665686995459100468477453975696 + 6834794049663185275577105102245452812771387897018848470724588835525127031721746222497385677737902506111966509521044773531500357 + 5329174285407427305661763207997349560549428910454568831186538339414510256938492615597532037011523362904523476314189986503671291 + 2718934812220309630578226399896956440076865897466517017205703733213982937662658920267819470286608114781834913036578565065677437 + 0292082835411024840424424503720769844545589088751119682651139453690649901159394940442554457210310520610468908232856172200322893 + 2168944494860484191151489757452268440986053558799687398611861491809004454116677153114993411395893222172780575772632409234094898 + 0022046237220608888434835342573839194475118566063006131560443847533169495969846042538404623478526559762435571079702487933385421 + 2451919192203771937523596048769324041291130793137730493766482430142235410357050813575163787479425148259744336129889104511577631 + 4142550759732390528563707063152034344178846568888223418447224601319163578533878251799463243956174732623278426810354689051255154 + 3970640202120158350260730117870456696154229567633606514596475612129033212370234978048801831781364493706668262862093481931515716 + 6561924140099494620364526936808552193114041143469574838371934269300545161105733392695711211423415123016324534422409169998476243 + 2456534483029530345127697481939835893243537886692901492470290039455511175154304300500928667293566968811328935461117311498383274 + 7770989718625939764088550940976599710169478296655836026852130278698487150688281647540447530622442916288092929799874814879443957 + 9848763764198437026743206591847265528425238321090574928951078930719540533808196681934811602035009442951951047723353414154858302 + 5787946077159159168774450433330444862738778849768023490388074911496672265084989382578533753038885946437129868548176233233930301 + 8580017107399342108923739552269357825947129658651850931301283981215557531809779053507136238066452267893979878894161383251981836 + 9913766525707178278575810543038685579648619267169136094328824697618419625108889858389235878109542078438921757522374605654744287 + 4829229647563208502985033637245591132219509835319418276937992741995767258780935271942567981080789563695276467555561800638017448 + 1643138233933525491385701115282638884356620775214978523597941747167932566311974729439511528404991306505854174907409034566035713 + 6143827997778747391148759316186369744390378766441792907186485522361511087226349625577289271875444080879557771349971812896783921 + 8151037464162282243454432112145953184331053916340169687740205103102595400733446898088691425582734935373310066807019088114280263 + 8729904943075565576008704186063345542320788733990798433124383054387825974302546390620173375209936756748717665874520884924479185 + 9888909645307351789982700065033105216388788398262734159940626037880383673919937047828435841493103609687935677331602519191613414 + 8850737384099163846794178899558085730334694261907207404022320796803770107876986360807427894048245601008966306481139963465178636 + 9603978263464022093387313902323305847024620528667574592309994157800256182557220046954796119376040712963053063896476690374286989 + 3405947975994172973640043088019552492100802303545308377567580689104604977659913539104938989315677959717470803854511462658064563 + 3191162645413432233404183050706031855638390349798393321645475424393193065096426473922012746067572812705091078572123464528104522 + 5754070330806062132016998542325199869791387417374085617357171312577717425296247007640670351991232446756043415004205160478899347 + 1725194535387949369475223998736399458938442651506418282232173272224426998356393475616690357433350683532939697909185050724112276 + 1531609961298179460965979011464443408544699180131732903518616680630569852510445519164321486062756903290742218453214665562625462 + 4277461038526097907874522581743597670466704734455633690080575913829222964025366450929288253518473640288917518499198469245997685 + 7420143434734074307744766434941598412413533864920547945213441905542326713457623437002740516606230037868321117285609425877483514 + 5509703411252690324400121230820675240247540075031296148576782911392574907974824839505516956261324207298130826703943230789524466 + 6235427271350178310739006810179034776823843871399578101065895786301705049659021548642844679899589499916930305008178597329009228 + 8708376738514576473422684695199014327164139367786002985515660277291737951903297112627302613852418677997201436504553518932602363 + 9576506417537859055584148204389221076679317163739081159093922729562344633399336320523856409926599959155324451664857304036979342 + 7821519375657055506931717396389844553686714012907465431386872822303418480617283652851337727643122589592938283893016029851450741 + 4046931470136635022512650864971382510668763279223722442081085741561189482186827034926915081819290103926309450155161557982601266 + 4715454308438516658794722092196206636934007267582801367477453071665674490724227142539801920570519231994847446963269786268119916 + 9168041401535492095223153393392138627537574429611826175866774713151956729343684934892542983754029148830727112711391973335239513 + 6515970901191127073416539618442535739664555006336299291335206114647465786032988393861387837528101930282563813184667131516357399 + 6965025115159934457674823672748261872585621777883115554117585206762204650484234255271173958058407125541367807442514328611570278 + 4831064230665616198380860322957982656881003885916660535633639193463684058409926839010861838915803748651536627056017889319571392 + 2850377483892889368048618651662404196455568541580082178826055899571765132140934322132515590245447090853398672580050380575567268 + 3835035801788676880902622563977805200108581423258706942731469718506605351522050771195525463348620059942550507473397926975656075 + 8170641249931936194409801838731827726032358290235160889838261562910412201128942409820711534658779929527668900047257962358847821 + 3914141889006189906618830872826326907793134446571712010041037077410013305523598603376182060668984447359850821728080727595426748 + 0524288363005399115153078597028593878897064055724890623451683531614421839812503951731500983120346087995189240459208148107096125 + 4155453406508028056687037448768955586471685200246991147018630064209861444093780513311415335160348800209398873165630411940689888 + 6507947702834259046810555837139361937816955993601288388902706347465220128545880169696095175041923698015462911423095653174399855 + 3762547022058799188111929405215622052455625552628888943381861262479627747983891009023031983537685246888772136743333720092806316 + 1214549690057757944760791464294073960482795674578197576015074847454616235022841464586043262062684847644609779311315421146732973 + 8541338437296411555067873828147460205050118794445175546707442427376724688646895066999337376018755680130878200128406968859847082 + 9053903102817499105181101245913670467308052365562812081988351351621302283720868904030918069105268441314194378171102376175885834 + 7390879175657202991792721024454048282348887367327525251428650799473344325817058656761335824140200255463527106801978883972849023 + 9114858631082305511415208423205161099795092979957887353079774012813446208145355233313207283275642795951235302177270570702859527 + 9437270466650300884205636449007422609778006468400075137707364599220020468818147412256802671321760977139033664343323597425197602 + 0302618076580610803854795974063518981909366239035024103586093127902225268380234904318024257226627138837362185766291678782029207 + 3947830739969480621126671162942463986987058328256455824368521897685045168203062702288692030759860685197940546125045250168790201 + 0514803654436570370324022741742361761085767189089724981006110323674867393784988265456553747645514420643289677440464150052019123 + 5223236088122199447858422156052424410894574207990368063564291905403412016110145065374098953504598451976662453874666981008325424 + 8373293703798267046749026333095880042002196112554036817370313956674653924174972808775910245525212215059736970917924397257890308 + 2688275927997288192485396746573266295779844438202521819272050705543165472702597009969819708658965256689368204413111379773538064 + 5084094239742086467203807611090720704742678798346329233433650521401666169943202745736920597870661200400002701183019652790391816 + 9022357095836768187469229301323281507939417769215045474272231522798590708421786910823915726035891376298601448255283206715063088 + 7293988737791411397897393109492140546674166871313197493347838700746175919251207836436115320719048184023218823514733017767389387 + 7188783211699643174822974868235729901402276203893157987109644622416046761772620967723823455916506713613144614196470266830456333 + 3793370001173936142455344055973062003252783611956485218268240522116090384604646513391487197827194186399975132117817107687082668 + 3534299426891086746037016872943029880008565862091417500370811850667508670706496943938696062708498042156433801209832903518387378 + 3612904603444715041436728628573199366360323396870491816934924984624193337784171063290043144432026274325167439913901462851257791 + 8301153338470277907154944290430893973748596163892611069628643761048471308522954471189690031882490684526895423581669049412645780 + 9532276724709021001315582137581907800630208033706211952374871095930264465397182584969831143514075753862615083949416688307055905 + 8388236378283440896890187881320950399116639874885181013806820276432717798539692296166413239097562927693580121835296266376329989 + 7227163697631743317865706478603326970676879690725149096075601615664615649563621319796915072035936935656249230727588009066864898 + 4030193127531435008439718127581289588778728561167418433131262502679346011703797827534339742404719888498611315489306325294200918 + 0822596041854995877122241367357937629640300673554434225279391124715516842541288461765835730255187409409295964047110843143360218 + 8020810762143625695211304403500380226297593451193440072241550883222759127723312388393491431821749019440262383840735943032001195 + 8318237479489554100626369597427649553987985282444811016365279010859228891440704149689826185729924642137537603090218575037482996 + 5366847590778547088514990246112762636619967032116058526965593868078207507263589910269699995373744003756645473632293041062685541 + 9610845056170949836472700450287286628803643135098265884778110832410350875689137416100768678349522724998316556986352522714663266 + 1503726130267377258411268772164465860231491482249362263232011498460531343555282835085236658598989040170763967052694908347332552 + 9494811816089738912922010509947751572303760145536902984045309394480942411502821839970060527331347541450194445987076121267053844 + 0578064800062529101700072602908332148334858119123936457716348054959136175842817084891684097218981249238233949488256020176601607 + 8655837084859592004656876506460130727405913211331057771278893395802267144808219629460783237220481671207469404413079770236276202 + 2474357024202046544233057042050406320202093782109005795759352430295741395906001878748884723478079164300747108788119563090468194 + 9729275772864119080887672349769974091030926766697899488139685369926038289554489717497100438993101868557613700320201349470541544 + 9690121476368923069792412981332423045488814436625785624017824621004713254286195984412682695459029135822031307061078889173619865 + 7378777371791906660635984844468930766958298884404755753328140351948727806677530013266236008432182713748064589578467419387451399 + 5958115863312505525587296099572988051567717080297066945899741469832877228284562546192870097158128338501540449059947967484049806 + 1525360297576645372782766370344139731393001666478941675207716176663153356185352097531952067180451056483850877049391450796637643 + 0957180541118429393622724140553758348088782996643755097821436674434023381251140872906157549968145359578492278555879752671991774 + 6216547228847936682579390485586625009476953902113956539812453553726263850745606267922068236416232274799633682965858910518609181 + 9364762411101864870815658017284551581396524871993598349274914322101521556813705161096159781789698091708777511072561306773711005 + 9372502462001712636254133123395734859574314940832644465721405982847453658518168263698099694805090947049141539874161892364044592 + 2081215406680382103751369362572309567943724594570823605875011736925225634106628852644577321897191396835476563249653975626106030 + 4349971249994089684132392481061788229278189139063384564147513903173876133019427848009965641301113400947275878225261721625731279 + 0221661121010559617008273964451895647239826707650461656354872916410348912631911913485548662828141859786059545072528125011374221 + 4423053386826713852263693496635804173362348029571154806846975163821408623542798104298751000786068795017683260714515841078366993 + 8161127671355970070573405532186939626037976009760161070135615665381704277318637283166773287886342633146869956929128780714287331 + 4724406673554759228867043031026142833731777584308969100843251135369865682593955020981079390823701606661557011686336153922127671 + 6320174341401698137531688064847461308245007114188039688579142931690284251799997677320348583442367762054912291140917964811725137 + 8202757825011219494192886746445679726841310275929718330630078072572216660349917135633404881654966136524906313940172149175596901 + 4973259052196790674213907468121479716985489021755170094314094085515986880378978689367545392713051595516162518064260512413271805 + 1589006020451052603264805726624921702203140540281094471735610296632014298925191276086205769087410850492910589262019474771202876 + 5301512438781961299615681939122770744864098845659058825055415852695585895078281739508660406939859772275150311279745599614771126 + 4288153404604175490400855789649207035885124038840820254085618553577028061229192741635233861987354455133991517534727391845052478 + 6258955556704090814031626148938140929500657324155298474719121746871071846048890688770977276676240866370191127535467056926311394 + 9986426460698287989606477786579619338308357811140009068302509875335795457387693847614672598016435455104290716649294340111672025 + 5987575195605597807571132149058303080863960035941811196802177359118666488648716460574884370433012992324776906424681910784438914 + 3212828929093079665577584834614675181147027766122500255332258719353578136517199306847607401381636227698622152320466280962873067 + 4298697726297500762842637031315949284066464528353792900058970168170276550530718742305480231641988165044232612666352048235992340 + 6528595274852601267138855685497658048124785482783676783853867479073934060681129115971059226209525138395957477851256838662435594 + 6333253678417649760854615241319608105505866305579272971991684020242948061790638726814427247631657265086447512599362760504729659 + 0050552281101516551597310571530814588813676939570968218933911952205870242379775297989531959401920856446210979962385790387518282 + 8767289958783485919140054170755933223361121752964753574235200401049015889601531517259131960751322512615901642287582440268512260 + 3451721805339224609531183820195682695971871204396323817335046115539455320833063731322682287797699412707522241064736997253801427 + 9838095438421652946093122030638044112929662006537527680294782737078006325003341225082530500978086841673076833294743067222781678 + 9343880589742192946487883613246357871516859764774916328816004546765194900049207055237803648799342279688804719689248327413730472 + 0721971662815930264205326239766135366858450956630362245585637639859898001993676716328053273905567456704608882800064784850223773 + 0571787432542029050900323916790197508546510517976343882254348928206749045986326975042209032481347983325984442399998495068210198 + 6252008138898607709468342620809002496223471138515742069863151888069692871096460617937300581107228988473399264367167623204729419 + 2797770513682558101443641688720044042871553905410373246365721075390692021825457052959920292945148726156660506042073326859993576 + 9943199450035463537495910614331149365062244685626306093678223057245690588586113869249388996930139917906887631260478153521760102 + 1950460426985566320913113822097771379876492753786278737646554639417059453209917138732302032256017931681335738155323404263671794 + 2838332702415027792861677040542052438018840283865010592299818970494138350530560217854544968425238656792859418734080761867272852 + 6010463746369529626569768506440616846423788144981864845682008740038225629815725166282753185272670640607060429451038753678650440 + 3603428316928538153550803942955541314085414603075220414550257874931378714081625009020301955524753074400211685480928675879412454 + 9843069053870715332522840750526561812419932672015609424516373833579891793837439080150576601064726524016745608185730860593580037 + 4790338120349419657809887950279987231778879709683733319593125286240898651454362025515251496405484678061036071464115462928635106 + 4812436174990135339020055889098969606774850114068102256726271424987296420443648067709292253692100724695627779636510134753572039 + 8737165463831035630144985978697481580718872897801411679391604620458063323095158841009595789901639579062186093555920948550517282 + 6684194497843892923374409974962663409557384721186689597945008117535697913915795350771799536776499659499378233933827449930665824 + 7081582116471192658574426394048422901610749624872891986363877792779389085331435286663561611309448994925468965045010492951543901 + 3680646340800173339218788077063204059241257097481947777145409084202800888856762009180382127277534304230302616826742040805136435 + 8971885064485253090204122142512764196490013452340872579790701372873179615012971724582237981895972101835369658929642000295179467 + 3378697466160221993719637822345980287088027594206423215053076460092623235649859970956549802453476198188280999027211336510921505 + 2652711751748836279015697510746966396333400935969997511167766407036252126460465825405459671454621493581082715193532241502957665 + 0853017906034458377960386056517204258262136080721053029202866891152909200067791240221407899628896204792320935757942824137109755 + 1860549007099165197284140872678756594535459353075535851412365063078974696027557562375802944288504306767016261985686187927040312 + 6976439902255838121317145194266076485068757990450059106045155783172858632535344129113251970702093415466811410640476211193415639 + 0223864295074452283847305560600110714424512989818888930888094361164360320952698546375108408821282297940103191521862113682311023 + 1062349856533324628662077342594233105268417141054370232872638557841382516201012169119621084906023902818960772903834214834404456 + 6774964345965594961633616650657071025352025214474328041017041037485163730502274877992356272868337521422636796698369213270452116 + 3863759791559426852045781221052728648632252466126078672480213084512794723010528131976170544126507023866299598547784848361822975 + 6029193859923289086357438220756059069241393076481467455226491973473927966812070493726378405565631775752820893408930243604143389 + 8322645429369121872596731546622494472770504292226778137537611049076304139170096181584862462563435300455143882748092410271989379 + 5326365807733260201580801629433084263428632745627040818781791453399164548163815232430786017320082301681273560908524949863305250 + 0127708812120756378948747377847983639315742195284498126386446424753766099623540522826797908737477298768890173160498925727449025 + 2938525448223494002554985481215274772014195861665818544594199880542548809977177276693721985173829796357491362226406805154130568 + 8969218337326188250536163628581836759650127208671515917790854163363077352794417610106050375787449708519147175922505361662892084 + 9818570904194161360123724397774706465600642465735373239577049512865171271762814912171304543676985961805640424586977875904966200 + 5504575938770959529220023577243022588499122259144158193746005510614090936240126010183628014128216077152330048541538274583951558 + 1040854914239994126791549056393295346381943572230033663200164558894293446713116407420635913349055999596494259230893231105260703 + 2206196014061006612340848198814409910794456229071521204012047591463330479752534343609457402515951279901699854399989958952429475 + 7726196843265136180636204555752895156585913253117092477574090168474904085406088453119889514918675712220848883891583790692329162 + 2932979781809321279966736276684170473868093894960203921581294390763273096543783962941941740885305313552176422059326344349963187 + 7716303606885535604492911546074803956458411462697046763121884171908019143640932002882802971285171891988638807617682091180833424 + 6415461043036191035529625558425951185907448251833755623616264167570352631169542482639741527208649286390063877760359771911261699 + 2470130258381358062929085215957585938262216089039199788226601264737025509814505817029779107756588940453410080897136093992799084 + 8707632659399021754985431789449236853018112947892026429638184953314257900880019675773825490255337783864219014358786450842397851 + 5533932851049276649253727477601106534672571299541307151668502286973847937896722437084410916259029864044870523541806218077954614 + 7765554877085157744714903505492619912731173476480412564678818534684847115861709661320561820994876787782948571629974821128726525 + 4958648468242228861341995358858962307381366972784922066788447146487993304134477988625345942386711833780639553271598395688961584 + 1195610154724201767373227499183087873970044260009821201260837039944092568903479517438262374212926002997007192595185854104973828 + 1619364472726153539242937799692428699593667255284692675884347709702639988899768923848970457805127213116307471608615036594270036 + 9983245059851562634241554611084024908123182475839572134087792577459483664336562817481606414919540980247553055009390347181343478 + 6678203813070191242843917525205623295811411258351922528980269188922471356248950351834938277372740881478275242174992792567496074 + 4143356634732380642139347869145766266914672583108623737574556686979737703412637109328384991661662700191639112734811399558605096 + 1208518184191671627470570937029456222980556566946874634805220009038965108642318793927711482497435062563764442708954406150308502 + 9023312095876743701169506435873830799968604505754154998579861924311377960500475654542205202570979796896262463835446621504771900 + 1307938351217139321342488304983730107947723886674861520928741265078308049241789485663045316829261201640722069914290181463616514 + 3662774552959414495906707805907185396346911240417542898771207054497319717662592108767592192807181086654802759806348618578837674 + 1314737004679848142363776160351558775692327407524329957179113590512266999745499877585915362625510835561292623778541138597816039 + 0237557760056059081432345998516737302912533244471786164779569231630397999149258259824248258872090314272651220971111732309368883 + 6627477978424025488072609778273019056422203214910145966781125727030515618065001832071393756745595983343475497495207623260839724 + 3342966216908293442342817978848639488604191273604917723840719378411000753792919755939336669416561658839344042868764649850515740 + 4843734023345647692176295441180249482639581287413972097837107583698158034620661397371501344888180961705583629809207419852455696 + 4443380077789857586353070023335893700728665808003439355680624696628418230215872552816714310195766329481088338871468994321119252 + 9699439754749964974015300163681954912050318298048480045612220669380962262620582805353459791375378214164628533298845978013550599 + 5105714350835688155081910384711576767489399113130569825483778697383765314872304014753426304269107388256780976698871683305123430 + 7876749639965180153007689268468639912304158853044482532644498399416286758021429281245070574658924487014301816203665832428101533 + 0785808281226435244861112112960701400035860271883263300268756398080488577467688265527817734331234380039587960227981962626600939 + 3364281430281513574894870100381156896475296131097244720576919647275082387947394192830802845871083057512101147458345259973497437 + 2352548478260815071941762637203003924467368412816659772061510861905396984310747338352315940227937768901334141297190271981978620 + 7421497155149250772882271160825127041610751435166048440557936723442915599683580765855387190581730147042311189334715395286473607 + 9469405090355283185848987802133089556363626275612421572132540664555746805117424373802421917096772214790891162942671883468819382 + 1589417274385691408452755936967864047060787328586473526198572660582234669906554955441129992972950187613542002387015080229290084 + 6570356377915672505761938151404215475617807815543585573009407518371861507851745477702147309937407690084987324419699405440825645 + 0612011361559116532371585728822626979903698606786712794256913394582020905043090461211508518273342883931278463866340432838401156 + 6760882395086214518227285005993629709889190889508417455761844997600135276044719721514847763212602718036483323892756763864051034 + 9188515996754462022639889466629680669832215175040501200558563344456278764716592388326318156786971890684957626542747491478209927 + 8987779229113917038185012511339563267826387201889188999106457112243660191988731669456871109523244231764354533555547239773405699 + 6489667993193399907320056380302219372587627376810666191791189051092938301013845696380002825207303265588504074647639636023424359 + 5972299897263342080767319345606033144822159869746010125714876643532020183420706758750193523599953077555495726481141414611132824 + 5084488926501974380578938135730935789462111699625550813110845128956753975680460172778115855586076226024263960948204752675321380 + 2481196609759725214010722486828189087368975741750919937794099496934509151874334791821893377695611203497436421390537165843568949 + 5731231776297026471145248406339411301301972034255825750883890535679456779763247607668575953175369910078981695492172415999716775 + 4579188403021146726016160128342968838235818738719371073259844121400672340573224465598262036627730489472180977859344538916635018 + 4072803135751982897056486221080699066662076832459383392956264311706786163956015331215770418998634239350534320417157397046765970 + 1201062381226118587752910736476250954770728984407318744902312031409265281863798225473350200683876473994417794886956931818743554 + 4970302735301544243501924330552682090042743013078749961722848840311456198559231934700094783625178641374367971636230883796585194 + 7528520099930871600504738859526542685454459947737830229008160696355714649737859829804718726706633142812661022345510571151124118 + 8421496990755255433515708880870288195255467739826209142506221198099596830401844825962275951060431553735295340571732198670724017 + 8936767354220444343191661460546264683941090169583805460925893859976635128662736335459378982086771782291262296836018682528094985 + 2091822408378038044344571653062122443897076701230437493508375904957950547708046448886825832044918141237713293307448531246301325 + 3809577056439308352524023850120731400555497421961772257434416551729487887916281181723448155709611102047050048200739035199609339 + 3691135325949817192195090067443211343266627775946016712851865749742799362777412328641698096396095788341581675313236780103509391 + 7728571205866997785438131913054881617576104163904406501238204339704104937888486853321561284077020503299289883355914615218277880 + 1111888880906892863133264981628224969781528602979570581183128605546822078255116005933260161155631478832277334536041066268750461 + 0079412603436706091984459336642210703864450821510237108480924013766858888811236465849216492858539373276328300134023520401083981 + 9032711135936968864615808603415924938529404508326233015998723558019026312135753805702013665081865026922455487474085399902382380 + 1925270181168851392094205156290625337733809503843149282248914199479920984244708969137863994130437975788618973591803506088013062 + 5670224338144189138135191184201868809626683864671529567267492650290228767102161777058656146469480714765930525720049680179040530 + 7230690280352425636146176530879993888167423730080287061127174186402752375468464868170738182852209838339454679149339529988407952 + 5792512066685362806154726245973930382853685512688261188341000372263049656702777229779863118583825044769296407053427341340382043 + 9064288699746230367766305172967912478546347888349770026780079432939827599619309710342120385387650986045115258506762134679333064 + 0440596074705090759141142692292577561658123037036520266673482910698027486128518652316613594364723726387332531338654819095216165 + 6586405699035556181676379611570196812319147084489164717015394853295535428378692362698265567241807453037131148384149957093387466 + 9613627657031243653069021006489437859522461371334813124213550061172753326963975967858093098270917873153645156857962187738174651 + 1136920419639517807349446907609250529925657860858085930986434051082566457439789550530915328824048952555143480521491002977432620 + 9723285190605612751574356382595987410097040493290287438645066768564593720132821343589116869402530302205558307160327389977244390 + 9364492329019171456987187525681281472110463501074399197748223709921114091308897093844593961700969890959904837552334397994454560 + 3052838056301761186571362672662664380662089189821373489289767638693120179754848616628936578638481820222476538767896516701765186 + 5650968841999476243265351662185220984505585094177664675790716289996388896832182868460012463094065416068468660526498381293391126 + 9133890615055659775962704691788335028541094043193982847019337250184246131745395473435608325229593796115617156815138186553076713 + 2129458246410892733861841029801352092648607760367150219892460311630359921628868730343711772190656001417014669173768985351029224 + 1665772830534776231474157241609092342166046079774561656411248463883336203142778691223352454530469529359343352214726777533890124 + 8331713345182730719576279806483123633260411891324365421657390996528436543606816818186451009421810586108827795803801756029033502 + 1364037207944391495829014284717167206349222584053304291053816472070825719135329033244226893785498596526306122826589748158594087 + 5166290726387661882217520391175991236803942524737711932725364262567914513184343152964650814367428507369519194246642124353850820 + 0827084375654733169383428093676562471650179031999648254047083978351359301318312364388282400723012984805620892215650029052432539 + 3941456090006715583530315193770635520541951076921761324088412023106545476103418543330517872032796586561611105128147089091776975 + 1738857734263197422168561159954861725900337109733462635773133902960240600973009046170223803445433108730659547191448827977753217 + 2930699447354813297267803165810088809944869393780407968089194813574507757841359950100327174854511476594508709317805723583889020 + 7143123510044372032973820765560757174132206252079849711539375893206623268969901549499791778646394614259993009419795504303081399 + 1805751816651443729216778302694093259724338799262345264750249439983832664270852123252647682716640466581767974713902148881103321 + 8726470726559295990593930464431140413396151555993515614244807290113117258035592083195115356107951148992883803789239385817695980 + 3921614672869622892796645795274584202330027636891305986908354816884938844639467554178364479042973665199423978535726526806853994 + 1879696934764137925030122852767473404168885624623810742903886724883175975872670995314600387454933128918537822599476294544895031 + 6035100939350635436051361083289099777664034736094529995818610825799950536521416106176327389907566363175789821848187634785837579 + 9000534727303607788183270598866205796784604375642000912263136681354291802540390456321071569535579301082240092546052754082125140 + 1036718094258942656960699558474884940333329012199962569808690163604756147670835128428656230386743308384472157735698077816035891 + 6071364091704432824311172611510490775020204802190669441798310247002139209451209194509056421614671635249279135552841468497623698 + 4388935023201010068076632458613446034376062184128689428896319432854524321580911853120662708261911385263651607882193115809188251 + 7169742597495615052582018265793684790742777650121858370707225197495242787747124696863007018741360971574027831332907655096436810 + 0422401456149077117264566129183248282220685815602963735110673297177754943137791219212563311879171990788150209340116758159767140 + 2965862835354985730344339045722772376955873793360410786309094363480176270871774839639924049136780870709007238189898961666868275 + 2861817902533679195525000340605947416733205573982037034681250485524002724047643727596821058644083422061496633576063860945664624 + 2693808963859011255454082437160794171986401169181404558686995397058453911479501396355062702756373669284391335723793677898504528 + 7653550559325583799147678302921854984957213549656349312970370601725315750255349048113259251600824306253788257181726835044331139 + 2669198588461532129599972595504488308041821964826043635029559596161652526633086414778498340817442875389328897830361220046753460 + 2464008866849845585427596306460289186014718930150794200485697147420894155928351507966633760981788686260275637265508592186109230 + 8485080800308772606343366155948976547130610312843499421865489766584635822710314441085925235277117540126323440360094147819765072 + 3284154124684872982729898726330863362356401302174583854830959819131037571458234265917476543549149369136036055331113709805046443 + 6448518117737425864310082406263081225358862769781154236900286043306718901307704827192440877547054996291784365092391305036785917 + 6937932081779624691771675203207782587255392167526245881985222450132700822827458180664476166098376639952639111122762216172733126 + 4351428226863320079499951081487882664115198758192473811033557945313783704183329712942802900894464150489698398293843181571708391 + 4008673285830233165375165239225902635382169451174378889470574573298752951780171507430341658864697744996790183195739971709305547 + 3512291497844318467447674406573948587271898370849211096489030445902905335005315909627516994616160913716819045790842998532630215 + 5522629798725110629827671497041697233370597035945650285606531591280806838835367751631589755667302233305861288279338186531242009 + 4038072792258238775154639697267095650759428219766235775721809805667537846787229698544718121429627243715285966487077144477541907 + 5934583620628679989854657650575271470278836721346368661646073065566282621355114101575479793022577251192819889432201758294108462 + 4480564984351469882094948004921988867959440174254223793056014056869119031094103106976186436427858310194322489736576393894678612 + 6908132113303990201784965196474475898344897609537622286517498106001289334026874927830753197509682053509801560482547631691338408 + 9319954675495203754314132567507992211027517777636008035159464490278748417535817989110579370702464528694578198640300697978306801 + 4761479515872183180982458008106034482409223233605055754850233921649363735633967021409784641062684672780275455212963103609820201 + 2564622328254102204752883685136476152747302286902963024211546476863845751873654900973840371931652957066788857238841473470464835 + 0397866053032166080589875219701391296400993039583315649582052801128849941725263617220137826074241870851980225112051857130648469 + 8173011294494728142605327204039773210726054522101869637370867240485919811250566145341338527471719086407653593120324797075262800 + 9276563059829040598662749592867289249306923572562392127787551507493862417784430100714677869547866344355462003505196714057035937 + 3281114518664069193538073304543737277406653201799960331850340753228936196208065150992985287938425817855366760648223669372651097 + 2101840795886669078503855800666686104431608113029414404488344962534581805317909553125776693807861855300451192405993773968098583 + 6961316934095858314386858284332606626453618369372169846037717301254036577518610498824984225850477019844523165578520651885370736 + 5674574044356298030636615794164061879134353864364329335297710010416084563498871752753647964277918366926080825456181880254954413 + 1539836063070409136278143569348758593204080100329208721008698517483741296128676983168524689365145284941105915339931290444395066 + 5870435438526474510831874542069716476806976094126759545431524918894521691790318139213265279009865120135936482961615836310836321 + 2764563926650270576320235999861005882574146665848294584476765322933617549606955812826398821817999980232276039438569048353472002 + 4681622264311366983045853037646736891614380849223091345272419576321258005567715693518336948951455962926248349277346106557405718 + 8956877856487148384136234859130353374642270367915456930125213227196134161996004529594088595345226945903651779962975528996861250 + 8929969605933523152819203271238663371252277051363612117118809528465712440154903065164514629518743371367297353604095710696093004 + 7157581534746462952501632250334837099070591121491848742704449306300549604064489388204805910975177833999231196480535164260229721 + 0485019965651431731437912577838502867419408108382589212055345268265256532718527981331506279373063176342764821347791812231845829 + 7209745175723014456091749043194092299024100594164185069424964912279120968460389124726898963864775282217153874785467678332297469 + 6065725443439620053836394925815928161931638271242410865193688681337289422879252019985383178533022928491349413174307090957339832 + 4700128875271375466912640968373319232662860319940601106545249660353269122104137983304514576260940899048020820371598690778056227 + 7730285573414592054013879878236163258148114953801223831916249666510471398921760574945529246282567489263612670937049902168944246 + 9130285817898813367964618316152272977147568779205131506356566544347370722993791917334237866531951886887339933938523558239665651 + 6324176517408834364349803908520408107012550850560156082064698531696664057881361151779666150135225685603149038329558618588277296 + 8952307375129199935262885586527056730554419885668513403462367686079193825971303716999017662160537275706617381132201851911575059 + 9097939471326158030329763386527360778246814576714519406324120582675890884898234797792200042538307916074737348191079713801271431 + 3543558395840050080153435933135880595590305720081325097084551423268599148459068228435603649060705649929053840511309887473304515 + 9764838954490408335606543556024437767253488401288444187782685927977837265995938637882104106333802927203512151240662538609957779 + 2886694819124240943375973107339251767858923004989669776842476259662336587537006376705925903350515688363082070599436191295014286 + 4373652465925317661858189411340138062597385913063993168012584788091469995881494867908911062927314918797351706279530078724029778 + 2064997451678388426343449295809472909654204980492286328038224332702407992526584281413262450071832225709127884717383554674100721 + 7539736814358108443787011442956856478411159063433502735600777534624427911961386455371172130290891500709946519469882478498227746 + 6726050228227536316385485897543745820479149980410361188284581130022635250330849613983713225572081803265842903422696226592604564 + 7194667876267325769087238008916325523655281922437602110657822708321617107090571364990182422106391457560890252879023326941272951 + 8084067244599983014933199534424787256031530896533024441147175887371345390886210891424383817784357384520863399170708018540336261 + 6756491974545573085147283999623619067108143004190487704098038956692693217789059190015343978239812814528286370354978428552071154 + 7449780712548692282752907313327411787266027754878897309843460775599392567392973717717866266635813723308899529146352109375925165 + 4589899290541494280337702591008141258629373350544520604291218705671399173981123075630121451176103241759370092474254377359262199 + 6674505740657078583031897307527013973936077370107324719073133704686647880878285508608449940595668407790459295575945823755660650 + 4398342537751131171214988271811959189579782716426212830903406974442463464257365397952526980356187741927953055943122410685033921 + 0094907389935032343867848721405008172219352354700721989014087040463745373039712419507660947640188922848825854691917677041514246 + 1508958586684510982818262867790308592204381251380001158886369026776930843982561684403451614590888186936500388011892045824866501 + 5793657116945434882250299286723935630635472763043771513002492162136250578168782159984593375232995341440779322489270838200480406 + 1528263927376996749090311110890532617677357745138138771708962614857985706783193215918275341078100860497124422089882672715412665 + 8047862045380193284671628316345513578527766132655289631199372572297400350940186548315099505461109159626804827405877434015762079 + 4497649985437114106619275583585240709212568170308750996103273375973255643809512987167799126855604592582070720993954457629607433 + 4115202807426887388976298359856110123402007311986746450130132490988863002251413157990023529650615874660044346489668889392287152 + 6927862701563682169262409452072639909156413247108366389659864970583248090206725794860315733927719571533833830245401473668394282 + 6642155549542044431836970672852504846515539364245490047433571110732970388069323446548403285359639096781185191635964711812010789 + 3758505500262572544806847683378518452890545811878275350915244958015902281380798955282380990829046266914505428380626717794710699 + 8543173740869008063671194651581188030729498726094049008714991031352383511909957936902571701241692397622133551499445586152966454 + 8558201709766887626106558682087493174247508346751479027758498057382070135663052096489680200478789301589881335174285636803583368 + 4021046412548985259286576563116974009718144433360698911802741759233868394233863822972297994024437477811572624976113883122932672 + 5381918891212001167216621281602456221735226414991801854696667000136111863626404844152191631832767778925457352443210000412625595 + 5545489652781686362831418324972755141214447870296324256972282335912548489681306938005662008761939913552064594595349128397481698 + 1089524707879456280414931183450523776892076608328015438392554074880142678157014194242067164456688702421957600153913700978618426 + 8305117650117364060258714900356625435051024551440455926273115470939757929013176898347131589373525848240533670222323888613399302 + 8471548092796793462446437655496090111004563242834114582368336961549825665258690557364306703617109594457055331363141186121145408 + 2838670852038846380823335210551520468349670239701607224866707358833084563155287946007354912983177147283657585469121005219622389 + 5789402261399916318681167359698620197070246205566424633235135391148334480479925501535906551354569207810065959398048065712057919 + 7261986944279592176600370192037825062903228830667505762121478097517284917101606104242575975523312739096999493662697366954853560 + 9155879998783130488358931786153797296783212124287955652349632245457365996542148509944356865191456587886152913113892875578626974 + 9514039241881963923397516312505696923391431643577404694192615351139994947842245479233801981061807552927418310904314043203688694 + 4614887134561403862531573523675942563015366589167507205886559178959551755768826801165790017789960028672209846259757000436195062 + 6712756378314975481834508159845487505561014170818191973740730433116802799842074666829329785272494733308089058087919052323067808 + 4343294134478763284253795500389053885558601278822120237277266312668433120502431917455874080753529426382802888951317455320771924 + 2376278290758786366787499337556544479743289945243171688237218372051181305516529407353834157305915645651032848895215696121925178 + 3277461207520288197080048258823569914990769314412444872094153856107817656040287107340131396038173497845042121242427193089822818 + 0292406985223320173089591545488895576256166382750650552107291481212988120961054843360076945546651513119822979777064017606102333 + 4155585975612603215642148373485509667928447809166188682093526614287990594479841858693261264552895318696996233565563963262273017 + 3435051958110889869116245172555488932493678104217964596210912258968214519860568648927109250277169274770553939366194092044056400 + 5580589234840522431968399852060022338678890148720329696753155804394492049184529967776995091977565256891476404577309506725891693 + 7335500310521157522656023934693183042792687707804385279531540473816692277059506917018062802407212114266734977379325447178574076 + 1771613660964024539818471437377426571013833744798577093945387086328616540439686380471290881092187502982926867793090143460960995 + 2854310614938011180157233734163443946405910506035197343508210254223120818772340019254546366421372519708012585990732220553479817 + 1257049653581939929259306981138171825335308854774522129783756061113569283775667916315356572397505175426434698580681752134340583 + 0335808023777690523056395860773496290527877864032944037336174082899748170635967157534100283308552217210895819668943595660390141 + 0793041940236886441234025927232106929006722186357450970274155143635586525537995503752589941375247670685666954666533793877981889 + 5778831921482018016340449172209749049865029154730502990831586948434948616688177219302113345681124510479338999307531273610240254 + 0006855309162866716967524960032543880915882390415328777432560766307982993890466192334347172872288555702927609941028091228916549 + 7852480060739012387300892561223523799609034777867042713542472004721462831725545348869852796577495340595446292276187383478785958 + 7959977096587753530877434044450370650017598273016702141156049535064683872702373865885204993323178473693440316927580843350832264 + 5711255434828429627433858416873855046302807982520306738509536092504233877047237492422270856933123651986965389822895956478482440 + 6861826464075028721520622101929991628946998804166738863536077306024363695385475918930843524639833318710346078946645157384213109 + 3481268732060383732986016495680958177849607099558634081654518008026716403239770966732475944721762791451888118885285069414233963 + 8027947110287197529845522807009685886470194904262452476975443162530080660974564750582146126181908103247560999247950332233807322 + 7124796294345362297022824568300955114164662928041497399401450052218863148267186902693402640989732333727359655944286809966607247 + 6673207022195790654496166749745020173181219341922393697843282922354805033819231485054350962234180921218558256719281039871046137 + 9465616068877625982160091084356867655695114307535279252535857794074660077470905649500203254845487633889884403918357791957962609 + 5439735864176545493786682348080515776951063552894497267405045766639566000474520462761676673185451169867195127044329565448901474 + 4077128683528317505947720920671307017612997849640361880751590889728513950754717072470243203246494346250198972938371059265537757 + 1744350487793132663117639969909905883135140378094636348689423577493817809958662291757247314354678873465246383300244542531431911 + 4940086036767442787655065360411221974038277063722727918083568388107313711402640446340277014461054034344740215045925518041320283 + 6681118829208967331321877862087707476476072276521025702668676229506021840555589912885589031283416146794110309804988142636941186 + 2405582757418961820523544833021078187732693088350227346014916968640935524755515218365262141583526578487828351593275991676198367 + 2826944841325179084380122395615301242526065149184196022148551459509194360014728846066978997793718470140240650758184827065285092 + 2993193263125920746329597500608467852384071869621346018318097029329594882972558366328973665134862355812606060309541457130668022 + 4276324020092753413044519728088179483413580580809338027992824022071273342649903541028827269643668077697566268171224024282173079 + 3298668219738409681902878367215423318085688425654045440812819269643490157963034537370434474347979142141704582114328144364074548 + 3331207723416487218945222041751113899922244456772815194220564328760009807415143846017951460454941724943113249362066483407691380 + 6952116171208702291147492954583173797003314720166450613568401114973391179929136073418264108322111138297086137222772204563421106 + 7600975435069311874768177860666996344740802287521757586619300995824931951698677022696322801985871429773970218124919477206966901 + 3780912628061324155929062282119787356103921261553217430966183645130255649596951891774470507549609157651291460007364039518971745 + 3378164561008341242097804088752883493567850412617992500593780122329644848355808639540910546811625908951376798420135130564695711 + 1010690664052506424047390590878204998037797666671722315517689809912733797153349697357764209138638827429140983606619452818262145 + 9300376547277559089699722018353829113301128665766029981150643108015654465357713345760938255089553063389045170395343438086345129 + 5388574617722177598048137212627225252667251794017646238607267836072085293351506292982031628145496634572585511875570432312724337 + 2949102931084425964911707872142235444671368657598878661624977383342922503912907622387561510392479663939836372865380891249214191 + 4125450850629924708967370485579795410196136664949644795471576226816969360966521409006096786481214505471016659590219454123795063 + 1052876846080196429866636468392224678653280363636952881423630013978399548705549755495939234226751546533383899311389616571394812 + 4742555980388054447437326569075723750771475897619661025765632486508214470920970384046022812610698865095434736181621465694089157 + 8053089116717921661140443537567547341019450706571788438437303262785839761518407332728972316994708287799676864196511854612689905 + 9729609228443111962917503361177873795233721041675657438816948255161968110343038443890530223545306466481706693430767571885086143 + 5688308264781028505036247702821583514666470671292172916350280224873269657299593653174145005772915708578064978186214186153683267 + 2204744465132776025498386899741825318473763441099667987231878067919021578886769657107832299974638025812458213339029056421384587 + 2941505567992035598339903647769230684834003209355669548196807243023989038563917277881744820709582631259852618961087166384306292 + 8258024223124059927265905619693379087206675705618331236606891852566067360854244728445479329673501981619440816785961582356678690 + 6012067901366243313604096658402361049393912691496270752442176761357212025454418262374116671287518874273805796136109140975751742 + 1773101052368269774971707329316287503544657412042811119480548137588711677240886794469483314479010931714923252443537409707971115 + 6673163431438354320152064250744844641052080216051967752388682876816416999627859168211126178210239748498710723469312339914116142 + 5806996877521195102255361656866436538966669931939141317697197556942791721788110932577145668299881351690980272915197702021298156 + 3837290410389303517128116353347856259353484969554892124616182205192313287433755106122400179494690010200326668121477882253979202 + 4517266820218197081941589722796747209204288657893693887244618207431797169277035145695561271253339157663193312460041285285239201 + 9619778362364427885644889878069243475033064627573715740274290928496163757241181156603865800841856421952950186816149922823346976 + 2573799739461267334017539893388809186322465134575561495883735717608135099991766507451755547789018617434096932254961072365198882 + 5105319049917763260343536285268328841500875349287045804710455434303605043562842410645690374572514107603618866501621709959657187 + 7151556358315357415841531703618215410583915203575998268810030381640117079961254114904804786046065507943854733690644791284850608 + 8204760879007736798651157366669090166543821998311590636584404376075249452086719646757979910467231964531015916233682304625227803 + 7147573127581292166990486442215222962358403851938571275150035153036061725108691622876773795056511233146161151053768550862751540 + 6784559304983902886590174698622574195988266824149602039534916660889368814614010342767085921580402597291566274193343471685906410 + 7880113249001482900851888199979393787162065292926067710104923584703156779327643300580458887132435255065678627456912854660490039 + 1350749751135031413626228320025567623412283741939627729115634082906593503710519533248918652855496972010878915554543211009367225 + 0004322455171197190670578109680045148889288778920452116958832375230435697820421502377733900228528866659062527967209953101213734 + 2911494504322931801753348544419729543749078880072226980969166346711819931480214331433779640233877327672317049984114641749562870 + 2396528513460618041259531318301991286281693049268735199694175803321673323893916691134629842475605991446026813330356086230228330 + 8981164060702124227875449453939249569083280933393885800497807219622718057632147355043854391102180378987437281964171835261740700 + 4207084959173122310540889440071390175078165835125695056930143838697501277302913507401666310496334451392319525169760616015349520 + 1210081234448921940981378280200458404260945592669718748037205896059223823726981351910671794263375996276697272684781727338912271 + 0029168415827572351727213122061796310780992187543596747141643738703113178475108090159020344233281790182332311601803329178285993 + 3777296404075934053174216751857062118469565443797038517380817156541529651488369770373411767683949249420334108704951789531604654 + 0677478972172417855596910438873967997191564526032435944553932413671467038312980120163881839182106666575810117448701361229089668 + 2906070251543291085920125260549397785656115356661440571177943054793731483489419102892567240649669779614310761600563474068066656 + 8852394653036692892038076417261650066148179764783605637155006560905389777668215992491194523484007340075319390767759607804494192 + 5467138831557823428775541689197797741887498255851810682591799669249141593216801183262480761866825456541084229589715596536290776 + 7751352765591319462216158866914539056239902442050723154683435064019845231969816008347645334022334350198037412040594819924724593 + 3021915992015948439763471750840891829476672656242373621059864369709314486194930162083489346397306741461969474457136306652660884 + 3810149798323432950565012468358334053474435740399651150333513841619654716521117976746459459286758520929133377210685994781661011 + 4783431510440557379639204082385220913253340902177656244399207972984745234341006126872839573292250089207868222847639289722379753 + 7370438575710728204326451494061012215276912157251877502908542289047363288154325283991522374002173371912625950441590135539908011 + 3066350412780717315157416276543477507139338679594873856557881443518665559120844101586947952288770461228629756299270909156776058 + 0225437513080408599402290104732039265518603222598728765215485627157659513804399230415740373980117223389491501554877516067224969 + 6906447098674865317783282853291741419024882827886344308680586123738306172623618313185104401579759220967002703474556768483264969 + 7905688354362418737693115373990150326675244455866285863285017259126406290824772728738190085605025791061658351412473817132182003 + 0647939692176384124068167344966453433916156302209336971942526032217331539621915101096729732974008611758025821638418841239335586 + 8207612011209373495228760846993905535758093646702045474203894639020884032055233069612162464709714659219943117947340234145019206 + 6685510574753704984128082407027684573335104766797904438216667655851315902097650094638260466258758906563426639941626773728838182 + 2859725751851113943873234212381842264933438665075493160334098268584252964692288511136721035397358821669241681360772178239556283 + 5410817225831141636647896001039576920297438613631278187702231335198482845481821124632157811564428311298381077638390915142518664 + 5603082383902365441423743060726658870177085955695406252400018823076710944733837738608757044351867174051742821082475300834328708 + 8478410686281696423470828758415498795393164508886616098722313596122431017415306773664281061410625509783895380848928242909573156 + 1195618788186485122683528679683670597289650244657656876407897279500115335276331331011520690820997358881740005917663903217514124 + 1469313024861648921401247135353735958071127626605430535836717325791385228578496115248025350543355198105506645012545576867598396 + 4272483837056013890177205566878534986867897273483516131338967706119399325076036529394304714161849476343886942682280685872295940 + 6971223873405564611431588388181753597862284579604627783908270991876509853907693857394999066866716324481756490631331601939564088 + 8692753456851589867469578350330459046916706027508903379244973723114291207510039578602992677933126396343784500936297228340222600 + 3596764762533798756045077959160866048043299983905049607435425529900440769757414376919342785743646389458775443875643589233861301 + 9939277922617044929198368291152778217422406940588205287822196961674791811253436361915620783243520085430696637802610907731339802 + 9987990017965498772438500667174890865212624587022291536612477503056361052627799082687991851074848222861818981269823302761583997 + 8147838382210431535807715103935094271794068054691587562868334683152631170314268604516246803968415953907592500669227061338962852 + 5229815249263579089803694020966160885001383014770540554119854860763174611534378849807683267399405523325826175066050422465261245 + 3718808810539902175097435162693814660278935973946526145133557384972950132995651178561319774914749271123710684959722970432994100 + 9959643168956842935132972702456973644474462349184166563719137832114600377784944150813295076399096859538689536653676932352320454 + 3562313742471254053603374767998733448940422800590796399248016870732131873285978468485675936836421845482343165519443520207502472 + 6212070810123317420939860915076451492474105989853395883410582273920108061505858814970010182505273303507369510379631126623445635 + 0255217936242316574157324758578917396184805700986741727460755136645033816635143639164644674079087020280816581372010788765004026 + 8089847944137656769780273194285160566134507215012061013579883469551314461311271302478380193931275275686279445049118291696625976 + 5717365181365376852569097535965171977412985242766246364289767242179344339616335652390309582781287529277190209039953388689399517 + 7041440160561255381091312862643936475613988744385378977312543669992877553324112750381702041222192086102659343479767405018249915 + 2110051683946677346707980171411807954606467103478530131043035978033107947826868347943468663705645386376022529329242653151632937 + 3379574154524802337331393517730441276946707038997138141465007355281465799683250899916025487713716291942082244114027843952458642 + 5030312724644064165890328712593254449923448331621966613833157539215136234997090424298061395610381815885285290455631522924868317 + 4994969373293084869354149476773798201740005462072247291096910619119410509333790774262072570461057954016819195195682237016634823 + 4014617100181465701775054953697719420102573860376968588430229723536957418028396409863878695628364581200214130204435051219695552 + 9995923662150908682939564279380158287700441111607726222291472481672861788611478655050339588555615320984584521234687823576281254 + 7451463346941792082220143976579354392136627715379752529027471716966012381538802459409604897867012386933986500209811720725405141 + 5447700282385988297313347229401494009078606483625633850809103068410968238448493407439403040224936061985927544263475630989480459 + 1276956495071860259959641422731621493130581830343261790000300846232499293476144299954615667025912420799180581171607386310558493 + 5072567626180671481702538305209899197776259094898315797269647260887831166441294066368414302707370453117631015362578331461379694 + 1152681127657219064376008724117880126055071670561685874051473152694654802783634954044854697360607744867225915714681210070391625 + 4963921877303857727536312369203728666152509364270556408792999159107647346567121427484742607873371889230959069964077737186080579 + 2539117036539210376394880318723799879677288248068497337514544989379323165067241670457629058952981263712005132132192204500173772 + 6813760519782616773952896216661044250831393786872842763541388164566337619519250295645333112400558661044316307967715017816016933 + 2537593940009216399181185307950727066601997003943463162691283637037387944868769661465346762713541328987499170590124382561225808 + 2775885197315288545943935069058879566010060299863101752754477420864624440405321494564586899592105748495227288314078895511070581 + 5073590254176183749859074321316849201765757369989203202482670238574028719679448337609628523768999643298161243528454637871645997 + 4654524903507892912886995134469509913539767744116890388991007614902224668150391846827264198768560243067636303891131378158227338 + 0324734826151939630626306117202466456571054839140771329647402994885021118469683547773949974151585727386291916309232652285623776 + 1825578079957905035730446040937650014976367810409736691475746813209385827351129150863065044732028040265416217520597270250595073 + 3855654215693196726130528392601924163490164258356468808028166928343554047073423362885338439044483545871577569335583661986547054 + 7793570955613127244841652451443245937038624291178210631123294830620894480548406463322651814043971289378075631025886964612359732 + 2535751039273171851827163526482017707846468207349048105786558968816006070754676314714316763865097547820424829616783998998577881 + 2844480806501005182020568712353744447818200854387376634450572497810731969576672980314852204195217762355809650187750497828976590 + 0779679209849300532787708183193857610170295918273464149221680774855800423860839661690361920242424552243626034568783063475060030 + 0715723560396890811677256708000602036818903166537471742271498254161510038321801193648871563911124555662395779532361864351019488 + 0796637275901473841659277764647010680246421160415288649143217531307967149087210418850695712273237810379507829287822942082290828 + 2503374558287484037225872566037347531382781922322502069198289211129714070730191986360007963273941619249637438751324038507743444 + 1257552500220289953409007738059857241268432142060119245938800646680659562080913958426385782354999183544917531229451796428251407 + 0627725746927523912542272514587614535547975158991752064909670083277315643027595358743280831654266470167938798514468394097718636 + 8318980485800264189777412075113224818829974167411737699158537404003402647667510002613635249834073904159437111364326870286724933 + 8736390761693005617348059895960699070609999931133577397987040270060440645814471436005094800905267014783073740415604380803498206 + 5542024002024944354928529036523594800851472969896531771028010643441490945234844042008320398276632902810470392426566175025658836 + 7031032484519885828134561441713514585691824451116624144085217816423547864679125010423917860268671111391465300826171047260397179 + 8220783551779338773320989765886440391559510492663544076020535514257589749352990988564034320388602959557187208585104844145026439 + 8020438087951116022977373383495534674635129594766601601387483705748972280627013851396530590121458524210171753315286548207527820 + 8153810125605918943918826453140421737748512940456044065444292520385926730447939082216173702077609971171912049413332448203544586 + 0886669881112435179401237673978622874656264303143999122578352317897806033193993865036799045024203333380525337357889563568831448 + 3748676570310585965679075167577833926365276411040601559021494474638574451420952356408036362315997810486031449429712897242856220 + 0680179178809075888645900355703866665848623566100723748395628721560414660071214664781095082893581316152736759533950009932003975 + 0830073511229116156443164078334884149650348116571315260656550335371524295132896582152314795929439939447827419494358066689706173 + 3038785789686019127115381229380791436051546935860047229508729818282744657378118473627065099573727853891404083449592265655152693 + 7387679714798835215773140865910355708661822160467627107526217765214393654304740207983760504979185513943991488603347106187504836 + 4959345618457216694880885929572868404119594959297665383045694122211724921300914575522725438253647266552305439505601459584619177 + 0467037747326795908961510775114924268777468775918327644966642534544042676564308146590029193764372898938024544197186375500357840 + 8285890907673262212647988009259010379723054727978121814340184295658072413264615156697842474728575585169324914900743103535246719 + 8911662589073033021628854642652750279152366994152376376433694906661951714454207190114956328995857009825646477784015810868978338 + 6105850627169563438884040914539421660727931317710596144077279839188308966168911142486835009941100149861369756674171355191560490 + 2993431983320455272922883788672722733898158280538086533775288120030297726075605253307507669239723828996651212708874872223213527 + 2383871203918607138972250186349539349163142546547549565946027359258489597478748862408648058675393278207850385093331126182621573 + 9149363763947487276724850656041160743708661373179229186384365572255499194358074217364047819850970764281787263423869876082053909 + 5827019270739581666492975342346328261479975112685223225619643483040396563898673337995672909483700478627244101352870984979237732 + 6998285824391825859392150613924432428270654497491969804735086552708299672203935039153979762171440238901122660133544046138761976 + 9253330844439113156612382643124565174653829532487393981769888635312756386927331059248556801164857640315799609889660186200071275 + 5612390497528583434894505132668347409216226770741805847223173711771542665456899372500390460954330204857624315915587829701045748 + 3597132578062559495102590042788395347495253649400865738509995118091093608521019322954235222572297567318636643867386469580449507 + 8425515407736939284693677162137557410259923224830338231554842919234034510500493129925331580967001474100531060588153614511993338 + 9601991297057389436503665001505251866564553593237174176487901010113004032749058341666775216970685449376017846133214652240838962 + 1863773381844384208184694104858797647539515137932214592371546918752008772143433088976967184397882651789039128762093118018510138 + 8436667156247339295567342218063358078249911156583296510351786615409192064411950727914656163850098232887122260394676405120111886 + 7683313388786537579802951656666063632278774842670516448032010207156251926218292168775800210222391153956472045994503212219850049 + 8209641417161775663979384085179876713787424866821458112247475298894421880117371699371735285979992519666751909878379569083863705 + 5145614759445599831570000861590726100099887859826097034388914355367729544959518374514940678332048394297378845981970826760413852 + 8761767120217732947982706113384060618324856798940745761981931692821487049372786616858603289668185012412091827806837321112104047 + 9255297129664160944098264261547065105677964568103165093339743646349513755899758152316922927563473869566225326724560456097296052 + 8120768832977744822631836021474402079390526097477803448973026451821196612519143995594879311933463926655409414749552006489267940 + 7017154772060236322937445448043347707331947096778317016923510498198624836901896034874919545286197554142622789268469355512048260 + 4180409321511968885143370514200618650235742405287713769661977834572569077057120974054874981770237845015640851329981775003008191 + 2674007147813616401003929214576628097932821870524475792725335810151140502429235053500438517449175945097953478389066531072308154 + 2478433215760250770512406042154394331540911914042172939884164584979797404189940441889258451913067147217070836370940898306980314 + 1416691061574950251933857581530784660502363969157027453652188159283670553356947339926944472421121743170291855577403109297001923 + 9846364489252978228078702013876774947354134510165101268064021721322665802683013959144338916544348159574015107727356473797086745 + 5487580365242793847184389294498037980764980441864399341257536426029899353090372478661527651346349015000812904186890490170512422 + 0317001187750772629199900746610544979042670580491329322209673449299816557793150957519344382208574308527216206006597313873698350 + 3641287214039996737900834675182665853779449596351604582635503134884649233644728626688852457677654231608768591360986911023898427 + 6414868015450446904060895609231719309486232701910101120865147273052264604064433289410480856555673255517305129013544577242362891 + 0524147637426415811762515415524550268148125432394280267631328443360400295790051752698236429135771292548014257090019134991791562 + 9227410989021340348714125220582535723860559138846179511512191891037914244234245126229571603923532773311387103298341477228375501 + 4041581080402587294355936437638145699274625343476210354812865278292813236740766242635378473283614144250925302804707242340663339 + 0724867859827673965725683173043844289022888248735884487800477685080844896245015920731492673699852061747889861151283779392092379 + 5909276888786182094219448158615991460321912732697015860009933234510620643391119454097956755043612428806923128306819132701862789 + 5863973408297121204616907602368353757254965361693796331036727921299882051062544545347637276552415740930878434572627384251645258 + 2609867181490019825132280383807303218611438271972259358234476006167125808789720811193408861105326321587061359193074883011503250 + 2053550365140441314774770422273440770268402358845803831349391590570354084402287239858709867448417600167758148787965827714400727 + 7156914133575985423380170082307013620095209686338890246264669241382877333719091759478776099336392938215841439510174135934515390 + 4831194527648288858829733221197151800308714018772578642206404911045931696147282373784233544435117870290316107286565703640910861 + 3300965303400428799995252612196866095687126018105212822125411581947708785019993474053195560005697252054488325120896486904066095 + 5685043938431323336868482886553258817526871549549389321696880672458619872963868160503420041705844727261813948644337640127844475 + 8437858633093280150489850618743229089133908480393577494682517449743840953324665700848231841040716763791338769325607594504384201 + 5092632498177396936492730922026153200701191354311511401621705191001018224605697557158822145660532720002740219521243300566753090 + 0884695364629948365817606370132571392316227842180869160712531089788912972870842630687441550199592940590099216041036498458331435 + 7030125885795773170445439886698551870214797580800884149092936799091801845209138388276070168782087225547258102113578759536143915 + 8807215865608701057987377248776702944861046260230342503936276411275965656745488818885694005475308409675094846381271540973613956 + 6869008153507650455021791206721217199858946589909935757514740552973399919912521587008600090842850454930346920106313925959869436 + 8747302342382237757458390343882591560184411401946674013753631245032512422678856746902092711874356365404625893572768808561925896 + 1816616401614372016489584185015076832989812362352963164309054653174766477426767816672229374164734973950570074316503361323429424 + 1677262729710288413972124464110274430459973064690910792449284824422312855723898793069294265613363135307936039462077553033385323 + 0904814204574628728334178723557725337676246503641550973591704771295724843533583760990530372617065538876854581885105724368370399 + 5318034405787225786821497050581659615205871549939335953839157390829611482749151979571742480565357809673956661177238715716708421 + 5050974915162203984880371984109598616980412684284404767484126024659745317958728060034806278671739980663056141392010690752871879 + 3910704359349884254016812391071406772666793577154924194799659346664635964157482006918898999240501149700799097400684650477119203 + 0922138102426301243886965897610590765176893150415296968278489084200960754236095696787157337789651225430707548067049568646321905 + 9034532106902339573322445743023271918597056331210862099117907113669633072759130199009133076195985791779283506809079562559701881 + 8961339360352958868430789580169262538709387737102199957461921100064868143051486287683576990974108237901843716454745741895109283 + 3895519300319620380905559168583475674843131617139726705719237185238119833221024548683898215318859806049104445070815116282206901 + 3205107673082159654286800880087962054713784047147807335322961266542952563116519811400145837980005316237797804651103815235446781 + 4645211086556795731679627686638624553276782440503123281227932461374131645478394881186841410205689089468850242938656791425398127 + 8527652116361873059872046061450470630778597394637649835734537239971727675715042761592888819669786191505268650105293343814467234 + 4729851960520632361339165114787166123924351946142914574237488059076517558856540707604936767815825051810582920267228276662907034 + 4922524498676764577221603274496474839043188887553906964245432382389882944444308052516105844797654740378920402689234115734188908 + 5209597697295900954976185802188459574638626316316754990028635919463918798002460967253179124238772322245122243876066379489508079 + 4508289933039159505453489164861720999217265104842659882479905333119333431390108947303039851217725991104705191344280222412086293 + 8069168568134508776661939124641765187854999589971548041638843098203486147656735371454412494419404765242018465434846607552127178 + 2927086453284193065980223266739988186690361081906781869605569767794118257589865157784413584255650425147523732344110338440580815 + 1748049647890769557692421227727549481557775151410048868814718985045151061237011017099100528551045245586497019590105694556854099 + 5925541326979395577276086387515399363166724218914221343444459910602377753889752768375789640169881596578910501727353216027189265 + 0670300499827706283025120061244353545380543254798985391943205942681540582832008582661334249048815794102101737939011541318568554 + 1807401946172440506670841188965007674553832019157741404977051650612570825055419487071388288683499429125090172081236081328128795 + 1574208400432062514192736694804153587958619698259830513687209529110862276181211516095950235354568516040903749851761677661305637 + 4121149896620030430814848794433445919918770329319490730619096312332656236065824412598168467443676868836685315118978623516376785 + 7498488621509709129976594981432727530944618723741457356588286547102533914121132990321805599546945869002131411100756554367181741 + 2582026542886480869734858959495104201677107827620049653093381222272376273695750172303884972292405628020932588645381010082785621 + 4289447606077369793749546092089501817143072386741950941157247080345113014329756464038358626070033871947884567651488044623905631 + 2542825564877135509885226287724296817068865459213301536696178082552402072123707396192496897302967815948042943248544343979991813 + 2226470997115317096784601264496380718265218871198752715837658374418501244345114451866417686910079224568758319235433015428196960 + 8662720543840647608329817530425275416788291903848716280076563958924728751343578053506896388100895823567897044421928057610378475 + 4719351914296817015503837199703117466548446025449281302558021903566930798786374684451211437854302542934198900108681526080958767 + 3447640954611982803365820977016952430036387460526610055495899354375691830575753318086903113772624764685535267168082007345740305 + 1797213012073375178436558221355605782112077809669165249433528557235690262339894762165301931035587761808175461223039297448962130 + 6950060736132243209446984212914140861957832417030579738364918001660026811196800334571314378298274260059705895036596817108824926 + 9243829747951735931284002210476722019445511064984030772651417194277223668272106134988724834976681779756839767862454568373306618 + 4177035873387789691442645602142232402697759139202124087044601161733861189197322918438352811683833924407803890384828993570282474 + 4594126055178872656922618774167034354795564094725497124745719061896909861368756961278327080697512762579612758334700763137442983 + 5295668887669717485226390123467973887358507953479829153694623729169375830523050788966597377361980793027344718171019365784257200 + 9888285370457729318303943315282858750583399490083047557333008218529891417381026015175475841289968239416942724745429537867737999 + 3215943066766119309004524839024701086312759322446215895076113158100056596170634794503064752363481133827922180405978563689758589 + 5959944414411467463305736849422386192090664596675188756343645002538240622043092367067855848705606619349233737685916244645398642 + 3415921462522850660711019463447810831161516098186857649733922254277645246597288489872824421913456035668900907466154510857353878 + 0820770271351282269897729773480908180216209552917101530859717823023591831191252679348064887785178954716044181664367902784712050 + 4837078657362119194233933526772924288995857318513107274934487922952892071107573280347076419494020490239809987105400407903583211 + 4566520950673320089105623215464822027247924240083971798563728505499902175676964769999078225165976694000667473401833118202304025 + 6860738161875565205941822290237567447513259073024464364524976929966835518792473395436546988594137222229184152759954076791794830 + 3322947265984158060992158624663708425488918876383348951122905125836522038089874259881383269124957101134232722838965307585611944 + 2514815461210894795746476799700740431234580399243562016925036790171527515771508119826976806830254109945111480181093741053447775 + 5733504011133442490826886677777865571712956442700084777358932735387221216646199198889278425501261656719619101527490023033629983 + 6816820665025994462583833453804933866931009904653183983658207938144775757074429801900721418490709180940459786270732207357575723 + 8952696642268346283355069787962809893365964014926493914452473794524489554221368619837559042723108457610361497745820672215991860 + 4686726618791630599619015305428791046600757619220375372642195506961581791667069381025833026424470965152344317512976704970780861 + 7817535100493702359961847958187008692676255354707895369219620793484182638707169828174557995935583658475438688352992259510602626 + 7874029548817067666626239631331985390475404826024086339339243583071276348104332609325698630718922399423989995185805657290031135 + 2250809137006081215712604683009748641626154723738138936917095298080941105465629041740614734952469019573555032467949707456686827 + 9015780860040863502309304151201467772727168204445161990634325579174702838004535428730659838209979201561616665321137059277802195 + 7650185512550554196643188069669262493680280748343975919639135449289335914799374871448334387269516977974949025899212288538454112 + 8893662379603774306702720358700430713868475310661351513479439829552220384722225613968805831874918699875259504799262267715048953 + 6970047041565543406988313458814942522252185061892588920654751003945616453031191382091583403673677641380943374412110595010134653 + 9871101512999920825593895837672777862350486799080847951285270490204712290524251977042420133385216867854292673426124017430550114 + 4761750275074356557669956909154179090706612051478635506091941757942400068895124161242203046266249256221284982009220935209300242 + 8708015446206142670623126732884105024418284851295914904738375122444129503796268180002105711502782904456582492253779456800326918 + 0613210293625239057781585677639979950255289284707390038337154693725678298193172844000279478330485593483147704265272812526895779 + 2716164189514060813320272610067774089300292554132648786501937337701166054949053895064937132503546260829302791728809439780621266 + 7313188607076954454240146509025347232689443993903699487707438769611328865209183398377855897661913914996316621615825549781446347 + 1784361684093575880030474001414660619024654155783784777347697077774197795864389624206377564266630250281594010870492871026068899 + 1515638387019036333906018359538519902111800466842577317066502746814101599618916383605825219038858550204877062732542814333739145 + 9220084992150752811004335287492444508585899566926596972214201784424729857471199982968054884285888711269768545472118962801716609 + 3225729665605184922610258057387753797602084282592399424014307116412082926636660405157448703031528431483170813038850013412917589 + 0896837209572767267939653527113544043129466184693048843785638628896239995824306624383959725609177449846462355536652421863726297 + 6350549459745687058464464835566280558244152696093628407065101518502946110700562358545869437041517797874386126356678480069546762 + 7437438880206605630925397821472561939196877744334362718590301519068712375301433711985727209285202108430567240861306104506294438 + 3997013218626793371442945794751768102167128014691257491799130532817890787884088430906840628465718832537193051422942089432586522 + 5767261809159521411906210527732505137517003452232973525892796163942363843586179566469412536807588910846358095073973053136806664 + 3610420406657475104037145580225980872688624964111041381549594329404718245302720059446156211318636072750134363504069278172819616 + 6203445793416289171078116228949526537345367573758934511473904862922585007326728074024526181186924979509692268351022430367531902 + 6396903617968213357545062076755915835538061764765669442173658896006627193712410945197598872950553456423579139305216599382954077 + 0380250815827704962815549731957552434336266476872009617222288199268494650352751383734703683895685962764217150385921949138345511 + 8687569627504118278687806727964146837523838460065586633962532325989849682060922414609471208083225295893531164710651416235932804 + 7419608622045901350837303269139752477969857182975189849619797931283834755645259685017775129366698872709262322484867769237487261 + 2446574648357299934768068561355356119075191099390351323266829442188920299959413380468532819783426950868690325166385302101461953 + 4690378580819708064900475904899019106498140395743178471011674929320871266333196561704778715716963538368801024314408279647276339 + 2089232113041890885410086998151297290297216269518414003124742833718798363559663862672468722436254498875698485622178498338429914 + 6550115139019878137719854465346267455296956376622672210869101826618943385242099068657285404811000189142469975735597865828978322 + 5550336328979484745931555695487878550858216320770924583332798110114879836414978841309407295358874518788123614542792919395667790 + 0067101966073227418786203809533671075851186310058420930636457857938955159488144881158165188969895896949949174391923269110027161 + 8258211496051765933329722240348370716824091139227581167499651455166693356343053246387421021603939871942981451611393932490380081 + 1143232998448167618984488431281685110452032295577636699995232387576558530063365443650214541186195345336376561664260667081107636 + 9153874053518331378425571758003432585952239206770799268110257888073536748287123822972824857968518689632999374391956653833541643 + 5746454771428065810576182766708428737462219904665952012954717596322305804801076045993811560187169208752861306869132853087960769 + 9312948167988600676884786283729313554222793557251794907465964089218336400060941052967060271657136677975942167674352571570304004 + 6999898093303477247632176216594681728525645905467929567402604064471637964034911185817952376210008390273053006469300379255866531 + 1000632388106711156678341302292429215991586500122697419661097904387224375829260375948304920442750157857268831027577641937349960 + 0561600453741069995026478401094735925203677529242298315347820295756013844421038599646676315356655360880496025651231310731701615 + 2967967299264819933654047107088552569694325550743639578846283279457367587777819171468331383302126179626852498959303153806267304 + 0993137404276474214149260182488025202243237418254946278036864473980040065830274036040054866953015031416924556900973301250401325 + 0611401987313671825312920644599670850377089684826838922442681491359233283306670402386279700142617583474055662080523345059224691 + 5939710996631567268204735821745742750433473750474145824948890280584535509141301239485088599010310179272128880118496394992466934 + 3357460688499765569727929892732936606129832020628130664357730146150594561279515636082352905831482949527411745350155774277195108 + 7138561333287682465057643618887421608272303910896561253448290571853039520359195699641420904384787139962581486218527455895010235 + 5098065276517497532201660511210544476729427289544804994012760004734407796257346283172974549503877915741488118551582294732680387 + 9918245303994525211620190522775746453648980603544567886385199869862202445674868474533709002221515555801308081350907650459178667 + 8721390287975913893819238889792260446828081274233551710328471981963516819510944667867602212793558775770710289206007250029862895 + 1280952122455041043530594319244152931145497436315530258653194357643115496210565410757613267156777417895715618326341142914815577 + 7155758483619829149138641241642134167637824757268284393191488835351550697663275036059641871170325362834558782380774852273848821 + 9812670602301209189800121141901793479005817704022886493550881027819499284489381378125534965938777548562514868791510874667018247 + 0362874203793328000664031717659796956361927785166994482222033051420000873310315385500469809294516134684467763731164514267312822 + 5076794324739899424289073581881385172449093717540058394689713271226423655501988369216296397971568827556688651950460247532081671 + 2211691279142831153117347297369818334578478434502829176759746633980926915557525626263924160377780019382684610945724739361356924 + 9219339881449560885105533284707871200679261887421531149034514599874409542178946360778835736536874753087132328398630153344208176 + 1738323078966650030040964282424869456011617229198020575179773319844636313591780039750411848469791355249483448877218482996481058 + 7662725242856974627520011178425574682734942204257582618062074645522175607162830607624141450906516065750218377963070171888324843 + 4118042284044277227029777215730052173836438075783336538165120621022353806541561734384066342123951846452650796265263415816226504 + 9577454228253953925531431429190317095770965424733462598360193026659796995068726322946365945449373804244913417484873047389958047 + 2530447003714965976379236094037411278014717964765934254550861704945379408174897820528178412885512242072953354276409893858269606 + 8161920683332117194434729439905850512943519462231619259091383414069915670154194411541846032268055950920748136328515080957772524 + 4455001394112823835403683958904433147118332238523201500644925421808301905477707785391327088921953707802405649821266420465223561 + 6446522347006213132203935166470869874136295692811490433897687621265910913874552752126752166818595258011990560857727236113871905 + 9408818174849694926607806886600067803753381428797382723099805698620415041534972953179055866017711870699147517868454045402246335 + 4135626065428509052074741682443536368971147858952760160985560880547769122981012756994845114634562103177568847660082033374741355 + 6629483302659977998713743227246471116209038004192175569114510152669193408163108052671223081581651955384894038833735367319970945 + 2019914369819713476232512996482094786229436696697562766992595975532622307992117773104105916821954959122045124593739046172932273 + 1444770368011659028126820519729159232409884803442212877208399135578736969682832974964729860145229172744181374244786183467104294 + 5285602663449673777986234552062489192832103368544537902433053581936823853505740285888319749907423551259460167786803225430704894 + 0644806832972865011089771228494426041526498427256197014809301589227000243312341210098122668991020924989347084902763173739593342 + 8397927825150753855181618641584202156450292633924809550510911217351590362959737037094558684222129548773410325105794129798697578 + 2130742130526719507540424131716191473755652175799405630787752600339151530661377691130274509280084673031861647779131553466473489 + 8949445645797314751748458206320095870152672752275260151260265707878555413048057771903238190200758654160960860864191150393477626 + 1150155207111417862229200794999414320488018094694431946879621916439109486610009948685634866137188097525670175207351289611083094 + 3459879841467541763732336521769192414341573430800023957612803685733924880739274791648569413015334203212412056584388583105695911 + 4207107909576145869607620085461426361544959409669769028641359260476393776996951928885197026584290166920423018039379739461412804 + 2471437021597594937922441016847924078362096363319644062767483944790539470640965768192086646725793415577156194561524796709562342 + 2281835051710898850388364318434644955789879751829726732802303436684019874264646806723409567549761608858039525219541663231620839 + 2007932711287625313296243751903200023005400873291491556838807519342296983784742524733445763971687078693207166472588686547509634 + 7628738900800911617227705711930133205924637233313615650647097515124961199263711780307927527262674727498690057241315682922136505 + 0493387404859274797132212785618181333173806092520644500400240017059008198178246301124430115868753110589721037771703980382573162 + 1169775643061410030855660308847307357939679557417322697395889694976054211267593984893969933792226845025198715121269754643254572 + 1728088919686607770305974714811474045083911324960307426887087611368014116902540202262357011208475439646884185432232498389602471 + 9413509858059972641349538923181108900150612516616095667778909942463828217847216087159443807284569471198894585206492715160193699 + 6728843665008266563029199158801993529576549886997200057517865461162768723429256920925422142043184781462681238742660537092344889 + 1931599731390297037090231505612731169969829636622229470099002019655957459951531223643763907113518395449915860761987492535032339 + 5034107674301251502545019517381773020837552557746624579624919732008873147762835295630900229992866373514578020722517390727520774 + 8983019600230774694685639778625463724553591351398381775880431832781553934906986888770789153951456721760712116772577734503027958 + 0722579888130638672105073329597090462417149082738030373661949401575813793082783579270436569787902655097641040401368636813371427 + 7854245354370422693429496181630052949425191073877308843275368739572310979470712820505147110988781661197587183674125970895995542 + 9743873036934859621564820909920160132335721185173809848423866981847229831790016569684947679721801847602901060080188329396305906 + 3397337816832712119749817143233767742905059889912076656163289731022283191890667300707504214144077245819520343407565716275839778 + 1635431146179533618869624816029047896887367730042516939278216433734900869272992829571445669607086349418935403567352277456520703 + 6762725385281999872315155129365300727718531348063401770341896591345777984146395511533572557918080490707700609701643325567678181 + 4555558906784569913680220888302706502231120206554070127879841389783669163314482027219519085496782129580409038602612227824819543 + 4625553964652973015688630098326028308371988997070002772661734916972323600534194087341555003249709049635157603584665553841867805 + 5469615145572204179649517877754736243473051237336198742915870594247954290354530866927776592105619674425818013502199456960100742 + 0688295929947456127268347042202884584629259939771429635850789571181349570944477662818026788804604769581716692572546910654441173 + 1781053017263760670442837500622338443773255350157040419311002126378320391255428265011649731680948453211623587016944241093429272 + 4424881884807343597741531983608658269276205760340198024603987236049280398955549067330598233254907076437393855435114528768763737 + 6402747544261459973943024136936806092529416389402993987239813694282531255632557296852083229095761340348625572700195393957513287 + 1528386320984169104784676953231416483588713316281109988780398093348714641247346320098277064757682809088330401558069087928359793 + 4836620934876383780592087107373057072272745160875663949786761387509864704698529847777036861011698566433232612309834845364039380 + 3575337583851040701388845815054721473930456788213430385395140774983959957647809720764167375524924858966015899435919948180069180 + 3727628368963430480869218342563326331182798677393171005831460902561217359479597768311004931085102290184621530025879576836660947 + 3475800984573188366693910563609274312878602294132115102801727644998770488363543862638723091471157432089891694987852322137790631 + 5023683657353497036212732071088147337120821028934424904568945720202766911488162370473709710449329167955152043455364639983165681 + 4313458074953427422966761496213154547288857367926863109897916806997328848306557928981283734566043834603735209469550380544603011 + 4769534552591442528339142072463485535584209788041390319662187991947284630203143273451030277553655546597381665676996289780792291 + 8029659403865541723176070298858179302484672898090770785814054293418165410123040143090326214914018331298053460618863938939353357 + 2504331261837289138046426704519324433487258219679900506483638261532541113835978749947580235779347318410118894160450785891787503 + 9154332931976583483472163920590162126815140207546760699499178902132160947370072538150136322051659957346811166868803166980109050 + 0222142484013400331297859576897114613785020913334195683798252363342695111135735081039945217905782047137997143182303582893239120 + 9813120425348259494442258981684713118897639132890990099359593568005985530954284388860261356040562648449500126432442951864251191 + 9491055336614888264152467342246996843863880300943314768116172425467094897669780084992632583894436406804533915530813948074710378 + 5125880262000217074108251922916601396846452955978383367381037097928649700928330600429463193168987527289334840125068384753709726 + 3250963913544985283516074025079436289530032965000091704733601456641384410110473920750483277883697522865698072624602352586775278 + 6909533273650494192857472271669762600062165210442469141500817398520087420757013742072500281461753556164642072928308813935348280 + 4807129228896091173010215184046472764333315290810434138260279373142369497015166184160402673619706065463269358547161491925056454 + 7992119117554165493880872181423830045252323577778753354174393490633929436643377607848377532573742197373252323683113537849603683 + 8841806293434459100805456108210596607134914383853585818153512788887296784056237782465358856155449499271949927041469376892328564 + 1632152697497520229603928059316997370226452543375632335002549957119486189260078571706186257203470953055703949967851861921520731 + 5864396596718182058160283419308429964136934231008821382389697128204242562370820069167753381761875728312424003987892871207159646 + 3666084774918882500462621483992172725824109862896378199142479129987559328773744933469602552905906375001745899273316469658254151 + 3498338535962144862096688449703329334091149790999664223656029226119319000718124150843673811902580542556051470065598276315050434 + 2588642538822153267060185463367170199110995449008021906678609426788891572594252587471982661988824671301251499893937578926745391 + 9319707795744627065170409664872689583830132047201026242383522246999299133923376128562725383185342894837098008031828134646969110 + 0671702811161136021518386108886822361915633677386996222331112492876474384896788653692739997207795179082317779078270838374606210 + 0529680562308620614160670757652951824510508056181488035417621544956335930822186390269360882386498654576366806627786546389748223 + 7121344007162987446407144751532917923911603613369296361423444081791345960568825786153422255467670330488573438324604236300940295 + 7856126749900534423962976560155869500794418586760356971148877729423323229897743690930063998855496652306786264023420507384957613 + 1115472217398806310578221635364703110916537667405172225846214402717552527160481181622222803507823937807179294058810167262993525 + 7733396618045594337624445678237438829647882527257597412143681872681853625778555809127382419530057648275810262641644934924071181 + 3613929384294435871056622853422519700112176582857461049491276578382237331260522744886532614099866550813707901946900039411643678 + 2471863854966531804604197010815017888282961247506056635263741803813648407515388558830396273074055989597305977778886391310447068 + 5772682018682680181055188634541777077934406094474845232952841473576584969574909042981622739932442934509311768673906919851347223 + 1971820335809415226886329944736554280331033759806916931583970783266805147633904060778157532814909009520404718412464333929846412 + 9304789467519446866413824868897777103238294214707967726874145548954743749977770022421296628566823077488711722686581183789601459 + 4520829387352906480220193366391017100275344244933837568936172706668016811057327408759076674979685576296077953383462420493700931 + 8246906431343919288012465266462141639350962646993227082304804964566869105156074039984736745415005176673660764795387467919402546 + 0186162998111273052854513690953012281012706484313894676418003816742150384731546652072390520748548343581415404883693106949598503 + 7407453409468893649012012693295080963235028162714227398127099455397823529445343521263605978197734068303737481555026299674237511 + 1229395187707069269668822522188040767339600015117257223444650130799671208076697307072988709360546665590067811729152682754853792 + 2543283984004058807502208094435749036903952553879602762556029245920852075326946498509084553554503835502118795067551626235164267 + 2007797747581357604343336945727914338356814330722751353631792234077965818274628997502349441503414970786616526353391356822676384 + 5194656346701670632084824377074289402109258239302810982753490912710811175011533673266509733689435108026608580234617657393376969 + 9037146495591802460947583581948869619219502922722697707400434384802310554421740985009894719409552319891457897233615461251631720 + 3990697080273078766162376909117528749470352764935216917028329174981312070290561402015804824976866738329336998564205666524939715 + 7848352778978178394189920640395834604512765967920164240559275230242580756053219581598506048812354481467677378211973577424576951 + 9532477816991813127692436491685156204938010748592475096875883131377908630365761647389532075843048673325944084338736570456096797 + 6164242821944626959915759190590818947629953857895701779138738262444662644883838599728736964664029753263536337011632748825080378 + 2817015241236739478928849304183816788634913242150862112550226668153792859950263630837585979285928908928017849179569989536100198 + 3188299380080735588065637018955883708261980780287989654193640067585824757814983887808561472404025858752559638368589207857289458 + 2148159553153805396206627740954877447246881212999958661604167091735503989349952300666940107138834649908131455364478740204253214 + 5183812867943299697018327767670320460762394440257519747758147645570356514775758990004394658301628734229570022912960712413921130 + 2264795742893091605616321707447640168594382931899898384410937459110317820561426704161424031904340033048159158399357351652777596 + 2139572365125527551258839222311219599103367463992672950511023648604600231272790630354961828455031402437496547839035832950304233 + 5563173043827945218120288721053385228256759107947287607765533263965688120561373605092351078219345874822210656978425318969319770 + 8518350618323036588967937820117667974812517069373788130975907844737917546000454481446588184420492343516807727330574227463796535 + 2208092079415381688598883619322045535433174373692220944523386140424053570720154062384759984606718110454232154813303857905183459 + 0403764445312406400743177177292964855962834587085077838226697948324657642954983884229554291774482754430895940798928630071520949 + 1218078030268093244894387180566099112644808636942463725970271185753041625812549630461585448271241111674252623627152709755765524 + 4640249030477405125378434884747349008061139769305596841781606951188241867017869136729477063722445205619856063985162910427240398 + 2909590245662898324814954125183873527735419113049232565629860534526664160220755933343864533662307471463902405211409478015729764 + 1532024154051612895466466141175266647835257739963433595273778351297990606120134172421391748505385924656782899507982823237116066 + 7625676430217706141880242765715903813773188383257526213002250997251341961521914541749167347954676286972265765550795698115431540 + 3971204449523415473814450392924406717851351635913252062373246080376997499866289003353070967905385783507116089156113219681812229 + 7080951492315882179871809720207741914174481310077398153033680591523295504167580131795931815413662606081970038126846874489797367 + 2964040579217611595547760234190477290346436427835968877980338437548172752209833653855504469466390943293257324156532489625950388 + 3972616808815375498057586682316341344883202169607183819718037286789995473261003288017415010063837288806976576286819527639032681 + 1290138051725002391039102512231630818525813814320415691425261417707087230623051869853213472687397101016144678883680930245168423 + 3850834662586016207855419987088023334696460550057253060411826174208076438814838201928582833181083830814307068201908029863175971 + 7944749902703521228274612063687297856087416799604592533936372400167341391775276233906976252493497295192482610468181988345091916 + 7011096175582468584236690812621406307216715768647084636075068364924266221366474623044001441060540006895424513815585241978347109 + 9612362696533734373153334851655466254197093486211639205861389987966709302035551682330490724447416578042696870553662285651851441 + 0111552534765233442760444257765948564305822466469203165903339169326584537556214779726091179725355707166736526121645211226756106 + 5885039259881836616302187141071464709494663689251644989212209295897461744225634984400183422383926438027326803031066696585257111 + 5396579069429715251643225942479087285188610492026082322649552644481241838275988175206718743351678720472794668564948833054357449 + 8688233606386980591001497882755114729508367160997540301693192893291539036951478433163921320714186025327605130043325851253234451 + 4872214673472278544834646890891722960548978190052377730643946484747055518801507106492936171927846554906068388153908514485343068 + 7214840374326612339276352609419398397127314205763710059777054421447567554750695002090543962570373028396055745121721373269382936 + 4524482436241914482911352925071095921316760701089039169544052169552093783128384931032814298463081577630793680822839743941613795 + 4223734008339327317027315036935919017365387705335808468598641390301926191406305147914145568155445735877807426352454856646393111 + 5101170944379204574558835956241764204898906557725918071785044288986731351021322301083120247570462572136590876553271594974477165 + 1498954940338463049076496039744592188429182308195708965464178219513192666612550201124332096109168498851228361187923717360547190 + 2838593784210615507907908324852279814008797652951109874718831612968151452611605913542110950712021617053098075818112497307624799 + 9381906333865113269293243176861228537211612376105763917319466803899016867981408631123044887142147183129506705177986309824780722 + 5409043531218283220619747469806558139995337403975277796517573718341286548125289716392847076083882092014379916668361163684338425 + 1904893321014375227674131798347455361695847285890504332145250525132622615658888584205703776156043946440538442055020240373771823 + 1351830991497076875181168528408533516757044944191964801761366476485666222599596030732870772285002472325833568217236712614883027 + 7315021210616605619597435420913698876375528968662848736161937624720303296895982028335232063555260929924269983942028091369465040 + 5072200871530059327653441988927547294080741487165355628851444397293608964873155978474929308924899776875776153220999350338874781 + 7297806144047991652107617589673777407092234699017295323732250434070279346790076112443512292202647551871470787944370705490593514 + 8338680194506251068070541345811382066184901866943035469419313397753521282182668152084983612781310002659403231835343007351253055 + 6114581775690037701739519471149107309520083450078485755172388779153808947468636573364766942355736298359796132744647242525151199 + 7574059840087355237287159427555431111919013708861023222908038566164641505519732443177083128309239177653941203870945389834998157 + 0673474392377001399825892148070125779937209491690893896089896421739180565135864053866800087116893052683453216209088258021309774 + 4693630023596081716394525302256706650097913048822663453433130852833930985337805085115332988734054335391426675730296735748012109 + 1093024463171151726057935490277564245957695353097684106836395483499057575855912524860400186656839768087931489404973303617192884 + 7635877951810419014091014411375539957398983529537012020519286943703105851379947162885419241335326379003488660213681674994537920 + 7313912009934610962402221459721660669217906503605255214027757570091733853488694769091622366303142874602414314687218525998341547 + 1566050559171006939210753283371737704974135991991141945660050193578931524036467433476181347487862613613591250793557188528520720 + 8176429431061693107924500762483197651311460029641913001176379201100638867103309766025948024030323914130084770751860668764418979 + 1729648696441840023063291425166270194908270401060650039064514332458826292034060316832564595611388754933869606578691497545240684 + 5096948893204927421293649874213362565576773971352082850459718459918977951318599802521678656926223913450782713343578245294043312 + 3086541714606171194181739777107223773075014101828171109460641650405365226657056099487143258905930679574237317845176027548390939 + 7740302926757091096782313708390498469422515280866564744352174072524950077317896546008807496266670386420521998084434771204151893 + 5027934064208470666653625072824590692528078583512194513874229573957257382460729248431045517338285948895199087965965424240384379 + 4571860754401274665671127939865476298997613160622025616980368067727347277864838846767268485621173877779887690613158095362529635 + 6944876714447267999239762443038959101083236381747476636643523496718859843462703424789350147757356429745707937022796547995361159 + 1608685279655308172831370710312433300754386599666997983340912162248117716366440489547493562293368632280675661325251959965144367 + 0470115155279779686716584895721905617913807392365128663764858517955975388392843450401077964641050043314321327171303982059553970 + 6215103349524529478271694130462996515027440018395285605756916821272681672383831564950333676633547276622946473458222960324229716 + 5752661076880540890733587009248458903926085507327954333035749203073156883894621881819872469950016600034383209674501094959670531 + 1945586770541986321354980385963397070039734408942633942296911586196737659678600361467268366772660352728384921986880900512427348 + 0224298460720490332231265716874929497392701347632450314627063512555464017409367105505507132766860559659364230297395631822230539 + 1702023132625842749699356356536784362975613947059773629978196487288877402990298821674431326788769352305708774873068640207819256 + 0837874454109632180336808361233189153201698197837194960277668995755988025271886650717010166150668262322432532297058508033324759 + 3169311626099247379274799980132948823347592107280599635475818048919814215035606030291543579920124429871014029266938736200412702 + 1914619565140979302991699155094170839054951976790499833713849411741065459327090513567799966465721776223514774008243762437394273 + 0284830262288056137733605741424808121279641702537891966081045603173960192239888264018200262442793489277094386722616393425116590 + 1173151387211465492751444105592198529015440250049757464822160661232074007786672709170841572180341360083386765961004042180282066 + 2747834197332941363146926817441453515366505571978984487189489275517487274745916049268403158626553738640115381387510687487708488 + 1958762131814281375452347210594453320648975262319481726099981862965271971390001963271654018154213822420613244796687794506233768 + 5861590138913305751605474142329109238465204802867089486028021810232894377402829167243953763417451369079334074531476305390636648 + 6931736509544684644323440543056340368361669695138186889701847677102848670844548402669049251722131793379128120867567738961962646 + 6821092152578736586590175476051687813270318648206546383329391485549308897384882743702278026541948728683530021908873051239269012 + 3127870261792191598343155115866595959890760429348459173942873213248004394755219777755565345896164898508858847846745938219558572 + 4104690546998169355396414252792133064383123628337383872945199098541769741499506855287626343383400914652705990644014540006261236 + 8792100596328961741396764802811919634888917999468524631681735602589600555328679349075778614192998476904702613310979642799638155 + 6734793674993705010403616483433595873080508573310753327845752574399663353072797746592366100412052447212721125322772808600316385 + 0099515723538668132596125963466202152817452490708599517233532239221132293841708379481396652887673374586403485713968074564071453 + 0083805755888358130747915433250146084164753782259744459712819051842998158461581619972310157769421457011089633907439164606444507 + 7652876608005273562462370933960187647117519619868786042595158425921249718553500241273244226393132978251127763667423654542879946 + 4405249132813172389850479368504130884719811118887711374371841091799443512801595585892341132692059703325567321860246290919547167 + 6941199045895501309914547487559727954258599982156757774973817213033640726217789962907551298312065690327505399614397188477788050 + 5358645453073717607933338901589045055393757684759513577031387645637409945004898936885098068574782470685593557377991753572387018 + 4706013177574137609818422036943485331576839280415982210652357962891328244924452137995064340517319656166353370990119146719861836 + 6329505987385677903166233247184756000826411332850477352758018273420949926789280244169127178212529891658087198774279941207714390 + 1511370436371213645604523617727839098695940567432172783593724006252095799407942743832278211803447800402891197805298593983426545 + 3022464264863164058488714249339098231034997516428008392896433897781383885524218363385806736382055438093644340647396074293733782 + 4501101178543767329620885826562169899606635544112652117620964836027885674519772391619599940633712271697963657935450955634525900 + 6375010018855545330452050093482150077359764898798182405456683026765532905675606074372556178229924063905296358938093169081598198 + 8483257277634207523851089755598501951207216079577367620523344599612671928857960638762403403726285770712060711385777082614045533 + 8256451384331378443868986535492407706512110875647453641525322621598498933275339800741719049869908400644823204415096675208523961 + 9398321546440720870569872262936542811668490033035472870984698676634686438176528523891161540254323161470512628073841436944062388 + 7797071423711013392162710663609589623668119033549706301015274145920933018984092472146696838533855941884096071158160204252589379 + 4261414209517939560365542448209082777049757262017603674203052224119028323101718025778556206926756191607192650438859403548542695 + 1466289085237622991161102650836935979121797669268051582725264475273671975785294342068745493084363600896894177743687712147368123 + 9181597431483593985916614200861015600827448233462428138664038851972627461175903260548893373194383862378492912625568875647273959 + 9257826929421951643418775488431746425388390160227055490497812088985726596130954189607412047036836095076045019637105980229125135 + 0051088814685847441269344262748461773674703937437029964258894662753422844953047676499113437643607083551852374126649110465539183 + 9719703193787962011022241398606941751940065229976379345648357311141518661729448144028369831751739729767389915436519514302519528 + 4754705205114290966030322546625592332320235853494013451121235653943274561055976709436804717429731588488742125670116982095506624 + 7915307785043160782062481393173682663021526076353055172054644485732609943157735268019683657488875580064373381138013382280006724 + 1348120551409342824081918999927191374394809490457882851229963796819461455853157081977254041113267197827298870478281259789531341 + 3812065821388690082091959389908490155933727232741583927718485507099116748923648769090644447688804257458798099398350465758474495 + 2937863476645119756329442458144939324030284617554341982278719802555921010666415523070911564773110585363083165465312366738827231 + 9179756558387423308702990244249813252311594585173041207944901196092166608366163256489844497165091829615643175666074910233765563 + 6459378049219057988171618077989915820678435345205197081776728544947416949166191536837274889454949606246062308000247423136050336 + 9590694274127077084581072678020481871509177233838867384578103147792423645131300534630220077747270144036126808318115046320973761 + 0633314308759908977900550446703882605141401119276147159777634200043370016079844602659915203435729306675829065339742126589258345 + 1889317316284541412519941066954231638054475095114130395821846044209964998882207473650227876029465587838652109009674311273487678 + 1491201614697119361909884499515016131285970573442170426537294317539659125369759905519191669796894139802704690179128614455530965 + 7312991894729010255958350913145958890797364015827373553097639087944419042322472672141767845335817123220952073258598944857610720 + 1824787410780276399243095677626477613009119292679764840577779945279669981000204638159164277233130499426714911295485793124165881 + 3599221696151384019695918691913331345308102473844702422853474390767392532790500021180165318933884607342905862054572886894689533 + 7797578535955366187957171752724494492272818965402286074464704517072955420112819202222670121573771410655986788904078893257371168 + 3476992235872213742357632857624847275225481432286353014243838356580086497628026465199448029895990288276361657184717108337186384 + 7666621551208709893696388991140973902647787737649797506777580191326933697405674502023865297304974748640809764705859758691017754 + 6544825495307606554357924631329747091007811292348124154567821317868772060770803350068486092232254680993513246201748613742385991 + 6866165375349816659160016479507285079045466715841081115993221601429358066993308321907376618487248492349626318569998572862307928 + 2954124850369537534496609519161469912394832203382444510628904117251662671751490677012621979800464348066614680001698354593940135 + 0193499508454379205949576005154484505543366786538069430200252986165917146991374529470556848495722371613024998552648030029385354 + 6300091436093722524653066330745577837674427424963685925900231612998930766803747751089009018089480544176580489192755004987058784 + 0521904612577648015929532704786690696377674858853171421019639025087849558650954768145265982042719739087464082587058116910545924 + 2995811242507764873679857631100733041164546962708369112790103328792294311269786039292022283070742012101949352297665947227182231 + 0598910805263795572231168128611351576632001399408367899641814748409013513401170040370795100905848171920487777572798457368620639 + 5688904469919555388263250672582090539068694827337359228605791133091700320455439594271216798892203930514646320638691425342088585 + 8515424974655688512862245643897078195523156507477939116050565619183311712594098054858317849757764852624936019665610738326843069 + 5113156995533534391502169817952742278838176530218998980784387996273419179922080679783505603663683376521615832986618021979492127 + 1086319824275441488370793880965889728722603318901376609034648244802721809098732997770252918945517263258021059460064891744542026 + 1590099478966776519298307952043122519324124336024594288380180094489716784777893529727657815697554594607079223393500535902031225 + 7357641282650721485620638312466056185406173433791953981763404688139736645500991900862738958018055032882772556895285743906215162 + 1650489828204176805947705046005072475080530548765982426627534295084219207983407930870882583588364915870597364960371942080426209 + 4961456796449042167841011430036294492463136865448894885627513655748299627165496853898722132001299392052298889154231937053221092 + 9292679093929935825812492666003758036634836903177775163898869080980492856814299385978432904050294518519563887081873640579238706 + 3011512315941368814678516363524198263828364895022582836616309022291899256400386653229758118495144379060943664767132561955347093 + 7994582030787878507087359159314617931782658556072425334054967106060186618004693028010903789497198319676911594575116984344480865 + 6353605238667338186351983657599555627480760430658384201616896420757729940462911589836581183482303716623193619087127242146945823 + 5587627832512661518234488087236957525879895860979271923639746468639388295216331627000259398878042734326931204663332399636686573 + 0672965511904852366825996694902980930309250905369947812120763277890579450585046143580711709629358309790006863408567461111578107 + 7579999047873643551313574662014234072727914277127742448350969386406545430650595860664380236476144348769728322529154001617830780 + 7768720905776990806878980911933213548469388055876623124525549575902760321680062870410042191450149173795942693780209583496274718 + 7500581851674961002356261345542689400915034872242480502581980604450197467020488142845109390383270729947278076491900579496982299 + 2129690101587171429651661009917402506767801016536968984813683892465052790569498753467876499730105980696506174974591421872344509 + 7047018820490212289369541715584056487037206133357581281018603240803633328043751106808274944483601431153046581012102597333076902 + 8327884098495349573228357110403653478827808473415101824363258200250596339218554185491862934594792362506926494486378909931564949 + 1740056330174856891125669279294923651309763604203532765617783458152533228430452541997637109088581841891669514331609715059758968 + 4197367157825328214419156751555885819747937310581379204615061923091469679845199014292435432070508700023932922581376409143095993 + 2165125379005342133424590972755612895768392827051354709297231877589314385116008084334202246281649011825694669304551295469244979 + 4509728839111272144692019658264673559690649474179262646699331625117318888277703635865926266976720285188867979085670193580891875 + 7275477166128052446741208082801962510905074668975005769114065221711777393514237422266031434604625793424024653464475330291262873 + 0817046411197027445752205700663441451626769878011224256767794721900542448009071309280703954949009199107668829370562168637408040 + 9787763619368655981881242490879775693879040221802840519661369579710229328600940826654427779387311550329699789056384531195194998 + 2723448594543172549888888596962814780076107260643457934204621584814413545214573904777806106803313154411323713368897701260407449 + 8000951726014956095448794689858919573269714659606606617498924039765372767236447524498222062645212525371056330185170891625286898 + 7400634580995643373473457408678165048789850829161271772842260046851336944770097590727744202976687517001530085639423877373364847 + 6131960772116097152434381501203781193864171006504601138647645912125860654370952251962787439280635180850121164508129160794934976 + 8194796768491845741394186667260815254416308027847649620467735109219757947751470402197659639068665099777922925932497275155739813 + 5209664008657449547795035193830830788192397569777052795318568835532699855624203558168754541268446171707037486010417690857467487 + 8377976554519991606329945190868959375772837211176688945495596448296939525690240337764633216663866800325009183616688088580000528 + 5192787146614999641495067302066620692218333148024412938301229255333067720338121642154391246693289222550082295681213541896998006 + 8136852204722481664059335120578115477689164853072624921786692464359828604653937695373728935390680120663294293493176103289690254 + 1144435038869128719771735108732844672639943553994309593207501141582954078007058121278827020008994616209652065957537243296195065 + 0970656298377136326223895516660489631269402730038663872646787518014244370067321464425302758563853474605729399708299081361238244 + 0240779629525661769222180612134943092596901392802155389763359378856115803129803025504659400407739325825079102512268146609621569 + 1920020849630289059227598433172661405103577932866917079329997842631426173495463282180424424558897910324932519322784595681717233 + 1144193327801538649747431966846093543676528159861420323208804005782998653152702827377592130780075570401214786834816747288844424 + 7672000694647648348909906701159130777349487715893771185782393615180543175659863092467698777377397102350383295634648499503885338 + 0495630306491592179663093479474155305629241895069310776977867647781537028272341913619281785471238537339471770501056143359192572 + 7308837601725546836619910084602280257935558569169920782961917685472285154488319168403367545336906857013748237755825054290532894 + 9661814404701500878628706398803486793202614438164625925828662516099882010742067149392493627954571934045651513234013334682059852 + 0312168977557161126723210896500911203207572745509229840888786198868413208045541779692684493190694384662556740715047630385587973 + 8520266389063839477339561111091620930884162729262785462465146299021058533677470756448900131157092740484913244873616221850614852 + 2366892600338849323238354679971377016007007696850190096980341739336594207986799037588279474367471064265784394163814443326245256 + 4911325423638475961054407270474262985635705119625522856108931080012973303196967168739739944802380176010145279834846779349851937 + 4257810389850148158544144932315012034020829622092429506782620637342284858172415547207765264086812199822149360687311593339577078 + 9708659858477940738903030251204629213359548332123829955153191520032561522000846708640602917979387525987407975336034837147466054 + 8086930623135121532860695594083516763569498334428501641151038532550501591735570621442476271723263173645629791905305955098548029 + 2777352200022791503781001509067591047738954816120020121065054036180446105221458464420759433938919480637654297994424050557216733 + 4557327979787779116307153599001198923403057470538783746410924085722270113118125208362788921890249447415394699853853075390237309 + 4365884384429048241521760483369109759203884801440475321881130286288789565265074980716663859447668954490193155283240957032437631 + 2400761044210689572007006009552492603834440745618264315468884643834376009957185817870038205575856137576307667033965516109840180 + 9737040417279915834911486990827520959476936502177184234720809847197612305989565105760154340868284644203521456078055612096029018 + 9781808678278846885397125652129297898882169803910679237997846224593685450165476495607070948013373905740079438009246883252169515 + 7739852920294363425633218123401420673829295163516060432640021373043583962110762867984429100483394773437741380363822754539046324 + 0883431115446791272406513984118239461183841794345923431236238292749873478934884995894017966307053473725524062094771916898837907 + 6139386014396316197310075826416043562421564641768733346779156742528616231256212666391070181857228107399708720583287723130892055 + 8564495834035892079724353995520557131026025067703760714350598180164418444716168502414005579666385014431317699567383147791141861 + 2311406885413424305003701677451722846677377710768986204839545491722958560065098823523147478261771908820851989126482817082569115 + 9602340226869859614696378992497033778548537442058541618817057710375353486743749797455027651809309416058045995383235110379798461 + 9628709222162680949961060074815226201933096277151174310696525731658668144988286362519156716805236829848685383992849148064465103 + 9735346812240729849346428396581006547963793149866858949294858741576251512791660305611651687839731531035722282235292660633788691 + 9538042061855430905977346502656421504814621398394569363683719060626568625659708532699356988708790883640172621307887407813836364 + 6305019984976325257337569429166547690694053229542307273781369534773313407694544352991644928363693848808898178142342306260087117 + 1805704646504085604801764484506100460470712673185793035853367748681894021658904030806253312188697070560965442489042489792077571 + 2490985236219600794455119570755743690829793064352980492197865586952595298856978623488801799239792633697972577551080842006688049 + 4451839628325290929728145285465077829042998419941805433824084767085375358192064592570165051059371791323138480645291403839150350 + 2979438318932849641805788421308077401361414307061802172300131888869924632094305534351210554801463479850767128364891176166829465 + 8872921500436141106816138238492673770588860037153870977927285412564501357209059187194899313386454964167921543412282921398037659 + 7636485131279033828460677166640282160440679145358607334279812434544494120552175807283800350790566307285400625724030248887429340 + 4680751592769547019498010899871228144441828285042700998685644394131763248290312908027689367430340488843863114128754770298553903 + 7371408142591796865710653973046215109255786437157352313924442478531290092820677548020730647005559727973069973416903159076053104 + 0296204614919758433624657596498376245793058852298819735885655373134544548701918947319286620768915718576221199382936906689136966 + 4514861015660728180490886079334753171354215683899059435960727947953401618302867137487819801076786142685334483700384896695954037 + 2862199178730357056510866292501440152986864077701674864131708177930481209373944027435441136206079828523990989033623289788521958 + 3232125855905003070647322986167904784829417211608519129888545490992306400854811324029764732798696566611533605039116218287211064 + 3328048087467522304174357185558580322486932881453149442008314359000540253074863751401069345083176437332910631591438430165816043 + 6086110405144344067589331082608930355326779125945673110136783179380891079747539440654925994890579005806127474614509336396435324 + 7215091301714414443069868776064064504395207482808517829405383379414684365187710912963053526301972343897304816484149722894728342 + 2436471129882505774580140273945136647748090634204279933544155848974105586771383680141377892142181597367201114241681187884944773 + 2048644482475865853030326358622959819676030401734261133906361439604280224652350627125083350512410927294034793877892580606553735 + 3602935472072437248748601211519488988169731855279575778400706577254567463123219123896535430970244921999769114868734160215986062 + 7783657628040022836086246510234417653915945131795351860293548640058155931582229824232337815003665382949403984933860425849161499 + 7472148054410673792713655531708222900140217409627089428063743914621052166172358563633841329724840401144427912925448192355476917 + 0347053733535476550133949622008506766494989314867137093489295258193336447136204549399148001892481820212852414088927422900419709 + 9639078047884835538046942482094804161605891002036742318046907668105442784580061293938476627159719249453272549683221805416505790 + 1032786228200415283294994910054729118848671075845281886209463073179728081317785205722424406468440642562912784973899656483223098 + 6968595178017412521208376863115552570593292656764798517030930445070380603195697501931025439581550142699705302804245618724490111 + 5453654356413064906966652124099905267347821364144623020142756809037695527255942562866173971391249170311659304510623511853516154 + 2732536262071170918681622064325048337837520111884271935643287214208402090379942906531363266640024631740298714867728868944222573 + 3147285446615157276563228822132897878376378847350594831988142529113309891139340761458000809351957235529902167556281922497506368 + 4354478919601617063477169153215969873898414180925342349186710519974948744199229908589593712396666250201617868945303106857533139 + 6882511013607261756622150246671069745871933132400620002505947164316958006187665439907383822926483113411891198332966708317599278 + 5134964407461253261959522854559873663187547708050982034442691200555341283933873911454057728258698109359806239057894517156699836 + 6450666103279081547887551782344908272320062944069880747023544207556937435206656509659651679103507702121341392065845820245893429 + 0369780371537429488949966165797604230927289652620569227359744404503741546226260737989821878745670653730192856868459952515531054 + 3093345869807819730548713734544643718538694047498494322996726007960107180939172720629651622711868833028333458719243526925076960 + 7989599203565850572942150442657633965818968052176208211383992661670496993990824695668976291478797155039216428981397014999174383 + 1307119242405531123217610464790254600437026788611070015681427406612197589802556879143899518155467294982590879340815458735590885 + 7771734336463859132744468610337712969586326511610847632572701236574882685603506834926412287387742247547804989759024383729486919 + 5271411219228882208040644078382620627789689028134461694434130394862996168758457553833289759810275955726724366779012750280404286 + 9512730467284947060387240979546511277358650894416265360099607348235188428440048072383761268322342324845297508884228837212297345 + 5520192598997086640709924048681358015575115024163991652287513881247554854286841200564378110057343645081513230448973403055902132 + 7020240592700662201858752560247475343913953666111892278775820432145603140381127320826667055090149454135269196723432849201394471 + 5046712344141591199667738249797803701007407397593500840656021101416075518278507896267944040576213675962509419570331142339223528 + 5009173314040221242742971167778009936788547416346651832329001334847054317513290947080798012432976916063888435394522306337209156 + 1366848096908460688950147484431870925661107449748979391978321496249695501280906214711588783547789400280700153426360634008817145 + 5032320677216082097266187853807984797656213614647275198101803139086954569491022740666386321968921335192817122277500443048900363 + 5004785469025981206660221297903847696398366951138307001168655587727211921402639926973173862035209940308951165885978641411045411 + 8785398824958308479147867520302086574154227898640917802025901098713415060910391722736844682709559806414137007346900318504025652 + 4829177039724412998798470463159506613910620057768809973408365008034259886542242550978070824664073713620021235802691404413458167 + 9261226904113620784725763761828029554734562287674270893824453948307773514334280989553881807221303459863642843519335273228474128 + 3311573735232406552245381370523373424363177967581228254334269537766809380288366330679697723673023553333593300509406940840178257 + 5850353980111617800710390835159343131583882096987317262767588967118575624615788759557354550955443154249258491730584290096574346 + 6058742867661098727133777961247323273097355895095662383648934730004254372357455111922489913009492093823561131792526688980983778 + 7068373836217667990225856363415691473206022105532884987579074277226993152918608006384495892970483440333181267244554192632887695 + 0375929236714973683664267906774009903162875936131255110025871545553310661098253000439303508717945000859600253447780364023263921 + 3589236909622208939924919255987333064134666511205037102476749734554331712415072770445515704120917930961110839990243914307170158 + 6795584768746356073781978623124211251870230688353778395309754364333319536742360245765209901147398777468379230149142523181377411 + 2729948487677410474357762288343380948554393380782338431844676175646578459942584025062978984890983296713845183696219799180782039 + 8853156389861615819589926505138052323380550759364020828050387019448769426662074170464533329827565869171293278882331249180195752 + 5354617268287092363055229579924827016859348547054043349609066878817933385065188678139799271936447212380584467570750380867131343 + 6669574812003056132820086160683395897628895296098843871784268115803999250621428898234509785779912888254113882189729913124138323 + 1094710833263258542617692112795417986473641110466966207723302828445199198995397058382901854029835381782441946019335577334721714 + 7084654187809403875061887873785967514836739155665927380077234732823032340675248478794617424267309726934964316167994411232825813 + 8586810770368457480021270214945101098418804122645991758117744041940927633232985858835902473466474854825024480648895385708401183 + 5596898921066046808429836093228050083092077217562084369964360104846761170405526779538921555848456229448715495096371173722462344 + 5660195590159993019077789825004164832246820538076625410586718868028600352830449932992980717485232030870587444549082470943172077 + 0821935416600837395349048851468072663127356309332941980901438793730151587795962214031501434310617749617534269164881521735791175 + 3042072934705160703532059769445721283937901499649463824595439982424043872605434635393216517511777007087089174560510963232009367 + 5464155662396168936608488040261163576038165196682279135320764015816698209508887367606848299565138365679605265583581996112669276 + 6753095562768549798586933346781184629087517744898743057935941129179204236737611864578907720852163937289062427955626269555922129 + 5716541079272109791401178359438691238957049044014297693164836859127158377764717929820749372762244199830728156908190474636597721 + 6048348633690063166546832299456572409599753235001536610146572139811087134501881675589119526672410909520126024302026020371798099 + 1171674402450497762501699459068107617561003253876215131387056282446344211385618131395030296408469586922564210025675216461987907 + 9312371022806876440175927558224158477356755411023006311819103124252221341547172708634888791607917037276394431911343613744399883 + 0922159956723896116809200304280546821592880397796462717485456950002852867129487923589665229233372270334774238944990617682919310 + 7658709241655408916654408381196074058493866541161875193933692025333882777349795393761970679827330490202099389041851596493234215 + 9234545178442642967566968436599668141535683259923279950462781030512766827071494181783393026832191674347556257505316419663487762 + 0041257342453564273568929735796453624713683399848511617479340816490608890963355058355974856413150349382759095918170362098854394 + 9592779304960316507865578967321355607760068698329045954497816675023927602619347677723250166350520531047186145206536424990428337 + 4299316161376269795506896486995922307501710625151467203920818965364151628354223037516185750241653836563366411298238504451597789 + 8841671421275735676647633262528681899530392131503705721695449652045887039670882496194478043622621695748874619557992717633215233 + 2073059696519439089739646800449388322820261958926389800326850308700850275001529873409140035288149114816334962577827586268363961 + 2490360047432436143344657376283381577226551875079136121637392911221073093866166045906272906769849919522908370281254710635409730 + 4974848754591262059988003622570276863287575164608170178580822963208162146400835022943896925242423440936618793540028102479004702 + 4372126595413379264526984770633204109208673880518625238463206225086878596008443858616399507133771134539070683384873925072702058 + 0639171273649854719051709551224607779261350414555233764709993649110326667200717789312129165461963429321431418833445603440663689 + 7186962822361873750181210266660607397813719262382253059434948056476254707273143420389570046116876618519383113357898774377253891 + 4319529017033432347952439153798524883464591210553274851928717915148566352954737293867412627976883192261494139098284868083014649 + 2622939111808623590774562258070588172127827495395694013730379591966886930134915200669202327099882207686441261515920355425526638 + 1200973651071533307294108492132851108586204275141332635739794068695424575790972361088170979623763207458716935295604008671317983 + 1251374850775260697268191392326213755565839271682628582402356668458562455145193885654924842502488021956636839087993338831884363 + 2092679910172237700017761223090447686346621171455515944807634834063707579619074178681232780539980362324148874096831135359068248 + 7059799025589703414119220067452626516006331839767724497907056535882707433149950178268364082722639297792594500281095862497786970 + 4542905544332920101592075397986385645511891063856851014878633174032148021231620025882083670673312205077519194573640381350698919 + 1312255205389657370322617251904525722465432117955235178041221031184821368449334584954069933722375723026079372281725777733909489 + 8940234530803425309074547064952811642951856360280155612932727691967562499759113316867977300723413954039644096858319695187621995 + 1667713304364140592650059312268785120415368020836414159057787321290823207568631669529330852196553357371986318924246623685192637 + 0422089184234642438098080557484372830069143118691288742408958852833389685002956551956492581208496774233386094905265339874099483 + 1677835356907666147956557529262732608196197501168021350247232245111279150809917571509855702652690905689682229523319549019678024 + 3645155615476272052329623583943381582821256380614894465459876556622453836730749021655688760168012160726745987877981868221817319 + 5647755640891329597098392215119820185325320967799221680909508299218493251878104661039386657485694867555315346235424508828545406 + 2249500944046395955203873004372279572553883458895334843433140571043474669708074473381457065865063499709405786900325552248426583 + 1230511579171467602223112925195512272958191569060831817009891427720423564097069405239471201694564617244826682098552152177059273 + 8469866721000791525531110152439789939013289745066720962189402891838096512969001059723536174778699525713458075138245336864075519 + 1296905270266717168150361331577154511349585629938472384230294812334459038517468323643620870384471376627488513753063864443527971 + 8484849516117452587091720711551100043539596219785764133452403530020825880462282298393651618450654255243582938022557870602084123 + 1944353914349184905366261486479354722961723711488366658700425467290309892874206605011693831609609440448499484127167958439545979 + 1904342525350793098590501390656028964534129323617049186915074724786886755773131382892183343708636631327982725884104881408443775 + 4047731221209068512782993439144246721190758070966515666060478086425710216870076434550244885851035049595368742260028400195490338 + 3375747312957348876639595293489234210411377963219380216708693519698209655124852272292375830483071612875799792380567345928238534 + 5110079232697543396393866568868109799067673989898575725771625847005572590499345721422620239447760726870678880204127450730489419 + 1892883230935369730591390745517921975081616548082333381141791553938700817410468926449238904528671037503779324573001732065035519 + 8395077376884962568002904176016991329810132526312963614723727626088091850321489438757392596606168596638103913778878129196298132 + 3938927636631738411085232552592623008752473475775738216360990000223836611551924314564820835426069886741001153829625505334993487 + 1299692449183332553204542348863840181665273246414104121624684776356638436277872632132123576236177751436546351690643540205371844 + 9194356489958293805818668234623245496942584158879649161401045859846964460358471563904833418667460716546730472435403875780613403 + 9275256836090272445757731146730052254532930338266683064726986679677894399506235508548851649563290194895324537517696553037056936 + 6401315045565945782629076626066813595555038611734944119511046358367624104666208828448443470577765348785145599426526721185590575 + 0586738484454531185743029468713911469676776854865676690022624209621140076731906638884334409090253652724218159918793965233464039 + 3171209020852465810305033445747086308509991604961680580404820907479024353374887015602705890939142087700418451581794807689385348 + 9424311150932643701645157338987499029528852262438813754400403069738023146915551968014972578206454343730343122265559473474927849 + 7742146609950233423816671939328483772283214892322537597846916524424589673152890736557038920458731659652032921748569241119859976 + 6687533180189782962288035952098447575892236672807319984532899523336137857362773056256776453970744401322852572058367357860586750 + 5112973080188345114036362904396465766939815911981737447433859679102909113460170044475876180448426521815838110280974934802651453 + 0141366660566071877771992446357332649851216791119528638672163150044856967323023760152081614645879961910911227845879654515023475 + 2214123760185353539707121031098580866690882823675580600794715047520486504684525675655152270550399135886572417008928998130462848 + 9223973656232181173590003292639341133004977532862200821270596930208889426180465089396056658959981954090935260888619248916061940 + 6623578698318166136431412779326115216613003933902509874343492190835346614403255698238178964137991654202739789058288364219841871 + 8291158969189181550110191401002122993337707939239499805961356987899937471416091612952104089354586248344316163672726189677077009 + 2569911973118347742318591298716009672334442600647034815935927622454202539592391699029450660978546827587095337413939180709898411 + 0899648100113650188435064875802395140965508050973328163902047496526339571954451436627138016940395531683176282436292339394573885 + 3218116539223354243511329358754444736017570099304122222814440304223163469524526595019625005310578387024223128529473465323727623 + 2903847495538482030544840551895363794476928236443136637630260470246965452066473119820100467512281726986329810864283236603867046 + 4226586385557184936270267709088518321173404628666811633771213904835009960571786348833009556180773685058946093743512399598902672 + 8536593915600232712348175092402812063615932808932457150254760365196790780020038688785606653890320304533826035350207715944668272 + 7207307332779658122899268750088169215451053148485733154400660830345046074837509653982716901490942833776007996597381089382249055 + 7354364139715042807616100729619187431380023428907586266528433249618278407719620456619422594117403277614144426686677487237152240 + 7463017222778211045789643242204755641148330540930800826901784405753146374489626927527265867849180494980902054821139633747003818 + 5151230162674659769071431499839596583910959703956345024479063722159584629356540852497161935430481786349464090482420412307760810 + 9834488101241849496636150547202745300929538510953947644624667132590235877398283748992791388091916279125999482122365178401663101 + 3799117737061812716778711014651789301773605485731280987694315010080752800132070053513995645594283497896886041897544784262244652 + 7787706667573783951864085352707088626343810856713494836743287556709150843482692271254078127357988781374166954894723733919964351 + 3850833609175684557920955809259004150766406752693874551692602542748508158101511651908521148570349768720243116655926752800025156 + 0542333256075861408967459343438031423694963841751597298639419078331767590705140401244001636510150856151990464720632445051520472 + 6303430699933496407768275797041897577889994294810383735293345544688537126863233465001327982318529841153751728223029693637728347 + 5397568768462052741831355049132795323985421528118062025164276988946171985642590654143451292287062379578161283874235728279748519 + 4640901822963272018953105436900070403241616145463711907565248533620946580204196365483196723416387548557874992063706490486368853 + 2187665586968675889547896116950223441017696539693810802819756256217188102291391477467930773393197219210849036472348714939348493 + 0530870138541801269405772003173391922440292694411582576482977240988452402062182324365937231322664832700142793000599915699446377 + 3232764179605713808662558293727950897506959582972158149863534091415959234408922619772945504672047855130269189456164558749700864 + 7976387712997851037838832161690498586021679479533477214488890351913481087239877288703362839723676811186594991567854176580725967 + 8767096970476797579593159059506720944428573124512821132135870916546309651522551842044412513318859523946351494542237948488449896 + 0718064204159475781113170590472579807866358541733298234646266805452325502205676982790448617382183104529620072495546016035798369 + 6656888096932816475747398102488120987337320254949271905969490909227960204913812078261626642629009104843808070570261399892364887 + 7197928827518406319220242665874355187232953000643123084932578105682719648228431872207900564999025910692470162420939628457406240 + 9390054304943829673541677221189814900027963471043254648597886086990795714249446234111674340418457357710907778877224567169903636 + 3047190706971324195888140547475741620358462920833528017528636158028581644462796976018091635090361132164631234849610385434473088 + 1299169151001233913629789222426928990506746164121889744635941525381099603593944992448532482489564134843216370953945058018816372 + 8022886634541463283701288620853613352158026264893049477075544241214340204041747957155846007535087712499320675089565208063975842 + 8518974453812680488184297781261482966404248280615326837256707090751389480480211355208009414536208955423929547041219391948623885 + 3604467721690594055924832819820324481035373705830034807313911053016213471052470202123999030910736617997566930544442854033269439 + 0783963633104292458209399376532444272248160361826344666316224873723641667255667675127680227315908535163742986352235015659049712 + 4004639628899564002311837850986616952858773518487977784208052701702476955042845648511721265262737849283604073030798668836277183 + 0862408653011082563803132060254754932254909982790619138767168477417959797920610077885997837256974272446346326081237570982197007 + 0940886136952306043500899870090754863364443344376526643707265847999796477272121932881155662360934605500536289044543909420287159 + 9325468416880604404675394196786101658805312863903480479928341990160539724867416343519113232899201923506345096672360143197907320 + 7602604379899247751883206653536848520843218205588950289513511227638017895858870330990465204694386615676242643330003217066315632 + 0851199846447079085502271034855714656668178101657497639831079366789502032474686387227843449343312220724903806454747746782689424 + 4098848471040002241791388735422021963275960354775258076923928679254165040693087908221190070756034164623860222301010088075103056 + 3055192757629057465255631284293545235726639464473675957498678493846951810733281325747646636144880693592596312740548434768830767 + 6731474905682791005984276464714844713588718904361218261812425686803684106123652431919970410078795392818111582997268429659349585 + 7924410389518202685905806688713577803625532077879713115752972677622209346192681858566234259911076164694414416704969551453021886 + 9355683562980634479815919874568756218379958083872036318959815690363034752884522901587704723069489938561066700856799286608658620 + 0543220462343036193244858851552821480362000689940188453022451557344919396300863983139599553360452940548134852258624017234867371 + 1067014527356580183151961289434647684360706506035600010429135039073802230973345888131418619960777100132646812026883383699827970 + 5359069383361932605007503288578185157851793814788353694181498218990573049785293883804780055838358139459377587968253742572072043 + 4573719136273381835268729540845328454994954362222395612112318303745157807658681724375200294326161779060096534923740884933625708 + 3514458846264455850674231783280205705825729759163794635971944702176098831501306476593168602881301267771422854514181550204581778 + 2814589926430879599930014687698610766303495462811227979670379853246555977897078815634814137435467174275073493314846601851573261 + 9109412328394243903990091864894855454386078755925003658916610663445020722891205775398782367407839761338086985543481077581229638 + 1491723826525165284311575346657279958318121038102570973778417404071686643040506005133105712555305338320966176072017676784923629 + 5488218241739200538202629320385686355121297434909655261539604247574676965715827475716615737941607238002608903015929093309168488 + 6222350309549145806267049598652344478433516262239158892817022906333942210072994901250459132730572231739319182532518293889630019 + 8044072077285353283240535057997955717161542654506209603492744952552847242899140500411096612225095709028876598587942929972397072 + 1885954490526928165806858149219735696470308645981279734404025197278823077339850867123073835557226495747843398970587652389656636 + 3636990744440216604699149114584326945110057025978680402356462092308935861145193409488632679598241716104734129398885084544095857 + 6069902893386332364062130016921517943943574898468298687528180638591233629526536463888804022514538460226447545474670300837773440 + 0715242925233223925302043184620521073165032928562060926764419538572558168218946544243657541925010495652673050247406203961490742 + 4163377094941935791929068796922863289449570870715728363127254502097952823099544701660693419650850191571787642058768071578191335 + 2362149372830570291861457450525257727016337864275693314681112878356465000993320675510813633779009823896594571255519867010367760 + 9335339409871128425332395511671431500329529218909754194982323897857550540930935004728114503428724192561034251245345901549129065 + 0756506273973719264925319448914314432556471353593665242663682345436151888535592338801660197397976918922142540903105362128344221 + 7296939654818049488767067190718755957947538340790260392001857532393622868997477129188922872359726386124323878376837617352814907 + 4078579999111217939011699307760285871218819333972182125286903838312055662520500719903656687016759241817857273468272683917688574 + 8726333004719198815434960721386959090224338905967680668744954339106442434132414526246207631805974218944345895924595868424575128 + 8809968439523768418749746186037611280882890683322020074536396621763557542013569567593054212148112921735580176883820120783267348 + 2537069038616920940158973428724068585048795501013293376681740631186566951229973336427931288891824421015980577224523633941036996 + 7974808176187279818828936860482106588007126950454089943602952411737485839990023098877207814888492767150658782003308086338815157 + 1588659669715002646102364063331711646691061797936643322785359527528662208821134749050337274899095692843563066296876088924734707 + 4549130202526685872258479111021810868210332005793914145311147798812593113617843971880716197778981371491177307945521311901222788 + 8560297570244477829694687977784621455987068942424983136944870380427057052887779787702603030649524780263375021654142024115901877 + 2048774313776039429808088171712835186320571466269472744364892701622816406146475324290364012640387008030349061922998372137187474 + 1958983930518040048400877463606239970518078952389442564587925608445408847664043055091202257080066087803944336882062127350978604 + 4065348283423540496042896789726757274478123900698244046915478972359449728574613924262102889566496871444268574144572205450579978 + 3629438124450409423602990222911509881985430704078927765904795404045938118161221397917848075421341126252805098426191320837834521 + 8085534923914835313209677375813349364458599796275600866316693139878003025545882010477316042716780306226946838431532163667037127 + 9898915134568321964545103764074604849670802062543079353666823915979509779221620608508897413582424170944308180311897168957048017 + 5385323115399849956058889239701492340513864492761797303099763383900112373871513361204005145800948160917012448658958645510687464 + 8637322858113048873422361029279103210946558131854412009103898341572774795544194370639320402689943405658836056138282160542993169 + 3301482949893831756487465487869018898293856072780727019945397657149862423574816057140762598392679733606145316506298182753363157 + 1989885295563430148607778298379580655148124775805236404809749482897588166275331919278290911157248463196182871139898936725797368 + 8850340804158989499571102548588275214111587736824329752538481445797164191835592201791780416442465525643066854658921528683230761 + 1421812723062059588410998478367550671697961940333154251595442093624642651562126033425248558504164225223871598921143098979968917 + 2477995193068866106116650832975646638319811948342255800290956070421894468168681224145709091760495793451121243995417375669474096 + 3150729646482352886032550446062928871539222609285098660402450856512727724053427921573737445175821849100475781418189174380995632 + 7046750620615596575236877490285020288321290904270312430965440858488622217217317102253600290127052465317624607416177498383288106 + 9945695686299042380678429305385240697039293151977430358157956385467140053019250720885367675692664936064594234820657654969335744 + 5571751022714308898152825948152037875574841245733361004625842517428626308101356793475497881525020804091668118665745094943275801 + 8608762448666074656196662829963227928222015907465782465504699762597437156318531429585635263586424089541092855892902609967867982 + 1978685830753176969518395838040278058667840236176435782603960672407003909222439483538760352906908927302768494238355233209217253 + 7074071920319953536604510843365153876170171633349491568232092272150542222706006804946809770825099582766752656052960983718114235 + 3280496115751440895543554193849398007467023324006497516116534251153591572725745514291959829061315518724947165745450390160259001 + 0601737046591989613120616719919874653529282948250689745032606820130735453268070027901333295387220734852357272804293331117523997 + 6136958737937467562116926228263651346592589988767235293060122410789132148757897567424381946719333849272080001742385628150689944 + 1891595701639675010992493605507619576155702842803896050077803395482631144748035073236453571286662875633494080865014296782405059 + 6994138350962374748911276067098522195781999897499082597900135054301540799702368264182765273926228557006482725202228009397664985 + 7788023609935244035749201882811852725625300846793646185552122933557882704452555648205100150340311907075711931570895497802594450 + 2197653103798752067286172607092220822596982226247423576487125070944191009560709583893589326623076734376750057424185701225493266 + 8863132327252007877822761700057804325184406486939470443703245734365105772001424789573894937476178130538608010471355446757855177 + 8174190110749058109791874932401725786307915411703003043709908238217181652029602262116068758446055873309569311805547464496642142 + 2490958747068677929992898459199669839140241121204680850335549077174567238373970308977898462513690749136086901700597984427253536 + 5982357462083434284507903055152940486985159078049952746161034961672224995628192794860546561549979398991180455860037140923248338 + 8926976775587697462174304166383030496921336111150196335640267063653243971405939737115496867091474614902122111713955464436671112 + 2328015592752422584686538755738383160041067711192111211555671470860520931401458590260603642848665758765427324349701633338120285 + 3238367054704111120178059574962944110115171398341904274585267575082605150464279484097073060481753901121878225454945359042570553 + 3450237761306126967240618521993384597368444622149529677366929462149782561575513795963740446321127465963106959992420775690369312 + 3448814725588587245567368751607825271329254275986408132599484784341832975302652140521158378926626072460485474580935278488412601 + 9150780220021887436734602033408383688852530542191765389359753381850912455739194414678686576674855611507802645590418679170889751 + 4835292344245385826099978982021385208338079311915794842181613685383986799333650292340449601221579759524765161463912861431586003 + 8364091375971775721571844301438463624297900164446658688640976105663184901553656708363187917609334998277021278755741801258289094 + 7084708048206234641953289421943297010794421803966656094223814335341165874897678668246105857901156960186097878571917343164253048 + 1580091826012825586670694920435572709977363754508123881333362672498821977048126176623956391025928031884064853593246953559407401 + 1343143393297933839473552543351834063051545756389274017156011730389906161525821950360013682370064447544881706475110217230969461 + 3302514538150761859786668968377489515133804300482090273478961905590177116881654275768644498073647264106408418864420104945624333 + 1455642109436975199690456185370628722356663838058282076416293074142932077562024273500214654758558303856335007961702080005015078 + 8063031532965823241531821249811544926127012157501395220835632529512891602224510304171587094059291180949555426978545235398053558 + 6792060710713434110654251175014016166953632439786838514140951524356192499726146571336067500056531834668571621898017480292338282 + 1437695510093265077864080367192602710341444418961408220405302548941539890702354912153612054318858614633735009858764482449040861 + 5181414865532338468286437374705876616670683310417100729198121447458573292151625305538384979133781114543503822301014850960361423 + 0442509889959385737920714766510641471461284309092021412176656794047214218226892073311469169814612693044014585717564971417728218 + 2325595356223658506960436649084028083363095352384800259697237546709925440654926883086116058532378827751785516901620186132035077 + 5272017869427934924377297497212161665902064352062568107159660976294283182349751217848859566575424801083760720335160297859673425 + 4927647302447341405487506286250768152116103802235113601574433911840768325925117428685709060725568588745725091307806563183578704 + 6009173829226300709392490503960716312095637543299322573027471284752881663572097511651811613598957587604124624018835545870558611 + 9874256128717490827444943646188644499417848153072863603454092200052312279880710501340245614763095671533551439274986414901802322 + 0712116664532492284027602515056442554560965687688409213710573265303359796914199163349296608736358741384041138558244053035969858 + 9693983191087651982342027390681525334777714170455444776207288727295047097906322701667199571113890318007616548536163726817679168 + 6706523778360875477183129443881169868743369990013775836046887154518569535610947164990958856446973388802060554267647855673512269 + 5862057420569669693068391429181291253874208771601116624815603880238130385298427887023332027652265710135551985724073597417285974 + 1151313997638402328677281725415458206631525714244607205307139347412188214659490398369065819541976622293080801350270699351750349 + 5489131825943276548129703872359273308252153537674522058679810049913479398153870812359217912596783251244700635734540612732369203 + 3810123181289945953628771451906051867522552261199661987069529884844103683969181491185606510174695973406830793843872394354042162 + 3346242314263710422512316433607417431578705396179309838772547308651613774189871178285455805352015354652802479496815910335754476 + 5032059944587174601615131788722847272253927881072336845872496308794095355330608135957953660775615970673613290442946086962710905 + 3407385896995114869865346803277241560730078573870063366755416777507927736959074993460049742600768481558296737228998922109024099 + 0049052520096863687692070927701978011226142548782375715516453178031755305702747877694502859869129537906539333534520649523091710 + 0991259574063512483397592194908683392249793361680299501959035992654866098958575700878621835330177239453007223378603834381079687 + 1103177507554459538813745204571902700244177530864339036101223775180048578597548931452670546251696214644617674818880606435247986 + 4019388020763636749355438098141001952281422670022244785922521428313256185545192914769702955966048643204981030086298329088086717 + 1549239391810219717095199987772454895177623386763902046734720379092060908409042895882464384442634362486868518995850543330943745 + 5263274887172899674152253042181056688293450964020128773142784973127071891058343458622006778652971493625047746423062870250661196 + 2492300927820520335243072396524887229850551524757145264574209619185242101186100663595852135831547431534587842715149723823788454 + 0239821705984933412196203741296576026949577895980132509651253316722691651055934018399445089497754941402505430183658650264000569 + 4454480470480799484331207273048645656468167612178274351303856622687362159020726843169180682079344623827123515453025370828135970 + 6142817374030811769491227966611452974299687874240073880283247099440633899922286466254504368749938286010203764066551001971357963 + 9169371099648374900400474139097217260717487967105154156622253602791903705738661081630850020115390238371457432815879031763979788 + 5560591117813511863922620504148281644660212448276865905578433181502848473767100143776780656617049797235772123812344362645447507 + 7125601127543091335948203843174929841142906765885076202058923049770681372235738838189576737300366872775686393117885907972185950 + 3813261893105186097817193647097680347436595910522013775725325978428043833139417789267610377229028363642103442485430761044994912 + 3166100516390908023193075423476442023657276364366869002050485177701831320339505415669888608102030204859429175627661908828955978 + 9494583112215459385851845969134725676775320276319447511947728695272882901489693777569547667119292451041697329224102769821139225 + 7691777515996491255498611230620011375291757353871825879292337748953866037150788019954259501731583992956846734646612549716437169 + 4674403391449814677760084246730522440833433795684947826674440906657230316614951017230444639014782979009506122819959837960185292 + 0124355369267161692186629219979251945207193338015531285271750882020294586168274943975716404048435047057151424920598922068881892 + 4259039872889979839195103377532319383985569925201669042943584292754218542022884377759029683915124413393419307275904131879991019 + 1735669223208908684334277224397343396336961848404316449603849894027168642444303310792840158007116435560970914275701222063897926 + 4461905512399641675513869110628312166872040099906116555152852234330620387342830937229572832948858700069818699059571737043133655 + 2317566091257832110561031578973018527337285656514910017567896208598685109912802746001639928928505435442403312983994465299665281 + 7100315234971800925514182498331922330287575769352512401970636582041663941571732261396082519132641394516031353060487765740093218 + 9334108345710950934819716799864030596011645738530063495673802842261253827926601866855793893356025796840470669373855061371630452 + 9938632519142602121728449903028585427271086908360215670337654867014624403654411514574585082225609074457979619906343109374814363 + 8543685485409092161128411354085800792705928451605723409112677460751012429082851977989992688721655128865875431794910678786635771 + 7286092726668793850700794820169050814700948490519583438078010079869324333131287831724247406778611721612540484173599614481822185 + 4574626770701467258525092815137010178678255624898097602082268698327798870150981485054197815103745515005378748184630266101601233 + 6996566956298539914158437280054873330111337840249130739283399579411421525420812145476940206933841167306808654076518530796691101 + 8418268977140865314494741099167445020028244920345037125932530888607409097769183652295273473400544354104335924214164055029523702 + 8653179301531871439574603212631671179611383475494609355467328013854637990353997237551580336715104250041179882078593885288177498 + 6757096834181706624090949791934584516326051126444323415129234296822035888300651545387936037901447054120865724936805272897353272 + 3719471070090385271298581540906250911443020297189549719410313905300350268160333497598330190662838247612158675798074496367653467 + 7420546839654007142424912212795950734732168508855699265941182387494625335487354878640173067010282119575715050167662820992299427 + 8999971488927790060730948508800281979058687995045352068109470869864835768781397747295222955822196732634803342790733054201967597 + 6576480323890189237090109618880316708942469888066595108911237671288781962755118036472198419023002661197238821372958077703913188 + 0030541257153278168215715641021711922462243607936192442241352641161941478602829260934238679472069149540374325351015851641339748 + 2308535064234691761213175923993413124441933619616103905759452431159366446936203305785164404138919753229165645626046227853031827 + 9274311478528593074600453989280243110143811549871941292371158642466286143077576823957560727090752083042241440289345317446749500 + 1173344584450748636805732688311608479601983149113524409946668094326431976475189882181347248492781101482302481266734427266149348 + 6919145353409181506683417908661000530570384104910516382895650835980412723990294313264588477866084060873540703108364930450237118 + 5325748279790493246685409745464007302387808804042056122442284885720787803880628218787879564860434934892913815793329423983574457 + 6453232382761168189611119093517182812167138336965744983593436983776900497001902946217406040709180061277827817549237791463409689 + 5084186690867471312419665514325307095801242831316185457562663155798586037028408988187703062546161289787145296742552136882463426 + 8870611874224684584815641540909217473850820482485529973916085066540438294865034479488663791703681082228740535939513197426568394 + 3829342886981207956995705990631766515300196466846957375041259104048073176049856454632700433183856168388096468289412653196954791 + 5561500767524576355366009997865394697845244227185393733933754620619491997202491015533470742012384145261633852618565246889880329 + 6777844984653507188325486982839438152297369628419739121210603276755667853986365800165693953505799574103492924940759456778294070 + 2214788746856145315547663790110177531050862742765653751073730521273798413515040644084618990342819820992718598911810035213540952 + 8641245540354058813605493935866324134857506571449379897541736929598327494870227097960497570120553215541706501704428439721082223 + 1700972466803583171420254007427289345043866532653318330426834471075577492940413011600530531542381075895357213715112384747031546 + 4123673880740060770118806009141779021375877044026069684883815887385967786493701519196377144556351001736897028481481645941513408 + 2662387772790420942409426074953672031980544055539694698764834339968798663047095391766181294233657281432203121874861027827377503 + 3000685337077147654086746625753896686864534986031835702363775205640514651662788785826457436508900020141827996232430281971022030 + 3024908258360292259670809665500668877816383415506517420287409766113445399746700536527732408780456759980633419485517682977905050 + 7609884167715679957397855272558744514159873182477148797463658401514781751802711120892880095270644173320069885204433134067923423 + 0014100455158046473463596055055311019866188559065450226001282429179589867255611231640796556419411721523548855378235369309657647 + 9633011209397874287442661801560684815176053929256216322999478244794557838852723961384875065741787167826618848105863793521919749 + 5428219888294008773249094303237486065991730028127620139643719301859855449270217745813940272539972852306476328220561773494939103 + 4521537632739898925531910531504909038824924540851609471635849282948417316063275786486909546139512668787750779344864961591530650 + 0285764732059028849862258838048464137495797174589639632732738487543884739338580280553036435526582504329979148309470441850901993 + 3193744331770081476790157034764887938574991726583896870321256839758584043852505285610942913104942834651377543523173599555843275 + 7417116084257040522072018694176431604709041564144995596676144624737792695410277079523480490262409478745371723464489814999444924 + 0087200564277539488709914626916914001557170500699327915642055990350944184767970585140183066326636283502929299531353689075738930 + 9142572663076266551791245195307340496553949814370587843903642543965453293671993338189766065010527351493298615638788367806472270 + 3051117521339185890745759762693550854894691691802102995243849634880012010573871449566457109934687770743470466412945533888196288 + 4158491602681925772695910708467090530134341332595220736564785569416215771589193350272179369165509097131151416084829009479740145 + 1103853287929082360008599627015884781258703830958532256506076724299192350494313751000293453841630584783094561339455205657099017 + 6669316988454995197629701325242327637911706551201433838323166461015137492273818007712193923739461699066479249555708713191227011 + 2113634008934694195638896909191311796132499125975665209093925839375449400491235035672664100786917876149509780668632265414075514 + 0126792384563810279878665722622429577480527747103593555729429055584348852183674740137123973052149872227487163624179929217676754 + 0429035865573402523285948804441336965668748085575713483346016033116457998360922288296258888389027618101688101669309692510329301 + 4327425318090553450075452219201170395108911828576562899226660479453870050953529030012653173886753094327406771671224243820895023 + 5520772008782057192477714645125967892355088889936328957302124838926954775059515639556003228522011635026617680256545865946919398 + 5091701805891827972817338370300267783615596474978619035655959815481776653782092336443749908777349150397039742672328322075757599 + 5790089502501043722549854203882262801131152082075103693079735744546403353282880501020065196803852275180952587214373981006637291 + 9796322418193084084142426874342342820014220995329829353218013607479946651207097461896332568716316883980489998209799290426511423 + 2380307550005537574650358548246683232060877572246000949898947779365886734692122861965160733025000170093436288569747823376036955 + 1082935962455046112099818942036953428151667543776795511944294244788427450015296441783391903107987172541886534905100146388519657 + 8380489382633120509090625034073608336127658262734309778765867742476489991527857117594934853404329609845740341120593238746572358 + 0633586457978329098387174811695256037738146638558272816343120362030421967763476640034051908578551893496813666553354240880945358 + 5373098216766144042601726925416970539214195693276289721208185447267076741060153916852700809475592729479267755151190925441394762 + 0437558873199426030384531618231327018631366219163826316141114912440580402838580312314548478509711368795320884000345769917178052 + 5639423930316613774685180001977671844817204570499797609653987640525926925309564084656003072725353558374445587925969239833796829 + 1210135977251946489323174272650887900867086890978166723808871820517325894679293066521051888521481265231417131690626664853728495 + 0539462898410401286175566033379657439604282033567012883413399478842279156974842259796901368805265470365140797961756617874554244 + 8867613639089241484274514628778139575529407010929548231466056716290533770512410612299882134379199476168691871070113322417352240 + 4833451141363445314543208606007459133355986460223413209331799936622495058516670427933156376684533870032838911569984108849259357 + 4227813092685468088212208364841572112496680733745196711345105782294865361331232982776705201607924522572931046426758698077037314 + 3298920484699256928312414816543062270280813072616261084031990462638788100585936907797010649601422888227353971911450080527103430 + 8677297821634129486433214400771371293863980023792460946229497228182272173859417196509074761854532992353908622744248599410546426 + 6781620363930103389596792660725581404654123168036180688431615736861252151699433810032668453228299140054818608750957825124796595 + 8122906022184441989524946520995601380863784338127264956306250128205898953341684941467474429559908562531894365353100792345598520 + 0411240004527716081891095406341655736648076045216518268298111043258024354531159970495009766409513979584877788837540685928510096 + 8110610731150417715423694936324187409013994345563727775716872413402896219029394300366269945656385788061342489896665541029423618 + 3755150141442065122724114186286854845339699980415816422951602029278923264626041281480497555316143381278936597056953084064028022 + 9997198501283363781790158682287440631540353151583792163912187892594225150451760679251039984200332891341466144376776153588743411 + 8117278660244194155818259161232321467141273951036898758016163015261776236723767428479024530348209694127274271155128147667928805 + 0936167378563389999940015556970429817708525142859666613441735283201399969921725036498088504412772933143791841603758820099231969 + 1224164983307664154773003073878449221074064106296765689183370554165942272977254560731754387603794592725273703193699452227243648 + 0945223186347621257574665017745770814803043072264123465865881332861490934432664674134678310921895127370062396231037904388566491 + 5578757540264948131008953288936928142006135647005490612913881156326258717861846071301620618495929699330750590715333343381570370 + 8766152138213724166896984751062466183413369758646701425025924527217037621942282338912065834670044626031344011383552551288896568 + 3053487311706357675549287442389024758844523549667853410498690516184480612259764698839374235801509026206625335813997095967736808 + 0878702145089270046099454388880300081151816870001049594773880813882330822460954086402671799804568587855965385027526964053573154 + 4675804956846633737319204649690805027179329770063541964923158992410097311744090492573918964775287855196910884200372242948299414 + 9493162547793763389979831614732404846665474684277822658912090008789913594349007683276852208398902139951370774691434150042517692 + 7345730422542157756414350209374237744157462270676494668123673800976571405254566784526649041229590418069453350314530822807850416 + 1964598394787617389494252382959463826235528571672258679974212194662236832005305369294264438079751870505403383373187745093885686 + 8249944446042573821740194113388700642890510755384482816288425486723007601353010761537384611960083168099219424928983664383056396 + 3337126174819661239061831213486837993026986769690178323635308622147431003839607372786324521326222541843059384926020501381139876 + 3550125336344588588098791695947139914704682212688259894589141433972450950443922835504195392482891358587151935390940488550833886 + 7749712101826086175922145824388719830543614893730681609524662863877518177721578349626789661635402530736054829364302745002369020 + 7052231140791673822400576065079175225485411488088090330405642998541294857834801823806307475957421894499261138427284899379872160 + 1843292586638145520787104685467083303977045950130084986120058743550949902430669077350548793220932862849879063881005931348774482 + 1487754184031131275500703273842524528318488976791651801275003631033587218395976230647938697685183895874331282612016119932243681 + 9443865463893265996646234621765924400556069796282223873874118161895663217586723720163197972926787252465189277090874867985305943 + 0897354453697180183636362963351299526862015366834373289147517835099724224465741319067052046603751698502499127219361448464402391 + 5704747041899601180624074915530540633028597706644514489974845238123048510465569828429534100611326273262355319658327363672387706 + 8316996307878784269659645906887598359322978350217418291053466278096200407791776549885681670136754711514051366460206315185892069 + 4722848610616728633370187439001656108169740264355894513804107426599369076853462061213905264840303368831514494760256744683488217 + 3692367810726295806823047818393633700597950772879297341267237845287738595298116096169937443486203130496785989216239853131904645 + 2667811751880900529395751251780403233472004508704751605995052039171718893677809009851286227285227934697321953881347551922850785 + 6909280644240056221753293916337855667825910341176418724960272141306897770589964342155201798900696411923242239316269753447770119 + 0999650808847959816984860421127802079006195715319055574680057716511026426618826912583374854994252722086849395905477181959336308 + 6682428165643537701794115175085151859549462586484758294772142985146427091765603916714315410145159899524436580396471513525615313 + 0287601495196877948543109041275994870460190783889596253917385102642407519701386785758190101150573237633840832279432894588540853 + 8953039640516871936098610139590123074456039528834700886251621001651688622097083336798736244961699802438533721144359429291546962 + 9090712409265567652916908423800558494486073728012853735882650836864723820428807816418262790577395429269519877994493798687893365 + 1660175388130474812877157640023025667491901812382385258466335889928876299301453437354017152844077297406456989761054934994390342 + 9934657654239690864626478281461559020855371564678749001531999572350068313050489634121119934441378970500982348402296361517516343 + 6359086489575862410458280767790738382982543594459454924194612177893193423779790100018577922756855011303081967830570557786235066 + 9627300155446988370785806212844429529453154177930814144914555470252140016234923123986998575098139584073958387735640106379021856 + 1431322355214385540867355391544675004031897330982334142717560574603867105320387323557316017902469957357722433291210791176477230 + 2894506203039713875024969465668820869708991702780944843854568441944017095189870471544531770235169544173059692732034123691090895 + 9985087463071783533894010510378579436608410386134175083499511116916575290748570942191993555978994826375337547024070760036740444 + 6261306132531269467443124232293674590069389935930085698373191334535132795190967480627467212037239181698443751352939224782894445 + 2120942222786996279924477488386308186164427794112389492451650285444010405583566731254920895180572589153915684428013418667038463 + 1430800636064677716455907326084896393465425867531959255704442690767435730899236888138775592453451717734356391997983296892276722 + 6245887023168571979343600695324609549057431178812999538431044619282851448174071578424122279044132430998592688952289021834131681 + 9674276988668745718949139392247616305459443871778443070291211471809698194880071407948810420513382171773670397147925755783987072 + 8396960072488524616931349500116793025065793132740236508100883299116095620726458675309257154864629749532773543158061852267047338 + 4708002781694658659895872218532749075225884113621393683821853677375696999740077965880387656889715948194663339565410394344347289 + 5555870327192777337829881158886331270254424879662205835411641384434648950116158681537009743933205450514200494453854527945997900 + 7477629425593340948832945986684831020436243430891488737957650425170704516063535499519492960538931301090427592749932503236484184 + 8423876423875909116240287411777889735748877901032042101830839646783823015629217546200038215020201848216827890202734808048558954 + 0807456230133883710789676060781653192722644571250120561750361830812875165496905115518629620725251203869040049714454953862738741 + 5303451865971911125648060457840129182131488705975454818569283523145391216818437057554152537823305765736049257100852046148635621 + 1261116302127532039373528605959266607418243283938981652100937053779793268699698358833723678904084230346993115051100507293779300 + 8426944066403361349421019695464969608724905091684569968020665596067769625988182192985084507208329554219894020546830342373194912 + 9836620096551496246720748973842622026481410313119306152287268352751048064398407415273133860155815754408933010180348795503748753 + 4609338756911699625776639967309034003047928015509904888467025680057353339055998784262880963136510735792422530687128803685177960 + 3794220657491630690779260465220147420857430753103256706506076703567632175129351004805264212916552247643663829004772139169350940 + 7434241221131032055118140342385838086277269231509234123959703170231052929402882172699084758826526485094213048561191825363736939 + 0904036155468367437756029547852649525568053491591721559536888529587622171812488273446127650656057211625693401063929504404510727 + 8594239813337093390867462989975908087174105244731466049861585875653241923202495711120654077327719056153590078128352003621088112 + 6550980939146114945715655019872060022635651047970499718424015515740106255804720532248662461951505100400404921280927158680583839 + 6741404050546354494349489969507458195999859785965336806692031040435145352201853821004643353403220778871762826594034649052903693 + 5050161106286616149825562707832775275340760357578872487646716309800665185049903572794595588208600449320559114964177323489795050 + 7988668426398349050514452498533331732900030359537800440340518464659495823291497139184592287414133272356549392805616744235453149 + 9266075338762306748845630416478232159198106165396768656800162018036519950819645985549720852139273704724379986117806399232175170 + 5556988932197330115132604542704979085477903108338527639954740461587257180160289420796745117217674397152069207476864049579397740 + 2173348172420527062990485233356407054265180085263061116024667765176353870469789794863489543966815025332527451848905334447400043 + 2653295629344700441742575198328366052220017722996829827117810780652298604720896185508927603921863120335461979927552660891307644 + 0066285895594775046166427188466940243950248922228033222148293913898651489477743932715196100030572189599370661700468278120150796 + 9557220581453859816276169005234368536133383160153382159372481458293494645221000658600106273797363754949138070903261376602472730 + 3805492311138707905865671027330890704509145113408439234581134791375788711343962876719164349282530634198140214550594966178264550 + 1436926045326544742314469119616902325996600826173849367078861191857896132772006881206929709595222480758410968732831090627983535 + 1444386260983859263563013696700221044836992640755935489313754181471481261753184503838050091200730279031416065367564840157446166 + 2902149047863838396186395637335864504592375088936920775765866174611877001827681253531321463980847446832448377620176627133555161 + 4791558390249335499772225358752569718358080171845842601137108723166037557543519329054572216953276760772287383669070062122544693 + 3653096889815826831439877436629034472435210543189243295673175535474384447647824085044069839822212271287638158109858092072312186 + 0748574544351788265285261914954044165932622710335856937231283900552445994528620171010664109729214838117784033934235805145199914 + 5275894527081180465946457660332530286653207667782652877623355615488795343761394166684000047525776778529177571402318083997867530 + 6467109418857304686760026137696284413841248686101454431645726165291910757652786986378480149853820055715870646485922893256858093 + 6676215878298696393785441082359744916852977084427450114208277030042915360587042453548139647735771416607502451093388273522788649 + 7671054706470997891661682369520143839129305382788490682363534839812789784359519127806453517900921204537766515545890569275307893 + 1361042207361371441527086792533736691205317414847988400835638938786015770536113548366581806919926001472840811854920801842703777 + 3513103534581691803636903931367504112887620002748826537288400922168108606124444688399865918353400722960622289440592437281395265 + 7889386408564819031497565924192895193912656422791697412472168255473833561450568882333025985344661645666990267705103860364236866 + 4138536431654239332667925068305482627915123154662709208870044077990559363503200410357003059370208164876016094801255094919175222 + 8463391696176344840026735185830036495571599978819527559041511392555529527154011417043582657075386914403021244017762572439715299 + 6162318218961162791019379824579408557803275130662824155987476456514181881477682742571553987831058318649000691189597142635269772 + 0762970133488857814721372272166424064692356325030921377174309564434883115428450738561984323237757935361350713032425828308741123 + 4714351982559489932236335028957017819906944707422172680018267561533474486226912008423131335876195206249325093723564894293512080 + 2816500946584950779938046762589915909515704971018715869504032011106342871269261795583577290967260307340084652876419981696310087 + 2895004364486838513889537109545822827678603850445221912466809759993491507875666091568956682275842225830234855225383245575493552 + 2650099647818037615116956954341655646634963643235750472739733468509790968870462418042203958941068786618484819431710507936599802 + 7533481270625343830151159727689285867369942408696652407015806894633372367355011778476566950994358633971847804532262002525341326 + 6932860309305588424128816753568417315152512711756820693574982607856846643933251360676478873401876049759834996395397442053366771 + 6368418934202491624332453410763014824694322271983857287392943327020965722037743354197029665328443075456374222598320483575376742 + 4282586458471797802238473382178433687724169447427314412337761093512867942490521429740324461721167516599618126259885014134320111 + 6677394682606606653900300409179091142196198876169170096213616729601352901860163965806655227312385454363306654134273762118341113 + 7643573234932937551595703701897895283801028602846877296702625125220327139117379468939484216431057135643790896852072143295568124 + 7835389220407382114018498622358193237717282193191181508848234026347203068182480302817923964772670420825100195578203841958774014 + 0034680494236515185913110737330886189937723492058708152408147979713114102686546086347368499582981596157232052021983733385897893 + 9959931900795867812310134476649406402976231824404571628106712844354935633442704883886435745579659139240624317737165693276684021 + 7687653483916295211948300957846886688394120859824086212655110896478780014654869246794209169764271870284569926071280986536129686 + 5389201304796699165935771717834181664385244359824248801827481372360749339940576454594000410357902778074011200874064037958889186 + 2726930691205319100949599707692925525547420349048657283658532712722412081334373160958039199607974848481872853703890943042973921 + 7254087398978104571457211604241039805468739560240953011032729779871018385163199958508492807104550542120182914215024552352099374 + 0577915788776618918085672242537299536604399259342051743390425673863630842390420280176568564228989365174973256614738413491070038 + 6830892093137210682654019600696831217364160874783778871977883927322860408992703263164973180938595498029716242874574648385670449 + 5774283228582139254923100205140724149936447963980034063069342493084827233283799090727386532026590721266521634433539903773672657 + 8489342339836233604189107412549422519166707342446243631744337172427688799797300485425305108241084447320396355017099790987982304 + 5579039086144583780301772101084268454284211524135896968194358624225126732215388025582474957280102865197930121676550220972263090 + 3389908879281737422526309759732063914252217622801815648828128392852505613143446838612931228798897371072027044252222238376051988 + 3571583131629499703290168358948884937302565954157189422433659984916252703476429662770576623285862465399735505261324990848316694 + 9423186355018278041568884367207433805709684366572651006506138520185260823230823570755489649379382727052958581331266615555167678 + 6126444225712076374139461277391085492256424369818965208777930082776462483927136117628590877335005615182912506580467844672001776 + 2323186582401204627524733122349298471005163415025134564249126647383086521203590734419048262603709759435997087128843414545136629 + 1421280371866708001926278928901318288694248295906455469958649830300570517830927222281187526547437638030692046413330135004977193 + 4201689423423687675024635448407327285565295542200018160703811061939134316388397382336397162201256369493787936488029791585101767 + 1265877778847130342563633758037018164444481581498122824054055477037485608751037801526946223069038643514687690116234164514587643 + 6465410554863527094647350795029177204941109231775452235798798372912591022108733306213831496272836341289051922220644943607370174 + 4555709604071919166868299016817656945294419168762671940808165674695761877170460702219178063962280901485563918842254363745508105 + 0013210837712837766354170359690869396554185818181209225721015219925108353810498389109811284979505591805687297968690234266672264 + 3540066879463905504617792447842885657986052603128773981944573151451301111933677250259888942146768184470087035596773903177095378 + 5526250295384032490751656419926139482444274162610961490517202317645513359417017299610996672882236901128269120411948696682951298 + 1147928498844392902179227619628807696892271738030552398135463750372457058220840887917423404648021366673468670510142397314290816 + 2022158104950164034675577261500173802135526124382488977804744045573154829053227880877248106935421683250032295002832455111826392 + 8408395848784043250462314109208469565763023368052967204488715596813441318603486322106989843882974610129619714497130039489786739 + 0214994088989310972413925550111779902382656332396702390689823464515504633177056625665996413210331231059059122014949611785985118 + 5638643037266704666895115401268842632588292722777701463135298698439281447394022408579092978979422708178801226855288373349007705 + 8326215915178072795379523340039085009563169070517125775679474479863606678664704404360480187047960485640111421757696617713004548 + 7011793090984794876958820884434550749243106407550272966012525399145703465211673094494166304978135466245182409167311669917812035 + 0646616697055433264306514791141300386873739412778313053422926573847874849306566154499488632029298944379782617421929711377514401 + 9297384752555069074761141370510516463922575237795983591479132397584337422724053423993525662073888857524562744276272922807488244 + 1675900193060201503933483483504265157956265823054822690157216718534136770295979836197494827206847083365905242438375193125219057 + 1431083489513661032602020638770515681536739853677363483613015298018233407875797334225693452983166033993589897236847768729569036 + 3412842920266990322594256412420427432972591970945387529406395749977856430023496367881365081011414676715347811993981995507454759 + 5814144158348481510698013052752762134884248303529348153673229587940320030719465454064415732294560941869034046035698546780721067 + 3694293937312762744233869259702927434016315955447360677690945403418821029256532787548058243155743890295919743842535871205350185 + 8704385056392271497806649473016369833786145282019863224686988090496033200166054190979749241314009880507707963024916288921654292 + 3157093902990992972624660747840907228349704051194371097267625916545775966277296334446546102566702460108399894331979790861994643 + 6211141708601791603941445199717151439636201237385208163393264036156546491266459438443028650233309419884755515206198073403412631 + 7609935217879726233731421923555596716242460372189351557516117275999330506730738459524772217152788164129973955538645698104965588 + 9847824808961328798019186709647321679530290047204083126132050648182784705034270305452693472108814807665149578959595630309221057 + 2336424726766825888588931956562955321343032371214572623650620016457504060828907233038750693736196960807811513112341914628133531 + 9997503724107344142689181995651896815056436454295876248977561163594537358114242360861284248276610577578928061231272901007371912 + 2013755472268039887671228509805013770238575064767125406070391538875450803622634669600191763159687914916440803301533482646017516 + 5799981996920369911160876482866900908859555470100550461338722440379485926728401393736777675182480925560316384661340355950830168 + 4131746820931543634876854491169439418699998977639325418048790558796894160516876451374044889060607036066881936080985211558198717 + 8071462893187814119459304307555930509471933902061826760709069595504601694208191737856286699434878770893482761009503838844594596 + 7181730908337307386590819037242463777795080011670425589895801753553643404874388537396185083285326538843075531064088612600268485 + 7874226918011033625880877484768842271536701038369116084490113476976040281425980324472775723714911411152630252812320962593721057 + 0414263983887707664017378501754926805713789236380580564348508099662975168539697702344553508537455836440798954696577079098427990 + 5498272997168152869729083312401990047724554350008563240202328869525129660589507428406050419409546123885174117080636577540661417 + 2321805983098426879552953451815149973073351984882483766093075912871745174124737636496091875961776384678278562342333189413446156 + 7532047930885191527458749856036064187500060909405487710845907268217223665450938676158247000950256593423837838865029236735406065 + 4326287344295297838879679103933460283015103512394382866450845885799711951741393486898208614864273534333346921541450681108663424 + 8567495767845161425037712088656492510273651099963049803480674659806775332933320452431001042997191274150089937218301268747409008 + 1892491166044214033213915009098534855928106088594182060850901874215590307570900626843004514029616915218847005161443909006676086 + 3105173474201156958194039816160955452881468075916368040511971709028208813038518932050264340243550030216756906608101248802881284 + 5437478863331533890468364414134511741947560918971502005022258558696334726057777326125552089511046269814814736730962698056311073 + 4951554244048858298258123156812226947705933314291630536799208713986095914743504621255604040168912151175487398095913442501527517 + 1612279415688868683265625113331706654838561784474685978138326507909792993504451472859581305912676732125668231491237540161852687 + 1352117401098609459260904440848555453118498774861101544577811081137171667682199549961162875051222443028292136608108908775783291 + 4668566015341904293075901042719184643021339885314119600028221153413672044545251474917661767760069310540295768155060202109602728 + 2520334200236839012091693839792035322503068072072460065591632021254758742371667902074341537861212278319285847598815912703706243 + 3175268051143981660033747106123282192419159048635214903634052864839951778255031756400562020446144172393222917501787673701002700 + 6674523291734748122422773809147614700484318146175088254981107335895144969807349660283900516719746118645468637821636061386059378 + 4188188277626583767786502184322569089569789412892621297176431619545847378700138574560707680259428721989759555839556974186233480 + 7390532896972001905316907714622971854007628170763072962479615247643615622571558632228493177244362089074929594584800973845536848 + 9849264610200952816901406520106384682505741852721568226048835135789532787094701294801848704745256861395407908649513920150263639 + 7854370986367091444291966220372693018093730764321979930716154354135718272983430773038337101141108835455952869661500155683833074 + 9808115836250545782744528663456612751035343126746511715032833222650951208562936847133894670903159578406935434899681616157157677 + 5449933772771897148631641377562540641640474848389783754029100557570032554566006191465792063723092795517702238425793412416470001 + 2937905058909924731783049378468003437910238645835264792097079136587087350442777867813702093887200643761896159097869017005937395 + 7717133729012763683884090295651337537034023162131283487583227409327777370699292346651312872193008211062413650051860746533410200 + 4095695950110108518764643338298928366182339223897361738328378044503564041168430011712729973754089101835569129650304327287404972 + 1174584897511466194183788253926349029362049505536254582209201338252575420290164983455933289840278231035884030712260894346134552 + 7761765877961955439161913415420485543948776016504802146528406434389546215574979243086360938551004600037990661153084242444222743 + 4353062554304250531566068529474211745999775668076123932253052153101156786485645664269792342453816897835171506547074839704777091 + 8193385707206057241016991296332616186095885707895014417445978963635638843413167453713147741250557894417823842378892716883564383 + 4414701258878541571780503656512173574547903536405524255843710113697817741762054938128322216548020454736882148058230445988304376 + 8363544420911047180282206501238156287142986596377518728647856328365181602387822102287895774281073353368828111014956911375392578 + 5780430022747871965685716392391425352083934583867099701698503567269032511748940082003282777645389137257025389413017452674572537 + 2606024393701221307694529871431154164540614164993497271619958131424791186768644684669356636777831879397734272673335705649633002 + 4789715983933276471694982923444249864558464851612286765926229253919876317314926011029164829296322542092827015562884359904206642 + 4213428153587165381335521523932052241841163300973801287138253226845490672931816978773941803990440278669979647051465348624079105 + 3419168581475572983260190361701934633564914249990805271700921787735379441310149748846950460105295646015883522763651311765718139 + 0643017584581435034370880134992336308617187531872808223433939732921528795419567765739615646487503731718827467059811489514462708 + 8240926821672036119484675230474136343520006840157742512260506574754560864426113591474981060698558545401924390339201368669580151 + 2180431409945375285121040004138946753923265119496541829137171528887590486854621739462433884861201148650039065347599969036034946 + 1220794484575763660002325630268586558185893116790653322219525972500497727914800636242536069684827121496593553311794674511534108 + 1435781606190730034271758074654507450242292934136120417582018758847558210750517197211614624177861297537749923102696299059068262 + 0472496196020370020276610485121224239313415267755759579734483426439502592786733423472402917351281201878422928096327388672118427 + 5664545446808704741371688000935805171339458791507069541059893057148797349299303009996748288669321167515451714205892864440743408 + 3539189653746007637884781151821846130210806166359445842675385724193537198834368015119520365512286626859121785638758771673116936 + 7228747311262908816869990638505266862436414983330364594232199408818881369887998094729811275091341031498735810192826600585848478 + 0205817711643909986528303579098875467050350065610591795091066174715779956393527864740830714556714738435192795203670003124014759 + 9197293866434029742096641108142225947219962019182256790387923893087254917713809995074288755692595202295289706002058647970706318 + 5801028709225408662416729985040929435165270531028696258985082752391299922713342941633843800570338856731347298583819618303436452 + 8554584149353583626116529209271190042567689752495849141906628210792514969913837494587223513509196504949988416482688661169416704 + 1402557567228850127015457900783688564010064141030969351494178978419198543363884975731636660451573493841983931009293074401767946 + 3030096749835569373371333947576923588432247404291305005146406298391452901679290153566364898274791521766815033709118309495674776 + 5711698251707518922789190956913393869735623141004406498318629780886567378932420667481352170410684788247915724815490088304482484 + 3076891999474110399724898312925906240059216711193634437769661170118805829580169752019184852464954183024109801959695130678652316 + 5549698831705307512844145517641207234201273500862193514468462342310564088815360136277681192006596458241962992029526454841238730 + 6411622599480809121036108851843289420809827360922656655734346202711742438003990222191272251022816208079113097900823895134384085 + 8642218596518127375568301272202091207693967578318544987425186514107159773089906580986790334784827799489119999185876094206749612 + 0920817351118635692704580562112859516048707763068110821230955827967708140350064043987570026933663880446183554485511010170742288 + 6208781018246003491238792622187493762169792217017386868912187285653248963115594278272915569084370195923738619149855997663765716 + 2725282513427928049648973662146630492856487618068183730067763515357833597788940914019736675580475997314248706127026547890194380 + 0912098065082008833983417148631289829848433926717155189805055489641556714887595710925279228500591899600062727405015074732933183 + 5895616117549258380703685066950990019495929210886386708101945826998030626417636766877015647925822567530097432835311405452851781 + 3061662816058323226135782103379493145683394691280827163116839270882202901941521202335712663514020076981153846416619848715503675 + 3704213022599283410938645199398840870678548274677230864636710751729466573816253072905154246398964963820890925958414003660031502 + 4630926004977081614276851598024033198734821505047735799361816301169717640380369512425102474864033576302498992022080746889954455 + 8300690807062719013236716321873014112140959900671073008576129360776883572345888774946590273926184154530838752149268349654124927 + 3447912234767016528327462063192808290048544233618790028527492173810076784214345126091690768646666027973848294720038771161886178 + 5457890600658613094704911994422834789695852986406564746776631261869186614541778685993675186223192485017919263967183543307324819 + 5220338990377375643418843097310570471194246573225298484773451484736001523372710934922163010657077255170019875356114982042678628 + 3627624529201855124798528837400884425278033564368552915095248122583917121126951781145851039073704399808416096566055979179720996 + 6138215215437842405346946457258803271828305596332127664808930703097188386621950424243497121232196129953435128118553466623324068 + 5920381194124220091735356882290501723032521874921419228504863143247804084726835859796865644318358484363167764149683837216715113 + 9615036434361215242420376195665243628638184799766269042140156331651635843944014951375098750172039065463946417568449326243598402 + 2848169979084951950982695318867752277301100025960923376831113692149385936857810916874319944880663028251022532340529140647508871 + 9496200698078244875645144567349529530108679183666387943211721642572053750534478253516851058589093730399207634528878897274151362 + 2928780676487223500661310045048476864951396027388478482164226318809641027170548978608486524888062863065934362652787878241515138 + 6280140376322091582258435509210383633979192424770386485640747341583226684971908322655364759264755383681296473387197771187476598 + 7993834385710389281257683754961049197160221786960013125265044154150064439440391405850545737192660609079271627770663100625583357 + 6072190114323511020360786591498148692349156157375850747362774972374185937176303811511475665210532862701141979885066767496308496 + 6809986728266957224821129384937931767139546739620244968569547174693124128355961928311295430759387663715690541708892900136725621 + 8713302194814326105418406542612287987228114780045964567511737165272440568730052294690749670110950977545749571399774020053301568 + 7216372973252354647766828421771297596834262561708247359782436050128141372353679212726164448161015103612893738264244644610968102 + 5490158565324437536585310937019467679460278414170537463829112562515850928229747475007728895628087831498962809803771938282971625 + 7508575669851979183836777758657815365989035447083239066619058708444094473391492540134970134555418935400444033568972945852753572 + 2681051665685441434594259287440247146082524888648989023037549139977692642794573123372272447282566487899476245382067369090850227 + 3516664349028783594652935471979981657724225297147289075312362875423752912404004312370632615551263897637065247961679885605652690 + 9466216134195188009940680229231563219004828730503835830166900891639648098483491041893870240357033427709041628218884025561211450 + 4848574180102172215721912201870496816515688173491866267900855346017402326765363320124474261873980008204988494006538252079431490 + 0175523216285771758146998384814407339456495403123042145864725622594607160861096627528216923235632801268714390775921555811885643 + 3472489136602420352765486727018974617090254641528435634640334942425890346384541194932965110314503859645146781896767507525832148 + 3797532143892746774112201800929601204074380314303366575611389855222496601937222584569281001864863917059035591510412512996095572 + 6540831912166873834974788036724952907724341969947205585823842409980011722639587514582627960169448155988074691268777322159243577 + 8665277823830969067856126267665294223334216725032631778088124483157924821285251588520602045895388804877588758409591955378022156 + 6073508435137376529408576041907918073738449051031545977935509368280423831551346121480713109837860058648169729195905582970167345 + 3067341878979134838523394919669124325563435281537910461171499830549480992384643061189946199980549578258740383418503347009079843 + 6535435940186811905537955923044494920097170641355108274375772163581055863892145187878626476077935978473720854007118125956368393 + 7039488100826115931812511833016243383119511518291750301509797980336012158668128482275262947277553272940357496952990711563149829 + 6786417640541461059254040553435360397444650993725507452127477820766859236159070974204514281362156361495968903161994222700825800 + 2231234046323964842602361033236684311038633571563965762668970125159431168316364793191351729000958068187715242930876778118365126 + 0967020148060045963966458121640283348948132407097784342111426011211692372274414489985481236783110642969061229593384194970583663 + 0518863000584387454760957529314643812512823643579550158516331617073251164731368407116086238782619225015253603821594850218277314 + 9500480699512272865605970060364505765826990178852739273720908237913877224017867775678563171957729835114722642208632758208282247 + 9138815300684460564222550599375232818221500256241474012816587003367381334232108533309664763635997507997023730828738583077664669 + 8788277264997082732015978733262501251796460091814731315709354222338224334551918351172940509755714499856609104221032539934398062 + 5201268981606265439495692981057225390935909458631770334121087316181673897848115792408678690299457980695904707677321358225662858 + 1753894444989509786731779001286291244699622264775676367978135041545186928742736879462156569826451402964970455781449463407937916 + 0502111951096040580120210611615484977765606052460541731989539917916976249725653281972573849533515652151626503088059881052346467 + 3880078154575290219658231687424062098862063067654268460424536569017374872824177081255701341783967148208402475928724455704261768 + 4392256036256639333393028072709593018903870460743710545351823219115495656631234924513636506499865017761998475934414247147614073 + 9879823269518650692917107025520590107178762204459762006129828636469652976104262657652867426597078219790167485035259125893130526 + 4491505097353181156857564911252591317148670618490859288558887139051313551147429010258650026546020137477020225229299116254389267 + 6985649712270923660498384674089852650962875340575045596604964662128408959309248980968270692814095597628820086983662450615030773 + 6856393844414418123694511010327503283724147879193562418774164993500731367874976787177535887228795026180482876909284579667315939 + 6933319890504711538399213021011090982613851985557386817639509779738587337666166285748238443831950809951451700040304637246662798 + 8972237565184004138743415214250280650420991574154677063216686873786654244381615346208802365774879184715316421935088510122029692 + 6620712954831004627906209308475373401688370427674946161939930227860450185388905612087218953668667006558048824549749639289702982 + 2252979368901033426647735610872049783979382409247439935969647741186385842273253355085952551816588123321471149874812539836048112 + 4296535534263007024565979896369915411490254323267398694533004344505948807352166933785377686738429645888455485219163542489241753 + 3740204196364178691705296568637646938043711157073683455458837069839389554673644717418013786210053159123354215579725572298341488 + 9402853270709855032434056268150751702914142055269816941745088351607954708943354365301302743628246326922883750858759728646811815 + 7702984283703968225748705248163911320353463996186650929366431271533557842658056577524133407573715263399635592058138266058468047 + 0714364441200044139354320382443415251209148277388628504182113543224388038221246572844030594506529807381529435302712895155562998 + 0439249856337395882945730885613068512496256701244515252923706394988734280606704794447812748091162906835016774939625011625452587 + 8701684848748737861671752322431955447724661967607517009813604790923987516158908955881849157986515334551799664962438730731109340 + 1331695486624815425190823239475277990544123745272288937823732446789801006674641059010522745250663013852871097862751638189259629 + 0016943722810447477028299392663967547809929491638369830715943306970577569121839921705532284065788504261357162084070598074698898 + 8301370408134947453196729774027640676030589016291539644959237246218491449189371838582480346507102754824929019477369849852385466 + 2141296007314745921128534279212951822200061786556429858733058886029876384472876002241385397319110771995753216118435172891077520 + 9778033995372614700099511429265411943800576787023724043391866778854759353346452408608492285235768924255415140931221126895275706 + 6825951183619818611745057594180574765846145064255544523604725057011807870654883273137368630387060066151211603237021909384345606 + 6330524686796934177420756525152826921339672339044318925623881985016143335928837573713885535605018904858579244102576335089585010 + 6476163553560279805504121578981537068558170447489713068606370855078339092366601341950660196338341527489856914865088585338744059 + 9336566578276542977779339876759708356666986167810967015943735975240831465492474205336898814725322385265950743359319117386285955 + 1003736656415305664502391530550831810874960043692083942495595913831106487788016650162073804988081719551806867379947943364891966 + 4573789346107222063252149996048100164143705560186510044433851243141510350751823081763496713992637129016266999061673393254758192 + 0532366470306788734368951439658028825164454629260106890282620855033982533015451546843353901652120510130789111458392221784617757 + 3253852880221087799999614626290882768972817659832607861376923098885595639154736935283503251479471872499871522284582447822302040 + 6285682722317206257124522813577367514121775302484636697810948128394195942996079881830875566043123925277038343926112033315427349 + 3775226925665315936530276286731605375257672911376828473612175726312446039948354980701402997357293119532073936998664168131452515 + 9033989479402366425600648174316259705202840220576987680353222246016330572206033521947195443476632332503203414941943726000075449 + 3497459952076058462828783375726894554577596495151945532419592454939988268844456907659575363299273992966202955633347460395801503 + 3425070812671430759768577458384150050234482462127557226191091262303333548668785285283704391650036078067518873006221217224813250 + 1772566105841430765131974198596141137685703304393653624186537427347991201369580105964338526460016536799639038488848966636423096 + 6770176829068426450217510320589346020757715335312260267538371974073805419798173049507293562584393319422383700569196675270010649 + 8817107380879373164458511189191184591118659927137093795839429896643513855977855984835472389317216929700259038397397174527984545 + 9182176191236023496232040243155433201447895622909243154991531577802143936144665255362367572046313372242799588041424257757065202 + 6776868876338528332502171518394602792217092464624165442452676081627495348032268487133922812426314590277917132179444733559137458 + 2894505940700668608956696393712351416879091173479440509500831009675626499007967467374789971290965256917798968433095199887640804 + 2933556414955828193417995654373126786599609721238527340939127371332396349156901995803794360944816870450892560704118441975220867 + 8553706670591731040619297656286157301262507708170329674504933402137245881090232925455937213553504830839742590855235282434383116 + 9795978189578883639204205303262814903090980902741535992637415797011196591002116065669674171784371634354111486560182744790314795 + 4119132103638186216017314646897106719838984255536083613903341238051086509058863316947216192276628486590741349320633205188806897 + 5670698885913664671019828424294908157556037863822378418679559826760134301152250392322845741422553340998938758664406467756180798 + 7800330341660310724142951110753435998016854748165017611258286920601003037645494210716339815788133485140202482683448446213209716 + 8180605035942700911937960726293062276511453378796626425148211321573098417580088171144007867547815289216240544844126601589466966 + 7821272307041782298994133562164496850666805515425583415056198384421212580796187662587737326754702942280674718201253410570348983 + 1042240816866808878998548317060777151321655529169893824595029339588028328148179827446446643616423322057981572730612868764050015 + 1252481771070461052389437601673649482439048233841755345725688472923079857771939132303119904339949419801565589936559095363036112 + 9690992931777916802696331919514208983516033826094247916936120742724743873182994969726283601645253015955852055017097669830871832 + 5020330232719825823684760306159154637346729706124058199917604069885798242234996370123942691457916122474221663868046994104598933 + 3075139912987034850456516141324884611162536977850304751997334983975217864864834605427571083113425269670859785386338318467147612 + 0588929507981854517277972648054247858977149919377574480251256787460673116218337687478964763305472549592601599187647039007311159 + 8091499973422866102588159323886136790375349337327388200287148626779716184548302459458465936817938524771802569873742301251650117 + 7114931231277684778417144640504976098202413303636808727117937611520910337365455884518757181692362707318939628346107928380267487 + 4950235887683950624565704360578955553783208046483127644086525832912071037741169842458625817412278583829306158758057435134618696 + 8199425955265652644399992914133529916068954186792582922740480043066932022166380883075792995446339961281184510898029007416993672 + 9600726548050421231768431078919064425306219469503912968092554459127359674333330276775477837154780938957377807571696713004700625 + 7295599369136487293154800206051955319915985280570186743302107975100582206721744471004980480977594771538574498512856521123216578 + 6297798457301239668561079936581574605258366525996359269984364801565322122584365843225724581654618783605926367931879918225442452 + 6533005631078137948109852121400341144965267577414971222703110484819122046478368287561575133762804019638669026806894198861867537 + 9875087635268237028446411260770380453643015454432015279985047995719605753073640336797720945754884595273185611911133456865738261 + 1289442162696753398201423924491482730765830984320927644525084976853458311031303193411990973143614781325043459014068347046089289 + 5407587059442212092113638721767282263392344800170580359252927060347500966261590384053868270413268344224069405566567860000139705 + 8360711621827142923632844470555921440996634627172367848310520969393805873503222609811062308946619951688125101610027026987846081 + 0944723049476073716566027637737569127176067300129222186002435041592350356420231369282460258580648007773781925508162225156920162 + 8475983626059931171149310298021646566523963848825823192493400102745845807108661239544077702836139330088359628977689491846874286 + 9167471361458822389556369913209606973474148790242038515231761016355472551050907573614312829544645064709238887157780557241782741 + 7014298247554687536486236050770971039248187073536082362810060976896826815113357515444053263548215504897920396644014795535941249 + 0560999088691723682614108804238530988595549473233071643241045493910124491974900926784898185428410219894939857122959475910314078 + 0706992135879838500099998224229773341412566822617554024599579881313516475013871821845580144033844736871959630619808210884015298 + 3257284534077293882786787542863570138992146936142087051892058183105267975351672517356758026095332624891123361507959805527300464 + 4074440343205139647276844490970010808052229358468787479224053850708044118534407822903344480715673998402733320764968913814756460 + 7541792444051749131437550370667287159419463038893712135130829128921018730253201583423068101308427818790061823168162915307740555 + 1517558628903132612936551305596370414201320454890625631435775037687907085643182588609436062805330988597026150223859036793476645 + 6591140085443467002438387440547002194892167702007183254656681949652141186889776360123350307460795672547510863464622633652798129 + 7586611318404573147896264171755514255213812732114705872658268827371541849326158561820698871403138855140301594042187495345343587 + 8296969079616469879346007981374601146907653922591351081026313152884017339179855411584129459367820354848581380738645777750515335 + 8731520753126192088044684618604970364839081511006806274832524720914395021711036520236353757973882463981033460910456305044738117 + 8522729809358153390546384877141395094866223397312997581315815377215593011496352023911920483284381829852239261360027871178466434 + 1761342609588366253125631150586581982113849076981180786682830283076537811478367306351425774976563602440271445970009753618288192 + 2190966255981782407270090701820316391321596233574351800067587131465490412933509752425381764960420707947936543904169527628499764 + 9513655081411394282745221856716659032453348163674130701896927299389413958771625248039619427975826651601280801943472380714643137 + 0617514295978753057337209914173385759751936634152085643157967813155609425512280471102235144051790721763863647958187237685008587 + 3639355491023500583172147594486316367021278514106274611239107265098592491987675254836995000835549078267373162122839134981244694 + 3032030608995234928881439477961757003027720355891764881759463215674265954842081986273329762678139617217680974433220699552082278 + 1162323720318256232198753258939220028085022540772566418699150206741508982674558652349158167206478285853624098497667218452569282 + 5449383863141380776369123912608347050738601579475359170938129811063143046219515664348459639566915361115334890006657006031842097 + 0352577524785516785715741803748070461694324222115473415680064156677430016348738412256655844328208932407174179588633693022145069 + 3240824351920886083704779764410813380504193208597077988968552959949184540967132284829781189340533621232738907229081350464536533 + 9963137564898255760485048365009768861444430624328428769392562608655048396702090989488644412080235346086820241525013306324575413 + 6313120896902229376551555163469139342705609183907471905448131939609829452611107992213294654747615543541094148280055017927542670 + 2193326928610645174628017287211712211408683079421721839813537852939457890561997238125898536070007981217325358023811789787011723 + 8243869736268481951401784440593310926754240433539070013976127357814953175386685024013642745787559590618261612069606519053423542 + 0179110493828168312231149822817828204338127248358983471224771340698766448231962762617835559498180861959832229135237920163613151 + 4787386815157272287656433720722356482569671165537977997843012106191355180546649834098738516604856452092754246704403258051505371 + 0634701773994997694376147550495812360818423051628930021511577756465075343321034591427451854134383867627150784580620161049855432 + 0766676598258381037189024267219785521248498516810290597640526034223344261052531930836169758828566004912961881921058343147697444 + 6482511785125094948376527886610692241647293945078604787929517099856009510498982203730650348969745313708621728477885759515338493 + 5205196085155489849560658125068733947071196666550006357643461400687947338189762369344420067691692171235090223284004207347050790 + 9809626775201561107404043309301598988061425083419682730787633868247584100867048954636838021112840948572297116645919603622359907 + 0822943415366943321888436141210445288839456758217953163265370657515497810970631795622846252681104767475177503937782564413276889 + 0099794234571476050102251924980186262893747705880229668101192044145818046711997376029940219465691893053496893208450200931362078 + 7338980161503676399103395907119988361285887220551606875942870878016149229490400212073840391368478482151725734739290023095487410 + 7899326915683751786630813196982092775796371026481722729931635095642264999233728389534905015911812126591048864589797672830096696 + 2751118177471534985294175817313968889734356500489672942275914873801559720503551024017816293024629330339229860581633938440765263 + 2579409952433198069628120504384999886282779583918285844878077794508256550262226622072460752726666294025165627679376513073930940 + 1557518549380248705140615993858146675367318700594928368305022009826106738355680320673267541599976659073767016002316705812605118 + 0706655774414337358133841048392051795234166451755892548200847217249090290629891786004054678210061272314883459040459769608941760 + 1894242091014594788195514987048397793320863358408872612791768967887371355399390803287124928045545098723504490408131463760999333 + 3060272094521186414251733828941054176318890330197109603090531231771409739699564694060282342629340263255630493316904735659002049 + 1028815907660526325417480678219858187627208188992524766305787455603486273947607751634385261335594552079352038645485771077029993 + 0683468157651545576501200944305620051155390867906355388005127965874177601579306536442110166029928489048442610212141268455617318 + 0988081700313980006604864032962026305268670102163784987963985127384885587927642407664223367758558519122248185218742873483956807 + 8435692954315269375984976106264988536738299966701776101047442064080401887709348151446333391726616352591853741366988778921917957 + 8956328839854159854532673749984321247777028190876411555620913589749860701945785300696279975495557163768982684990843868186778431 + 2520325381475441756157721367873710939223796803781885424158254911912476533014496257166233162377942526340788173572154209732321202 + 8180099306765466453860728219641256442389031828386563717730489464926442454808958172470108839488494541309400369186661157251374638 + 0628247148382602252920534144240581556722670156430583076620252695866327968997749969112676595494827895760196984828212360640034869 + 1083401588117745555669152288505435653771338944376475705488767101152826312238533625308441022273664874833693060276780849703095095 + 1156085057274283778724094356821366624982478225088443694900412624860954703963723162086763699442272343649549404340286403255643105 + 7910121814653271873529362722249047841930063953194714561480180469523505989148782328178679381325533730833709002539304255163521040 + 1625855113537607234401449098110230513476322963277630854102799933050565678807805089239388422442620697922678611315082884292068865 + 4371620713456528072846857825011777710835705836437187394614071662418465730864540826899869210260117229659041798505650538477261368 + 8985576750846387981996728278040998786610281073838965731512714567426037576813755214228497693635971824751946973019990502558550741 + 3401249486943615979298276104790818107736649764729969044884395409904447217117866856126816079991915988836153438356752147841144170 + 4762938795985970542856369222277414531064648102624695688826552014393694646959714635482411149329964264665288374841117934547255987 + 8266183745098026650707351627828760547702165330658530132998099760473617506446329738701905894912433667123567916471538563863907720 + 1749733602645901685261363936495062217041689057898136406969925562689807608184144495204588063954048062251421026224871438707736424 + 8548102168448428644279598842714118177587767821370906237000294038845928905112282335030976267725288843840126116450813362024012439 + 5938499597145637343173003399875431713125443282016722261731991805628239317480073706051380874344456692406363674536084190692646142 + 0730500561374089587897509875647211800809704761282604727960645054003482860298243507208373227297725664305984934399424216469588628 + 8419154111597746163254112932894914530620901371133608712199806376981269451117389112518987662727134188058972066300128519445766440 + 7937806580759161251998478953470159484262859343028238192145225348422179576900021837242945100592904945106701907680168893307572302 + 7516873429370795478978284132360296301129718931677825172903818753611017830921544550227392257770205145640364461713731347634995836 + 4812445494938381664839724186613091405433366166945041207304600303147241282114042034521353097954231266436563888803937496834589712 + 3378087498752524611421562976032943128888258876939559646852575538636633313807640898785156463287303741217790696080003514700600687 + 2916828602935343245489574829087284839505734067476926451104496434541582983914416281292812699388088495707067652976139900162078153 + 1962925444708479245069456050692574860960690835458249514553536707157865617717301444683893731781098151767222498616081872995504896 + 8173903682609218746993851247188524280631112843215665762250628484523471921122641923241385617676960635551184550463145418449684690 + 2919933149036430836155770474842583951453613631150982113752681626101371527818957365564134323888669717562193735500885632774199608 + 1609040194815030093545138643057865379099082109649230423000768558709693305039551156969735710643672277845208035827493067182565724 + 6908049177553254273158603203912637795720376483171212869602699514186725461068506421013630496115516175113680573200157037543353536 + 7096806396941038667344905110986317666939904573544009284947400783005195693194103701914010433669991415780015087815639572682791514 + 3680756978168727352707707927350530897842094443052210887958488018513662258743146529661558086974070289076864455883890457256934114 + 1990854389059420349848505548169668954938843880071111806085356892226974097003547436768393216697877346132002814225746150600875921 + 4374492277982018508835930955357380285574652568017468028145914088210165891776161047538281175076369924948661559170128551211440651 + 6393090046195615488795758266312386404911848462625030168594274415704463604586947949625250757933039912135660379167156550736214014 + 5728243934436503311699358540925223297549609990942386098315769782770878982264993140803173130768644963918006938211060093506696811 + 8242993502087208931436768299544970974899425557012952209431499521399155627662162396837380424393929443574272383673835625796387465 + 2907417733054963303298412175669470571774232019901402324926626651661243360954715973085766036500273697051651414938093042950467378 + 6785894337286818807967188916007632157799934091531302525882785328964971157321099749451607078727217297793573097237856806946698841 + 2698558719450879861393803875387234736047009367170703129862250880475805397892793129358764218650002148641764709592993056227677164 + 0081971305438865752091446464085352177755237063190907377734114566649793616356658589817576855323559323530686449621884731840150788 + 1826939540243947080817186653825740075444935631469715645767626335326860305087307127848152820195439244125563274241365606473310540 + 8086243883958240578268878611599696204485799969418845316458163879163274209827292559109804125366908746820981499563030997204003905 + 0386391010049409963011357239704626669689746915426124197111331235480408669200583724344735150698143659880232480059746405028850204 + 7070621356175994235487518719187218494861976025281218293612423462113181646903473241591007825352754630207984555163787848738511210 + 5746214941035113394857005157649321493185603337720914119128667915231061424163637568324581504110784614852811094476768652380182856 + 9112517888906528267503001049949573135127874375506725576149307826638851599758326023611417494647191891545342374452874064341534379 + 2427813650814077661287436979575407398921688136831196702246080880472345267198382221158754713144173467705458354166291752011017130 + 3427037443878854401716449891823089902160247151232344993329995686205840347612271617101573796125148445827775208799719717001561364 + 6663271105359323644532079372626792834540392816461024173260479629489907065371009161907255452160867279588979514640773444750654047 + 5973386387254971355387042682264494417370956942797373987206113528047687059080572493246240752693790196755839336183495531383520500 + 0786113322119991260636829390212550532753074849695602064584008995135867708856455125847634381213436388672553141147016113632022246 + 5315245540985412852477846866194175059739189599584743384794049685678013782286205098025299864897730658726559776885622145372207093 + 2947046237055804495388214736381241294012375243250351412075115454784594240484997746146442841037234277389231586332048832314609602 + 4940560326735767175083614737052886039378277408442894735731934794992054788139312451587128497131293085948245032106415584594528368 + 0132772291233611554088929401128017045937329980274933241381990578374018596495898631586186020586965351932668997510872004538098971 + 6387651070790112849045385204698059096706128798635300671169181792420546539133767532896269735055635232257735434930885609585584847 + 9016459024097607724588041340562451108743288014737496316921528251742165151671257409207041532182399287641327587310586187223956817 + 7534883738445463926481692970148340291005837757179973259685921796789142441810657257829230854362459214897426800925224271446152113 + 0560193061957298132549489635518745231685759631661778699250394638322691452161479836232887573811183208096513244778566157714733211 + 1547430295477490963534296984638628258877576273566145152920369666682577588376652374130208299869130148553971805471715526321961195 + 6131510592032893543765491267410178707297913936975805122290905928404238596549066769665229727337467790389337961037867643489553699 + 0609065177988688342181444376437189336384085173474299503743870199156371216381879438127542687917993261590322648797772549606051885 + 5486486858037007564853644084702405129390388809213365108089374357918264647019430516503970264903210163964653753490047274772902330 + 0461300174226405350596681300475321223682365336534045385167141718398138848125986935473489411898994178547406946367385725330213907 + 1293509274626976153463652826393079169386713361776443893666230924263947932847701762953659799461100689690446626123374959253884277 + 1306373580520533113454583490110255646387329350405309931889447247185635126485724261288069862689556565591921946727772549017471108 + 4575946994632942954732825619796920704805541065043930109567542878956936210283544264617080903536339854736947121491562648913229061 + 3705434044613436537344272909123399762720035093491390444488810776264889843570633561219106570438196072991495500597843887820183050 + 9436774296203905562085230110417550251074216179370977223886873788396051869595539699599654175540263842606847704783570758848289347 + 8739544541060559735321933455321086474549444477666793232318769795339438758735396350156993223591143789407202109979058296632555075 + 4292457420547255026544250001229816943682894619632431862491477990869504856164569154248439119907994750443837979614731379296026483 + 7759359950784829354681821925764141180511597239315053998175532245470389364554510124781233539932768390441633522487434841829277108 + 6460068597420725351564334958788443977520626552046510044910725038151710003467025913052244964411427404827820741380296783360351862 + 5211054158075000733081570753562084145801231533068994378093380973748015206056523195741701721944088905307131000364624646104412959 + 5581089920926259625216459931700561828077094118449960988240945610479754976194870306805076133937666171790939426378434449418282506 + 6039057527913534217575393813423847928955750038761332266774182283692275076570170104686335201401167177077211434292507428463611621 + 0405115165537284758792010216853186661681734615099607405177733845109910013152569350731884598363743840624814198617754273927011515 + 1407618016023682414983073935592618659194377480743081488662206405541839291934958759003119610099774589701968015068594030177949217 + 0790315691986911016674475309797543936300728937674591920985541138152579574295860682375269717640514911824203818306809998011275060 + 4382117983381412972994275528147432373242673418215434465602805780063289348278856395267652713597654578622689358031371373016193682 + 4971203890127140128708179164505005602256484886747097346823610758765747601150832737555748482400760746795103492345268624660081193 + 1238474101549902789927134668369786012288633703563425355984226013256465916402333622807942597885223175366854363298056733781480165 + 2475056989181989715935840837103963570756393472493139600699839539995767516688497969127775142807367604482540314805881080534085920 + 5110483916952128964226635567750120557932419254741576165448818621280817929369091427028028668168593266857526132988629197479499338 + 7382097529770364245616319813419439630747996451787212372784898440040645194051307376865641947314145623284843530906118562837024282 + 1180719306858134644273288620402473339088866088558646666749328622134176944113672979075244216767608666882416653166422367766359934 + 7454692494850748528168077614552490356358640467830959916873691009192683520419187156489031520981784955116022176529954332656159900 + 5703126531777606205672012335960434796458742284617167876316278828807209603472901804370309819783462306443611963348173237324352923 + 7622935915352142387734818536448742013947936195902370636105913778439778154319304174619967238291501475263405722167671985219327033 + 4192469391918128902822325360387297654953797790226858555687025028458729211895927349803665945095655786671449147679921097155626406 + 2780677237649339975622761955036413080116980723465856549727438471457957358521359815258203894427475417964365478268462653223640340 + 6384355742271287800278025268983527483432389226283229170112845354988683227778986191910815226499442938779725664362022274661446656 + 8983529286956750153487719136198257278584599062333134754547317517831680020077715886321603644059583997509690986046227389994861108 + 7329782796097322937140185361853575699691754834694652931632748528792770060065607908729085140248378226282625852546158156687855610 + 7542858690282896923167331772353246169388345238738453225427851985834084721866947550098641275435407170332769801857389664211235898 + 5799583185812386717849837795175430854770749931463501139883970148364355569591352178627597816164651268936590016366615235430971843 + 1626691744466309451182517845050907803525893409042451069687831523577743242687080029262942742968372360368621788807914146915526880 + 5318459023686131069631243003764992320489381131276662425282581511713606116289353391248019203404378565007089996278162834011328054 + 2940914263304203321901619997487124198689066488749388375440671721678381773728920019056941032982814050260828373786697860844945937 + 0935106263610485636127316359361586585062460943315331019818757835533567856247177900197592421873824025425985298148601575872003838 + 7678845567273084139170475285839065925039600025616987691701666903861540800590513965950744386259900437461673353720707990879400851 + 8954549187260534626790030686600472676242184422173770737899202674956746463128211733652450269429272431346452882295888511514249530 + 2678743312277245350760231139022995628706226321476561623183303095250671287742041881664219630594695703026351221927214229218759706 + 8754746770599874955073426285210045733061478934256278154824723752843570542480374148666553082213624470594178380618511944338556770 + 1258342170448502309847524118053510267304683961421264512188294654208652383435713573419843151024833136714917076044792376946554552 + 2686790894179727162588194653073820095034068415445717821765878768235572220948743946189649565838289653662296142578461681042115408 + 4979975702994756010947392018214486397764251254586716632357033001934850295130508675410334819960903160411122706650159720668896818 + 3588969475934951426055953320940144471459990302441248110905750552714828775127383961567862284258836730043491152173444309138622805 + 0885835602018492226235865580484440117123283431801851414462459989105042310153202450298431895243159623304698553633960555968674076 + 2495404637338396778354332975443524901010204103490577360377282407257576116606492214532864036869380580423420924036214250605437552 + 0273823801820228766960129999040441972228765926389245168282516822705610151382079832776017382538534107323345050070717318572440468 + 3719693296470114077607298610532514071278447231443437795910351532332738448270051379404482177889663554053263746637709700053641967 + 9828951429348008059079973550469791268813640030847883313731919419849614743360559828672182938947231250356355114573949483277719010 + 8160147790535337222916241165963603517851503563087426894556730214593005608351479878086372777584308199478067490440060949884647159 + 2948684894394971841029364986618911826288588400559264365297543464936912860908849309130216792677280193265598685884468366012698447 + 3139146768567604514882268160880542261286448423327913447026774946542138981930662613526814753066924945383435581070740645979592320 + 2648770517875200683345474598491811627153093170689853703611806314466352414707945002443742160480066256003350127740349411901099140 + 3308592816806695381210143529051488111319581220479904092647583948868369653515446635908476209492392955841254295107008775348098134 + 9546057832057661112548846778480873064251831646186943320977718022174333455691510572548784701482794043711785251965805930805124302 + 9797598220825240487337675580868560618123083511865310119111306172185132317065154479238514833175902325985968356007574306322665172 + 6169700545459665615556940263207457415925074513750097043236324790451429771342105725243301487094857682554118664272164353388631072 + 2065773265591123476370674843120027879502951065822173174917589895449890375502164860452910893685397468281488262706240927914630538 + 1707471421521563472417257512298478800552951214730430454446551411959701879859928077389843110236600965268158074916952323108191254 + 2504020366275453319690764881376901720307904782764373433647976640867427413961893744590272111954111461916745192557787193817126040 + 1588579151481338108756894573873934357158704669830936720767495898488860812251579113152660788061419535504615986627104261122375990 + 7331623622011754370645778091243569467777379728540842719407347993337611435365175147413009114962875879124181378102542276566594108 + 7484609326756980072187285780841286543812762762534587441056462410575222582806689121646585229111979073490526305371963936438467919 + 5706586317647554978296224372749817614542161459685489294484897802898801747536653246958762657311576344225567199024088879682797895 + 7982416710167868709570332702438980645861985176457876981357976675349506324625350574864591977896798566893422693217353865223434242 + 4612810517637816971256206727690640808547458195070320671241318078156152911173576755031013652809873321281227880993755057868636257 + 5869566853914426396407700744200965755799089377206196772845889331869496057116760154715122075783787728423594874902542137832225559 + 9589225721722482637458883619679136109478999500918895037360018469933679740571642521146059558547268528193088694289457407297389417 + 8114608149302113225536168603740452239048816211285413122470267658232185443153634579198429078537401989102386028340268733889611123 + 1658771744647637356624539664960206812688702241127922503053926273465214516451739790546967335354319444825617690989800359892589856 + 0053465651697302095039711511050038742810220818349852842019182724663703883278427036626489847521335203092583455303768771456368837 + 9461783935995459315552854731516681231226811974225458662840484653357703794689886592991537310946084831023202899386375997693481512 + 4533585921481186000403378289480817856084298244494770175994273545179036968044114231324393781909984894250047249639320078105176941 + 0088337423065130496692628858394850230047403024636567775158827661121094757863694577077324592397639708861018849419374525563390572 + 9433907825695888321692655143225283986904641901823924591220365135713855259383744336203797993519930945597887702113356326830645826 + 6988446116797840398450853279454162958768243775646820798515687585868046231740714350466068297160555230698894793181661331483900976 + 3228255598385373641636782196372646263654896275851591790742732186929071139789500558984105284755563028281035328678092579289714000 + 4681011094010579149015425103883784622081638214345888273901960768244903621448040859732301956914911242855175944393888342553563087 + 2560980412018398873410432462155957943116348971819529996430919042949095207925589612393187400930103605496273814170584912659092382 + 9069469616610979589154787060025562176784632650316733720274832314981371020706161084351225782272365506817110974959084699634535788 + 6765587755549143676480283034752182178980320308874937062805295265849032617917049285075020134633510431916668093086266525800515736 + 1987129393090049213521579473208927794007157494973792406906256045288699283419276005662236119067885571670938877198469481410429981 + 3722619269607651225319072582934109199126677644296125933160645018724047938190291886105626593185859522559253131444513872231301882 + 3878903450400959596968323921819162239731394330071230682797573061816799122019281619186466630116704421984435128057686311537024574 + 2171772674581440679441147914828465322671796713303729214917204516452594596558898159147461291026535836576291138961274078954494387 + 1278996875658664588862768319875101010284199226028473900312140448349990579106956212227946883352757991736474264479730037979113425 + 8251737524782800721142346398693390112514424073577724343296177123905498209033583895128953063498814237667366732979745537429555278 + 0896743149526940034664390783553213882383502205749882093466354195761918368893140199641725113693740413564898871253806941096124190 + 7796854830589872123486600630498401268330698814798157768931103798808711643064916232366065296644778046047073412187780619253278677 + 6500537503531609708551372800808683958268146390074367413801774325497534682441389495398023074938743544207866592122064463211672009 + 8374007659269318743410884141200642883663626493756879447578129358932170292700541285549708569643545027306452528039696051958912164 + 5461313220523803049639223578843432913631643532704665479011316367050573380692644563882130994146341345324086855525040200238888685 + 8089200828994642111859047971321583377842360402699515255215765930754030446170133309029861283548123601950771958367816928039501979 + 4921861981592932540366839797291842409375656173168252866766746284441002285941098783812692417408647250610811303546299712956961745 + 9167799975366484899208629064327399424255199740686280222254809555146344897012896217389558240697588684347940576269967072665683864 + 9259388885200851860744997606520800745929512006692275733677005833780389985037437438896650034386964970221299725643606029624930990 + 1923555984126235140744073661251739569863134027553494228555366490941034788475845541690058986834251129830243447779754071605873640 + 8546321296959618681680784347875855095908171158196021873844044080735403609307093046577378976184646301996038465275795577308210631 + 0292841602799520083981301964025702228115813520124006499666068950846030422607104364257191751077960220252620197225981403964787782 + 1502322992487049171872430148257934075524270686852895414785698734102981748355080650539194240735935759095611779799454232906920170 + 7645673745116807956634247517521534891766878215315481669195796109233157590171328181080639943010458633508897705148841450600988472 + 5372622766288568973430030404326811200585106334044292931194542876927622884286129265334479806408440904927200146880239590676743160 + 9737852886366125426992930022076166695307759649277919719824038921587655496096287480936269368326605698820270793854355939980396762 + 3180790631743853089037422811844405317287386545411386410379668362987107109358079426452748318127402761332147799830440163526016129 + 9051792458167155549317710812956107571797762247756516089487421498534083002847984096816239076561386593955153876706013822381927681 + 4173095560231171732875361485159122658902814416236442472154640300288401422165407659115651941434514022078384640403200843998671972 + 5966470556331046673745430553457883526280940892044422560744252802816860579980940340917982940500224988618235941234788610789509168 + 0789375239650015659257828854233372959702664651151444414363942452653680312005125741160555543069598467797693116222658921071003474 + 8906623899466461239060702070337224569185523906567051838309830757794131815206179504935357263945463042333252081048931892858013514 + 2565946185596833054040544913117114680329109501977878093743966290348734278988799428312347727405020457211698124070822545220367599 + 7887639027440626642608258462581197685627001806341140783071773706310063459682140433859377089948217599328491885205500920242752765 + 9105042785087589492163764806502467978793005126850254340679666786999523605304678430709511644540488408967072195820451312364898977 + 4806602335002501148210169758225301946374240051070758860058332659173580299590222924023022260764063882929324416573334085874519685 + 8860484115578005776711551777005731510087855975894724843956874006078066036507250577776451260714027733005242056180700853839120022 + 9972510062716845450929888769682540876602068670550887529330503339523242901354677312818632650357341649500497585776441604969459550 + 2623606137079639076047135393717143616094073824102105929404170935516181957666178130675618698894069752882863773580174806425770058 + 4036671892720176871088682314351824213287902597131301780764439176800136663620269901795969751693427552587437595932156820043424392 + 0677294124292240149296066696637747776445858679559483174535961774585189431151122220911414705647847144029722579499169874681984001 + 3515611659295600392682520429928899147250410034409210806506732173247308027181439461299331344368884698174936563300497600474483708 + 0063773420552619484426050490136425686777123343387056930411442496315945289353053161802745807953399447036489317450479861853401831 + 1025437802898670603956439520711493780674154126180902484921242469929281393551385642769157018539956452797615106532069322627218483 + 8759796578568398063968102679425317647163292357375418469803494058822777510870684874739268000355169575539187937262850844553141671 + 0520130761108166376660600783005143635657232142524978468353606381401953088627097253750920455395288123559132491257402067683088919 + 2890887289996966535342242107315365601206035014159576380219737883962373302977227719789793402712556663655879816814402801231940391 + 7075049290134330330911964129274745947329781151686133509827045508476840011833420977165532815261601339404747681713954176358695787 + 4190862513692697255977164180664759574127822507052658315853043337010650269787647027656260221445450941719360532423677717036461514 + 6908155746961875390092893184110336543104604423996158420042649680420697682015958655453176718660496277341803127921088518280061343 + 8331309328194407889735199978235437818800306669005429636917360222653217191676841870581785131998034245906906399415366961802496511 + 4025301862689940996141896458524993405457637230423945068131717803505952316603722440206101338781745994056920279938566008667957974 + 8407156560172061727221211500538117499687747789630891734019549331980906693172176957439813668311313041124185359330130579817813671 + 7466416959132373028000515440426004927338552129675365950832267054293724597329240325990928091976976797329108528262309484406803795 + 7029882344252063506996455416881601769204928489785629548747090770306190718064516950313796925310576174715934481881905681054628070 + 6880642279419324327941511209000580929409891074059158709439715032933825582097408872913695012908119133558817540571147731630417054 + 0450976304961807996926719984418185237945644387146277128118939816965978556618267349869880710186417738649005061794411263100794703 + 7430304052534898545934660709004803179571319216041424124846029027406133093839979267839656729246840664461817790155804024698154985 + 7645544772776077953527747512204638297554270388027111651502874795299134795410937797070656228161921719694817879801901345933313665 + 1313410076049663998827811921356048583498283359569530324863158193199961087225704771561935232487625934010979224924950123845221938 + 5542450907649094312430747916423053695607417672358828335758664117685424978394617325307248658166202146920547925646776725087468720 + 8125710483678181819120321493187443931435742819361342552711290450551262872707443639793745995943576289709507020621251828473114770 + 5808995455056792083922234742431742082106369821885564948694790039533752228468465967393391425326441602867483086230714643155046641 + 2407915004627569028579526596926110527896052886334582385573230907225818330304996992697006735418150830862621130034997989250568103 + 4747836691209220024929494385208567863244371223110054782899030754719240501536232821233744154670656379727685527957774155672319475 + 9632183735133215405359145903218054467186662532650851575633645907886287911612022173510068469813052313582577723168904869118582615 + 1758443894147315526858202229285381300192667883978558926059924490571584269631902778078169815289434853467255533171050775547788250 + 6827379725903576619807972215479471705793002981926808670091729392075163455575073588508765374074600361763199064144608650998814612 + 1139348883195112842120618191199370895634072657781661691958053236883789482321308598352679539450892103726749423679416567117182472 + 5628380449503846780627597266237186381426941668768981275727365655268389180764025467621494196092237996217033830813378898293373834 + 6249982118767143075646051931844250281862161753132641089322013640269043322260625061753846454820580624883961230554153956989845603 + 1506389246361534372134008198497771836659467625678409854914006570144648661265229365915719554541771143877999578976720337073985818 + 7005263179523699177762675340194056182817188450058666203568903779623473238455975919469726862072009578002483873154457672262756142 + 2974648493466373909300392298493641388947991203930909247567333382267233769728042131150238686456747730553128288781731025800074389 + 5103801198075821222369482103926218823537252278659224466101143285542928579893855240568803378461857010249847636234366813910593321 + 8255444368358914408018189587539831385866661807993390145935560791507824844153502737089683973595182396850151415917641412882278385 + 6994623624086457510788033568938511176649748143257081559534249807952079088004873263643117220080770572410226081636499222544341556 + 5868861827549149829709753995576140261303291609060728919357591890769431437067208298630183272025511291993873213366101172628545169 + 3536668590020988868465523872067378130539719812107645831862475320339405404292929655894962610265222780223832442563481658864747632 + 3855559579815655284020206856324714890689773172461142431850331038157366681406979208119201701019291754639995462477549126425391350 + 8450291792039621077539436402960450989801386738795258875543765926494042577259109968714035988972694939518009619956412673656801521 + 9433075795122748111293126771649210779744396506362417079033687912993766618349565561906099136133480366162159291355560623721579187 + 3378797875509332216281558051343681937584540368139917115626876588840206579792879445323063696609803160334574023091211019696117960 + 8286659856511129135392256673984667705469454940089344874655311260297659378259031305125448870028720171028350742267966605006358033 + 1559883131888908511800248016547342952257309383028102249271256078844439208862517563884780187208616611438790446776997799461384713 + 9213000700276768725565441947730287329227888200262127732583001595805481558214719061412862292967561082950848644790833398460564723 + 1237463356367627789252505343790157426584837476951882453112990120548575795054118752744721410491509448371890573822392145256573546 + 0705282244277315586839396249472907788988824858086668101214804950902161992883203183045693099700874860748969961552066568180233875 + 3649804362910298143091615106831740058421008356128934335979284102172120855125136327683861035088765145754792315464262726624806783 + 9434730144784579817482674138286237679514020123482574946846405367389289759453442305761634017866345369865209680919734485563877769 + 7735810389258589718835809442124950108708303704945904199371845065484839372522859566124912994258804441548671551838820818437896075 + 7383779025406555287701082383561184897642996999173556341153509465466385364878232088945280693653997350128318569872380406482923450 + 0873625836034957145587001580511059464110231294763738687292419746897783167632026738408026265866915946594910670670203196220111099 + 7591072259741426420367322902499121885937012842290323842004604562106110626665272233088406003591488022718144482545987747891823870 + 9175117307974364573779518417573849521480439605413624062061689756346227400155445091604379572899069013192269044493766848399848392 + 5240204070345240378009455038862456326732346785249576960346569277468135720674493354585769115025511723751059422380004118585409709 + 3349173998694448270286501817135410477702569648480525937208264068896413487832339295364105296137401893118290448960552591536754124 + 2721855377073042117183109540215181252714104113649070283807754222580162122302324470826848007123339852921541117150545915474905734 + 4442237467667117475961916917266329385273400917266015718314637687934575915917583933649989627896013912399205012102463085560527584 + 4091026285900629392132231811067909337191049861336953793421590084466340471776345574531068461460044327698926685026108185944785273 + 5202568174541673346987530914965105932805689677456919213224331168071054852507039901870720345655716025476685968559834858758422493 + 0614858796890361150654138608860068135509273139791153876597516417474596470901950497034522305572817639212080825359999795816120790 + 4690019462662785935463711750437540580321430169890806355137538513325878535253326703788253684313085653375194280379587086774403636 + 1192297531414960747356858854539457018921020998476941206542822005080405209643807598603349026957600933047420780702135587594220420 + 6385879114957936148095665992720513226197859511089355764654052901972661068207137358088876405026746758171573905075146612191621724 + 7225256074560068850195651541217829216290435321680622077492940113765770295891334808874940394348277026794361425754981697514840551 + 6579386119350941004072171940171520374772062901476128261790580552298150743389764668933362002827319670377285437400224631386514541 + 8225060930462866114265671430768226751533399557663700459188510439035058277166158167696828360029527807376628848000272330091576713 + 0060985472860653127812993949032906458731116791182858234879179245998734711417931089452148679024170798661176089885161196837664106 + 3722805008939449259124307009136610112592018063781886320098372656598331954054355261215122816645348365251690431718100984807641151 + 7671563753475866652087409998956658850991352510305691362750704516857124752942784347614592502287785972007339688267613862027066735 + 1058283061155393934892259910225706182663785747481861117691921311446649045132526185682558542054377226003665649454406375422089246 + 9732227956822666337303879201449758438032098745926653063569926833474234804332766368153105341066282800778041496886005184241210550 + 3671076559003594556531982936604847786145732585941552091406028722895252734130685947197552543811727116647815405252804851390263345 + 6932108260738047486627928786730592183240725916073436786293871274003576099287405402166418657664483313714856186223383473022466647 + 3109816045417430083537878210451471667742535838802468841651352736464574926057073048472886864367560530408263557356129708697457730 + 5131047990674797494394562345612521219564146779615283892037401029449518064490250135341621616256327661631926681344727899774392825 + 9793560539429965156147946048811944830887554283992612919784433839525971829092056423046384752108153956186882584119526879128063725 + 4848894438740997315189560856906795393017681147097928684567412396811955257068230623390617279746246419592475583485164533349133972 + 9247196347885177565475533963701634576057917406510305607776085697222055528129649096213092034549229625900854393776713393006598014 + 0895574299458423626122169092017122327940337399418681543962293182652716019527292869659349372977261887962838657423721599638764034 + 8069818312801265892359056947805299813404068292205524125399036272188934298155723014962611157660369164361085013693243392717540968 + 1746313469892957608005716135870516847580996237870651257913684437466577959076954626426758903637186057505535214913540381448786350 + 0826130380070802481888865468100577235559992056039751752075537240976306665243883422413804381659448597324700429367218879041686316 + 8783969310605138136810926575209117557352903553802462523920408350875226887462880478648547408932195087998226093346126517623953622 + 3655963588132204550439064715232312197339282921758181601943083078440247650220106399066615678880555199248431536315260442825292972 + 2898418712339146920156618115849473564647025888554958680753487875973131958912468912448106432964749351366422577093050105438712807 + 1852498129286540733225557917645869957332090278845330056842464816843083325044360873406582227952116884337704935341689726805650922 + 3976284069253193914079828201683985526108157492968673193265258027640406409120387997580216531505549000204500196895696438933985023 + 7344227386409800578949975082890327124630045606308364332447462178940410322375677488036092734345158152279018751575711953710675611 + 1365860719506143953539467521806358327791893587420884033512557356449628421974197081525171097681451739962654458105945042338824044 + 7339951041651291336434788317295707347631976285149811926440821662705811682404836418364754712250487175296474328282212659994274238 + 0212161973979980092408896174977830808566631947896643996545492647236993898876722578200269918604906863319277003087190525085408577 + 4872695328272197013637039406318385585335721591609046713028487734545081008963689929406578869624586103965589484238888590831714070 + 3093781382852235095749474972285903266360882836791963595009076006750220113661602476802687021999748113402446232401462878936110934 + 6435034693320558902105688910308538965196623309949466683973971294957981775446228096356658904951613108961843850602970532678592796 + 9900412913465232057825708257994535036127184304885007026505543104350741668197223958911527343764741682299736861152999772201279599 + 0514985184283479308437214277006973884479296109534451984897036545588323471166529442587769709637302971344236763633165248653048272 + 2548677505362732783025625571327094753804197898599649990120724885114160782630110803234921618274764179324553264262464188071111602 + 1490102219572319216164107062405778780633273426833137366869390517112371874174117264586848123441331500645236212846316718716883477 + 6374557134532066647778099833443353940716636987739316642710720220881882944339283639205849477871629369917099561362221287484469397 + 5537933700604880504714026554029166587597577826204845542181354963551493735767539318268321221914383282788245529093887530478824907 + 4539736948571324006868573970323898689460869616752573795437663232396854974783326373421982301397494963660135114656842200560632231 + 5417628879269942844019831356484605118567348015685889718110291011794547506306795984565230200245047127434730978214554859175571386 + 5244295129306313578981901753289283565322938724988065200258490956019375699629296714989839545066652554067148655850643910689520282 + 2971836240187409511885225271973597558472371014435493899110877817281998758924278138897958733963027723716372919312791817550414257 + 3718036377547310037822620295119160273747183347935451508155041258644862468137971759991204189248362267356043409939280563151645203 + 2059403653814048643066476915696010105560937121353588493219472721117585709084500577027269061641086537899045745026346755806963182 + 4321247098580397470005864122314116779988792921164422171095663365610591552259489098505982208555327107941284015766148898178511334 + 4129075760977557106793231123557041651779523250483585239932004312719534628408382643294636229121610127684366632908893383504173184 + 2529072874533404417364878145806482135038499775952105421793815591456627903830117948809720387389717200574623969207051170720940841 + 8319746694698707336604137199806790228573013581807699678418425604568242103303802544153333753105945256725487631110225791990763711 + 3880160358558853965367146276153313624158725831047412244380280879089394407413109649993209520904697096729360273647396579418687376 + 2091906829462709596208568404663223009844823381264480008433097662223468678702122339891481765380241818468489069582210313140199504 + 7634167069455911451763369770809802453049016134384625283172635485682336911180471943157282346432504400241673963332048163371168819 + 6945528084709716553738011980160563280642542751055915815221655609127228922438332498633425574184424076324567457335614537707491118 + 6855985221224698806898182154405013337026345633363958698774698699505064139860586968819626692305575161911369355200549282693239574 + 9661995161189339321012455875057211575581587182476156883528607442238967236926672903199283225630412167629967841892682077069456544 + 5556977126081270383421853880021926196747677623279360503448724398127284807443362608046943892392030345708092629807650879718315338 + 2008556770184273576766805643194174770708191017610672185545130733621276522353464775534219302741371801405182864900478774809576537 + 3865082900785088869003731961311138273432940384506242628178208362272250891137755623037615929981020628600026015312604846649871045 + 1810271541153370013506194385701474067688519311563701121092950023460871685900667973434789085894353689769155959515852286976707125 + 9220855281244525680311255117572398240118776083069705246489217127641378521494501271090294888487837045515780398860147999941580644 + 7341485956164711767365322167960284966203049807458284565556017984048646824943506319395879136232290301571995491168074801397213067 + 5371405547126368328180403806382396944697802094247261778722922120527093199887586224288144259646007747572032786762234373440343768 + 9641998676406552363362334096338343938226513712459780071504106769464358782102176567281764333076640338559714360625098972864983029 + 5780224793125175832096440772460219675603258721147649221639684097269727175225573293185628479999177881598175668238919939024400140 + 5871315749737173437146622211284749783435729572078139529891438562616324259909214610231102730312223921245301659630109254504380334 + 6697637358599635782137313649853967748604644159075078379860391872979880640358744386814475406235163749464766557762029498100317344 + 9260432917913444420430985635427292687992391436924828756222785655924726309271829922076362876173530631675597755661167920958784469 + 8008272163146127952220122593079694523591964786341879588418492633364085713190449203278430539536800444410958318893570820694596913 + 5865771428552651226808077349460469511350507824410126508014924137043903316541107301501243645730254790431504727160432598689746741 + 0797866504326277547835398517451743711623314102885283925539211029404096358855485908679412360891989483761400122402649553985042303 + 6315338269917337190802305575034003552890761126872174385267928282692687307003769845400327640284655468895977857113820663582843212 + 5883143761391732179613778683464000760776952507578651405618216504779945736760856433526347237980076786027307666785673805176780505 + 2608019170724255979187609288672429113478903050968752935506997075853793110328285209939065370268834945095553185289660445134585271 + 5934178091636548622002305410563118241322636012045119794891759960583808782939464117247149044590174301040963274743429124451974081 + 9822212841254646950102433569804383682318140936706127266382165162763534213426673482380144302560262856995513292329891211427952322 + 4939074943058922639133209628604240951813644498408022254626546671648111368884617471264005460319454857408802054462873323814596304 + 3567851550694955955743156890344607975932611999373517821856035756405925438219730313496771878294219292907299376903706456079314724 + 4355891716120089571168867921156570013309057339164893294310027619061553640293850173132141828093723591781265620877693908024633891 + 3432150765823697928455051347308237232788126878764759364421680111689906395962403729413891780224106047993476140159348719814489238 + 0234684991575714928121012708547654894568292786765465546202194583822334911755447378931758555122045328265456840620648627956740582 + 6213762564459648735386518381734716590458385722741140951208497160837103126054522292981022939593107580769282971517719856277138950 + 9795430658880195944561326976463238641719113418421451290008508454179670774519228875316092692131997401436104108663905564902246214 + 9652373982485787988119955149332007099514930250170109206849474570844779657182243727422415156736246473756296181666403081597210612 + 6363221919442807657179269261813196315614323943076172547080772762082497876523976444410926957078802241443845971487934887307740781 + 8442538716705496485993660458983193034639571775952652456130115624584796446966906201307091498198760859970990751619599499849168922 + 7540755071266549940783200519568012630337075342163311989445430751720634069245959298519839175642543857453232073106471321794307960 + 1699245059009156264426959609151370644710641713396754020166970217700932248280718651485571836633670709702375632170998942628345680 + 0816396190588432801059693946646313280382672711087244012208759747817406868034578850546787526313820913242493648577159472787123381 + 0759322746357530465987827894614798343895157467747058744481984104257507440485290934854164189380366013210043776529824930881371048 + 6385658080000822018084506735695449199723297410443658699992360702264595362859622022028092450523165950738306668328519968101921178 + 9290969633149036611961423129438616262578501454017560337962795366936304454531175225394994520495848281893733418969823834849646325 + 4866905011511861701376543806753349151579844197278285044705460570867283644779510401658626041128258372474841328027560368075591684 + 4097340967374048459759351247293757377219970623863320131555594933368226711740987383236414710324945367020743532195606500683770435 + 8777289231702354648686196142357855572861820397757772835817870476148855333166772599103631182225390962911857675993162562793056451 + 1643701292272316612682496492137369576459996136135417810378930005125534965897227946840522877611416279622753205256995171831362038 + 0366738891350724663780781742018384952618867530073606447030185424566647732433327301660674858875240792034393577096349757765316310 + 8289591408206074373434407333542355057011414872348953466323958988208406535831896578204946085981588003478321397316316325936083627 + 9704718565559121039339280928457498417206123777131839564784077774260566019404908403357317188872113841441577298919813210986548633 + 9293886303171570837540716535349361584600602170148405662530496205079833641395026663688854207586823003823193883976384903470625532 + 1727675041270249998973772127828169098733155135266069947499638944765750528948036161984830730668217006998355034769138526948886812 + 0092789759212121413625842309085282315688319684507180858726957280563112424218015623004324904038907228951254860936129174811193610 + 7248502251808372373101361237612617365642190393287142805878594705588056326330546884029678052177636399750149538893582015648656691 + 3367150919108114535725714981888781359653934702237037159199343298241562681613327166427987327289684634196866794561168570101129576 + 3376393226054192039386172081865991731275655717454440752850294664224843539838937920883445641690602345087514795742186569107517414 + 3623971382393048718491241619316545941650237621831224965329865224908967972818626887372855949653336237529478398264567160685068577 + 4052813893095863733367924664141451148648087387776942749014403408537141959668060633169208644494300366994545481397333067992909358 + 0667669402093903159518564734675653958529086910570255872008713355774046040785518290333034404789497402572158389475386895486868259 + 7468963766629011848413788837165962853506507117471181320045844652746289086413801588758664510368868946415159144280007188633881726 + 7244685543653493127669292847190750279258471265994953355225441242455255911176450067019362851931161106818923851255323971731656588 + 5234890473800747514454607303289634698091529945347698407177688996229422965619449293992367330399443066079751703944482713291326343 + 6459044264277571164204689989304404957960666476059760392612837445978755062781098058819661144475485054149528425812865761888665230 + 4335062014272927898970122302854052906295227383275313276798239957308395793035503825814636802802824167294443473540831595897555019 + 7272548964073946058176039524239703608785612474858328053422538963447385787828187985994849316214926394617015487472147004996421715 + 5996250931763812814551030631847429127490485716717613966608339966170653265360723312151608339298980087240888475983661731432872181 + 2297536852364764322872184823063403907099469015512172454623275616030363118664676670421610327708607480232788374190290021972622793 + 6341746181410744070773088966325798253704849845010112635545932402181743821794042899160348845322610793015131752714444557452077603 + 0974929188283489944704823132680006629007254931129889666199080416689925517182595848963795936091170595822025233402048475030835352 + 6345563891720858751435127759306670956633219054037703933137927110019397801896389210768937954353107771885376564624836527498565777 + 7406605189056950050564580620487220225704555865872099535962165458171814654057503675391062376917680202395298499820248250031013118 + 9646002186451042668001138188414741520592517338749162144757726571293411846579111672780359450504540363461450479439757376293399965 + 5620887367929571798109873216776069586763980872092222280624201174614361433514239488022226011723867237579885237366697226018636145 + 7658816676965243906096876039909445364177324988679848256414790985301032302828151276736018655718069421805321528401722943260148087 + 3504531887253350368429518151187892137924735559724530027941664978322897818820489478004391185810494126054267658700325358193119630 + 6476950573687760010199531144942136546086284325150545828401223666989902218958065517474495615521528611225439578736181496123291235 + 8141273699960775743878136458997315091877968088833966155435545803714212437024032432947661397098373986850161208575249088483734667 + 7526564869781879172205819920641629162261070844597301726270751056013595355206013946667713217060767795442616244184317275433955181 + 6807778755059399042252363801724898729347456888637350665052001794960468288523356956423878794195125458046129085019792922364372832 + 9606605635909164393346308754559022246397895156754911940817409436883533684563312856180585298884265000503280045621922703129043223 + 1353282688124152832117904166784884443448057703427122162928095824570260033806131301099883014390489674198929314751517488130229287 + 3941712694041861559776002423763440625536805158907454771393762216105225325673929237051966211204216493810015246774275044495594616 + 3694132772158289887311123798026659094603586436166517150338257882694213224057803554027693325965893134619716724281180373864668897 + 0965421930380580362871564338408316626579345707567981028006568747619015807088576948951469852219385041334895298633260796214042764 + 4365061209195177145333592267894941789748549729388820653503884365772532158665492262305741107905299439181875779535940222413616201 + 7002692668339856374514202085788525299569973429859432424389034479629705876996023622182434169328690891870930429505413389490533136 + 4295933444463189433951574721728951160043627069745406122977006157620687110134601604174649175489421916452229565760756130297102064 + 1960368933597422050626608328849588309269037647433491188814133197810733941601294848194060829957660144812059760171213031036827489 + 5163673581923411040228773859014781426438397455478270422462230943695383387244412044104565525899545629313341781559828594738866880 + 9340062964014870509227099698887936675774112546104074153547361150335199188541340855227153532746778775047019132401967059701871242 + 3486224254115155530038741441994666898680466167832566881940775772365423817200581937154559007068187829334117784945473428671685916 + 6007443619236946702946484250753989318115938165448366527641686620981129998037010871500824063178061129082786722904909804168031283 + 5077049104333703032159256335893142225775472800145797927383645074150506549583979834771372332786212436563421519736302401896553214 + 9328253090460566002578048864828230612968529907510194421722878024618561333479693530779323192843841998003032594026649617397117033 + 6902940885468724446328665796554679901999854957523032465138455983570952184108442966984143957137952183112915545991326476857170678 + 1147940566264959316051371696041947904637481710293264721589819021588178200143221071704512368347198312678908673679523259812561827 + 1664627873674389755627490418493705966611982979380988314739579220409030725477944088566536789756067951060713524593551031845158984 + 3598081566704365022254984411009080907751257030857437625615151390400729972784657938585703465777027605245686537246903748184890274 + 3743523412032108137414706768919475408652123860125336712812291505493576913938367683595349130153523703056997225766687176144402340 + 0831940301479210349558229457276992358900461281585291044594812536347699257011182959431429011534075284989504481274394019519138849 + 5294182590907051056305209676408046536522421503936187377406071503791132907536141109384530248717758304915645762984125835020638228 + 2925263782209751558565689180869492270244285946019041108330056058905348740666223484108200048676063426609063511425234359377856803 + 5066811579460770402822516077692569897555102184861090248580603480179709451447581598869819018321983813091599472628576647298283510 + 6074763977940235151776420120127969582510026900568916108091774893522283047922950769687105424389690185426520673414305707753060144 + 1829809239775426957360751626081187328513913192137296926783947378382044283754109795780048763911203026361961183033933012273700578 + 6256148707335785289325167505290076615535370263567053348838880542975561767345020465640090418173271179915907484593965695502745441 + 2416400711412329501943051474827325196149637971289654356289167838113336024091716837472756809029018726324544210527893716549434408 + 2077670900805210878733285491095692143052856294682669529394939361462198474814099442765549871744436963471806447226559851872954947 + 9082929602325709346337243734095265641562540772131425161193766826203999287761238275537747088073534676484013517045928815906520421 + 5721840157618684926859754448303249283214882375060250302441861554867804071849460117284782240184817225436567120551507130457965054 + 3640323862784940017360312940091490694469989530945043763136591022334344797040629558445856236949010602808244365211211804494530091 + 6701192226260174575156745632984043284760428280836716963199179332091776863302070789290228857289693019520852953529236479717683160 + 7117865720410815041230240613271283107726446255341876904224653305719269008887983911844926604802435682901331270611392890319564523 + 6692783449614566649026808017316150504276465383033625466313163064737973819404507236614011588134611220037079763294452798973884759 + 0914820111491787540225084826895277018554164459289529667607470230351077932208310255555375301186238522549530796497320559115264320 + 5836662613656654780353360816866098001238641884282152191319830259179620144977780872729828947449487560906147944637380292807461055 + 6561572680280173994959056296932010485999239763428796091258639640337313710982242786240160248574519338042692530967139936885572234 + 2825509566854748807330632140109077953768464116764873006974740017020211637781546586566316927017884251448954820201170637677959988 + 0832497323156260043765386414739221132824464852853436205409279663532624738981652928962852787063322728977472723705113895939816648 + 3887836720640005567311856937351200913471468555895780989932698604802967755682558413334239668009044766569135994431992317817193615 + 9488541867758126379374062288207207762501971013768400508156207999323493728384215408284344930017408986904527951285518045057193770 + 1193456086093196883061110691053041347131507623254475732487481683124957212918787096719880296652189465479161772651216902388161935 + 9023602670135872848924155417498176225830627494225163432154996996459879170929691453342113731711303819248475466023815067381174572 + 2080493294756115922317931111866355542145263306791051695700043555158422272380979294286809277064163627702612725392431921737967789 + 5506584820111354803017904304944193794950330337626863953844116710622843699200721933361001889997152111163384731679702997569228667 + 4453953407265344555661480951607569587119336749659238396970668832430048807500071385571032957421002113212240607304287845329689873 + 9400568404300352678168177542306869394633571699501805048687025644577243527012594817839631515308187464636399822139186673563109194 + 0383996386779379889997394025888104236940479474160100383602505977089098334042031033748699121508022116963448387393566265472288965 + 0847531693445140037287515174964594859379085364324835476807557964238229721804605800683718605401718393447954937423707976551995646 + 8901279644569224520056558762822223149315014455057454435980383798016264269841766056870811144787284148299586773970705052525539895 + 0256120889703056267161520334600912740468642740690884187820554569479971860126461193414499951106260376564440623032634236822171234 + 9700910582776001785061958742334821043319568168457980526939228569330951842352229610659307009566518307187068255993195333178816924 + 8084009439471986482548298108494644279210299285939700414080731141355145274821687079465639330167799278714667429384500519830074150 + 7502762255088959326392982513450122047410180131292434743496089993750128169949631240918611287380175422097126458912263961350683605 + 9825024574318602570230904976205086057242856859840660113304499069379218541308171998260227484149937812807157987838492362751492073 + 5236013621279011602439272005713397632062733928777510296548649421999353087528124960783236699168282936749555076309059950538448044 + 6316174264399599155501461815935271957641181470379962431535756895151732821144407472754664303419949275610161730902538833181412620 + 4057262138394989003315257406621046570918156102356055537411042166653273066886196141130782850554134831168704085162214611295749827 + 1728494807516097505065593608124398864640297391491113562997206711322054216710834884111534067711304959653237337706486015754839628 + 5402941401919360128506367871554679221289967323748328989926516006333132440966780154068277893259475878724270654107817685397502294 + 5331749302510962305291613004333202326722920832094875206002590142911609625146433305314091631233538797653208605364527924132244946 + 6532771118816432093996083328883576769019322364788699903259151365484388584381218032915424365355589731770063912720956702509258388 + 3882789530639893098899335537330679624810372563783381211488557543067129370526059579061942074775015254040779746533167078485769900 + 3805020437690986060459807837031266916198079638277454221416718947378635541609908151334933790442634344916435987118766221380030868 + 1492873283652410067454455812350782971829174602968575413579966330593167559586103530053302924740897504468176712345572924410751989 + 1402681422012394852214397745855323854981769611609240399129690457712558487768725787104039715649959552365787249656873757201153712 + 7034615208236270834171130441362610841044504351389336191409989539270321328989800821619371048375553928712514470949748975085093770 + 4290878195796201049040671016672715493368576254144716365945552067883559930088219118750514982822693100430367769784775351909372687 + 4911033872681823931983855759969195568792322301570737362071175550474999508803728901587248248809147697357896852570255543589500900 + 1706971004869558605860088419347382200967993695904618287963224847080176675951145483137675636512072408162582506993137174472960694 + 5573663486380813348973168761749599259962367833751791115712074445847171992391927789752756447549332777671869328971664763925290830 + 3549115232652328982096333522858191070453865857146234126898896140406643330756492575988127393599824952457257137615690188707592890 + 1525981890012719417710592274397314151142262744434946961995671692595224961001445969622314797497698000523423663899015096913051877 + 5058249696800337974138653960205886721218275906496709288754537792787671454609339328245451684579097878838116584542322616579053187 + 8462720851869420776547815997374420654356793047547706068426425982466357700923014078111329124212863212450480733486009748682342594 + 8687099289779458763026259506520765785275805315714163404563447144528065795533004752634001703743154416316364697795177031670571395 + 7862389886797621228571167458335190181377137309906389411269247283889070732381228453233824760431622453252798014077600435024553202 + 9884611862481302466807813924732912660462964877829202613446787892509006450191623119538981968974508042576824347741032177030382425 + 3275371888164672951716608075300420614160898739974183834737152799222716640347298255880801705875381815950138367820787575063612645 + 9756093031018363423853254508819810837905492342390007409090686184553436757595124339753724654015162734521998021981012802729263275 + 3427616385168365599989752741868814273183927471411894804297652680678085002922251517971806076560284843234235639397961184180625624 + 1126099034992853577542894567722591646934072315106827450408752081909824273574814734547622072209980280969251694858199479989346866 + 8324744163428589301098203537736106384602289116499145216551769186060030444438336222899526023763743834415207190662514180019708518 + 9860319477002084962218177584666884101089885263708103715532250072465740590415811526551340778700948662719303811079801949032990730 + 9442895797928578191430950680716135775881506952099465712614129706777971670822951940768332168877767587109595551931372470789023062 + 9676406861977772053008009279919036888396717196766804819265649832410502497794545528956267262992497398344695416980354321065043902 + 3430450368036376703613028439245508507778168871582511449294099014869582746432398446542812126358198966694091267937409209466063739 + 3928978146389085853115437005111689057451518521401216175319263947818787743509560003599577334399518674836615112723186476720359894 + 4447676769726440097553180938842032872197723469668279942479093598413513198335476789357764400869873866217837103053672831807359964 + 9438439139166494727711797686854076602382501450775000543946895474100528401256910882752544466058353451178988269998012104071279388 + 6796506900519353467866660536525382267232333410870940350598284296015115345501330091034294987205096937204489666809908368374224287 + 2156069024262468587697645236488193119228612123037868983120993219205723939445417381491095019098927648926035392978843470867760614 + 7821524721406495642677263766762922840188657758664683038649201210659149304382137313140079079190066786903508941027377579459577045 + 2846438208088991099137843881611431007996513901288343001595074297103385844197112994321057890476648269334831505632974358825733750 + 1231729513446989718094794150861322831069880594276720936717092445853573977523050237490193119260788535329095088882720971495287598 + 6552792304258966749461747651069123750999083956204720301600561922121624443601785058830034234673249878353748610370038504030736047 + 4350618220429461920496227812205841572163867546971596032105207072905191109123570652010474485250661135080242831754570708916683989 + 3648963905128198988374985403745574043149005801382728738825016196793544318399117519577715497903566248991289200713376389062963733 + 9079224255192675318799042558252967439629275533715026478752109034505102371733784051667760885774671501306079109448761994271014212 + 1512159183483513720286072997122368280567403105173759926916954869853277451339001028186617037332009159449259382498277868408842981 + 5560323178755830694146107056035341050323807669577457330458808700666012312546070466530820114714620579338594279601664840585122075 + 1503852393417110615057020185323349829356846940778480270527833679702648854699330937650632301666517518142397830288536621388668145 + 3710500442232649775196536006291799614616427004022039024161898799546077671371127704078583325133930080437162856065176543455363091 + 9667028302235222877392627005222715604718844825560371250888081705125248380997161235203510947690674677658525524540413177350345055 + 1651124581699981562124791312861972388295643691956825406823017359302629847041679857625842731954319702741028762561310737659882575 + 7234973146912955319568057648697281752581304980681832088301794847222733894976160526360976917273669474157112988773823160903919773 + 7236452528456462658486826400719408745377253190375111579049732814880300278553197889206203166333133501206064778109147665779882391 + 7682375338032730875672864027350071637472437979382544031201751667224513438710165103834022186623616196654886225240056588996350179 + 0853897451837131243025169955161135908558413022976148659863288496875873894764829106676107357256982339087954980489000376844916919 + 8360603574420141848805577433559168689130304284043047944444385048148193572183817853604188280975779635124804366554607129505815592 + 5620546941760373757081442569363535705009166704002199788324439031196454334794954999272772623824166956059123197810751221134756232 + 8439866566091270892187388961159863817415914847036125600694319372852752155914048990490541073567566380258061226260248539927574844 + 3029318850407273236073024405659942071591211229297986931569472429177060698779317028894343293006454758184946754805713329630249820 + 2687678405796666588388227397973494711846620655765600330508932225839545844068520955016865194693435829894249625192750034081363961 + 0826642719445444861688478619229100303043863369218122546764063288271554588608667295145429271395132923307142550915748046259216532 + 0468573883399305338589054269280928735368128284996899601120318736730996079626128417354949909634397399033464297120851931573621836 + 3410567460401768661525344506338831729399382001213762232285178082217011433200810491330007874531405259479829710109345021089321397 + 4652171379208756546308171186440327278368902304830062446989533198226580273246735128676055302820200408293662986737676930578153746 + 2150739333645551554065559172680067798805779396460259578671413082802669062176930977818789038399646027209326563780688854879437364 + 5947149323195596075203471654735880096964253215673415065855952449622950653788545812330777657299303345667765138612882163698466977 + 2308935140239438613941108953213493640813697893782475635075053824082277617694735156671731366529539638010664196515846143425205110 + 8579861845970706058547725114635120976593327222009873742050798971923964666256857891243866172081317410728590091574945331275284201 + 6824605749924142731964725200957618055202505975317938345133949930752079669713432776367891693447902213677009365812998801001720273 + 9233059182009261025428591058709759978362385968915457411652886788541048883340218037203772730667179361924214082717915090369829831 + 2313518106392278036401430877932921941234750269539064717318812526416633477902124303231275087598527988161235948020286385526463743 + 3838476810771838510370563675061364260967203242139687527568417240328961372800287193798489828795160993501686735937478711295496291 + 1519858055532723186083206022574209495517859134830555261865370844903580200999194798031588523243896559267197627522165919682799739 + 9373974604821907639636032716761671130085088834596447375314712571767917652624045445822422980937123575808022402072804691330745798 + 1179538903767384713618264919378659303577920743409425206952169277638505227558099310711226481165660388253070855325241107221381882 + 1789290788643749161623308260296145948321831584631161915478987224126348775962249568727630631570400533850489485693171250304745466 + 6433974998050768158826396562741859990471614366251286876757878787725794466582791436968613297526831824776182286993388108679611273 + 6110623308937612049537824555231489221014173246666865428966654501963681680683054782880195354576356714786682961340119163196471017 + 7065396261977852039518801715732959486507529242741135438482938793950709913003256496248997903954928882444470989824659787821204683 + 9252764834270969572461432198412629509667322770306467304657216423067070489844755342237360066917220335677138645076622463524222641 + 2863822477918798068216749348395676325852006154849615936810666235080045937062299799315963185719888255745874252084645488043646414 + 7004033498629565919058730350299817723186869899372617107591275993421694639356397475575742082851089041949288607800654160534708316 + 4190299271083535674187523239133194914262331993315335908926599556351517813335151871562105201268635100775530492262605262924734429 + 9412474523205479108160235037378746252342301320435142535429384588026050874475919119800213524490595720796240406073642925771858154 + 2913084106745765525951041794109785827673640207212541754087108553407118981892598453634040675583256537303820724542193091642590800 + 6534476025728340988278166932729090239881218889572681282009000341783806869952125287383734393447529192404697677486779298438469322 + 2829214412991708861478313576349293840205174852775802339069812401323737815710652651384534932732051408295532745074816386764349267 + 7099631393624915897100017625766879968866232677413779562258136847735611193368355358377164844416154018729080207420593111993431521 + 9679117084184583456113996444214687961259734088670459741393316532022602071869803421115792325270648228861169427886111180946003583 + 9793622141632553469977231970499144123659775068372909299552862631976151882730222347477076919808461706462627308819362671717147651 + 8286017842303147776294340423265613507963077365773181170674484922475010476392279295555883161702991597407378465228254838715678283 + 7139981166981912432328248939664037584747665029041762831645786266577343138070260044935844528507385472563673503510303215480074901 + 6952789894317576895242795097137355300336216988450939924501915977563360873810170551299455217264567889345472118057178061331257728 + 1694193485067381935776175208128377412895577843695434073687471815717642677045054952476930977756497488385115713913555764776948263 + 2231234433522295956531798985522781927112508008839457523109337600193193052076325806292222155384767900607744680674492935529295805 + 7875818939048046279625548208487559794494231792862975497567734812838016356460114239167085114060525364762528245992233228644094327 + 5021327908105698731349894818836329218148701613108177279681910593746940136925470307141167410364253643713010143547929247739518061 + 9070977175221547245640857484222877237472955055880739878012461158071643167060432840330043982130511367475881160956788509827952621 + 3413847694252380420294340031416724229995257917239755969134460592475590887547733435481300484633477930736275363875263891668995643 + 6581430213176248276716948697514387283511867935196454364984608140452221982505162813367283133818168866214263555481101556955727420 + 0078360325719735185976311476426092189177189796469613813653608015870137963763116020948507804890688620493269983909621885486957143 + 5618073667256477516793467657312199638612399475873899685969826531992817695372605952175192740133201709617218497592077143464993595 + 9686528263740598514413702973825670801929614448327903726180967797157579946183718568106283503561970266617924646393019216381949796 + 7239480687825534075396618625255444191589146664116441837547061247242846107878949219756732241373337771333630723471570758001480280 + 2126415066562760335451168640052256439621013367706107505889219639609857343988288214828754545448713238798703235273922756046005812 + 0281498418252644767093639973704165385252675952065796869316299823450944375075913221341612192647317518382010547568017829174497579 + 1057968057525848488438423398887379257534282986505898261044295544509349907137424691109525427205047296410961152317113953498675027 + 8037990675600906293845109738467043233236225877257801109348395466430705164075214123065322814006154190811607337254708305938085250 + 7210750787555252394437778367913891376849871377061775971887348544361550409572803722815881181222850658661431069707417398802536368 + 3948215469610248733031315237243553696794016591253408216711885250561262516305255457076505242344244633141474145222490778655694723 + 6617637025342831507631846476937783337058482960397621355078541340935495458638237325584632545957068938913331687735591931648307374 + 8523372206558862816505119548118888594916440410353297374883874035661877591624592793870237386066600870369847319996357899821848884 + 2706665246531670922861049993051412169291896643639078882262700663889473964251112689202969447822598990637782956377227324903867608 + 4848299459820567898610921948177867341511272056149848749209193175952272681698383112955078617288403697439760095671946801857673079 + 1356542472568516852079785586485413072353853487441642185000260635680413178133480855130718255056119475830508178140915142512386038 + 6695877448601376560251771173382757011161242171039619918232438391997384640483554361477105518555170292200647684746099630559477876 + 3728050473071484393708670159181207753885192509059591605951929761162380613874243004953769191772521075466929499282741107419333117 + 7606734018487546777450475520310398974869459655169606480072758933265326533542081878074199816338268783853568241202511239916973258 + 1633835831994903654810299535109070687398984404650301845605445387393310102422388713024846802629758902868815270339924811537344859 + 8928571046801342106880818013492293682607259787490363620233716285093685649713330924728743681650501355104561967670012038426873625 + 9125730098479474089046067867529096250921613432172766348896492595710398358975815806788579245423344223729093128465048555061302778 + 3282236766431701005576011421891586267683372954054171332350103840612998244535378427127331925639537865313201470923709392166490250 + 0060953065190643840375181038485605085116833098863859869877736596835368776079089936760138916464834786551291455693169964704950417 + 7199761056487159527818318808980388404160177710661891595418127883387542011797165555082211982772990941128288012248134317959535274 + 3151702008500412396300814816932022272142827209737059555958537947102106965289850740478085447869942031637107833939492398930644696 + 5466978918720768258413199259613003866496795654264247159666752558539556973496507886748391341566752558990139978324598436936793928 + 7875629494705039695595741518975797423129800053333398650746169290789301147238968164288511049704954808998463415048261417058627843 + 3675014761845381637345570687526385375856012330298649384510964329070850231207976330807099687112778366295062201878036276787748707 + 4186642715813159153197640948334883431130155154184492235081536887094317988019087470651733545171824399201735161775652002448517265 + 4661100517204949080442753518341612732523752379970048081237708561434446413436675964518402865361477156495973338379138615279891674 + 3104047228288563492721376497746751756302186258285396146017997376211045579689813619459200950120798719227167890408329425880640799 + 8361120737152440781721610389840480574105404073477545436637229579684528270718993412816918987324414005130598864358095704485655816 + 2635022304411690520549036888248912012839104866750669849182202670549996591599148236127250813538958602763034624939004690945598644 + 7161693686069093177957527866565203934639363610988615731752113714098234889877144865056494208717095238090181742851725619039913679 + 7926731919437873880030756176008264549114452715998481120029937345677673326677605995613852123446385084312717926880869469763207023 + 2138495852046091769881664603146562927499752742224823433380060312750362684368906102817542844818392822621059272739767561472497448 + 3487585927757204836571198808541456058695288628326581580540815649602826692062251298954681717253220499784757374087955966951533070 + 4467286406109149470022526422047665420981641926169730080064026643952810388751979407214952628713107539097869076094466606508205808 + 0329251645328585224993793572099403208481085245076448698022757086335438075955415420248533451214205820043135499362946801092902796 + 0976117055234786919615481110380099853162437989837673156044051970682580784609511428623279845514623277521398030431160849037450740 + 8697358783561542570626868871304762629606530282055602229180460161462702998318108546783149370269213126706148977779508293460733304 + 5685401232626893164468498498310349947377219975132662081047738432680920912627837266028376099158214591714411685177672935669560017 + 1991014855525662209159171891334726717439346791115150429082237201563017187579488089876803702248258879215762021955798945536843228 + 3358779497231258973228903279307787602968091467986183211284685640196892409994105852728310998830904989480714242762651865855421586 + 5348281152141939663360571564939207399533427205490276937846050282692131755481373457167966144301656498283646918663467663563230116 + 0442219576879355438661813222738756969322895770177941048443578213219939881424295242319200710244313116242014329915750902609753298 + 6880215129386746871145799105266743824027120004725079746962555401718867449525806260178086747751584880447035314395435465651034570 + 5590819486053989106201536213480377379276227468376756122798396628016810991489235173054754920663273388709967201645610835786499004 + 9939124283008389379680409146709896607754411605235108861950292912142332714272148567105156028757875660670111321491114463297009230 + 2097548826892083113543893580713808393001576983724545670281722041343097928800752617116438879952016563025042978404320211936405203 + 6082731184886898638758782020161455765775544117220425974704422223842521161418889571069655363278462600259872240060382048674290190 + 2889620681353481574769346958935531281292735580442822115141047535414968598234054161580569343948696497621906027825367798221210232 + 0975609392326975398368477771498401808897612300017559800926232766502316691201583773217274029458304062931758320244725915302928993 + 2656060793106179140097207671393073878144623719159743370358884637219392258120064605880204498430784571518779561821815030688040645 + 5261532754299991261842655852754335348627643855237017342819255089240352732014055394202970458645445920979909498339363437891353307 + 2437642062562451324051185886722830951326647012880268770841964036842838215823451274151497274115272960818748924818830295293023164 + 6427726746699539771500247174272715628837777269348318525014112099038948379809971189523179740600410427829712055609005231760641337 + 2123549160662241455227582001148252334968910254759170985955722387116765936697038502260200822286774138322324033501219326909463806 + 0821193700130194457116090490985590394866182284594574006494500813138155877966705322490599457628280712279954157952750704655060385 + 3280391474844631197279842080980749627555722515522776772617462578270115902754706089142103829738218939451926197117850790818482759 + 1294311329582945102206118794968530880988413255047180804846373165792608079444603588122636074961065406623564621335429415769062656 + 8977139076449153307860216027207885939587708357239425724499000050811065643249463642868728678159848609219920477201880783130814232 + 6033248813331250043643381559597258568598550852601730339407737331740193572873459479638405202147132462334764720678461849283231967 + 5244706826495860145056785602766589976181173320167438082817365766859974115630195914700440671364272919565408159761417527099133015 + 5244648245024168084347025892989203801674105350823195087890804798433093162301085522657402786073312465657131861678950736152896502 + 7020998265858326008838932594312667517103689364315007929663379806725932670838335332530002316590322181497959301133051038639381171 + 3173858772156448895864459261457987925785493055610741437909826143835126197998316368571824712159171580331713288750535891179500215 + 2461289349520625956975133669730507522155477555105599302736241191876700580974296813158063100071375109901417730679844357856593047 + 7673877787687493268983420698315905381260558449663590054448103444553449366277579160597491777336624754840213430260072450113764481 + 2114017564926717940676432504294232477129802350412122813350795229854770687737407776153546967564248142801354985562159014016660409 + 7639567903574424627121988012936196690968952173335045547572877439937623104537739475753166073603089257419976655666993295754279243 + 5512010810515840583007802011584440810442039388430026796415104195890917308156926213851922793907826473532250186114497099571038088 + 1090443322487112398586196562777035714693242567109619766467418285811180453954969091778067062185341924208029182725946749209676264 + 9663462321929487207790152045012463956298339314526151434668136673612071349597053270833334450801647517402244793354108502290993012 + 7465047517200443480317342789716535487720038254767800382013521445375492608318405493546080410946096145404154482214436078102318897 + 3241343339884810074493047134584332154632775327907375423171218727031001503885369275032870180181698599353279959939076928392091092 + 3566208126745756363429701058439360596278930537654250601183842796400352091131220495755538686838579076983412474092980588063067246 + 4135280622573899686743659033428766204732217042537180031329938266218979406566474637509065330050474399644477629470645922989131608 + 7243489726801527985565622807882110752891684081535249425920277363697188485817835521822988850811873532635201983418016593214492469 + 8143017528502801938786431108109170005870927726570176129291655180782741998755590156671788445329312481442984040900285747284336895 + 5565100360014106030272353666080827357535103165363399802552515662750922553611500390854921288593734087100792149327574407938377815 + 4240318921296779247997230590857031671134516419731819431863267883435154179769593315054293181367248263035923946261410558920492931 + 3065344926131172598974832603770803242453631170305261893085619634353617662701712503317939637731383890741691116709803904180847998 + 9640635307154881695674450558215122808610162087865073261126743708282066313632270460083280371892143332906784831299555537946109939 + 0645039315913940793949968013785570770789031780794104310782057130859521600859343415595288573910289771410236190253921849657190998 + 2817116940059523621717397073394274259776453515913607417038665482821641102656240840561075406926383495205691566077252073640483438 + 6876828215210014803339974347992473188369840859181281062746399956666218336920552262054357048613213862945863515439475503711072752 + 1206178405392180823761458212656703549891855527651389518191357531805984535259972031066177734136716154598488260571189715523538978 + 4990265766954047391630449528696946350646833442858182431131915610086870866589089866607870181211091256487223226710174280311854030 + 6161821498017905298626518871081902325899313379230902725132275803649959728622670760552023317532682229232464170889758455581169141 + 2416184842590677978922625659052895162548385411298782741233394356631320019382233371212037232115448059660819419247622831630454503 + 8975030577721689746153882576268854827896373568358085985637110827886139292888578025729952622899410488518168089967179203288999038 + 0077221628423351964468120440528719933928163566191359047160562478933063353123985611799118577768774930246047770557959247998776831 + 1721135782157358288734205102478591394569267133297228431858377971925993589071779657700502192679741782178657102555324869244446359 + 7869917278483084269980405860197759252589350638010408763257025389708116328761797581159680452123249311643134587279719495772936617 + 8130672462738712860454774853313086658312258840823449860002088944658955778609509469061098214154416089413962879973327200377762688 + 8704019840879290058261002736123709853095591291334597972059260229183193853550672628813904508834589255323455601476677738648315934 + 3234707347670711573887321944356094703845291499731243740116195333742959154260950396149564697796845304852992191344817095433298019 + 4556001053283765367945967785584518418747873282740299536406596053579536242035383267115157980628785476579854884310834210027387315 + 3952399660098012461635956108592408478331533765191761940733106633178973207757390760027945616808844645166556348572120907508405281 + 9620717181599113391181876705169833156639227504083941308593882555592005786644351550764764616222603704206370090556397818828816448 + 1082150428965180471148236660642979232846204673076692680655912004876027643170213363695294926023526278443457817518033465638673749 + 5350172689969152071949149368789531895369178652578561324968877842847433493285130074155790255799028895045897756190837543509860775 + 8482306198938020753154634340975595193686061652677880586337892305604321362120530299145893988789835870281018804163394448979511499 + 7488870885383052769468046156937025798795341295237597526911841052145121608390932943180983640617731865473642038426653712735002335 + 9011612227214170561522052833657180847394409367216727282193072678838450183604374539578667642858779645471672950276478435834423943 + 0042627888400396166577808028511674909710254329416152368725303977021338640330576476481308582201268866056584880471857573435293178 + 9268879578435020158729300163317051184609265956929202720052876516659404370185319984314639348524347471621091689443144604058655054 + 5852357719309697687694316961668030847489545691322959818739069805501234210837740692288860145679956618287254425865421435945272722 + 7947183003454715593442541393266684657719476151125892217474788448864376694397034056195614730803146207684810002655419508268188406 + 0212392708824827732017576889397138488570370042723523923833128481673477500325568912519958461261978143669880070457987816169424188 + 1965090700335288348865794109082688653306331467742286624350702924857750689705564771477934006408695884251431946386364556639034176 + 6475202723487206164676214732339055881658522754087991356304799053722702797567004357975452415295767243300651018833595864642447417 + 4933751846153559955643592816488612142322342560545913045826692544542626150928640726729092043333739064265750508139974673275834713 + 2427576527067163076789990338481516933446902541780767233056948866977560689363984682741766823172377515643032993191346658956321461 + 7240324801931427740710853207105854320415521035336023346171992089619399728628105888007254180361185035803733126321368733856723085 + 1503702321045090573654976317248889826950138261936742489712456263150062608622387827772363799121813242734818379753299053724286228 + 5076095412377646585652542244868299631686826272014334350505998081702990345584728215380800687580035780236658004071510394469994071 + 9933250676927268802066614172669848689165401909644815070604643321993975291059605403370117318954869373816750869659405704139511279 + 1490487519262534395623800813247168885091994099496258142463552140723866858712657283749576144012562970919330051773400199590563572 + 8265606609996094143464919138293434901647769730550988047626306005465014764814728223656959001378552960458572921902571777313119856 + 0301901698751025073371353819870024706444286250847057963018585025053110220589734085318599463450687736352183212884401020231957087 + 4456959908526601850236631528599915374848039675582388183944917813443948321814362879113998039695208714072018715891598727749400184 + 7983572039054110543265312946188122716587941443406593149730482849110607363599698686119685785597056173835119438876589991354302327 + 0157777305454082280716591110467065838967277498987788761274920512893356487762316080383017175970582934458813655903151031833258038 + 6820568297362586686149767416323236376371752928724979488399337093603770184434877480032885947231535650930077949030676059598788698 + 8108972963805156390445400882624903314064494634772981427763122632358977184343156109534055951999238879890515883719506599847044143 + 5178486334616508289086769240536520705517396788807705586482419714104331671474772634945045486037353039747544411584344166691513962 + 8343543694892040940224135766807400138072678909751563547074645700842179499138145819361180694589974178543789544801347334713872045 + 9708545131525935820756667264787954116125739691093797584888706242100925330533736446977764101332858478855148268301440155677807429 + 8363906279880507853775707450188819239306527160717217937065519073363784713378967477694756526571005707114651691767780955073859818 + 5651083308096512159550753176200623584419958971162109603579598590262428369134046173758247656339396228143231420340091898293104843 + 4302402395996304257050404831355580727247848379655438560342120245630874884033522016540414633929586663157231554069390318916865498 + 2822530065271711681487170629161962249557718383135273443686990757846857063424817696146359531243469019949939521304535035359286967 + 4074330918579124906980668220696463605660380759667033381676449310911291881680221895239419422515427861193964219305035700436309668 + 3698935243696912496491762756802269973014707849066246048122302860046406677238810686973357352423777172732249145383686882436002629 + 2170964033471347644711273905006241361125626168342597916481066003694402986372839549149179850327741026797871619199281396638967050 + 3740578777458341247832731137954141104761544067127564384269992513879476807275980026551471675919580563967451050762083496336212971 + 7234069436162575416758566662736313504628826119312240011212647893254386199394411434394192850902621006968244175625150393585420756 + 0819505443586556219267270131584242241933754418772049304646166400049758424842433111724173775260453475529050201556290830854251309 + 8694504279853225298817987700209881068598742151871017058490633074185456825579641586256200310473031416146096103034054724162968499 + 1678422417003132262043356103744836118876129032014712571839148276942048121918851516621273265839886300177612597618998212159348375 + 2526979362189085413641977979132635792430656327264789820332281372901762624494315668746921549021511066663733746233883697857770994 + 0998995661761657851385372991367035240872501467476816162857262794643509591735415040438155899974797001865973911239317650890930815 + 0189734426599237495702149267240934080052773268635893422129378135841786547348314154856133018855495625125449892981908291205858083 + 1077322089308800545276469380562276682750368988122928137210856581036772006900205486477908581832538965073059726766472615915649559 + 7595664231420716081656297104542741477179939201745233207227457362234020070465865805626851389405073254933773440235630530654929440 + 4561326689796974026193323140357607026602878702428514108628434286473624453127013395116455824218643518830181373377505009554553648 + 5175104916514700448781338224183451234036582197678358641053766734457042147404203339056493172875783393464733980674769043154128903 + 9625053130166787806916253108452498110678784874573415439254136465274322837153616892957540974054903367967131773174510386204520192 + 4708907023698793329968287054491892003035884220479471761449794976142360667172403302792534515419470234070842851218805657152102504 + 5165815294615880424810698811972894519218327570376404414484865603951627216319921021460205245622341179697179353800333764741713858 + 3375832459808523959735342163302977206974789134934574309888193442489681770595931407566150654834927560855722717629843449379732533 + 0696873250701946777504053721122628669489758761941472800177248115996803185013999823071443413470671100299081264402635064626229095 + 8025269049201568533557667082941257090329107268081485134499591411578665111542402290969079825247733361568938034890137999482482426 + 8413571137578802277713985161717245739847221863546744280234586017009016274669615970285654793200770322063367655004275873714400764 + 0799707402410991916198286689965775278824664119744877317308731118045964149958722032731308079677323234905411311426216785693702443 + 4397846375057495792019955808977919911307473873070308655227892822037825751568866737076516050806909779275729314309462325310751161 + 5878515311252357335941687228452716020488777361851148660668041257248641752627888839374533734775241618706657533250097255962909759 + 7924103963089477116974416014956752830485444377913838660792557425488769129517146048639663168698011387132583363962130759916380103 + 8854627858331158799334753893263279859800213644437374816465531701511843970386899153300191498875238863924442400115037208900760391 + 6931077305054934679510399257137017692212293765671016977117885559987800112104522229358688690556795828786584220491722127422607686 + 1161689224772384204986305992766453244735906304538266466175104130240871760142886069723737054629941552777930420547825827115890782 + 1184882323411827620265622192040661772065557335415769691870166844416649885380327832148533301202237904520864333379649271453239928 + 2427936123038564183450762355240415926776086706660362490151633725587501086167861442974904906015877742003232322938651897499721504 + 7575735828907721001810713381085000197583517056663976862531026160720187808215284714716227545242555746984605470134836970810868686 + 7690274030579086519662066594780770842382679015250578750543674207604336237491570959207826549369435808803521562398005006071237827 + 1591235570232351829740515082573934645171861807176059621044839781347865804129548447089911918892970375115928184446756254541226685 + 2615960213766977626603096139489045595459731295282305420627566186367919926990597793979775395219871115824222384407322704217828184 + 7269890378837649922156673232477845852726935996940584696490442582150880559450498906939124023442999694271016368614887466665480687 + 2492299648986452580995323839604907135499552296977074591849011346778726414701224990442027943081442825619102646860492552917507521 + 1791849743502515995886083914654782544108637930226038487802556564179211481768559160141129157276978288393204371047755590042629364 + 2476979194376897909780308753936290021359131405027064825271771828980164040364357335094434041723555965477129434483174161190644661 + 8416023154844136801169958073248822091441560069684654659045233353502161929981208692256561137140555110119558013208216615513472071 + 8088260724856516409808086622373800856820389920242427841076949364650960501816473316120878023138924750918248626057879988336142195 + 8686116426096280530843620941389111299655341997827197141570086674404151699053951971920289530070752071000490045958486626799786432 + 6549357623845124371617655875408646869879278421775346320373177073222854384021377119568271293703313232299103659136776571632693838 + 6591886804108118051730248844194375009874244915537509136047158661056246282742880964703031154340229700891206754898355101039366979 + 7268446901106376070498745112524561027602391892725887518917435705098580461006376837385629028194839014124169131891549609455012171 + 2285131899533028794555938374512548939747904214953588004250694538667660139983891321230034509152717542342156366790660293952707870 + 7433656872059365457021513060668191880971221287545847083471271690608548455879533083319220177538857519457319889888751900959653068 + 9242848205306926609548172769597825608518368367889673409305233019839916718283755877093610440755381268416027885226989117854626319 + 8543014996495123544046729990961256012932771211075541381188839964005105738775284593953696325073738652709607173130510895811417458 + 1100281056074250163495442070917233405800039282178047058927490789657980634481405379098411400723381012395226453993698124096414583 + 1497707784106353163476884094382224594079935684207379351580860836917141337699813295106036949622008098195962892923132082743352822 + 0227639803444432864090266134712772762851750164363159986164200332551145986599690734005702172852457747000704439537884708919681464 + 3297805927942628853699179019515733067501114704121488080361171310117107236329567894778609250864163044875868270159183178936230020 + 5632160100910553597455671868785895773407892040726468337688933116567628214043646404787040937392191211462332257825317687874338725 + 2296104873433207092085115555734422123208784998029195153841807872132818719198275132977492788603520666575735728468601968901331765 + 8507664661851267844375807200747151263758160914796423476220162799279781135476440706809418288627923653896822426541736985486808537 + 8804577755163112469882477676592666556395113447285604375941404675578061757730014398552781158003833295830499727417346600077947853 + 5831914326747916706642066586312780276779650520761789440673709492335505292573240738337240722730985752273930258542997960743098240 + 0068020053146252182779250786628431011150801984991349353593228652822215156799328870412166924618702218796377703357100331644399678 + 8109188902158713215146842638263856459757440491023323555585167449490157093903282451159411558188534514053282926080246371635200972 + 1083689238510925211444565358062724034393858074119865447872227462830480815166007221130324188970568012551002420122076677588668537 + 8348566408824119448641450955381151117598257925347235252204110951120532544649854733446808547885490496232547849386772180981787081 + 4560676276145414580213909440734926632475864478909927595616312861612204269485671554044668485757818928586611911258131650112268582 + 6442754729881254198230970045300311192828701003356370115227215491493010569367089158620723231028014912810350816540331381099940995 + 2865041663295338237509904105995789610569727200605222728767332785967873952215814407401152907766797309671425581760149058652925760 + 4017820912206849712695013871311183547029336150750415340954915312119753021914893470116876327839429907255892388374033828544982922 + 6915440546354439943941953788638484102813214756761743923515532313884486004173505190595536349294404018810183152351908266279594331 + 2928244470990795144278024903861617956853603900951440210459677120550845092043556188794480813102688176816346489991301120405759270 + 1186435866287315352826686449165308561598819563912734578580650689933009781657638259105653726859937343022833693021987646952723005 + 8712542566252718904406054272317438859093977264257379132707981296910101101713844533871886378161442772031073848272459192591830784 + 1058110999534770164492882010801967465978671453250245066874219221865094533085057504007502380425647847612715483754244102708112443 + 1742666667868535721098914454487184166505673192687612783065836658057498575235907333228055857705494275550823062941047285844371213 + 4854496575428807093051119901176270909165842784911651361479733219811770760153017103816762799215219103460967340988812865617828044 + 1917561105792307812885764646858740340976693913696981626941718101122829669609931847477816007131803415395929587982744622533841587 + 9667546614449025826471505952967761841638682554759010436234535597997076544716136876213634826200883843816631177929989595634824997 + 9075236896089146108414434690485647098336762127620316996183949539422311636347004018452729032082455756224021955521110115243171929 + 7022352504520236787549133408418756692328586206498166126138700604093881377702931259764322041155662852059678496015745189492835117 + 7091800587591451755394603236816915477651467511713772374848670866752841854518597403280700140135675063538245814642015579501650431 + 3475133641567131461159293976535068676192194831897897611380261311134218099223461446586431446131415308645022873899564559364425282 + 3789965382702942084656483383865958903699057640653956948168423022124988840895696969117651267238844593486453639829783832289036588 + 1651772364049655351227109534629863148340655489696054950189023140607819232747963074764923819690470465024081626771998338862194589 + 8535421442026745607190566634422441543153174467912420591988970152959270609189415618141521453452531554132027545470737271909694248 + 4266576066028018898848004953928316732798903447774832407967130237423961865629656870579836679541833228863492849112635373253768730 + 9318620813778397458907750295204099889575365028367626038475757355404525059311775107234951920852829456542067713455662881377001712 + 9660563316063581065664074432670545816492979485719464785114250983280531864483884025594604925138921571079067953012249664289286107 + 4733006686229685087965270923863015490601420365854224908680910247314401508516820945614321593880289181386292705522860502467700146 + 9595467875394655716250868523623848001720836247002935008259127820208612390799061964695134992188932480652490964335096936081240148 + 1812489955447149372964288932685703059456499125726325849419752698359991222537673326627718506868098338620828381688669635638529284 + 2277365318750471576552640984213353147488350298228497735938404810800516562727031985237579073707417430708173600319624539956749453 + 8558865515990107426689500711926656694092773040192992037548490908808858324669008603563963750417300374317505710614289622964156217 + 2457409596680804630516887336784028949728779145781319560216200606134423822190318186800036885710141555957030479473061434184735920 + 9100569805069607595713477651532945125488629510591455102444809609662844669593112401315706794492448332303051585825039449951564890 + 2934068975480357331702373570405176114572488785747724819226534222897314789801301206100799457068445592290174980265109976510186964 + 6974436264361115896790352170073260547419486352304459996628335808264941225228110927615548124284539746249063361590443246656233810 + 2022987197590236256417410387584617910709314684989417286318087666015073752226802244527631727840148104686143554769788772100971964 + 3931314203567669848668014170818609543271827823841957939988437792149776879965413983671414699512124596470803895106449229017252962 + 1646897058572253319802460817369397398067528887800488520057974357980724071070615260303277654527720835652573050782049698374251316 + 0612949136289175984348022991134845911118529208723293255584972808307452158666230105816460375784187988904522880654792018341929152 + 6230320383294577758148209875436786980246088588555018398742402423700033755813061790265512976391765915810238317924960933176044915 + 6724326703636717615730930803229989144709304487765743249773045992631205387565818549594275877262188712201760168274734486308418567 + 9793449160017973876181891146468573134118620184336387033315592292444997748610681437980592831049932965491128002640896459624743912 + 4292773888056347657265747923515456543197563688072118373801968694939175467616839381912904118459023550508906592936405878500629369 + 0726575398511990054804247570050536297610421442312874646372000460857738421341575986454091454129764640046210072544927787587872609 + 6223497359073574286258812426783136238045789247117981734256875260415121593723556039489844073919163685845325053278772517808357882 + 4805353931456319684552807410713836603840908704132137938671395582768618313934438378980539779778185823334069713366782891327854771 + 6127074671224214243978383308821083055917752075116334068237357481944923919216084154202678626979129283869929664457025576182992309 + 9095642603811777857467738034071749226163187428061948529437320054852470403172207781014210493833697169288095448800181203251014035 + 4736481344099852996408105951657679269262847981157582390462101509329835494113215114942443801348682136828613264161536188227115466 + 4003055863718708771225642500990071025833297545571403747979992978828908605722348616364122656556369792934466258936918430294297508 + 0884716108700884651920742851823456839844922966806960079344733214332219603718719129110850475334654765668025057309956984350345154 + 4885236271502923816983822161323233481126598003985902081480145736364185121032980985643061033399360057443356862260970037248156868 + 9095109506937315402103438551736664529148909771957666146775454439817301965157339466426336556934667643823128218330998524081566484 + 9554172468178139926024925040064147501158211448170728837042601105476806693933691272219558658718966118313273471191896511638062325 + 9954369358233682690458005171274421730241048095790588467590844502525588085948164312745806267036443692262270244497152879755376313 + 8540761990884030057918282213961331175575293790886064372121411245265558611444044299259702033859938015653338871057063134186390567 + 2937295853774855369815055903708691070046531641376115545763368983982874877046797588826386810643172084809422213611867667864377575 + 7456129086242673800167308357557286842740029636829456648911252509981444991813390655015368895052836323823418477931875989888413494 + 7619903401290202996353920197163165845104216512134977822317453208086977782938058360962563863616931222677006031494617743246676098 + 8619837607929254793532399964916863199570819754247459608169557658376643077622610923724449371091028101105519894212018425361113161 + 0198232737234871539712619394554173033293046636313472444724663228704935678432306609229598127499957898688691002287353410535746129 + 9160344825935915883479808009630827527538308033068458669327511758149831271072074138691690968888119139014429832927001663077896093 + 6075520157463461341098226057137016444093714810741234441217965271334334440753561468859945005901907007749818800609799068435785758 + 0546092246435123497159753904346692263278071121042508101131684892541656872975812647089730436015791483195690674123772749878087282 + 6758449872382291050831212201949792798424861556134983601310627614120558124555112900385099751123167702480059628861813816928572678 + 2294380967592455168636104873737766456888729486890507823276579714836828251933669783531511408873018452811541618386657467835047578 + 9771964953738092240932562360117185595020635073758269035209960005817272212266420970453644822258523689081214708732161974226486482 + 2078896042427351080221479050978223463317038184395717248909464597626365437809427793625231151897894098417132582150723722131356816 + 2733651127665461066112679225653017158187022844835577848138599970119201959393371465576981148627618500453766449113619920556794832 + 3098796406035170187586479893078215549068777188615428168013041309627717475700524281634638706348659216956344427373631234955931788 + 8266607652077744997152631910857696622624195835857414262086680438204284388121731692389911117940177851680318293050972437430080491 + 5263662912508589659968304863826115756592152285582835871560573052117732379831943224939230850768149596127803763098910581308889239 + 1399259544384714811458348148272122374447108528351486026748375991519038080289258112233626298579932128994892803010854830711867003 + 0120562601270662181088525907457246972630366755109340652778459673777734310903812432648671068725042051752322546900077059823883777 + 1071975377081858251465844724729282629412278512504579575631776161691808267150394386844729953211628319505799528227342615586982667 + 5142190253907427483211782117002935160362621628506088192922092212154140185826659904555543974037176549370222198088358512119912742 + 7709122677369521964052899819214134971313049580616225982506654419124826044743127724976092244678406630989264402052401911579629855 + 5241083294500875288635504487164898666527862404520007162909767182104068330196614730977680503144106835763690135404371824827295654 + 6210246422372066059297630639990103921525353988425004032130811899385175353438423745075299078297982811812894692845392714907314914 + 6639687154171290857100923298064297354897427312066201467165805288117452112109293854180789331988821851079333157010919824197308857 + 2725453575267288288994357675260613771455378866560128031996095809604727908410382843600101001039972876558637948184365207490031492 + 3022829447684501701771651529957077694566855215179433255048106574130176149607854191690519660804326926806696105896923466573489014 + 2276500150756721393101309310240889850130747890241895231090329328679796493201088708899083812272168509412763541079565359287160502 + 0441480433094880222135017379174984153891031352882663477623197838966247123264644246447696041370087767283894667315757217159981846 + 6600209627389381111032923919248323966625789375205223637463959729585017236548352912218466643214096190786355523902607233701011308 + 0879209770503108176937425508560832114089876275039410069927508813642206128497418765988069857902212785710790868994707145334746457 + 1573213691519886100372421851125709104684878670999887084420803400476797705625591520633797149282934213606570900108998582064311163 + 8676807063736715112005822408555267407647050728641117839753641320386536310057649950460984214505375532528456592558681408856748600 + 0458633214841398749014431880145127111888700604235741500367092065118505389545560189317863466505700948103428117858933891140917600 + 5132202176401630576193346962510769965520088034746560321030328807272795203005246723655044384670879356197070618995577734499503916 + 6506939563329550580672846170456665825955418030610189100857896112174782009029170826779986506077333681379230762539236049071683000 + 6370393487113254502942284063528147627172601717639450424195980075047464787096908959060881173708540962987133431304917906118868338 + 9267746888420071021500735075663336736361717345091433424161991124952838871022030399503645263408791327784786086730026429717318657 + 1672147391408891002327479016767689503494648768717682253138108661180075426978036916352251329255918145397491166698770599594009604 + 1973656522713866421729264353952482643307862403936073686775977710379738331755646451684387173747099995521827339722863619385237499 + 5408235756969453434913224193378329404979503566466468217232986076880098924660185616188785089771941834979789440134998311199906069 + 2232778818840350786605080110308895419763433233707234872571290509162878857914634432096414764357358087088039057924071148091731175 + 6015400792410124384152213047000568844879712268022351230585299428537516602169557527154990684330404034064121063393300034030430905 + 2306055374539312465651241264233074065955242079361211680462145344554747450796349210759636113482252702608031612245403353997125476 + 3803253691034432130798363413192595243576410393487613462409388440991106589264853952016023685661448176427389232941666704057678369 + 8628747721532797463638681268551173019525973277356279608142072485533442125834239673920151827309537064739870526314899247429664781 + 9025827660968538606553886333865132013576294269585884802265251611104643759277860774328243246331432389944537967831541391858902940 + 1930816587488360252688732499160213070813273038333861895643529140656993608246150830322861238139209540926180077253222099793719072 + 8959519042048720068153629627140256241685908963439182993973204720950662335620899080859042503691987552467007737450276337233761755 + 6288965328635383011799009079228464765004787324704548708119617161002013632986577780042057914052383556753286042031709306907755664 + 9921350932285357024268612614215975988614776231803905241441720250462994526451363159473639866331342141233807338499617054943944238 + 0578049360816576019800945237402222592171684814088734743903979539564400529178521960883785173251341874550331866956766247772470369 + 6083904254700701911630159329372053705191987684688500636724033475465777760911461588784110437867357713431148790643538763108521995 + 0296263770538400456769346062348737783795801732870097577376952964730500440617573963135158364912865598645263299913463769215039071 + 9483488255991073328145731534454837990839423394416473517085030613349147333787972449423197209621559003595529788900553100012406747 + 6566884594766054381929553636693829055015384572992260492476307544253448277903698366356427152189807274375674035466963843196695551 + 6323074679661834194813723642658721376145252523971723277400835325217197190050897668239821693181091121061162219401288326146881306 + 1808318984353930429816050257400279035517547964016766257303295002919848213345027516727642354899576468006486504355233740324100211 + 0373421583654094261005790222006220690243740321608605292144463259644370384862300052723119124037021639917903672109294422220446746 + 0968367458627898019517765631253210766036998155063276402536135475040822567588712196840514962484791203840216962030611173316284918 + 6730753402413401318179055308056338575836289967262947906669540139949663260817034924092055901733213326920487904492973772740252118 + 6813399504142772729322264698007839309738863435169195740088479397131114450638902610593694986422730992468798340242051077542153965 + 9094257292692469011371694239749935666279240094911204646416349941755315640280190692332906803301138668428433338486284139761451437 + 4927696735702519573953727266824755919361553550569177388087634691983381789617481807188380885676894329271297374663349552211867549 + 6214976348118306656535007501010457882239285954427884872811741042673638154912694956412208130004776408704809831151781445974935728 + 0120629582751291565009219505554682954747176012178127728953108970378564330824283571745236870527703343674549433801104649142185888 + 3235814158776446629647585300745371840827518705724793256416163401064594247074494980560274282618040988687418212805930332830675213 + 9481691238337366800610093527436128723725108303743340453678113695806808341554588638276662497395500403037304969340369996972707032 + 4082676737625354210464419813293767706297361241754982481007296169725698649583516782177058747437891980516222464440989464874961596 + 6461961406394849542189779035893533584829634128015156718397540384299215958366542622049511074988966488475073248255117221338638960 + 0142933164629079463406544918744481398396204306933357431841214352733485790844296470933212820449310522157583393441447538375216436 + 3436698506912676403242337919492000906428711269510381173399936468041047249569064777837314598565623718618433285256806067639636763 + 8460415932660725184337524946121929924205499042071794021186039050613143778222559008526610557979170270365704047948250328090311884 + 8815703597819948360630939744751577068004694199231149936335126538352407733636909351409964233765563167198074923729461436493523959 + 0713926842635856417640343723268323797389202591360887205782568996458244122502082280450763638212538223700620622044815212320168684 + 9492871418408066338755969200124883796242190267635257673723366249954282292979482645457308347074754036142876356477739278675875440 + 2183538168589813954235091042917215997797441009968993171615399263341109892414323128649997905799043937988646881424204624530006049 + 7733957096488341212048475007904035717627062565794383079540365496869348281433928986222996400495215587152772750589584231009322321 + 6967167721546910451512704467642578730007590171739084668065616508498732163764275594573615283985791091469103384452900988352107000 + 6807413612465354023458660940481659053886101973060578770973513038430471528121342377174140575232152423951725002933862875035962993 + 5491625968951170241792359320698419197951622254963187269169519754789130928703155856710378168285319433421425146672702276206900357 + 6582314544521282948303668171056488977803778991914594073284490075274341682398796202525053587573368003492350674264590216915743030 + 0229180917308822559423399370500197589688253700875858499871606888817412759424516191276640847554118760685723541416666202243509736 + 9274208984682823732942979222927492539292245964003720945726994325795924579380001664666341956208236538074900737136200088724900215 + 5814292572624892701632682972030886871485930705868231267185916589385811869703139406294452824977282139608709779376891002163708313 + 4033763100173660376690182575379995726083861081926510802579785312647154456013703372795547129639766049095465742696104516613357933 + 2568315805640894925038031436747677782703800879694535494046794349191040639680313707242709239136167699797774023104845097743799234 + 6763080953224487156488442945555613963349180931811315907436001825754710792409694328952798340996992622252003347436512459358128857 + 3954533989335010638156841066648473526011867397359480295694595402042037502438174479721797977373598413288286342098814213128179837 + 2396433612158432510452891115965816912823381888049756989510546093247222344511226918341455435352327199403241839439420506108676964 + 0795850610161143815844607948060775881656537958435083754755508315612517655376939244238451149176008256028242905067513932423707050 + 3517402986146524008574508829340726577308717530546869694363472906429850377209335971237767032862995433224020904386089476753728648 + 7922151222682324169544546785791039508552110735905147311483313421452486749631056709157326288104257728264776617306059521303067262 + 9433265821676424821718658733270406951796862690935463256100330389699577509374904038151899940074906081844482171701461900939078601 + 6186077218855804555456232441080881439587655776678203701080218698681846807414980313213113823373021577317623820418853903404980853 + 2057729858963790488672801591735476430626710017313638370400064539747700089967564851982820372204387613607305955240060602392589527 + 0383881550897793438940267029950019121382581949345028853214775595378737481122241954444306274659828618843592228475107234699152687 + 5284798962706326315885441962112759776606317588723708150855167126722288961236786090248841992912344949773249220873179712041971922 + 9678187960541674562218790198419395947752158216709587927827286969325482868753908887434457039802709422399284864987575179916747347 + 5327838914777072714692085263368643404584146218804037383216974773265161119155906542869845216416813947477024304569196702936579095 + 6268003933265575972147374394617649572960257762413423428779104569461013465964897200866208582709538990234194911357542427621601938 + 8074876525846270711334089333528645517621667077382560706349198812216415510664481057225472908752257947691952856523071940619013694 + 8017368030459649790293701927587307177007662644838805113977690349437913275410750363651007980050566471766249753077608880102272532 + 1982797159364965178888531580373430260986522031868350608333752657707407931000254944024943348168140524874484514493735113742249981 + 6288538584949755098193652659249807271937205648283720864311553381239244146100739200355642491916783137202534161705603274089556521 + 9354739749045138253043275273268328367815186805183694069007675806235940663397422177024952828447038786641822001541524569479714913 + 7698528117160783953905420058390896481011235446749390616223922774275291430828661119528466868454607218473820114505896776059375354 + 1619019266174818706077047840193129831420498197596777970098691437675408999864116292704117680089265101055969410774137278714249866 + 3704870678985840970113166302795462489950063082099943547515245655672648446079824717316402600594084559028770660910436751665528235 + 4429408197253611572221699160867353954702111945889329273311821911416970564822252007768702453855504730931208682912670990901446785 + 5056501125351085290367349611566587022633517744283896529455313187439470673480194626772000636195743336806541403680260332379718964 + 4062991551971333412504544251310884322830607074386974123640580284992839293238984564989258127209764459890435786526862148574118080 + 2625522665812777011614768650094518338934467618573508691312860257788451631146950375887371627144471854275002143114396671788841878 + 2226696461215179698643658067033045890658991544538880319431666117259518073995053382607108900045909290904771038098705696699068324 + 6726532088338857549906950143621062126429461929145317128221035122460444306074528944822699784500814789341052158726046904507897034 + 6793037164285887325166583356411787362893236497739544799385622176244058491240539097656877256235845151279052346581850041111149908 + 4093573044381701004333825958081420923185855648955716595548583153752167241574306747073123301312447687906770815027018933422227596 + 6707271839374572454938209957923490292030537274459728356418336773458317286912917431092307541994164910938497543069009665010432516 + 7241600538166073336929364870095691302789706058064621204209320909673557421090888354529446748882788614331747011940455844576764284 + 7137143302702161225320499515565654830535431434870632910006167776519433451398361978770695152191140156154509207190258738746324525 + 7177837461622149136708945368215880972643302158259696018853584758017706472295497707280871705217770629770641478542481671610250773 + 5554013978114456033660343221358867604345109625580200393288313536168463029481940254044728394046188030569648323861618169629477000 + 8748988786120543881188413407361779739580428614335192009085939766971185616502526635854198592751325209395171686208426924544564152 + 6617729010736669611153048037379873649289970538055287963581277014784710903080627770559078145423490012308690390159447385760636617 + 1396112919025930755072794022535421762089970913319020087082933809741223660404657644541118861471741622430838236195432385726159361 + 7249197652757615950334012535738132798576509936889286629270864681020298782574659494783085110319815705595177485744225974776618676 + 4858557343521566530159783491610288461205535017137620369901510860776505101408698469561089138749268742702921025433191359814405089 + 1405508073047405874902803040100792069570430571449445778558936794822787960786336616853548170322337310425822658832018643837559079 + 7255075818431908394615699437073631405701119134607024097267578921840611418622682373870814723883284591259922905738590072345115516 + 4240694967339735201081972989105259182809574142617805837465112261091318429255228721568810181664317538777929819157212160575829023 + 2748237669200464565992816533713130419647283186413179673011963172187269272224647869974262327569585442612854368077691269344188871 + 1222760335817459965853292578856201576938118519312855304508610105281112231513426234814422228921425942855517206703964421120719762 + 5224765636718330925202872259803187360837016560225525039097597027027310508724003400835919326880989701929146674585353105826375662 + 4608686356759945389820261327877835956104857982859971343770150256738677287345081654437248462809898624047205228119203349515135144 + 6762635128848980939500701402251709503914581106728361156687648893186497005364492516596632908393739083848785619442884628144162198 + 9408219837678921746467927680318487696309519621970987584546154535257273988915610716263345779849862915767049642549659017655936977 + 2878461866210176159858735856155729710212544372367962529421415383498942572742627275020994117127943578105501057737118382232121164 + 6202970140395425040275648643808519609153095822076099220917958127812733404125781257612941188098229102786208245263355552763155862 + 3412899983063072356219645639174430993848691176774827540248823520470123385464397586328853608924297363157128484769714643392030260 + 7516335187749776239975100738544129195651952155894618035351972235899711941435830137791970183095848641340212385537760526454996975 + 9326117473414458915105300842976184452176417489508025383214692364884363250764059076859137855740438113389750789393201920849913143 + 8213713819060950631004232834986002902474872793703875917119551478078092258435100422531909399249521481966638648761188280089875780 + 4759150755939784604117474362263502288999681621525995527689733138120086197663894427404346527959682389904515329738583325486736756 + 9325978425209872464237977527958499931962722888446298443732493719892549369851302316811008601401750818556435135705126450083049922 + 6347121675883203194927076244218929133933870815129366063255106247006180593262999464959953693728515646161688550961478583928288648 + 1770297585530292141472219789662846895032928913171250259285237148388628954759446094661658933173846573153793706711301693991850474 + 0792606603197595851399011444059807607822829889531316870539398964731417122727677982590799094547174678976545309066723508642538395 + 7542251187115005568283732133757451228935803355815247833157647444961116649664568241618566131440468159056245333148920222556848970 + 1686590915600101341570938724862037843381611006851337958368672209742162426192678307570447318588843817286911928534762475716887889 + 5985898442600265569905129276649109155018541224177922670883691334985077196371351903258301592600475229763499481236752268688794381 + 9908334038229937596478744640386393429233365920050089472460888907538665294038594595567391991275514366380037563916695381509760722 + 6697176988394487279550132960940875716670256744139528862226095599316038741474608986574869723524996958686407456560239747388319182 + 5272345146409276991368562911742268892736319679968918454777104809692672080906197146972033144703725807051487037561295160467451538 + 3361581138752178146561886363234614574825214993383047665369152075131490893168140965966229773832573946751662445845244243875117807 + 8497747825333018837277204487016088859935993376161231128402571833027091271675038762646104326773996163504827534262519513030402352 + 2850247104178367791237021165640248127529302018809122924281078393572312164207913339929888292707995450264033189457174311609184073 + 8924909933371581642458243436549195910810805622486372258791244747556044533591204446068293714215938334798650520367000310196349472 + 4508128384366452869820524778886955415968833938807781198993008689473057745756213279992800316467476453813822465284911857999907387 + 2023953430847273884483235864052375615320236609720705596526699723117087569499174093607783752368506950667179330339328300764225536 + 2114055767363508202672868934173997107264743852817603394956504753530153541861401139621693806395357957937922300502759889840467545 + 0621018093521434841220357944235687355230152336239627344725027296978480489999738827553268628247847786834042126152054295485896741 + 1728177905254640772617413047936979080771772313470023078251325162582234445493894126314939244900306139362255151328277418578396047 + 1792422884816727055970087290849551106652457784152258102530082023142369893647618177451355631227247379577671860849853688299849551 + 1175037347149672092098074310747361251964753674884333700769847744830036555394374700856740987145924794681060765600644641697283847 + 9174589667717240975144336198616364140632445180996668524271118863864525314244946497799850056518633949293612226613509484575056441 + 3024489420602308444377762407441001512681502589345978196662197798484057230208048085644756143263157845710447555275495197040972213 + 5990095737215350840694710792788564049039561363466293476205766559255673678361573392948770517450420686662337759686497763541080151 + 5536095650185550909008740808818202276021308469567387829730017248451381382214473271435330569988489076831395673641296020100168963 + 8691489605876605176450990544960425812802030262532258796192840475047025803288315858498575542856190938582743335067317105863072855 + 8766959566097551451268355313989562707945501704157509911384107284566676448181401117485715830603954518469086610851712800284373857 + 2622452939630203014872224939693671859800249164641618680985148159351811785234412541320836473437263872332827932949209391274805175 + 6798235720998149184680985250493187047397164050502295623889415695762080775856311836882958794525078302171514915009308220188324579 + 7404140736104785086437030648484406734008243907361526117865122472043884228991384547907143497695706699559582484787176857952820522 + 8804256451428134606481551907263647977538193140987930551038510575189609463453621867637464848455610801693723759700181203650436839 + 2454914648531519297448584075603475998203868332048006750382533505496359960760723675619846780966293281981298326598027774066580197 + 7995861529357273876737015678397822856184868318896981667361295506177063218216975663372922918478316465965515092121524544927046347 + 7075516111646427841984461388320881450094372462158722036978724530408790912720869813138049436688811195541657354372228803333585071 + 6429445107361977048898774220057765467210817429170612447918756002833100352538329968035564836996813252177717820091122268457886430 + 7174078917945962391527335388096356842601813618444449251961003226992399982772853124625379285502923443657958530018722098893816397 + 4966136548214340660067711135963960273659031432856630667889996071606345454141323196469871177597395097849304859547230071866679596 + 3726141431238995322616590363658851982624885785492321657227849247981548495242247508727680411775990290110420891478204977360853532 + 1644317907061571688813615690182418379232646792079005297020445585096706983621152261491067330546246215457831060764875633375743540 + 0260037498619368766791619780583839981870124397870392302778118229013764892065306663721631976910781105530817819103416467777655922 + 1257160865985307861172892171513923812618825522832093610372208245587343312911128848417617475098350804052464802003464019493811163 + 3766028847159301257741274325560482246090419451830573366629957679849625493927009484554531296839025641820596875488169323390321224 + 8232388226007759579919663974563407506786051531271638328419810743863932368666194478382016978871056258046863096095307264426924960 + 4549834654287891305590680957281622094960361243150054432811463994295196664383435297694301203486327605844830810715344529812950660 + 5753311902123482227347291010505867923405362170620911512612976729652957268599586765352146177919457594239032123428411979879139233 + 1756522666058959488542110121660842887596621268641851969762507171503624064440144225359791257651455405971257235743672383114242117 + 3669744927951794530124706132421697781115421405857509254735757547057701496218013526040546290811670945415111481766033696065077908 + 3743986898663416455838782244658330408591406810811925113737418608085893951934341548820971030074613077943621026895167359064570606 + 9471978412930979202834282673808363212715221979769900548835760002508328425519756934140019511728229374555172954389643589129389588 + 9455543651731906114795743817911783078297338344457513508249293073101170733009370971042675747320086133963697038647918247059612888 + 8987238012717473365026512535048463787033301244418231940438539856074603360903070483058902057658066015083363248256775852399567354 + 3364502373064620236820638615612559600453180311037005397530277541350185917242503038852432559174885033399595723295543954546558084 + 9899331087165498351833150053347482195081440704956752507876144131532942935103436324218551370249739155812929164520262875021494783 + 6908904643032400627041773579937621950623563067061899745276566450404645141582156514162192031414915906603166745603027411059622640 + 6495757281070400862553880509625330137059949973388167457480215447233006890221821337932185784669081820552176614865399261551583475 + 5214987707999082292941559306056717820096495439266384956685554643672988468125971218644583921446293636673793845912080991022068721 + 9098075542650837679681095355197850211686123726685262897042587789900344672369748441583193738857149324437982999889236683375639656 + 3454737499177458611505297150687929879276146562076664745364918792408073476880967147036390541767431864129948395331642282070602239 + 6878237499611110425456520778926623547629857959652095556385934261653929146175223058776396057712180642186976052559776640567287939 + 9117825842497962507655739795549675536045986355442960959176637564697703951624943028930326642942379066897205661256857648338706258 + 5607249824040048715831055763915681630425710558796489860046207669351392908027930067134903067626066854044057840603625024212216072 + 6132093035960157469992103741008683953459144927130308314821395510817197195888871912314613073270790771658400690547770532514734857 + 2289766523163076031024159344583085122839051296194651927355671209701571188590931542840886950235609126079848243347538568462648984 + 5766639281060869652151900461538022230554309323803322083408453315192390160247383316259588161796028371801133887539960085255308323 + 9483650441565836194775795637439945189737766569777908677905305601319160962603730861873961369931413625520373523170442339205096446 + 6397277751314562067770288602692729550017088466152598972362685935373861021657565974015373030623318967239986491125515528075018887 + 5402601339014610197678055292860126657475597634829577844878918241260173909075027791997352414032212153167271561905364752619385786 + 8491863948995147633786778542070447298998068007279647829967199136460489001972567744945790789456373114064713748773853626265799228 + 2370209092117301003097542080527068882722669167429990641325299940901538545419032212913930826834352316812337709858765794889107909 + 1398631884718147949515763634548480975677014453715972288924837802795200463595978496786857308537512388719226166051585776739717368 + 6941189534316796817726911487247546420252712714875639017653467949442416805399033991555627055669486555645886651826109264153186819 + 4940516166674720818220542130511334825103331157208156275492549414655335399338455554953498955587141484886410449146234826660024826 + 6659792948006838082450272697160209259339168888357685416533244048793279607628259013570705943914832132649302220555803191155769678 + 3450607770354143996892622745433805449122734203977711922327068576407370897444833149206827486642681899060356549533970828759001934 + 5727275520263633514968976110225542746359061074870472786303946464842833869445090010825025879958856002949152638295200941043841906 + 1327175710840731608371208629917959139504834096615996636184118498113010168900528468440699292352911245996048410672241669829930509 + 5804872329617982647538232786144744032881485213965459136524837612293635959247462464117508493059931748287964717902656930987863246 + 4277723315738568098484054986328302182182023008609946701266751039890388797338292226205365731416488922689962862442504898912370823 + 0169167783207015850910326779335592201489472916428336283983741331168324385837589731443211700684040249551018329769335204931232483 + 5298537282274168905097783252545295159931996045324669229561719918373117774516092756810950028198012718738992851067743291059615923 + 9444851345487696935698137109913963152214976022384665735269814043959675847649595558507091607437770303094115672250928216923641250 + 2149472592686716079768844857346451000286201002122320769034758020998927559101579776094371380910427183625784710226757782544230415 + 0647876642293735785152692483992423954470320088754545909378609961100700126777198798362991474951795873563734734785888619665299138 + 5849838488444430649533263787538811331357728938722568950445006777515651519234515285808516388251516110101450462227962034131202241 + 7276104739525907372419126181186384546119321638501786879645354354875497667502927550069197442007577146458961731206493061524033007 + 9422217503140335187736221742892478886207544102369268483447607791356773560830807813772377547585429918129160635826252418480968692 + 4951724274446263780114357613049442315030582695389596800003586264063614032462365896162651936067640252887621519671734335954108739 + 7454566191860852039559843736923834077952568697550937244831873949705841445761551247253789687164216518186201016215799884228535871 + 8439893371971012000885553951535059948361302183174942319645796198457357286423328894929588756597087846522596101434099524110623679 + 2208231333330844864465745363677908966068876448934931718761801046807820975248234034617078513450119384012451530340905431793537946 + 2305572597375584599916270867173159433891169944691281508143382202813205881528811308590035206333627177252785229699333403132814188 + 6581817307307772248849032636830370028521484024024459152842727518740380359881146898101434552487760886134249651169919754088451088 + 9972253499037895070298514770518285390402914258598519025675691003304065496834156654347189749182550625905099172508363395356804877 + 5758008808025624632351941198979018660594929305107322792450818499652772086629264781844489198081813129733546688788720899531192457 + 2745675328488913480621264293304705435951452309540398654081411328496424730516137398740590505211615977997709945823736263422098774 + 4319217301030265407335508264753089155109074707762624338354639950177679811707826932551029618948153019495825747590381756914645981 + 9125342547489286004121333337059776054538539726153714180036823804029952720452919240063140345998373975940156807239544138619226508 + 7242675874264000704878339896544038336920890771642735504973073959953113142490324395737352393349120127057115852252907686376626747 + 3473321596354209308933007945651010752129252885281924230373167976919072240297072208573755175225599946410500654362886750707794528 + 5727589543974524706691693259117706864773673979587751324354353742658357813584415514973239116989629743388388478173856874552697761 + 1142418605095869987288446285147568178401344806595851658792922110020211362874700057924021743582095514290749364426026381491938886 + 7017216586801442390706943294273005287782115442259090512088524168970016375416554459606914186390125156135455842825317699271637907 + 0211233315441242280840462166926685973850749956345775689925242698347596240183158491250150173733543845430700552741593194555804750 + 1797724078344241125893042060239537330994558786922162379383591805537659608535521283089375039292199790021670953442916099772863332 + 6130652679697033488878720295305832453720948952785209088953761883766005724826476556165454243473790630572440696210857988190704713 + 4744821686581324503785124383460438165434233854467259677279955943920755162775872557500679297287992727542016808831027373389642811 + 8818850180176632238377551894120301699425047464434209428644888921239546400810384063448594908229208386662084553428371435016786566 + 2565402723149127183692936818466510584042955514361987237908845951130503356391102529543147109435545190864583265738886354448729716 + 2555888389438655691918145095510314610669012618591908132566801282747594112804817710376968735883323783155393749243633468461076212 + 4037970808854790499072817736929400553034907676890898900783090149602127450205466513482819048073679969106848951996174948205730701 + 0816030875372524859030697931442206128673990318458281042368684773151576092499288971063578724086458233384930941299441451767263066 + 1664521612180858396451529620088930659358500352782541669595817923485051339758066634536721977274523994998146473981701939017205602 + 2524104027099484717563367769361246592695182470261402965977193164101572566284710942794698915634141627566609476347965721168530986 + 4359025426573155220274777012266852482447049345363636421786714781355224872652596955092178684933842367455487342490049229104686636 + 1405127824749409497462184480237538519293466992317964479311951604897323056429690265101169427550747026874617333157171121236924703 + 6018076627013550295381656119236991061160617457180144979226462876301063552180250667955529552359828561142316939674528337208856344 + 4374830018868998904944977293261195517662546966324518234611103690143089662138017933662034152841911712239931096922875112835748433 + 0236447221655510600424621887641222992324877860049632049076965940501963553949996895966286320389211270787434721126820780971624253 + 1124118658886218410732481795333541469161905682578320893049989427979158879370075562912903672274463984603712619157580009287344826 + 1490073439715132975375184719480763004789606934374075237219980119217402660147346676094869754304392997432951402325274930204871342 + 7507088153751893726167389642050254715794421419546083151335746591084804700733010001661585164038391983336305667211157845088930512 + 9454605864819889656904342091511833717539963300409957365660591244004512939427858955522107791635547956216918186634105330346773979 + 0658593516322846162016300446203238142166026181710436615937557978420890524597354295972144917810824199008158678995080211427722929 + 8980589661160288330719076634082892363742482807739228207426629330991685667550752678607146578792931470069849286956087928508404855 + 0981420843325337105199162550260043516249035154228170027681913983488364730292863723816365277728171439162179656110789246164875870 + 7235989772218476249654125554327002628917857770756363184283174214585030441232386973067535578285982100385381595377232095167172355 + 8531968481709055316167180990447601481938541581517577911736493317452245372585792259012856477270057051421673563226983021870172320 + 3966519268023261060863087111821082801296148611252172465597370204173800451852480272015584093876590792853690848377385063421097933 + 4667059194375637666825712724740535719642601441210189891690016272378550854485280624499553958549215837331920055819015130335235748 + 5180652276625067336617174370015460185337302241346649852510792894228685353669611675801310899772318114006268028233834332313504023 + 1941303813100529733477333374209673305915978659212933725574700988773740701325826021523545062039757705261878074707241548966802269 + 2746067443336418197240323253838643666106109625323987238695096142699993722607024221029583744572542375113816178166737688431737737 + 1790082381839115387609873262982695752275538347088304949304931589485737690198187441832377091589179048950816796427590616885843542 + 5552689266955858826481326722121453449315123458065490624658389457610909531278210069460670951157478754958271396713130819467585412 + 8161144774814776141255994752061769287038765060690866140571952344698969957192475271081186838639007943816699743960034503332953194 + 8789192141356424274503562578603345033063547574284980009602843989229909463071658256259561315235167835094522110712803401150014304 + 2269120125327746733199585385420581800688978135760399189023545691870920243025811096318243711254873352522759304218250492540601301 + 3220660009367443347579325094663071621014417170436158246461857082697811419327408184450532404128001876815109034413458694764955526 + 4236810019612678173215181621403086283786465950563987195979676317579127299901400746488219293603220797858502005948349760508971512 + 0842456999754267165377711495312735495780613161991580964945616998690779002045181519007002606802172925174094502143404195978695837 + 4416749583760585438101952975396064089728080431113199590836008764153005621794368480547875309689843049490843783015113705286745691 + 0795274682904383996694242263473123412015847505963674606830368047427506205910859669522416907398900276339485220277009294111636658 + 0726660439712285671104280059752886748116228091939311944983809111670167487220776456879193368274819545300958924106260054971842623 + 8150764216086897115298219326429987785009191738597276238467913392040684511353140756968540557235239878544391001829270153861846092 + 4383222134341106409110971398373626248863354871646454326385144812872101996077996725153807549596115873770116755372384144360289549 + 8170673501302124114120744895395545744756695363267571023745570418014263093634951684729982428233593809293841917967048459961199699 + 9763136038244743451806991825890314924556837135102471133555361059824564665398157293669951119702184740695499289874076409711970682 + 1422421956968116348857989939957276677533229421063047970708284154758036180433546990214632661390471026182712000805513222171655488 + 0790454789270387069048408785812014404576158995323548751958890039523932351478622587142638056133836919868045535455845844392024399 + 6828229983228262659292226957969701095193296498963956591476120614340834793473477949399153199148731691820887892496627505449096093 + 8624492093374718033878604413583151815223479591147786368391299257097621796393142945746725700896309907581595691253852161958930992 + 7107729406703783687280485106218574382700030054257355689626925093581880354626104182184797971451190514868852721286584413091561305 + 8741987234103316893377380144344514006198840745678799814654988835056150781397439910157073114301452768509065135515533734967678598 + 2735043292667576626222020726140529203825880750760734206750175908534901067729659839678099054130592189468939769616706044680647240 + 2763006819383647925527431911808115681683993973822624367816274873450252222984650251537326892288304742295886859351709349425297650 + 7134753100395351301348083365117683812003850761712390745630056031799089854945233811860729771699517948808663082113548033370410055 + 2156718353193091760663949540389192861228968135157606923907872289234299014121301709409557692508414639141148641363055713300497167 + 9323046502608972228620000366263176485575290223984881067717695579312796433503231136630486297616245185739116228913473000321724069 + 3402413948021099348085449161508115950805641814124236561124067595528674925736958070838477983849773356429271615279624883406948406 + 2586362309829746055325863292755259087415528960697154410026073785183365372343620398551768197389974234910915413966255239135166137 + 6948141006945340339297784658800718813009858499271702100629421441689482806248257882748211373263608811093415305500022007093455945 + 0842258683716404942736428616895358695656655266518974938995151040768012671515151979466768515865903424648012383400333040320383895 + 5049269512019956300105561497239010604854186206683961343893764070138734690927147819767835829400814779254514025647466904224213470 + 9569948375696342652641662102284605174592869950745185014008552719701570802715911338264166097617707320465336842190177333964575034 + 9428680684767284183633020532362541285325879314896297017757679938122092115670160403478099811406505218708402491047782860144041267 + 2048668363875460097326211666406188941409324970507852534507916458181293600129195542233794471499710031501087442970014489278431811 + 3405993437193068750979763065800204417948705854493241428660974718747020128492308645680153785966021095932035295060527677641892559 + 2814589083509652662902787080397228682431174828014560598681492336798258054680671382857806718386021239491601389601875295478518945 + 5986699496572944083337074930929834075993621216590713141225309670719782429561351058677320246208472110574056384475102009208825158 + 3701143845992716374497567663523592738178836225177899343548036997338523733500001300643656167477000925420983129066143726434092701 + 7423291379038754262185514882391794604313384501082737513845672893062736061561920457702887522180551612186897189287428790772663945 + 8038882462960387008399150903931548842040303337569963977574310341965170156166264463639669524288945874943197641758694114087360524 + 6755427287648373311476510042437767363082433235534497669444705172475485394287772438817148371693824101932257743465051113814804574 + 3302584529244780057393036854445554623243089576362550605055694156880682183315829897197741778897975736012282052319045886108088033 + 8087176493289867561968800923375092924482419715512093174473694625106772042668885277666098646361898523510402733964872800445131037 + 8320007995921770348498605128869111626930267035943426816435809551556518111290098800524644244409358410267473862764842446130048523 + 1436098828025610017328979458386153232076446194265248731690143382189291992244935737904603822794261840119592775301158595671929956 + 1859896675014716704798696047818739852245706249557223427847334266658566082156593745460337399765187932861285602937611319183698837 + 8695387218535720582564065835479455701900416698839376472323627804365945785468346621682197696163783828936362978547295808542269445 + 8279752484506847142094417985544033613129823835703913986703044915444548737906032583690923865665220094573089105884291792454719678 + 1316169725449877686068579181522410565098719766530274437681078973112896904796812316498589687674134438686508004774642199962324204 + 4690063619499878869524791692206588255254568407388459022366711747832387099104508881401463078787110967721065394141648606132537550 + 1451429470869671002057789223158518659342906175930490990163086609677315590447420960904216338864582531646704745882645257996753003 + 3594769224483393076962577578336775804994360716705648101110515582304099946203974654110102114903083901640907564773113403226112614 + 7842811390980512417623967516307862595714647209118659868698680060437058188686064362842966029195804418885454481156401460457680810 + 1353730331240432284758809177395482784888827256712163440645440749728289433010840369051942073911490213001477219496896397735829211 + 4601945158211709423733169616586120219445506544455684681994448828365740758425856347182450418912396580393258871768216932273389644 + 7546606883962070377792485250777570864737360035965255716590780907370097846008363755114568550428189781279182714576817370377989913 + 5909871699164748481388103916215854782263584875652627145927520783000462057342075067627629231607264735052014948668522278967261465 + 7789853062938105623444363261994088544665616630390123445507860288440231593034911635167838522597643333127458708364830418263896184 + 1286144438352596484065325500754944308173042437315362632781599996019422261591416810474894175619846059414717720198222378370653571 + 6971462477582470633206125394932199429053380382783796898399516803651438673139498531736021776634684941580638746309619120992683170 + 8629432822993724963855361987882118654589234693568266212440633573606219295689682039033133123609808063033145394447533709295411896 + 0281594967652261579794466637274919984182923757681634332365968310833409307348568763974412665592870158544818035335013012421932763 + 7655826860692715418764005666669293766929001138134358352328235302135813053504743107776878655717896623753934484760219931500298692 + 9290168663678775972562133999711785783179036668870829240738642007250789936063529444287722257668245891843786516368999364205453698 + 1388094089899362163718773572230079214466119375080348978705038480095898940916060131319234067470176587422484787467679366538347868 + 8017293664803927630769729168954945146012294840940686008911896485848777037133106837925465110245874730110174759001141830380040038 + 0120439722450454617928179479243857705288134086458602893871161972846537382451740227055242495699985657918659780373398590814158015 + 9185549346791665800883510913273745072991047690371888044204398878541170797025220849684634548447569944177523688037116487344544844 + 3983330147768673814424552255794031561316294164196820680509267685360230979960997521617397764375675161021883986966830273621436840 + 5559819786199323213875219658620019627595340113429135282821726501703289978583492131096279542835050405087347140325687712807079487 + 9787946090092230362250195573096660493646419587912974580035697132589473417918325240116393969464922906025196729087774385693764553 + 9860355320714920060965670358032280168554148297437945180860387882403591842300282814921233640661490871801402207762626482522032047 + 3097025361491117451005377278198487212237099544908247111077372764356886263791448989161160949762415522639831639294698581458345985 + 7119461403366321455704765813404706513096376229662175435103856904757065360840168635845572631764671801632765978886309611217770123 + 2355725108730791813146700353437818727398062989969964100944171032459233591148110740093249920429111285758187817891195538479372333 + 7717147589069034365041184332554553609756818941590171329038369697464604453126540943732615622700321916184110353125350100127752260 + 5400719243883713007355805618610788516934976237500923767706894033322172234355015854525038569883308926393709084041999484656996753 + 1283666031444516796129629651038339271512674202354596553588525167158551065999313761923723647718179391480101442800341777895133996 + 0753973775383179955400385390016380992296547654995782315767306424246762945687075752145691419815405005932537449947304486849576643 + 2979180958396224767297581462043320034127704743702992357878029772922817116999851784773690688789215232089766369127969016032601856 + 3851573261415488209314332793330099314068046066211719044146103127781354079770099732602779302176734228288014045681315375260376275 + 5613084622744138175415292879907528314309988380989805830104342547726499059288400078772029464667932988421246953056079406071204771 + 4586730576036740853854978952480253788859203002939257757392716256983049436420156853771221502897572109716517239674204969203181474 + 0982119350191052441755943123327258611832950316806139591389360751863567226397368531779203766930988225110737707276225086269268083 + 1166609927459152345242074308503846915870742513191815496448329154263550697382001973332037653901875197894977220232463712982961473 + 8742250538546251559619529217497793362557849446641056066254726761640756859174902719692841027963345440941200289292587371677456563 + 1787473730619074666648808301286212846168364513813858291223488226257956569272198811926719725754005926219281926579718279777830444 + 9964885779070155802556863992597887379404305287991864566420006473195804170299129414259096081893003248613986369776375193541122827 + 8679261717535638702784929128089835277682571491318590535314932208130153018789998592505582846756436233025096155853923159667457622 + 0064101062279216730164192200983393569735835140706754353527254528463606619322108164129797836707319607352924077829068257856221565 + 4098966914598730293864163204728437998349124344700052324246741119119244973881766239805489297351925527481613098094358252765642656 + 3256631812453399632987567720287450907847236484423613740997675264597104916297183865029408528402827703543717537820987540612308827 + 9763193844988062420108359297687488837148328286540087218373263127565810612066788312087172343604520200144217517124505185828378183 + 0839169941798971803467138716750724876136916222233258526467257984594030393990037357389464526262272705365500201964650768865692587 + 6552250604997641261294087071350242489522328429130222914193744223497369981001341679952214443941383946458063259049876349424028513 + 2213974436158368636025109248174911312580051245505113315795959437260475388392500593400331863318219524296806654096778830779216940 + 4878685599516319690797457606707664358483790224825508827231099632903629838432588023623129489722939201221165328880348763488094404 + 4425772854689128756512183299147748549960529805463272504802739617344094375960651486501133996216955411590283887952698362709773340 + 3400068591062085249345178361745959828363146278918068111168494145377017234716441154409189698261322125169944980545699464089750536 + 8846865398199885991570109728269877331973845988335052515573008133676441111176443077214835337189028637762538757833593083011292020 + 5146028640720658045073881058022137119722140728994381646856170548927402303281330627742305686994941764560406751703346767750713886 + 7209258975092391507951817856714755923161856176501059139093203502102911025009832983122251947751287786516716014787221574638939756 + 4031047248735708744857275535082996528246946792080390060989384866585501142477546435169883331570932498501313613151748523824910672 + 5636536308963660510951867259797466984603129916969819578084787382312187680895777499152465628258228314680156051454804934741689251 + 0512085879302345402847429395015269085320583560263939898103230391420972595529857458723736782481282792113866713373594735837816637 + 7989131244460061235927200538684991689192443600011394251966967305334141431951393722271395226793607939272662478632186079903315157 + 4105861225129127048237596511466748710669457275423951266966241892139141936555720690437418563605034436351637331842274069357984239 + 7714780490538701008702866992517751463558344819912101444037343071198346617249265664311758101747127784897043351442589412949637554 + 0794058900554049165331519254294841158439399536633260010261808293322453935679510287405960977887161196498223064393352481611148599 + 1300801876528225731545729262391681879452425698425569733040068970789105907778300649408653356394071182530765139660697696280006682 + 9500403460028711452841481826687628011337250118712797471026118134978473459279189369396543791538899643830373887355243212938105191 + 0873118171200026341001915337132116843336126642682077009436271005094613931653248785836179383736770204896797782028704969977499350 + 0015763840495758341501065058600781266869591393444306380925176998016954972799133300711081355008885083487358653288976991291458433 + 1182038281534129680784410839850542254891681906855217404657576532842299794168911463577129652659153953666202320168343676218151354 + 4489515205537483086890747806185147028159038841561163491305751443503026033718219551299657596422184541173585136713789948319572208 + 5427049518844513938239013971033113865769356316346953363872557559769111015332419532829697997722648255367995610629118024243751562 + 2407474388820183495631279695253839995841338363502759887550630065930650395810552864219034911688436057782562693639597408091177372 + 6597246835826333390472023469934087393575305915386587464255626374910540525559513620612895257369286541372428722814356277369790926 + 0540482329932732167361734686964636330198342028336626252732092257904785101659859937597352536082164206650257784256989122547150860 + 6958569549047812907458129176134743095874743438183862052347741885494624143736509130890665487847350948675120079666371405006768737 + 8780431675373547960195603385932928721012510177772630104840609721475744144915357267790854338213160647630650329373129575638594956 + 9496521524390891252020171500116808958864975665633521384560269916937417268750283135245520953900937858745308291830904258244389317 + 0015367958131832930196538448945414897381505579147872992058659675192664335486653438990141847260783598099119731774723267313420147 + 7668586967951300028516829535113315808229408687973080784960696295388250987543953394689424360452251573606982659417899250410280988 + 0855610169950498351316129660470090096789046559977941298373823170600445713232790694833343261118257499105417238723309775430866295 + 2330553865870284141777533356762036585595078938692432368606760459748846645365953536258322870084801797022785593339163737467833147 + 6997226216417469287126591633487052682393389785830401431520389186301156111690874765557617527284900760279233718743071166517225051 + 9560345000426728260399841368953209835209100487337639538936954570820031680886090876109665021023200759147113373797389077298422122 + 8175155068276335352679806117326566700814346009488428499581701401590558929437455938924635624938224553855781741120788865291783407 + 2295536946679503673362429092591476438921243024065802176610048872694278802256805275897901963915809617356852239830206442834187860 + 1980560976965565165140981488552352620248220002599581191144636050647934285203553865821505084561426414945738261567792216102403148 + 1151908591260497769379834919810177114427370448525005415075150280396616811812913926897078347185577604045023394052213732465977204 + 5152624009308747654657296667409633669797187558140762249677298229159695566185953786763883703575683368256625993695568514289670471 + 5898396239237604417219674285036697981388707533386023577734556605753254850219222927862511398982564982295186931657039590148578018 + 5932796785525089331274908323688642021701636412080489905006446995970747450915290182470813258134915840332610387871533886024451368 + 8138194206803987511384906150527820013265474338857553899093509868964543274546783521373587071739152356855552276377502435950664343 + 6671221923018976396144288089085545597962326938710922261699996323322275457923099268605292778087753199123847741515682942101433343 + 0553836973054122354894964985734607674790792609106461042226839499946875666977767744836458472114784382708675816804952000351499560 + 2364997010884637465860014885474868656892220025469289156670808481103243684995557245150848863996066555128792257705475749161690025 + 4110649532154387762250909130921439734079690118528643911754202049214907597563788601359791270067268169269560624171237553348861595 + 5940616224028249469894892261151683448506705471885912971357007128279832881479611563158245452847817654715394431167451576558923691 + 2701950548115303007534807474569747157173002064876638265966317419898895957065042960548048125830083650783906003217529190210069108 + 9448438509033254495362865744281724512323137198768884725254104680523096628653622761003126111128301647813853623032837646549389708 + 8800961571279179907403520239170262557803310568213744508717356574441764473623277516011904000012404016704294869157929203333991614 + 5621867976685621217499877201966531190154493625522363719922688125680349437187226891224242675375445798588375405091275415995993660 + 6776602064451444697704536229609651834393352676778641614610712731028707328894803760218379598569050464723477953936124087430950917 + 8609350069628812265374110081821823052163446196500492527833170210965201939797385205224718774402651526872691305286672629217382035 + 8488697066441224751559631066164022076293716903983024132971083317225244640782734589625800094058649006568726351629980984900472989 + 5845746441409288197669763941632849306888745439411555999404218596367981143977695990224865577494042079971012624349908586273448094 + 3944731944003065116712174476397673714373918870846441482703374457072218866041336694655582361341131880499845103050687313792470342 + 7857292237476195260600973001695477364449307421802939526518179464787823934178232688755800049682688090660718430541383983270572304 + 0611341821464316878794523833266573224644012837504558841156871904475125652999503438286924058574554384509785291956022252381864357 + 0405626679943651292212678664558286589975871490755359605369624889948784641951887207653741241486219388021477385980747033128784838 + 0349563685997861866328510113314436119201124870929479544327167409917885140426561670911266619220856732660355093308773694213795936 + 3842271417777258599324767675283259950186722960735488702869088413460362934496727774403713216022454808579752649987147082209915211 + 7262086846799716572297263071380322488276591389406786696601706848938742607301811413241169596156442149745813064652698654676224030 + 5774876540806221409456713575924968982273367206175097023050483195829231424480633395579433434537883182331511499750784779245974304 + 6819745509357317439429415625378554567362388569070215909977624507836378437106698876357999443207523376055325643289588788312580731 + 7833148656904363694334569121139758945904938915660261426660062808527488257575416983895078937523942074734502850315306918181450849 + 0874641305830980547277712020017148651915548171250649493853510014278214375521776229277631115079740388430042785920214556466053488 + 8302249778400205215684880334891997915871809162392886542987069548288428411471154533517912205528047987025944754683578880543791606 + 0358320982227642668267885208147099122293592290139450664586369209811129197752858004803010616081626472750567559363814707696436535 + 0313506752837594147209139665385131531998918025147449755897149885365821721038971422038604629058413601987368885444084132780675032 + 8698373618661979252204221364880007737028947769589369624595251994724054095272484618585409406539000761630748495654887039290015310 + 0800818173175869261167775704612174999230343952148568401102639665953327107535357309312915124706207238389207300777172747117401698 + 0640073150863859675544943154734483059715378564796905159762945298307365280446171698542814284025032267504158534248530901828343035 + 0873201504993233632733239057534034773053022444340692497950449652566396669145334447109018793398061041589027430348848568737315985 + 0702523531880691374404054678759180464956226260133696133658291458560416403819468440250477647013266610552428012647058409477074911 + 2679888054788444461424298005407130238905755507645631966764120317200939342102226493489457200513433158963725232826211305616759400 + 6659241756332251314783750854468182797311328498121933543014291040088680657858265588241030117849346100683667795040402222839296842 + 8277427249362157833641670896337597700968219737912856460330555628526942419632625557211562429343845027815601523792180592076379859 + 9754404607631948362062894438912954500557072195072644550642458309860663622333701157823267362150209715197912528880882392701349340 + 9392967484360182578733939528902161701930343748675665636284278981486199253820383071398887821347218338053979003089742707812914379 + 2904235361284953393462862403685101898073830804299574939556200135991635904384199077467177409693740584708928799458835571980205648 + 8121614185438088992376830836290018683875444583668400234525664787649173577729566744205001928280399848363250846307170382670891227 + 1379156561645180509829419293369128655964653490776933715927876086576622995107120980971557236204092369803081979966524323872401105 + 8210634652239640140303181717302977441319086010060056823202877048062527278336721358234059108992008083109338742139836036323492605 + 7384031376893772770300054085703713950658765604751229388016547464754511995220292088356538057488534591958960218276518555883565725 + 4074775956662864334941163174462487475635543748972688834049926463696503634025310758502751556398690346342648412837461668031647927 + 6365750302288055740676475554487791055706610049861824646116595120976061102018119073494765991803213702717674747175954421813209939 + 8009331937511328151001411154015547213063838109162601512214845406533014265983012161008264010599651427488015290161524354573353234 + 6470978945561557225050621564665550894387519941185513668617316911095236397590508616848692919250154411755818493336504839734750031 + 3525111855377922515708294426372763399105358667430235504503228627410198905334837234851992023849271193012460177555030458178964902 + 2832205291216922852095126506355099210740893308816704635379794133382523761361826241501772732710458333973916837834880210080414250 + 9084082447350749526849475397900892283815818083030975632291741303292925823304366055091504295072069505478412237935230243114270458 + 8733240614953524515745727759843129756538792646920469274157284227528661937418719037781765126256474601006075476554791323844619684 + 1035243868690685092085007530104395247063420667025726455865466535541087734271159372906562129287612463548495628710375386966180600 + 5440542501876451157868698528285357586655663503645304099842630588650168915815059917415278238955617758631802903768822104984447821 + 2018849475721498910886528030895133588236820109040257215930892013189827568406433756483461049360024443491773721292902184969255790 + 8822875627013591731684908728396697952056849491038175568000507526035874582989907019189676297477355884544173196568562596540184740 + 6207027832469439408465681825635058880584562540284002435337574271598044807397129809411607354965616450909115426381853724556891033 + 7221658030059861817521753782741366902139395897501991336285575875528980544038829626149666345302799699624831576475243396464744984 + 1649540253799052538081391692469181324705607910980425515252483873483980593877409055481936471747872491282539042199279780879543216 + 4236145733824367590860331474571745015558798839670826761096891349398910243527132904379844441054007921880393265550231971508677926 + 9325201276405157061556423958329163005949768823959483768715570931105074676418085399720398268434277889429566019457186074673651582 + 1556755082109554008455021604947841187746491317217027281220528571996910808491743715098726471698066342041982149950618417860098084 + 9612051527440619756444098523237719085720236857461176953239899550769256325996619384467815272576473677824512425753715748473823644 + 3293706412332532029368150574309147409666660955800738909802362577371939197344269404239579009973609254902956047445459161013030585 + 3889810572293351817285095560307955387570122899356894847953368306309169743185951491528192204482516204225431961214922057114411745 + 2466537795850541088028557343809549480793529110899163252329393397207265339963882361084755962562912216879860134066671514387618346 + 7860354854395803331508980945959835169783983572284248855654573657487835485311040917221652836888254950796354469715116733559514443 + 9649687850645361629683896013084952406507914922578933911589068814423571506614639956792270631464418346423540206296752844238915237 + 6020288012912630828121914201273847417936995938147436941121877369382021368921214557882494996867880498498027992143690818597132057 + 7464732232055318247290946075477625177092427701352448918522702341636498386700884661390140882325113012278493389309349523351396213 + 9696483275515491260944768055252019253491922403588385357522280969636691193420388846988546363998678336385777443993831313531774583 + 6282522032399446565965739736752150396232120722412203505719106262036358824681398508892551567229346012725815333843066908465157756 + 9407628149379572734413508114861082667244920525693627019900560538557779908157912341364139167913811711711544677292025506854245811 + 3464634373606321375959043076084467134891991975403488809906777158185809859079955799214529934428440394715803296141747865907907489 + 9423993889790762040142434803114305323935291193328498665927373291227929076575533913306444776443880643225751481031179680675214923 + 3368470912062297700011980465345274304044785588310672874869214201316579834207228249128013243107286248089143869069547088156308777 + 1414590222708121116814503748513196371955339806257298864789960510451079590735116383580469454857965360874314128844784304143454069 + 8766678394720390254448078037404671513243310605018703312189431738938607517130277658972087080448195787216475306011123823302381254 + 3391550184839202307004590614178501644771630600861096494601392733266531850599404613838770697571965897048614790913072319558856284 + 7803230787138777594218452988887094396749088370117209351285801556001096168575241228759515079363186428923678980339871398190852582 + 4019696628533985636279505759337532628472390302841917324608852947709111244515112700445738982371253756187679740389512024539739520 + 4770847899134941839230668652175028834007538603739876886601634289336067458758592877494727624461743546957277223347887135182085175 + 9704365765485920770156655545282270424007413902597806432869012806155483311798101235310454409760720811406614955012826140011450968 + 0313480515097495573412839063893028999786645804567919951099814820194282264604422806064547777371073192487100289094441987847150568 + 1657543112009039941765308947835121413396501421019711136903259340105124014460634621836811024214292779775980478293474663062122820 + 9705767650372955367904858685510440746508331239334572782478185604370866609254504064506288513924921428844442806366648997093161941 + 3489214963851233247024856358669087681654387218345765317192165484089902190489810844772030255183904855574220071570304690043795231 + 2065091959221855386411960322245401320421129454685844655947550889456851989959823948526569728196088066488438899595441765150072821 + 4429114819428348855107669954324003559235452502739679008927728613312163086830142833511895866448006257958165946765071157730382695 + 9882679827690443780755577550740154748999710142655073573245474660654485200341800425388615819101330831466686148830980748666684090 + 7163405135812565179670235235614927720441373285793867065291904861238349709700184831060873375476942470039510660809272264903320798 + 4462917767939061046448018044214701368685457860623889616757211734619696932095108903120448131130054208365085745531785639497736359 + 8218165839330532616994196742532527473553555966673141549749982047712150106818828620285541917373915693522694719282613944281399835 + 8674485087809037160526520795860814268331241546826667372648249043039257847644579120849321232434718628926179993145231262359579173 + 6402705380929919120941181769537062173912605142768108201761013755197467816367902585985810911153925853453654100594647121313245913 + 0666872833826033632401371436548685693080139022484100159022033636174658329127466366162032910540421919446428986161784748017789598 + 4723199613767942411247930612753447325541505390129994382585659648148388692327147276519250190560063905452973361339890280400124358 + 6913416888336681958297148217827338479648390575317941960750631878321348332412104016113215430987661026879407929196484877377640061 + 8494663204235300224243052398541725825482919073092074355975063032796596426605495082752541621103997044605964809112021627153615430 + 1932408491193512375077001954464823146678231602554522550896013165127235920096414910813761330938337552089472955671775628068540474 + 8216732019553272236739723100215131535386354969462704414412180804694918899617675023795044921436432605559415902678545425651517812 + 8025247190590822148102225680479409002058106823871348717740963812585351667254545007307100968605826752214724522314039708032085185 + 2898242245907570507615621864533672777989484514162394933849338212142607118088404798508269488444104500180113716320167923336719325 + 6087711919535546884547342110103435389748847458344462232091767124995184518172878034781269231230242533893228603793308922587510107 + 4591474660599204864799066811331150365409997858447042372594886218949250820247279474918230135657009456785941687614114216570961562 + 0712145092385555182611993058740320634997625075753366666542910024626577807784857468873721417913984050547176339602792705731039726 + 5904226911569176720780206777188612328120845124057780320649670149526594811111907198960857717925291216166167928639613716137663067 + 4307416456452371611701931195073322788105756639763524372948315105493615715372579618838296610933712476520491005806495650421658587 + 8328103991782890592563008949384942150246156275152343753139757736003563406755966669814359044466955928045317799518086337670918431 + 0138083133435376046718367707916060720252112445257291714225747183751131216668718597844623190537189131972377334685833227229634752 + 6238721382625606157004023423898943602807707672999152909288657052128785368828226605301253816178238566671806542598902348311422328 + 8320139586923410723937149546492213794676826048701166669784481756530412597915193651538414740148097847037639468257092287852640305 + 5479022830982203377478476331811758576901670233527290215872232363518816501458927070562308753377018843087767143244104321568604135 + 7369186061703793181459759961931363593408835426106781211446368072605366366571248851597783995945722926222426820630491316650527779 + 8828573417201809585216027386210261861298732060253123609864528252840272478045882739663756003736716392199489082689850824432511971 + 8111646983909651153366476446390221276039522740932580204249319217339578537772918571217444956420257260371077236650618481206170288 + 2935054551970379324008798030984106801055948226939968902171687217907155340893582643366397894579369212912093597160438593641683669 + 2485378257568528389277310889609277386833678172566456312002344737328227016110453362502908568225831332260414575845627976066579941 + 3482852162228716106007258452673841400279159876124086723321209861347673279139378292982201754962295388660515249705755465339980807 + 8586012495756212505119149505421333725699491270326513988475156468533804482583378661782959257850441126447111003717332538997317723 + 1776086627675735007130894098661445494477133237650830139159997474669449285984774365441233470966013545796673243563388041724650925 + 4871204375981896728514583939521811481161849278118060344334503543763509824336823270998963842004711517359429526921820434423765506 + 4949119417418804810189631493303008698556136954410752013975187350631734375598695358460132019129899037320268439555839944615572946 + 2352205983666568424098911534581381260867463768189900460175744875437666192115066390019086651996365032553554531097825841729484867 + 6396761821871154925250940721334814793716957966097731930384514803099552848004844714015522077211735687647117734547230837853524693 + 1596031648179998000220637673943792334209148422484797868537888852196932416293373918035158752836265069893009384789762509582269339 + 9695024706050496247098862490788952376578622083442656866053965079277898118236124486093149364786379996025483226916387856904200464 + 5207178534801739733741859262250257717063345689422848102283865760573174574242830519134626672907219548945944321186449133371889496 + 8091522599148708961675484538617588113615426169855145369191110338586586013267131819054886276010519517578355159744969858769754154 + 1409888192657898889323633959345553144675637666158270953101126274823625732454329591205013981131246606853736622675628645701807371 + 9520905296639004266979383969455080705361676763621326243504360544161563837353776252465278766865244727756979870759572455920688699 + 9581386171160687133121725147597447299189214610587624098233087649334093755829602691095533964193964555227483958747057992036054166 + 8721053344317784071933338712749304229416314171955616978192540365793299631623144229526476496982594982691261090976385827573975900 + 7821592310703338108652726889016577851582851275588755649801212540201927028394346407971389167170778763825909054893860501536766294 + 1680216758688189041294684581042122535978201496230771039365667061380634389195094311357702877874169983055267901138828354564408227 + 3161070157288336465271541894601581266294703722546655378330486847268915166615856440605517140340676687703279431660743947236511822 + 7741994422834194190860106225475557703581613419594307564273066500384493526007784089212735294217591917854424698645245431154845570 + 7453435530259083182485810144347944810673614929556646679467919668579911140259730381818980942598880746925296760172341499274790409 + 2328005309406832991426090784212693827689769275846169654962563240745452602435209585710235753460014401490458336687380630135023071 + 5366592739312999644456849006548399917819901894358497737731098338943033079178655254808256654806548883980302404456845406302737523 + 7903862311453131512315977712627346676478344399846058399879029101474967706599628983635802084695117268292559579897221003598626395 + 1226042367447825280036345293351132154926212820976803484997329381495188404459278925205516668444497544901886948777923893344531981 + 6856828147900151315527595804653628550631963940129883617356848115429626055627960941822258407367220366681493979858804129725050531 + 5342427449777364357294403483728929672993293331804282077540029002773232860603723492768689779320843055290078442091489307669129440 + 2646993961014124319764296539370434958358249722078956842849671467698536721940846395173191197670777284048312934901527571955362838 + 0198542559113109732314309858412233715215167131228324026800689688315670022802995393900835564840785241774828835077665262843753444 + 9550183762744591451958276893980778053478437092327149970098767098796188062615518630585477187237482484844353645352242801527565339 + 4554133259430221270883589344804016824319680145988501368070988742027201586296359667866696516024912143872664381709357471736498210 + 5093801098192097809224518282804541968783581829389873304181998214634779593308644761544892301474532546795113168811568716153209669 + 1410860371073926432124196875939453572716037044352794395231284292433400177009767688979893244784882963302195811252949131002020348 + 1963827673323077855623143768105648991600618303185458508264555147286917125868559346485583695956446151749324530132278047444739067 + 6874456031627491486993438537612795741124963717273593326065380547768578196708046010574823669488232340781667689355939847002297664 + 9059011156256654537948571823030159169978023672567790424242785131594034312912382632898662220373433122635586320057460971136026042 + 4324851680908243245093083193503431558790765585803419091388697495752260988154385332510991556891584925155976792883412406678432776 + 5169890219592441180988843355694784180780002217839745830787310928598719082559628331291213329365294364549008762394123896795514907 + 4029304916499522070046006091292088087865888798317559803991873835903034439822636248876206336683085957754970026069257438125567024 + 5122833726152490145361691490840338977240905109443464507374230617046450541939205551391476680636725777819582830317640677472291259 + 8887879121383290774133008351057610071339235010888965861277804156037797773751958774639837524541250075316907358014661336099985243 + 8039061153806899718406603277773464956989757949717475056088907096202984062415028201715624897091896396812284772715615886727140592 + 0697572299245622972158982736674917157478112408603912440899066443377237594315710291599368603222944799827489902803052151032150505 + 7013603271652485049620063445001242816749693945247727354086779497318820787447165373787134099987577277741625609459410605718145900 + 0792184428093364028147126779227116462983472771162905140500152025984437549037622220978921623538498863508150200422542729027788614 + 4411728159030287378714419332373354590292666051672346415137756916116829485503628039118411108736302251425180386282192968531233608 + 3508034331771430567756401746605566004814192531598982097023747313496871602413228109505959309225451717487757635602112764447022631 + 3428939513944422073187530514913804210377096901814387277664055693937327821063211837805670103207586535472844416128884599982345779 + 3765013258236529201610750246167509469405857415384290132571908547691847116538830356937781623544344792657443940779980096189839626 + 9024565602139835552337325332903285437411134785405743434839219379066510469685518924233636921521087402359934033983973385991471002 + 2649847962568274167726165208946386788572121523811142222528040146116227215917720262618074588389904637062666528544746561556536935 + 2620030538510199023964637151697713281829456055441798954059894139613970616409824903577033806155241943903044175681019965795785283 + 6461188416880024087073825761424480883587286299792763357082205040327994699188993856940062456204962545880583868705703598889787721 + 5944413986797134250694896844973795638537262177510549522817774683727110576630405084332924025735617088037709220742387561124513292 + 1615973751057225002195236737059699517585264539200525680337988614003524501832730480276366257598203042140690301023569755795697899 + 9008200222469601333665860661780983941015300488620597776980944258674129973552734738060885268066420909348372616142102733523433267 + 5003598890783029733738430164315966147920008508177297711130783619606431201578483617231981134136392404255762575061631480099367673 + 4714080230392459893569173674100327560113467502678424574866012722633975629063693151545366570327641280682622355521718987259238801 + 4739385038824895235096103000674296240229268577109938375885209481939108319170129231324096236414336990925757528939018270228944966 + 2361210030668060864499350273214477998565800871680472680681932947260121232176894643185754378295528202618772690219192407686919753 + 5156059412217536746848726448056144396547837914584560922069735882550291341190213498634134528385275982127813806960692781201779053 + 7966885142214723811725348168549783205309168240872140544601559983829401790243561220385975487819401267336194223205730538148703619 + 2086985085185073545036414851529838204481235650803097024838796015231330542654233028002529608154776678617456164886732320375739646 + 0833105952434512974899609076351921948939569136092110228925816092118172001373677700416412487399777738494320581470807407424704877 + 8185614688665309617727123329966574828512583312557787490171669059879359795468437113583190694186011613831079902014081217754134725 + 7131783601536200912167420913195076409694857630710552837087267662216383925992631278943851251589580445676689967886327863559646484 + 9888310805734900531289699098784350167801387862535778038559729898236704661594447329313866535642213694637004811239940871137589762 + 8123715241748226553144892581245052850529932097715696995932059624924557269075540247991049472713937530723957720713793716760718395 + 6093034172460809629440737053209815131819638726936540787299401716655839213840485847609031890782549934060830350478366179240604434 + 6633327894940509763972045245237235718323112502675490128278367355639972323817271838806709048068724517131782516093900913433491465 + 5582353019666679291426183344951264862654895560952921265198755899160545875749490172299073507227437486882523588711701507976499572 + 7489002650231525223980434094738594856401532028510616419177773329613390523750901433006132084090755184848290450781826037290985462 + 0539323854296447671459242043430937704073386171637825236119340677027183609466820564020370547139050173937355911835070350187485451 + 6965582154750741810065288181652685394941853476132562873871859640024361243300296805283748325817168878484565585632754351908511680 + 2886210467566660836736517150078351812871682359935951946868379376912994012664524203941072154686353570579681603704825530456774626 + 9665362335544365210262820037867343620764616695075643840510926473275049084133707571284177399685539645626628023165977084111958392 + 0177820463043321585863992470028736425683626513381632161117010851699245594406701811450201210813697392240877275493182279748367019 + 7250981623715632368538564967386387747576695271655268440119068242579103997269027655460321699463398768768277613166901925556040578 + 2730921762116366900155596821064099866827590787028023864778747307107976624095851829841563684215591447795700215410952638220148923 + 8642501753068607515960160175361362264643558443610150876742595480796702902130477857992388072241713968623856298400849938588555032 + 1187308644994319305723690746675187962892871980887310999328792568364489164541385679772588717510375815217942384186220430941913143 + 7605854751867100384861067666196612302899049367936234596159545293447341885894031370313641111815396044152641244256403303821921174 + 8006560725678932454993887223171401960145271946857211912769628951507047840598467703395747670926287903550867839502877316151413748 + 5747061868485506527664044246509977629632520838572005928929416857628593497937173916677705472302579778727680532363758751491026938 + 3023153622006915734476058970896478596388304728569523091701672491484313935627044876208043141561946195882862365574965158147452289 + 8540852691422877019070250316861163162391778272197273383387116022030059687803664857766804536240988573448290819394431972776651275 + 9021443311810736715901066501558981319880316837771114344162148017989800388690774710489918382047318311988709068050500771418272212 + 7599513906333939122554708100671399521304710290565461919067937465641955962609388316053120501043224440969693966990639899533003437 + 3190313864768728595063193176469208637792413542897116168001394022157595453909893711585707042678368387735204900683732630413423309 + 6043003917729256108805619361421477310316625655437814740309514638761344462517487426501249646525209961899684542352037279524879981 + 6813035487710494491438894246146083397270552071559892438473910394670225142289451782904407545380437720612171136664498766583513111 + 5704425501897608539934816199146825064755643795555188152948142674213138361295684789361927194878162187162220359319096077044697338 + 1170042273866788055113160203247185045523345121557337349823787766288071325865947069357672811750151752362658390610542086745537803 + 0182650295086344086825098102966797093995388649163271139864646408250278380402342942834021881070263294572807189069134900984272374 + 0906668841731928141540118014775032666661994283184008007242068962044782267000273516374045366478779586459658472979356032532424400 + 9941559950477797261120283165043361871515058911345852440301289987592080477208449029732297262652194811701835630896804400526302181 + 9586422168434769367306983212903836891536506488360440148109923788291834492143450307170521991049310812325101209435949795579328604 + 8845618327364168114007785559410459235882830447965260478796725064238526247677648804067848274177910485949526784938820751326532317 + 2508842138180368207641530038974478572707059622379262380563191970615374835570345785749767510398007047615953484581417608147080414 + 6150921916969845997446844026937752931358496152526223613349123080269156525204842351030887676736715854630790139383298746726376238 + 0031087628812333418550306049252849828620365883770156880965318518371047868891562748685920081560624079882621440888924178323074068 + 8556547813934656680983629186991073869359264408784267940961601835440468005712703124932656473056207782384291231611143830784642169 + 4764006946356475094019331519107580885428818699148255825445877812529420751612646315832517900095651843319599421976422128038327435 + 6209251031135205676846184796239439073588798115331056299413787815047447544760251266043212878984345103105431840273907195809002871 + 3654931993884850780377252970969582655676559449815451929264323578834644743068604576736541418957979028943061560532360261664725787 + 1145330876015831126155307819990268909839073491920596329763420311698726840745194869089228905040694957988171983477254803375572985 + 8257437969668449439729079801079379205727147223003815670652927114347162605507272520770488283403449339977650008075057150876981627 + 8526350745722665602676982911174850303165259851752432760991481586280102205346134401601648981884690319798225175260769925489404224 + 4638271898447020123724423300538195550321048052825314720561544239062181964769986570926083174181155377779882057584541395809301918 + 6106817249634524848855511452769182264081765291797239837907787970553958190403210902425419707216288535844322802242224844682625560 + 0987012833422099095295557450557916850795807069003361331869709388270541973078686998103429124404642889230735965872322730527661759 + 0637705394090134454432592452488278594036085049343720666733736875565892704518648963039960363828210137149300479545174722900885474 + 0438909745910598389431226270312843755719991811348892485728211852221096700168476622881940496574796916264512821293932878797623865 + 5429545451401418793893535526425687987849470147455674595433976709030225358630706349020692453458568350635883987698939555558472630 + 1147145098629672646090540159437091576295858909288901226882948677153091610088843747423989951237804279634707873305141146001310035 + 1453067258355914230711608884942303119909820139748995292741299997309447939834224950618749891034712331269306844559292626045946290 + 0350632260797112269078999525007760708741928859358707432624911128337604559525225243942115958112015615876335010570860522898738781 + 1402978628312279477469329446037732401120697968328000813953667479029085290308524043626235410022744559135665074491331563473370347 + 9337757755044278436081677756600946862635252212939271849678018763209718297572192696470355304192247185638719953361091249281203364 + 5405880207322161294391822123973103190408090878564615457135856917654118957703067143223083955082019279925860379183853717628861577 + 7799366841975673356259200026023839542055869990618462031135739235438635258865047764693545067810235010528954960166478294307447628 + 2027467028086256924839310527875817129214597755080392073496545377860632428440004957401492609606750537328284161904594401425287572 + 0946928415702129545673169191304792948477302426781915513863540380482590408165885780307409257801864775225156808756934724074392504 + 6885597618942836774284752567772379904321306380471869189416734595292130350179577547119957964477389742383246612250778027835962842 + 8375378564184742787926400597138354486910116541106048723078444753508902260690644823241797242756355368838174606975331846084479482 + 3212968824505986851162688090961261899834237009593445525206396148505570975743205626589129717163778397732428341839974826649188402 + 6250784433605236331523177619946160387836454523224441645894992796160653797716355919979290100324224314406791061386652716371890152 + 4400989435392530316607884601954369502551234892963245103254821300716613610559994576020035792556553491043544497572846045958494663 + 5437689141597501417826982456539318735177994543195003033035189307876601341936559142966278723819207128349590261078232012690448383 + 2240565515565951781099043148895044873938264025267367187036427905278273314523689584565134739736805096906657362307932608184624022 + 3576329018410785775670826940638079688618282322990520892260090365771287681416891560096002562633570097542699787911417555916230717 + 2453291822907103982064112069025122300625453433920178638265846617355201994938801382944512864303440296743023682910689965580508346 + 3275346241221900813564939920509014369583021411699796257800366335780055834288641882272217012847000156622653258224710526325808198 + 1761823047477639207496107226016946214853880512328754599996142453344143869395811453079561049784458849323538032761380820785136205 + 2258773098932947134988484220635633194802789720564239663961212480883691013756304617477696306260192353528126108628749643695576613 + 6833244981505084786837439890389565039428783638198451342774797405426073205683183254178026538685346206428799444442723636136435573 + 9080842459252171303872018490896413638818633597602353810855257937546412235233854346618680040369752485990328489156699457496819504 + 5734956183309699603857071255358660306282081929816419207249476965467352584050195709593369245076183392383809049796820142290983389 + 0663950400843838925251438784404925348605007257769726864605575147487057019983649102686292523010863667700171976798290888401737766 + 3133554911232814826547253321321519762370231796859406653514455605268584403622162920523841843001241629651167179835787795168834729 + 9915875102181929094696545619337694209374642713183714372607433054204210229685880508097695696888633628128273726076768020385810595 + 2987095117021662238907432053186678763052465613665295736124815230360572136345177452861949998291445717212884676001873754746660396 + 2589155650613427623626563286829473395485125944790254164155482476888221798281733050713864337019212875437294907722695910181965531 + 8195108479458493218118347693154287549401864008165971140576262020179031350059154171267408221692360825699802778787719114529741055 + 2994227854778559135194271668156980433699910463754412118741685322605625614010496732911474348010716497147621915462772990056635740 + 9885103937597375812527288674502022238204092589207503781840088970784707532373479354579114899440649532568358342845263798451171893 + 1120400390759648596081862269355864764100400822617213332109125827310532445408926542692499006220714769552811438530408840934868695 + 9637352403752939344901814991765254063329438135234927589317161742716459240954818619945185528105201605559036407476820639345279573 + 0967725725520221343652248725994878515580037117626550685849684690414565200284452932891511103030564811419601323232328459974123969 + 5151667166514928638097099027082126182546856178488195923185506331245117707219875304117100373941938587261574361349595466933901648 + 3122056019614029244775838489907181693402454194031630939340884628769127341314464687448572665248434305566402372170442289658220344 + 7261444332642187051262725693834547125915901896179000263992637439997458766108204237403853459573909864356641282495892771557042023 + 6977452997091657310159593635773017261586291897746068707373152247429150821576531204588421265308077483457611680883539505380780214 + 3922860418447742388907173493206552834918162458673611316176697519544920126038326376534410690399328547067085820148163398020288911 + 4131844303372153660043567296613439825919900174540571926796003444468128320273120297033737036976412016725245066800816469650561843 + 0565592489986925533018758592782811877964316768421296500160427160146511217146432195095933744734673635804950107620352420106654863 + 6645406729317349776240373018557665618972564221260681309297356903494539710063100566543717860365197783559220679304253096607594218 + 8395581134093404449211217585032937525052183907591091053649490577579801329664352206258963567937765723904612138153463659172391420 + 2858367788679710677058155486700833423902690944634848842142528244040019800469662248189870722506296487688337321695524703236140988 + 9562335938642263288699025637860876864417622879634601222106055965060418025394207515941236354344664880329773638937529679471456359 + 3869629127425084307826072099872319475018151572502025420028453624372211412720817771154291359747053407476074728284771551844057529 + 1190185706672366345077026144989614660307994733718658435474012628808621940611349704306495070342196599139286091306151010932970462 + 9675509101851273861946201556462769919002921112388488480221448504521451553534147109710141587683279463216951321945573166307639217 + 6672697005271871616738575015318763914957713525828413258526916822948066768551357315714715932196912191677461856418144576263544333 + 4907150429612203297659855554908990742757537394357200499303314336795187732766056993269698914296065846201908473023132752908744956 + 6150083396086150456609926582054844276634569272470435640456573226419822868710777542210573165448531019738194685407995076708226492 + 2678786284405544977160356904372320894983311525398796027674382539921414318300162458602130818377816924569056780073177178248997811 + 1585303840969268907598807940355932272770894001504038659615940425154386157294260258784536698627961267225191113300660353374029144 + 4866449090853757246935294981633041248861600653432843768265539085865624263955878975774708775312072236190746445124355521953038339 + 0619885412382828558999175920193016334591402367369763220140054897008235791975355396141026004273210423619062237213937060537525842 + 8976484958039104695613723977251336268561215466702146950426183444969792826975925369611735319989524615202694816932040830397174311 + 9564951821673710247264553143623225237946783695563652359502341538660577772441234930760198015851060420035149363908475167289811549 + 6152784468367404157734119802017549287296220448855141063864170092034156049229526992205564211402819767239639089903951267480899195 + 1084349314003385023967647400823528491190700765335630550586981662116778098851626565057148602128362406840285312235675524872617927 + 5940674859942896006453306875133525569054425493267698876245403823203215376527985578976643008721792339745957322665402353157011446 + 1029563432263058113381593903721587363928336506888785654392441615160711392515188910321841843403492466442469739247826795396883496 + 7172639941661127457144015058984534581536740542737103665437103773621233103380626067034160263026558390443198760839727420004712631 + 9914873013707039718441199896815680469326923849342274027255430706708553663676894461369886145860075954707988128252410758852549672 + 1551922530995012072301491677655182006822391780785787705916872826260151900149221019724939267128249948853451126842232399605725462 + 6980483373104508461112547210954800274259585332622017453698311994963928004018795768275261593898964198667538969022507330787533788 + 8940619208645823836214853361748146283829606466502798396069751370937123229891589445495370452889766339397264192786388083894708555 + 7956574006856378561036342289467521536334236359576203113726730817643632648603038458281607027513534064039819509732524551295593096 + 5939647576077639500586029620496592494701352335060993013958711501324112331829653462612315976140447947573865479895456805542744172 + 8296423959232512165579460974983453693457497491285869113279013506974543084139634238126476293873284263151589338438860044240330996 + 3782355276288558083473518137834514003242038994143031796041577911531844210313799581374155317783854201414730465792201716701206550 + 7105406465035531748842630956573813909293101829709167100331101814849787778408887961527614275809837033921260676349397115972110690 + 9643615107680266865840715334731751157919061855580521203957602157773380969437003086918579100512932764454793288187949797876169125 + 3320437252833110321043772044039248321368660878095814104499448998676046985620748260108371162632325229365624907230743947154301806 + 3552088981131531046172808385452694435204741530370783735986679874877536428004908486014008409001068550950540888673128998784481805 + 7440503329453373467657006789991046671852958451887155184801369224781302834630349870843861530093008719949904514151022786314021716 + 2709390621195321800279652002200952192418979261420927427122958490897500556999549527116421814590121223682055231817153659082402135 + 8861992826208042869383343763880314283402643395875744203109296333659792215641368608715044344315779183133340656043459727198349780 + 2734853139703811794155039071217208536677070354393864907407146911703003457454092806351920281851834356124440898064979131802059323 + 1762234053491518617088128044036706357776327020285634889111113700954005526394521483443227952188980642686375398780347144135711592 + 4027397751732022026309364751091606371427768246571192961054471672221120559486812200168063013361795376094462318094221786026438363 + 0392038021743121561693528064882454352142444617962196680006981383051817202169379782864384242280286939946138589599414498933359730 + 0182070858522164858867574874421689046928982559988292189961850204180007351631664423841067686122468503764793368632417463823286265 + 0700191191614031195459835157848968083002627564348814468750050055060620960050671214092145749062318287857521361265309131257106421 + 0309993332034066779054757057884677047198784197094514566927373158826040214788501636945490789604082561095662632988383214277496388 + 8146430655840989789550968117320096504739356599535135443521661785643633703575650679430439992282453217709233862686803968241138826 + 7498984628272507825242938050646337866580174070972879570659031107873223367860364402212183428942145402115290592836227443279445979 + 6978276114539892419020829624768340474210713091442435775100177879638010349673639613552216581396012901447719087628078745824194120 + 8522095336564609176473140966826492093656451125709888847406519188859548795021576488451306844892007565711047730272408121668647900 + 8524767921694471514347227180326839537161579546977834075174921433329341884828393393398191832645952423890037661848882505051151043 + 2944580067530192277404349067174032715610611074091485944569506105415953050308842454649185132382815370040650599793085560858695708 + 1141032332340176333446374984947231196716478639118202128308413932621313966803046203929215874583358851861354789012133869833074749 + 9480985593249065406361871874582636508161948209786505592954264261087303579799611153927773325602584185048591266936288024303976476 + 7322835259534879703369663910307964057121123765236316839734559189401161415410496300232441653039670294405632163031483814775087095 + 7887660928641822340331849719497888363217187995951806289777062854449559129016492535377000453799053164705981391283757823729876400 + 6020813393115291018308864451756852473844549771230553274019875173525511163873500444811237248088951714603052752360262642567865853 + 6201967072308522428055969416019910663232530141827188975690227560728650829855364963013282370083361622353100870401742620986225707 + 2869802657723987122733883328526226736949680510879014974422147235169606191520933028844627505009715152702759247026991603640320467 + 4241131697918560404418795016499808486429648304834823604182336854359989655705275261891160035233666029073733408580774645759107173 + 6464198087662041784095710258475229347049766003901523983606673438365749432588484287371422883288614656304912471987516429205303532 + 2029089639113957845701115097046043607676790299218866434022020078360708383436488957906770062559366765186955585351813372430895635 + 6464504289920784076224333417714908863182256990967502428628619515039237321418833968508382684390570422398059844256244914931448759 + 6529784435502409492045275382927262616866859838773431100600230894559679830532230924353989524323228472158682810144077054469603044 + 1378563204070129032409938042343154208174485755861395799608824865872543930138962034925792279431758568493941395394754047686715676 + 8867499345143102872671197738475892292486346568581939250404454964808538362896520373387072413955104371842316500056740851235207639 + 2274346030168140429762079586632175197653839654847793978202115595048824365507532766797058257757822432716594523867292474757570615 + 8116418268033688475580223253494948603537184329744599083311334953737050247127839879240255833527455107807664847505065047983484396 + 2629458032033571400314592548790506246485500676837502841162113579334258598171571921210523629971864377357109335285657941548264619 + 0524276024669364832317266608416143775893545796330992023551256594493130557067547024156422646526989759981543218213803553279470269 + 7049845656048970965053022592938828183548869262256486091586477018991837255857719144475359084653581143521408001578287580561915936 + 9529610539570129132154472887914287431871889778678946943105713104741010716248000242330469610192173796870030679714772937881344366 + 0545264556901297919417188117578751509627881737016436472816406518703771084849520268761391513510275790321817000658619656930708957 + 1126630442325657535785952978581421903165028332745161812379117711348541046986438165712940213350699237254925482467553006850919218 + 5721411832634196862603413999653849373180502518946059378586343176647830400545625593156677745062236816423794840646924829283523696 + 9566889818345214089079695756528442838502922581513940730675014653702918250796815796276266282500947845827720283326159797147319082 + 9317560741024728849503640154852784294588264197172188120649331980986731376355567665746330692183280397742589194244588569542845631 + 3577828329965372354724624706136258680035391223875847298805321085928193394693686066077198681054782793606636920380474314204706128 + 3316822771568615892652610314018713244424614540516258058981790879447066097870072989300359291800915299516058342141748356513095635 + 5061676595203394978368391202469283356586340799916518917181619890218937093078654617621002548811013022192072875054917226111499567 + 2293159175827100175340065081112035701753220885751903235819929349733241991099088182499008327172200193308932710369190557345577793 + 7287877879088510408061450710486988984638957628372307246581657037353807145126249736162916823230146250853818942298633104586163230 + 7832024984477944259180948598164959684871867948848537597567339850852013498502229835859692193114794153895539003144519694217709429 + 8852158774260606249546637223424939759148603134570091996953512424441839401422606873114052812717989308319825300637980593162367504 + 4443868737007280155976070920335648272365458102007219456742917706885599061474160397874769568586074099945991122357965710810304405 + 6905794745598083595623675442819199614676323588131811003338385631872023890221085694977414242799825541355735846812034684719203047 + 0457011399186690441251124301781521567240706876614307067167646882762698974983127872249705063133235031055532098528898796399551640 + 9652581539551646223682272835407450811885069347498654352393131589816331647166209087054200913809824196442611900896852634745826036 + 6159069172552131589074592658415752799244670288018595097465086916954714517572062029793973193555030320732773860687445556056374048 + 5349001165930930982732148212936887040004758525708856986464739067246746909509060364496603927468208068059374896651091078566710130 + 6254982141720413268677308357696628123925721390150502950572640806864637896561429156063059840807574455370484872143372214422469569 + 2175489787129382942852202790241971823638922108920609980574885762787573196139571654120370722438096597478384547338469999448759583 + 5779677161907195059713244890541696081649739347821725617254499816041573948157136918495996244811587574062062152794567408848302587 + 2529817818204143798110200493373689828340608796471631850589769739013205825657411890682974212480864416875107897957894840172709126 + 8663943826538718474564967927014748693701498556781723819074861406711142155938775092841806948205850959520646877840367557220520678 + 7792447422465445177106699668289442956655097062959653482152033676820332098951332376110889269353539366684304599313150351375802284 + 0121046685822850120961765570267263832452267770816505513149214924261156051159905321694021977473033018289683251782668439030324894 + 8869657128937432079954235872959567283205921860119040052090516147170061627077989260167387744379514761600478703309504193576305611 + 5381561915778733491108127139487324618000049052071735127115368151009776782599438434551832876965146125033956869670863387976299721 + 0949362683385697791271115461446907297573048650262795825751967646029677499691298037462050809938530416641818484223928338242122429 + 9766820839983470977275951789763019956067562051439591397901411073621068841669094149499180916451056538781312613407170881646764399 + 6524347269748594984863393554929474287488214701192085748591350202439606866037583191335302568028741994749726846505035406608976877 + 2807315518903493816008029815670675803410749049697801438415798820359073479308467800153777926573033244523898966885887408576598556 + 2253435971693966005243248611373406144205306206628977772254035623423592393288603285157497164481644751059433660694427679833172764 + 2802621839144263944769655055452576122669485060013276462140874654840615169333830556593045220363613387004343762888697682047116295 + 6079893975072940528060570984236651746363761678873252309931727588216926947288076839743652207728678149523270862367475616321714661 + 6924992946415404337508448250054422067066309322273329866764351438985216249046429085623842949432537700067268248539671410894502789 + 8240333706088312915806196572306355577223650119535205051323962302240268709606481125217437426747720173549677961990418013172593155 + 6781963827534077258276934309689853954408488415498885594714929736965951139633336078246485722224486449322009472875775669311469575 + 9358007010281073437748629060353526682504603164238126641900438090676758229061250503441387135871208008336678965627603224246244049 + 5356708068957856933330346985639541006539430131114293957097055267024756313531830324556261486697384925986987181884646073628504968 + 6088781492829096627570053299366443750840538654491246720498646497885473443660031433479078885663560146413659899024021823265546612 + 4698755327188359177076358836200498034389012684305157808211750883923932482111066086636126223845187785757048164121301047675382008 + 4187475464845783395113764420886751702440050366103999318308171948006157647282740757274766917041519563322385269555023048099709528 + 0571195389552617367126852668538451980401879674162973150705011024259186076369903231002763667511763488135226006543931654677750804 + 0619275562362999032336486727097255819748979447931027384044606019902431591438640635467977566427621673095319535200747603235302696 + 4867604449981342383768009732025809614182230646572537976384930951101533738349930256172344711040076994914315737263468451025930022 + 9527865696943210023342715736597334765710291291516121893348495349788313734498145749015674214471321122949483123539062028956769641 + 9765176523721839937410174251025970316488964877877371126040698433360574265827174483074565633308845572364434646203497713132542776 + 7378651477723436227947997821691317672343016210083663443777377182287912898006288444888091959123188074922030160615537818420033213 + 8447189492947088531974966589067358589089364485475991918412867217338548681050492469752464750298772894247076136639226285280041834 + 5454360318746876235873485912565983134779435530640178745325450114100396790737296942281564432762776663339965033474759509011312252 + 1273643557029602462258772262515086262035743506025601400592823850215645680844288819770466248021756708616474262140257830085882080 + 3749316335624058049683001015861489646556394155367973498744773935515065243970160613827515488862189910777219950612111041830333142 + 8451480666232257772267491027370674681436846933893722515862731717525412660342458091112720313220482317659721562206466780128741773 + 6590252632454850440238194247507400433748088629955607174486085725118788995595732312569896819608944355538496441101640124949497789 + 1257684894384392174484251124503854845960148691603301944875996738800826596693185375085047729958430171553740436704869195063748372 + 5735178593590752060263331193146970071579446804835972630866651058153595857973419849597143669821080829676089777998056446703836684 + 9360907310859244502541304513473974522087020370096397612021384703925636952795854616525882877878108950663963286923299046586524224 + 4736748114460524678435616682271235781989815828869520783049700875658488695718736121600271316948975177628944650186309894116256839 + 0122265134749874764508072046641714144031116931952372994620287753392883858943809994533079487667165865233880719017940897178306317 + 7314139776044966808676160030164847624119585864721750026892048897546015469276703858536945215709271741054424782569701147500084232 + 7758065860697872155705967293772173137656465001477901257876428931468366029449777184812467116641975319314916341175480998066511678 + 8213787357873005347083763974187729721493820664650580516006337664286359010259386041876040802392491656717630783835571533641496104 + 1539726264552952565436503783866624559510200362458151625173082533487696535010112807775556729174429917223668593210128877186508887 + 8321470309679685999475535888469479559195982218922599887296055650137375133750432460874145869352229391171673429325865805622380834 + 2056541359048531447828515960692963929079449940672170706409337197174760052966541653050946881379320800572898168412293068662723053 + 6860373992960297640329729816572073853997874011764757398797944036292846733897735820446934726176024024757470895603256455220029335 + 4569926110072668348278664329257941057438032693980297647417188505086076585913708391932628924011735966680243663432137597450444007 + 4011230494392556854932236273332089389934747612548401261998294903567663125297736568382740395489945640372131150054623072337132335 + 6844595318925439547616931848005923901307170686601327728283791660587722758968622818978597514280133292570491476960507397213932185 + 3642313707941792113315508020910489195204450745180517492522873324890987317406946100562361363175345008151634614618218325839525506 + 2427692898230648928178646301964171781644216637535917410571457842164951317391990752953058484915364895813865613835337731245388877 + 7010431184482412816244666073504621100130866578971286677458525711336280431605171233723698610913008947422033976946085031938114793 + 0877515916454772093488878527862660314336276524158489551235818954456016892617227185085470522620693855915519816376238143161430319 + 8799443736799287358483938545063592502641553678820618531061987381595925735003006045937462381053795139314188939327005235192961861 + 6759340733723316487592044207138087167698990178309899096979902164464364089126370344350744470572331313727851480014896363857798812 + 7052560097987652474276867365814450520379120040581256992867022098643876725081745248682691582583629292763400638018100065591005268 + 3106774405492401515494177672517042073837303505772295474776502959089196445416987270369786947855131616223965006450641692994332025 + 5855582574286277020845503779828089079164761761910842413066849248818854888626393445367304058754822066188520015897444131019700263 + 9198472044843711981048071735258326011544302082682349755642269651044020224003915379747598044212429909878394016016714106491656407 + 7815377808589332772544290119723706266101079820396212755543706404343739006942558946534655221133089320660150834947988585978442816 + 5845893139549225714132593150193123229669033684893833205775336633241518807901847649594321897137880458298454663559120194776464523 + 0400879116612606005027575801357996533825782630360057558670923510328348895013335023158934967383007297478557740608358705255176983 + 7266683495403368714481550525556638200455893453737443660389337826017810731088543589057015038655883579293647540385262180527785917 + 9515154749550773405200793344557941722519749405852747512969927332977178984307036495472318127241347248808326472175619457986406723 + 9518368191888409210468669956186116750302181387390597344128917877355951593149853095697850106850745402883068932235000062455347402 + 6771238670568019918070196745624606843885430053371888544619960477580892136283363206743364325496202732003423537704812210825777485 + 6482929731992099113054720411204927077100453390882438863808021020983016716953161187024589380636187873278841457216002930842647147 + 9086580408882584727439595283961649388079282398490521121307077379799427026353954996467076132654318458754445407020982965846766574 + 9211933498567658239813690464315557516873798138696846826984940696375072209871675004339676866312551085733908702422475770451671522 + 8116601759554721517887607233127079564923984623323605008410478991117346586220447102577578587384958136197341044972808673740184098 + 7135146663669772129679997894669791690347234150535985440597324857772792781041329129123706810764665585549577867626836104138395091 + 6171338134734949666403237923355751356314985925381428193696582138260452767497882006262979715518886220518431969713213052164146287 + 0631430030464172255146123719714749762611746753803707576735960990848350628824677285326419791772891874510486806367078208015683527 + 9792995724212035781617488647953282247761468865566020082106220151676123008979512284726786406279413459522157229217252165905352918 + 2536766618340462486482122665210247152075138704341907443423031644884751559830028648873890163595496896608683668686938870179657834 + 4207985050934314372862959059606329918091261977012574425026916852113090691158385845006538026326042605485030114114277066770366995 + 0403083121980863784638665369135497943380554934143397132755814677874063414921737247611566476833724738395380308234640207731607371 + 3017035318366003181883008020161130977715784016586015636467061595058652062869875350107267130020471568933409734170464250203156306 + 7978597058687788859694752086622825044743069638461579429486476003366615826282892684888720644513019714307671128574626623134255754 + 3225178060856930853571262377435203804205020419212526191171244624283460959473575918723283729545170705498401123341048944419740415 + 9391613362743685159686501403436221835235931626375947101387495019232220333271032937655938586143908770909065649064710101953494614 + 6134742532053652776330925214492259910738874571044952830222662538392022245336085949987893286559101791675451325204933710093660895 + 3150091954112952712726674404458997796890860249938694466648235513572474974162093062356467502005784802581269257972393197375619808 + 5518818055326965608441276354480052128774778908643152331498791242682676747511171669510551698928872813137576082004507231113018234 + 1869442353797750668263237704646436989107574039444714294394574053634166211680018322567901718394177095139221750525981664718345874 + 6533895638718548550755018968962814261467954303937753456123595613702977896395623181616704065331577434094624992851719491928609615 + 0190398690201868871739512766894228210227318255924906586297140986714101681237768762073978231156784378903908446734627746278198818 + 7031625744207762150055633900029138852849133531239672839021846058540394772383588961074862090538883314417964060795273709151209027 + 9458808924606129446923894166510777560369040702494184195952257501705875876785777050661631817125173124207320372163502777664965913 + 3571992627283246607384090417534713518631913006344389649603958134572814682981286787015904497353080342805307719694940285614675633 + 2468021847965102322233545270789228088801077254585303970545296705237224231512698609584385993582329483075661032700231251161660423 + 0192713398720255736106913269405387578211504390721637672765578917354808072397586108294538148319234789867624965197532780016350565 + 3634551422633123938462201786680417505451646469018713382722643171537409460426340292141021655461958038710203141816197429713424286 + 2547844227738650654059981449340163279595536790994781981453043554676804995664853696521066106987131049223085671186846778658607485 + 8528870512517578936416926762107480564174061090150629794502095506665701012457777925443164598343164919674568006002249856403680494 + 2627259489744462745552373437029184782032929858142986221112288622061305496355657681071521590855144706970497835664724912122006599 + 6545391156443312660152544214378226475642958908136790116192718647739147551525217967757101506789062053773824320749961986081365820 + 9807243716856995753119727006541625638999515827040154011379764506202860312616961954158869599676568905867509226176218277805150630 + 2073942766462908233406965969896132634247796801676354098426177499898295515362604488579021522583028021857262554533983809115858178 + 8347131968232485092731301472083865394183193666260253997648555077371404915951205500140212998582177455804377214724298329527661383 + 1594405101691517143629153539833183982495777310394687166385933138800061962945009756356701243200756906586574077923344666352145020 + 0197245967822981167194710233250484229803417371108743341686105467298388178153158024123847938905011673366872874417478036778662336 + 7258512385396982458981727808434299320938547592708453258132441101938548683407696744955847650770224320115020029123283233005466171 + 5842172497719189784583681309409508840094316855599405125810349460717428156132068389884811129531014665690641559952450142631134435 + 3120882941134196144363251034342986015603525881548802680508329909569735321266175483509995349121263055144465010373367684170785550 + 4158635639323481056067212351252293942485312028596582540399759383658505450921291350114073361212206891492359937785370602986743900 + 3248674367436665982259747983227106329784209726320992248877150489251570771053020539956408865849029873307934125408634817191607873 + 5454247998356721456240658773994350865596498454154991883699218368604475173834985657275975908620474089305230670921518592231403386 + 7351062162946891390363227270397968233004651810177775309863584286429947693132180002624305405957468154601633114090431896806560396 + 8578733043161456354664012245929168398575757646163138337526746639222181428391936995137008559247216584486677942670927998985802859 + 9200314360845834380351667184778736242928721806415925103242410837162869501355174790557366226463713207146043374288777068201363073 + 1884840380691470035098733943006470724355475360919052895346183170077857886208887006329282319454011758272954888828936243319780379 + 5906121108044999002595816055500975401842454091232971454535066145382445630442880279299409925299375855072691591936952415415855608 + 7427547736672177870270669416923472904176994726042270600865769556468182342137641250127961474267696372215125069986572926580684930 + 1283565631209283359581543095011894542058022145233771315616803743285668523226044837411757706026740916352039927306329889089649349 + 4270078841384513763036784211367232205576108266657423596077336951308763566593324577257390215814671195914760219863020884678789417 + 1094797252284852472558752948074017934025826602284347674097641546447667688812462875419412834529814608042996511263599028929742238 + 1967645060681138182820884931078366878249535027007771792225806188604957386423876036386080705880427884926800392921951044407013636 + 3181566611581199324907272529442720663293855144200609139564151757908337725071341353176155541142076746946246524270499526229012582 + 6539374062743440091085243475167651698361455560983223707251591133463685518000037795208788191244350973724875956194617703899137414 + 1430821502040369247348912270128694893351423782952149316135243013570919313886614565161358637079094402119428463930234964822013013 + 2907845492061431274313604396416192334514224786448855288597321564420931438182778758210128537309848899766746069430202195659612336 + 4975634130177816916191624410591783555638901610254745557743055701024321622685828565315892206810167787457147305784539222040470909 + 3426187794037654633853814952285180680406547839298481434679476618025289610702493051123252356926166123963245694601391065308079166 + 1560694708414872555648575097110162943981198563540849019446854403562264846931619983425916923587136273462584821828465235074422917 + 9261979271695865979574032703343588466946379682055875729180379739323087400969273393174411780309814669530363099378105348978942035 + 6060070323917526453062047842877465074776912567111669196792162790002591482979059554932579116312700674668070694919873464603223754 + 1894071532823340571620020715489409265478540234593867913381245139145940908648942949383027523114581382713294341230059675979933347 + 0475001838386962980608799805753326787172142674741106499743819708928855603482127536974433291922816520616537305575646417283646800 + 1407873654137191433607314317494815145886982224527312502679184216570574189580738684704012553837521804108283635888649341886347674 + 0746298331021251518403002440748995086111379224255590828431961727677994867561042572035686044830391992128329363200090117946273786 + 3394767633292754355096521352490384715569381533683416319072637548165685703657478638050012390155682264692286629389917053497837436 + 4659095138863302858042866246863612004771584058240848977405503610643181773657781348444480569875240316081167661626347187543347285 + 7911879124009359945066105568437670726515538210712672838972140937144499494198784053146413298370949806905102557089313540518536047 + 2387001299041180490187017325756798839893484841126540625119691321202951445764540357103908077323391792392357443606419429134662703 + 1311387664343269938420538390428981548672980222893983525849983661962674897972783374663857036358464131799985348402057774789061484 + 8274461005931054626156020913275021215007841002783185917701579638808358640962009486666957046897388731341995785176631521816719220 + 0104967747699292212229371707417874791998945791320492326714053322534677090261456035102963665329391198512545240166335302214953529 + 6438295329258114463806507486440728873144766916788136148990852634546220929994618127547833759089567150425084541257262887419748944 + 0763510822819190844430827630471119922358130707131670435790654181644862502449964467386506947657809851105256327118765427086936245 + 2850131634530202363427136221800593088389014446941597649063703366121196898996686256705732620416208851855006823708510518951595042 + 8751603030878422139220116631069675693727662503215348707642267571256820475012856064445690912370994140681017385311381651837184429 + 8337808674514385942347760110022916345088925240957432454452424792146056100857933925448423669501901023480223134384961261737051238 + 4413770733662528673309544847059059161282542697670213119975814848684886926540572546980353008826625285683672206383376561174283585 + 2470179376522057019705141639334564346002921054122405868536589549939044185327352857788406922050956188186959812914331458433168181 + 2179183768538040087965101925166314083741211822328135691819236749579736222030235331381929418960851621953749706426251383153679388 + 6697638737127992949029219495456980219928837272379992149835670720157263752765848341694925460132961677719444757263352390287952092 + 4093217437367696270862739890376907333913414784572650839225342564140670817115158483271922969611210426005659701735005263854191680 + 0504868284114293941201391805305848644129473248052919285116546768968370400211720819698688057290313111673099410825833594935299522 + 2193387285480585675810105037896679125123370546559641586098343943853768828725430307316784909701983568646060993578149869405653861 + 2934591075689506327550526527978208181872636707486069235044785075612292358262482648814374144402086535106182407978781842722397427 + 3764043018357659628728101790307107498150768318990432916850503907920600389618490690749145152636599605594698036095369786495988258 + 6957155927715716313765479257750780421880426026172174055737331392383266819616843853222801559499877374057106670897236097150948636 + 5427827682310804721340200045877249335498355065518235785095376215323629999016684789788057540796773407165234965827360566567682463 + 0931247633662980846735922260231265500967979148521116776842985570907612389971711829938070907548905323760203422391349321697221760 + 7882789193682587165711403864901445874796286061561018238012019307540878080647271091752229028944021330264150343818926048069144244 + 3829234846305757977743751433953176195429230057570537421684266250781148509555390682508579644164157541082064669789683815095364787 + 7604939164496265670478495045765555257915418238903189606069500034604107925625520169975834751123093859423683572718773062691097465 + 9536565688839857043404968751102502068918401627692404156712144798677665827278179931457967293092502383995754188611043728483106278 + 9597088053951878542145390264364113151329590157432302502341917977233379257169202042072712802096599668573120272798291944153363375 + 7607153187541747861933137718609189822023639083176590969309128534131402001720049300131597786926920331444518080594310667529269598 + 1927075329456693896562301483770530596686903351047943440879405951056391325510081534440975417269136288862213745763314617080452571 + 4793088300460286258221203503876214260288694619740795021100096527276740956582412254816142704747725930689538001063488725674114094 + 9964651944235263688993656306565044507502459642744800444126035956827838480470927964887269362894767336619648517065502062761621016 + 6129875810846273188094595526245494198400294797450838878997940481886389039479255372079045644823922532826285987109316717080651452 + 1158870497644577891842220310991400298247186591687353490986090963675370236688750155704648708257105452733670085922368068618952508 + 3951586474153083065442516047977847063483146004542723388081748533379792081337808607910165722930346295608653437371334690508592931 + 1348798137260798951844725481726752185101778730990513125012632961668430932041485231492712161518123487434868038690945449294611190 + 6621726374054578571840509185550584952608718450715584685612358931363303426238432883301985179247942967408291991891183249754595852 + 4638603540391846589823234253913403535906012903538328082937776681713183362324668976651509798060188640593955628086698902190682737 + 1314136004568121579468174164410670114683609747309631647110337083615027244209788221757184880343776037559026360829925134683110860 + 2743916110589248861852284646250771021137678508599837301158835778690463663553082493519868901155377573114305779992715972859595723 + 2324106156194950900453760356879741607730365869344607490682695136931314492042609961479060353962654666877592314030242319785217157 + 7037168535189901999950898708785124945709252827963059451445136357835564541820565609455192709322939082485154440865255543678569770 + 9896528396971770400160528156211153078421941311469208430939294234515837583618887123400678449175339595403746664662044325400329517 + 8261684885541466594581605303831216257932122772017718190045767780517645346911853652853978624682959833140344555022435113362676062 + 7591075563360347900183625940068873872381827943795851765368024187038497412028598183964746465300474453614206176090307713158346489 + 3374371123832409332000144159517441149498304308931146086397279524284139118811410468196667079250510555507523645907234786379143531 + 0501327353064942573752656984727083020738199901757943687656464477159443799349546909245912076525128236088399431523118269843367482 + 8613396151458427790408589367894556692924575676708650976493092298687011565830641071449135943255849354462437020422889320020232241 + 9743887743932345248629409670762729564753828800124861494449000192569258881214737190612239921652995520457700328791744959299446113 + 7181302058928852380763877100101757115044093853940723929209952955676211472249441292704903663335543383186649963257659728968301134 + 0388255348661563721653151594456333702528830265445870529546222473972548233646402200780627751622560467191291529956825231887562559 + 3526669851709736895997935055319638614407522325558293993145073133898821442020970359820377176459127571138998803488194418913023474 + 8960318055715147737928173496291103297340011637615159200331936657806625012838282253984371770704650788787874077528191805071976481 + 7124181681951361717176138891836878456339953961111533220751215226320942283255447821785246102801554680118941275936544271258524058 + 6005709566240667298294089625210827175355499791073268532752944587487068732200218887976443970173147332812756704491687536620579417 + 8523733324824779870890616722944885692254782796148238417811553337420218355790067774624307813310722411932853894530043351212104621 + 4208314480849782328920489549263981924145677154566910149000272410262683233827903445768177081248117495913152923052663893776265183 + 9942787773857699223811513925994334863462094677096830079955240744467436994912827703793978101340756041298804409547081408298801222 + 9436460738640015479585458718857778968516432654013043215917075749663128588920464616671554576564466134592276012302780087016944245 + 5682263919237157166619832653999221365676490237394196490562353201595416072759662040168607378605240879904649331264075658653944374 + 3188760460625654041085468641256306887215807672289682883500357801180231951265973876967365453175824452139544361480252271534860563 + 3489612971636788170285039991175495323686795856259626029428439316305263410995491370010061781397716962628385590075791887118786041 + 5311327330508694662530309261695611418858308192623059112240071130884198746415297821301302430358551661316850076909001762997643991 + 7081644935973288072050639441580584025029531691351232277986672643518925684337072256344249262810387549624475090299911463668556533 + 2269997305729536278296569991307939885225827949212711278683260974334694618965859001446604029046584493463719653785353337281283459 + 5669018591396191702482439366148219818778884802332484502882028894694251543216632761518648364549018220678109701293026473478656784 + 5216611642715035439533559692613121139357309471021194983124318134640525984115565217254793009252347891534891058775512107043759248 + 2075136627102497321632846769129196363043810766007725332614332304423370092169449259610020916402169233919813196199842388493441962 + 5246508710864902175515674209765293421695856922741891032048768583212886538286815573096956696932708558353574597425799726517739782 + 8036312671737074585001040104552777443725646270711497123342871845885341214930320018750607319709014145767035316932229927380726251 + 0928548556204438876091471205246192546298228533150898999146677973522875037893164503792472130409496157160476844265385841682474739 + 9233703771903675834839283547585483443926383504808637869079921199402511859863654798938168359018632590649252624952570683979540091 + 1817221547279336881324191918747916105439761395909101897519754743532665651720607836479601826466707285601138161807075561528644357 + 6507813758533570073431536118758351858756886547831285242021547001802317103965340085013359438004591048652288218222633904693766526 + 5939230267672950104631374960137514687520839197558900123956846637455545802654473302741665702939840951606373658402834814254928601 + 8899091999774572904211301414279903590789989799671058329810205159495566404297154849221520843334449344645035156970528552300030222 + 6795649886498390391442973828383660673784035290138239807079635557460618362207456840361649348840778636144683493328779008559160150 + 2312967328418841937893181097506584921132253955130661944022425054340098558673444397656011485902801524597729549862183491017801616 + 8364392130149044788968141245875416756772094094121947877022476352773253705820364822300001844264751712000950605882778006252697459 + 3173455702957684349309232875767407323242741753471239292204928826580888927330167241766284958168551480352850879501139241966892452 + 3677753858072439789438100033278254013052115660199724677408997086225534466921024361672151595117485386004966423349406051295735713 + 1033555069901179500855772626876468463729168610634688507726870943003645664213844575844814874933857419440136881531279514876328051 + 6902431911053955232595350941009434993084829394137562877137241909400659809326832785642273291709998822359902244140526746390924526 + 3598394230231172238038637497155035177663453584383356974229908339909881383831792443286626244348781344679035766390554002582686748 + 1986522033280153369322100953745103819643767567342601672718065640720320991063977205827436045236651592119137181084201370425284749 + 6005671239600468501156161076186950720461257574394357624099400895752471978287422522141370855745760936595412914180235254380961690 + 1248432656688783102677099988123915947205672369413239452092262942922895352363751338938332396260328925306803441684111264080959934 + 7043361968005295354938534781857472787124249512274641194624952254981027355960086055922235901916884500390183949326239914435749876 + 5900769760705257904732141569222453308536443186947518812790214535222294555869866712002026766787105689583023017833746154510155688 + 5602689240796761919744677404697558271913792067417789140292202440216539736230658588620970781000844620550456371994946471279052637 + 6983815257060123566373254198705908764725007305820906210985164414734561111049679088421536404461082246253221142258100082860407483 + 9787291977224975917546280204714841440857941451156318425600052380180319358748436390813045531423344721155836168161085909646309385 + 4242317405737007113338681399774018133792533519976132559943781717607228562711266632582303687475696334211416518106220430942562440 + 8001103370755032373531777436355301854609759653124445242732075706459884158212645376386153155459030396899392086527430085304137547 + 7061352207839212087427452963168038388774060848015551117972221521512460122751953993512403134647980990954916284061921026824432536 + 2639034110356917513777636397443311536328136804898636889890450733741495575783711662670202058347655591164148410498512181752116112 + 8649347704311634713230582416874077536749261618798919119607870454970552954421518115988625118329175121493449500857931770229652333 + 7998158841528743978260913418602919615786831528127648656825638874370061930628233997562266898051264651939263641927874506380487439 + 1169319905978231587648398211672101766334393172127691275996797499245406750863796639040056909542250284633880406494091612313210866 + 0317572128063301907416088057966656497607301508200217804677889135103287897506118599601843251561058377858126583470533794642274814 + 4690147674695890988264540020570125563698789420115878750835681272646540842126992805764557197985389253255527910197264650144295636 + 5798557941192958990661384529989091262630978788566879170732007097819131006336590152363030155153413704404260928053167322809868601 + 6850987001199817141644762090308087270676753863496477045191783385382914059759989907264265980509298271071343239640773196627310409 + 4389027546704283892663222266104915372633460042956234973983464977451929104395584092104280081159181521725125037452942372440981206 + 6675905477554320026243055974304148345728455542853879050278442548087322107774875373656985055242105650999387599625064478196226162 + 5421451962648003632206646262643905337837657920982111146977004270602922886008501562566012949545116457517171981566495094457953170 + 2653749527617823956383177123455781619052217065408026747322738616321944929384445431993242259268884094539560852964142946672208945 + 8593461023191475746268918563613277494098559522521079968069246435865433845367704112809898386514701303501214965468624316127309978 + 1864190494247307693037266993358200097794635502447995520938928657994547718890764619887745240985736437934807473704761456024575292 + 4959121097171972205063831718099245216438006228886790229146916547085014590026042332430672777678300137100806650898573540666242384 + 3655898393459642632004541036291612193425851747783279795401104056847304510228417238922574433467131806129145867390315264166063875 + 3665579208506648402815517926487551967245716952452342336509872884242496327353828450388024010049265610889985970803926589219237453 + 1676400095916770050334175293677803863116549153471866784271105726012628596876429530293900006500470621643237024986843048814960581 + 6303887230138382981362522022235864197895867379102358980372057655831897690287262572451017096062107356032913949946624176978299116 + 5005151176823509060156202781958197462286719252108370751542425598689093613819219880986961622340717811406826396835254749852492414 + 9810879199072089316354376552239141698257935918222963398002559226752773027118660428719265494441568442234264661966547139854597318 + 7873099218250455002270603753696336287379126088262705830929170584620542532170428705348694262962278699570554235741942919271113853 + 0853097378201921331418681617335834926523454159799372408812168044016229123296540289846574743942294543985242874224122532498334672 + 1490594866688679908867416614545427520723745911612132408696699789261886952468259502210832466240663473598353736119026236378375966 + 7870513434223037902717553793135590258545562641705185546860782749440609431080399391577848963291799745623426666134231053217546405 + 9446201870461219368892707181895875357863356844636097852807754420432074309846001997057609966109454410826649254380546761753175861 + 2761057480832813584246237846523502525922933474798627724801784019360724008460215340269094831023982649184534291701279975122991786 + 6747259709148196213568727070749193520741364779274424639307959421349714799461578583982498969579857164144199424813392167578660320 + 2903178417498559526330742642780679790900780361831699904848420604973586382034364851787093357442413598696765925470890327590522104 + 1850819839601928427102795504066478105300817488452603819717168073205087377109510653761519361878295067555599575161123548496116519 + 4527800014440544203257680309603709183834604758224679743597378438522340853371773245388147497516647805604078269186299047096706230 + 6498133304861002880698895980139890714606455707071690798907848409609045542981039802321508092873754941535671659985239738644320953 + 5988405032666743320254142929561597654494413403431947291535930103688912359712380841156852022207805099821357330225186728532082090 + 5547768444839618341918220237864475011631317876613320699268333350020360283617553420136149953194413589978795210753934389762807735 + 1597329107893662665482951708145282526843200385584016605115945831916977370397498490572333755725067314085934032787782477551454989 + 8425608912417288932359069001529317862434139520899814966998471303722622773872512411876898983545914085663888123444680470167948505 + 0434379133165396213883414761877309648582182115178764180968488658223225128338783723464562383576437566308911246233632408447704048 + 9663996367177301008227471941256368607999821009483324708241288407336982656214907935931597532047696000543001055538357367423684843 + 1080054249718909513852149584485289714580193379500564799748250805755830508642143351393106365614646908548224506838553676335276275 + 3599779694595660288226660287150289204263669082115248096828431008225170485272045909181946378454893228880239576553739907190878426 + 5885850036699891408378122906193395367309415591691241926759692588330412581784093438940668271882079466692153184239937668982303474 + 7878175454828248795271539884473981581982185106585811627218428403581816331240364769920118073711196193240357920319448764087086718 + 9383157433735677366088538314691739001878394272868474296524756761536638899101995873845026009993980779305151574599223381548532836 + 3668859832227797331952981131294963911962283005597571432352599223356213488863688452877543275627906341710804574808946808990599277 + 4561238331796792049632393877616772107198692076748218412457533127281687506143050581347703755397549089646358464889763941628738646 + 4287040673613995225940479030356811166110299081667864088662964809883579567473005653984288637714354335572597312336813053771357145 + 7067167172790181728147512916597493867072803164173683458648511730308061884633961295638170464699169569357249648229427546009552241 + 2411562579887913980455816507682929933659712945876292627871263596090842188654178242939374681016381916432972311121058175582055725 + 4171582020877122298082911042822107332503076877376941726903575210668249614607891518640837866322224789915987615341840992350582413 + 4400620040237405249285698955673350511161843009038833792839643496604322064832266848854377214512824709405806535993728236489108631 + 0795420398459113177519012283723869747981824916722015034363766243369266801152099213940570568038081676315926730528271844090048984 + 8736235449371678977947912073661875499227319547901313273871106645387069884378420956151320072268281471236296252518071417869812398 + 7190598905022008877003332225740349664805580192380729307470319849086922459614014566654582713365646665851557294353631593510036953 + 6381552204220558217529826167930690334372579521383903206328505035888174852614555542283456959315756641772011982607288085297853686 + 1349874783384878827773365548625629981523061054390679273761674753812182403462337719746346989770142792526923785272095298042279054 + 8890444037528702976987014556298735324481383261103576223990679497009263015064472090831542516594399577027449370238294863246623636 + 0336415324118608522678012840335823229090847361254516690870558705257294993006716462941193893800422308988102399798523789694443112 + 1923359529945753787122624465725573807149022119989195390997561541611804328914617110055244794800371476974622186846094996027068986 + 6556505900937451676724626863029277508817962303859724405355623034880805936586542708527460464895044273023827975806326940478307069 + 8592969583414428893231495897818982129258755657382413367672348099201190652878055544751096757376276397486791497622706985221853529 + 2908214067134856191896613437551307015999440525676444599333628882928075642102806483213033250837448355509306721853006604031173677 + 5140214739575524129341946985893116412008106149871779041808900801409064849278864166852383463573647719274024968463791254976359299 + 8847571119606652336355242986018768524604507411735194803338041421026584303361841828532589747052208612636774062068296366532983021 + 8655354613872561646045351810915955927958378666435016019460717328781560793954138282423423334855186987151419088975164710160358441 + 0049260799204162100696414303845623303274803491195157588921793903647526766706979672202295037308810197036167390246126788340972486 + 6425819895447745350399433314412535917516434906996482513931003678441923085763619185652238830813722611071936854791527455947241273 + 1522067822697883751451720158852174772439898925807262503934468921130385503850561421474472046621939053613032754307326343494446468 + 0373529669975958588899685583408106767873002561071952257411549791159364132364256139331134266337194556486549929770686277721381623 + 8699593258141567800940600698126100601323395696274203924322395263563919165964829715731584976772134953809087705318959395613991572 + 4912970610760196588068419702343479920035578132234944550622679160245214714573304402887577273891607583288099465093463035431694610 + 3905758432785910691737893861264914959634002377051354781210095863851654985098474884630562136246052330525659496807184083910344772 + 6004796506916845030772132724200525430268203485146341239363234592583508467825890468047631822102162429469995405739029446103026786 + 2936254882880449606977442748506803270167246097479977977827447584435796513203817330397221813580364844509174311882193765156654656 + 6587840516915974691152625347076034414185867253449830309514472874859872212804040804281552578684775759016088925401886242253588410 + 2136162082678649695650433358835719979490577896244051036608023014229544782516370023231616157535453095718156293168346470255374077 + 7531511647981041419067438947595659704304601529630424537788677553031920743289991068705064547597248153946867352942473723492529159 + 0056165493810107660174271077633956520600765977621759777545425851195592595759244720831020706108951012298629188421930844092200174 + 6642191140454110070088900972029229475358599582028206307088525106506003848087788102905904900131739063517620939825620312143365317 + 0312737363283798477941966380713988316123472457978241774897278441026567305606285826664686434652740990763564567342068867452842418 + 0562084816143782025599524978888894444210155619376771675521151554796594041637061218094181094152665322539245369886205219847245940 + 0029405789079825038952711651290857359659229927344229997950428696846444420150303484487905236128836752670607196713086924265912777 + 9562937968844743614454574043893713056224816312429825464738549426759328345347674841205841958347360767579803402491577142236137115 + 0533906692397009484027899629862953135204910641799594877569760336943034406380230261140675352675702660262675371335224685084951739 + 1782949915965578201764231201307179274400901440982114344774078855036237671988151622145580473895458193522528339933303018706591388 + 2624100076711766326191346479084275280944607050965314374143191066314104835834695035041295363869510686680641979042639548470149337 + 7092183008459177550878010123635992307868170928762105253223870251579666192277376903965022436031647547645865700232025464698571152 + 3958091554628717576397311569044621708700856680671753736603162545139430701751294444844592994780440200375396353670083705904818899 + 1158314027781793782715830446196630725174972102720930236759032571130842037840584037988906905557214975416804249578167992887315936 + 9206031432141826113994005343808438088835006886050009647865275969654889753018433197685269199002634601456210696285807629459472336 + 4978328489062061200804108082671938204870858983057488740461332416429168822452529945581949038775475758752323372301506063733079805 + 7738055653647518591404108351211994677622659177154884456890162864455435902069510745121823508583748140331565330826498449431014143 + 0674653178829590152076432119041481195951363053106794226287750227106636545367810520707295978843237959311321898828560534345440055 + 8038620990007430479290370430002421271720574168054663731040351369363896772189503927548376910184417619479114290519008175905383545 + 7118330213438952390733597389988833345665275766596109498963112726494459652684601428898616858980054673653547857404417055361966561 + 1587037091185968630608431240360245295772438686943763646925036642543820946055469856983284464996007864493360253900748905383563580 + 8745104358873817076497065734218673552778861792932465886098953358042048623712145278501699290745480384052380874247143800362538370 + 6251997645750683187872814541336341689788360883547457593458471177846675162375769376759272289262293759496680413378317765946726569 + 9307054144320271279835934039640502070988256340708987512314880763049398513262419383032058404111149286657762258132166819869740391 + 6208679111601546062938461491996426928719837110414091479969117767614499297075986816870114797028327349760763930021316392342344670 + 6195338739848107103644806413130142942032473433624064988762100818410644021199176248704887358790343589713845228788844183335779186 + 1206612776301905227273380391656909985775786692526546380296204581461396277505352115889617471623174433491331255641939009226704644 + 2188221413330256108594133828534885890151834345250541767462459786862391647167810214086311680548340646481922395107065550293841987 + 0422053725280997492804556037165046616311376881740818579026242231815216233417949738101116086586716392810175144442461269235250030 + 1446402688506317648015492449267953446562377233978895904366659114613140191253374875252211719488638375761957759777329556920444079 + 4742234209552120961058674900214350131325585573620862943651827639544267432934381233345762116672659741592229252195548093031985971 + 2686838533752676886446680927399440863720061868372851834815109578907201299828776117754439315722227995606329153759209194448678185 + 3375830903591078788002755338696975595441586005976260188707036346541857769978992173498220429575524475532930877665817876092460756 + 9351987353933462923395374235495972847763917223789357531623204700947268441087397398182190787387926517802157283116535834305980686 + 9492332135897364643664989358260446062172464533880475533980243165095186005367740562491795933632109829107385087893207785894397713 + 6433768862702582156901779207532027093153001807004150434114821705300991777142257598550961217676112326241485864463713890885328141 + 4370423630135664116118217486548726531069411489498186055038679029605744527511210064431632487827249384739496221986798075711280160 + 4424010886610887880437216748921409021429656729228727372446155715321241952848523185619209556774687672654909818027324033748491821 + 5647085557243826965464774431484515106691575517669395491646712200606275072075247550415886971532904779039992053369051837694948246 + 4648536696394853995288135284563546131345084094639405448329957974626886591260968153163248670156108903690012016896947562864068947 + 9335817025706673645248672808655206936988229988506868855512246059364735571373658692183981236508753893624162179393300884572562525 + 8454550045708811850843967602772364889207411447386933113146884803720821905371224276398839301167373376393299604166530531671536817 + 9469613971479940226446065344175803391558840869442680476409858979317446638566865770776832153252927434674599753345041690804354354 + 6652209314699751202444785726308628207785053079762876873537555813669271605409315256570040001991644970781331622466129179499281915 + 1961444894849498696928429106294385830964606511500699941607840002024216695044414216800293243595307021832292431154543081449089313 + 1962091622249577961316459709116638715944104552499484128514903058588880092425282180366103208523455810521574844650965568635887113 + 4368421159409460609897114428104781398719260897374658539676968461604386468189383954460163078825080336107872167576349496495408685 + 9649536539795842583228826048018046721092374785553431643665884938389496673231436870435149786802809160883735413992798925929876704 + 5235671264707293479931013726706891341489539237837731840177933783526465474894432047982015526419973235553573918270319559547403086 + 4039735888376366609018757028506161014783678583356813250677778613982578318008203758267120384291005999279443777316382864592311739 + 1217739163779382661260606469702245656794710548611797988738048091846590739807732824364552075368990683393959928284317293320069867 + 4916615035875154768600732328677330949063202236875210951540534956404960395079564144372822026855682749788976197007630147709880516 + 6877745432713411450666647170018266444463633969867263093231179811756276204043142296040101066040921365338143870829243201412736978 + 5181332217031028793650384590762724542630876907198977592730043310368021901782721530053394250577461993296684728562642042745578204 + 8059743569954838104598948856222744875810352375978155248926213114786009876969666524615446586588275065587752809296977777941299366 + 4960623850950107986976011274245247425368704858396317272530283837294761704449561833295704741998045363670811422098828233894939307 + 3391941685834457637274247913999521308752675840541536848418544996656831007389255133631777457133457716285009673478699826403200309 + 4519130151833287959851246691876615538787874185186936205145712978930546123861640155395430711723899715676633532061887829247109590 + 1676546877970973940392277995447472865522499015178996256227821980732651914936762181112328377073844485649563827098289006561421904 + 4935465846415256812459944886042442740776629289289624483798607070666905637221701286036356829140962976615020452048228461943046845 + 5324252244416512745242538847575585469682159371913734134263569496276780441518422322618507872746192259540742513974372774167973337 + 4061947105362693262133270759088934938816594942342421443896871674922874493598103930292152723174036554995062078161445343075609331 + 2764956618470182052214734830103729160245043907968784028181813618886443201986039333396356809943270121754709713915646568740151206 + 3370863211220134665256513439944166456784396566762502427753466744044215577692010267595936563128872570057590311781066772952724628 + 1434093271982951335221748052776429614044261679575670437872151960576974124250079774604982905427771724749469647670243244251475834 + 1955236107353798168181042526280355939682930522521300010742221556820749544725933966041624888393993154502962490618839145486969576 + 6290416028546495661266540757687391083370341491184427521635724821327522535027514382783824919995740288516481937621675853899158115 + 1271233716574270260984632585239413670925887252984501086126979534236923438493445631129740540692858583194337904806381657298903618 + 3300535021488010384891010505876121956740827701335944021678777354223576529240510607458801670448052514469687591418109583216371899 + 3485417441989301906542262637698405742722722240100485896839477201597733807155335120248775000837222824525999750714790729423644465 + 3411348746879651113262757268624543364109755847832677598538228869268434533167862688737780726486206863057323257234642767012961381 + 2165814758833781311422742619981746792464126525574786109619341095871177233773859607236931880493129178559812250332066463408514532 + 7726034975123054527871123751165334996022991283473243555448093241244802428165706217812562663617393968824053366244173854470750856 + 6095264928940472527983481330401867205683258753243162756860090551147348417813873221392674935402798968661528287131244490650915944 + 4846998428123345187768488062434480479219313046695253889842680691405315693254169660178067961065703759896641710892485894972873800 + 1685615608144031413476448920807056587474093195656920132969415782126007882727463216577625078022336565533036012495150175153154793 + 3655761747568001155088833871531145294046756206587264284578974630056937095900549928662096625015556765632408742933996850251895951 + 0111954704076325038375601656210245491836721039674987643056715722213989286056097567862156918863302428121309646750177612394901330 + 8415584072851574023474900634488379027144152280913594573298990276864512420566377677406310761330579752357658832083046689763512425 + 5360991991088493887837058948075647761797269956784924198250160336333432026534756149206974204145691725795668303825556473066440146 + 6308534942697410882776557732300657800112150355078878291669302663342797528117730903433654703116183867380240849386640798032108726 + 1472159005438778436757327262797064431019220263757862409221343714482887707767271424863105342534371712556647665588514796238299461 + 7911386503568215258552458522450938485043355503569972624134133652411157539448177529209200030556438822689089819514432813580599189 + 2365679543813190286281972504483805742897733392239676734466218958339246807222637911353738424980809257547217933600526785327528737 + 8206666715147505843269892459203855284050942439891047557154055608815102510800979065603928242478158845237310517156379667384978425 + 8564365639950704666389094627317673103441553979461958229265682055180735168285879029143428791049454750378104825426147990982959332 + 4829102499976584107337249497306375535937865662615510579219221293219668812136853030161705938471830225621587949094705819774556069 + 5123783679768692703321434015951275136482214434898378095577232958805557078721200098045359198446613744587543829867662788092598136 + 6929950567989350660377223378484336709625123004431484409297585830087971734242391343301362221372782329683381841402343240854937627 + 3027430314645534840941417243615965839776590781088050407903488696621208213787375420065466391992905505392720776395628578270203968 + 5561557545896908531566696290176040220677116087315281719465429326728445015278079287297460019260738872427151255654689514071849986 + 1828538379287013993210377215462458395873947138158932974395044262987261065763556796656318930386507150893214229366028840942649836 + 2063121041445493166725834460800448260568700963104181570946402318291105228818528098805135391601388005156357001178185451101272800 + 3370800872347836800855502143109732296211615709327616533336180819117537969874343031967516246129400847851680499950308763513532698 + 2261251707986576560067694894090522658489287994163408241552992222074332750687259975120713193581210288235466997453538082950570613 + 5547333609592722700682015971929817349283991994515812388316385424977175852402318951978198762120074865379726347089860459367729850 + 0402544338102912384265553136946539662518389179790301064640333604344279296879018653656722109731114774692564467347146643170192535 + 8993673525857276993127971955065805434826324155448624528360859774191561165506877746667502530039089420897916681025323026574636061 + 3901599392791219781553830625484740571991825540511807354859441733493239937466053566374517381465227962291796387571020809725382544 + 7574422026948740113868646418886560822423385797395522913481336942061412395775696211559412859927044430059903817069457531153931671 + 3666927872751409403909634814246127285265889024700225210198280286825210509773750861772507551910169158603017385059974490577083038 + 6432266277247351230987806521470687675699096976848067098507903096237956371518053276015484587153777797643144785970196659271124201 + 8805175031746648720776866745620376390338985825396413633102505797368825729966186841638401277578013322523402620704692665720430906 + 8623786671348700175861755678175427019767971457395145977447813890266721740858466375677681653108760786751356531141090929913781526 + 3195648380237469630693855838585465684458789117617495694729011729035913248141836338293691788762707190185659273515849140203833275 + 0597402941284234251455344083137079916499435796408338558567042346638713911874856299057564768580158647502818908352952487514100356 + 0970868650564875484386825809898953941148685658470222784359891344183429634142985332602653810091182805015332286021467238333362385 + 4744217325804259157671625823323830396696824326946849733799160663706608011805733632306227156863544912264884279245494044730337851 + 0084125575216079610672037870038502647338343776533232876650551512543864312081271558094734273891229896844012952524148474639077490 + 3953838752044271045872553760612072547541462596253868540540395181295139378941954659771594736894686221229277026890071243182491089 + 1570455075037097901528554345355410026197839647129067342374536771901052967778273115724862482455356615889491970844930623438114267 + 1113425143150646440502818701009316634243943336310155606852136330886016200376990719743484314150050963993583980070237708157561869 + 2850497678307680310432965409960545878246397108725852340253836659713228648432015357639072103145170515437738478376685162370275788 + 3326664187179079200022042294919767104163644624649594061308737509813605056856101998334843842071022724849290393928923994480353310 + 5498899160503467457596940573659595416916940383633806231810327042150722695852999362605105557507669885448657908253818192962915295 + 7340742801283937313388827545354690848045358633204829321755059875964474925792234042792682433581007092726558257928146358188938017 + 3788737611929951605093399738060446796551970972956586328702617346062935531918635358396384018139217900704517134300111877098173771 + 6556088236400468643295262663772005261144129747959817416429151644418457406109514416151746327186627985567345268051259611187659664 + 9265455725916581745797982714801820234080260053210177213938914050671185571980281286595729366143889579286214314682943150406601728 + 0316466611292764222191535471075816173597528297677167091929792260801201488249926367457821134968651224754973624583045814966898991 + 7240870813182642979734405654373311183972717838426383954790596720674570866884378092938010438980361304392635321123093916926377699 + 1098769261784660364965755629864526449156402293650490776352458745073647855811975287018649518441512140869999035534937655163547223 + 7318570673563180482204840468935262794048795191854962451038993504158655689641517360974735911839513301305317748540458018312631163 + 0444738341332226086089060414609016104084271113844087095538006211914540457624942221411569773470678982159365460154412977671269730 + 7214452687225977763650799051005862709711542484791447215218763058978813997928801482608042879518784727437915756166238817248827266 + 6180378877242192988083619217841832407955378736448569454941330027911152317402955093457538120111385592095583433817050629741079340 + 5629107620334905196700840557766414405147144002648539402508824797133924214385476958587576623195377053042403089302692454844253984 + 3318554062977863170044352262420619308431178765567333623647941692615442475752129139395428889369180754179899164103774056228855177 + 1724684496632837895268448877487345538070342201067523252247951553639414362390924781555578381060846820725528271757795755177666280 + 3668536899528123873671104403554809934477255454000919778770432207141030247047304569687086172422809626838419879927821205317757198 + 4281376208790055629568334266876725167967493231201019877577819781783383068774238210201096426961674885308966481435486534817275888 + 7577712459257967273487604669410934219901389126865013214764147583539515778668315529487762810385482472159142915583111160208903283 + 2092476036780853093515438486821087167147843243339127524062892009959789660882873649427006559335981769826686296878365166850602867 + 3343172251567689761041900651298644580155321777412234282871319882978374041565615637937824367712999898962026386244164131814440583 + 2523107617535787966332348997625949033914601433430397210697903069041012073594953603672415272693571514416319482962732360550203007 + 2354311337820780136418582226046355285087018441007811818178174630131348892691010862349686382003869512529793089372921566890105315 + 1170999065500729991421364651545352790769082161371433138736113416719659099975772914182032395782369105406892855739430280792570755 + 1474708015575641879072739292610329996968899496702225715923818519908679748009454327877467225863186123383312506444593821059541320 + 2519230317068471671990663024614062738285094805102560284217361596105049865919692357067522503590280759438003713619649669926160819 + 8477593117311192072667283113407927363527106554972169624278711433088640030184820529565097341512033077210672824164404101920707697 + 5928625658638382607550288328629457639763193426953494665267869864411489469568811023649446369996193687172148618677078694284120641 + 1646459774821145583534736023501469753322215654392655710781868598002276354678420510784519315703507997622744075405271188494799548 + 5604976454282399594837769165955324714117059445288436250408738807427315530171196984735484375626981702836635871509821590209332491 + 1535805646302302016352504827863133089568000814854822798689081283591430708834238105002833054643250911507660006657799194089124227 + 5554971708100609197716368094861383459498089313293558900360605415466184945588159656825590482066432370186681671169454435798038380 + 3849073431364569441656271420494005561747519609440641325324675204133825604638188550112139476449622000662627992498117594394096623 + 4191048491581987672722516757004987334900086209495744999112552193520096404679809481469054957100693375905822779214877756331765654 + 3967826927260531495518865955487463010124395050606347758705435971911583515293152693887305102817702226005465633434328368776552721 + 0431488077940753541035965504802229919911746684489825460131664577839381215244988219702491643455403072485117531612606199932108314 + 9410075360076281631174487118204030545727872004911310355915647215932318325233997786962419782803117783722823043531791703707719546 + 9979899286512850189031098302495325193753351855488331350658951722090011555997930787556662797780665452620638874492236108755984250 + 0652520709290586245394513350104966676213533639227604453023649959625928591554435452582297988094318689720723128469217871904823318 + 5154138924950867908591044177967760020371009497593629645137446770819235001454567589699623753759581616298742234368099793781827967 + 3473470305718567484348272233839660441345062709145235638650446308235096448960992127705010353860654270452060145032963280540290644 + 0926811026419214969150491345419181845874142492157134486078145329290631845342202476471135442659122079092431512088292118497802805 + 9354612782399796245605885928858715130206027789349453872862552261402417530015360315458931199778666063128483794096976323329377872 + 9050549362931470711847062862659110650055274307045585443522892077774880073956334195774718662309192081402741882514069042809280212 + 3388599022582995822369209018970901943500870352576118339149315315976479926966165136544818295802570738444044829469770910136539354 + 6564372944547448237407512632251508379320872549342100765184348768929229061655816110427490635344170087149155652249787176557737086 + 9304726910793034348084164624446844756267779275838929154374342302538079381563499255177774157465080422281305646532991405754916981 + 5079495135477953063596578815549589683659295982170939553637877137130071575921564130005951724009912627770427858856970687414583660 + 6190459320672966822341653503087470382689354052580606552329874275327388332913948910878502521194902477705810238260537165258752153 + 1741863988657791139389205030367955495311579034712194218460880036525975053623461402320730996642095747448443229185546281279794016 + 4885628580837209961221029576497258511104739050257941549091025711288015307691459924906488083252587010968968824529177652581775801 + 0763397108119317156892696282929270919177456927168774057189218655020688126030914415663313590555442617356391166888501048989509961 + 5152773773826793584772678203560374056030587370542989568481592013810907285435722199937156448541686535030998055918516459522290076 + 1305239048493423602262076973364789510528152271858803400583562336066393859447415629511735131940444974630579121650398527184965704 + 6991327733592729480669828930382613428226140528036104065114673331048967012900401318314500711300298883332334369070527930012816139 + 3452427216705740390119289172699570798671134046758624232397496740015824965414235594660630239994200610360038450127723765597890208 + 5175730522105055786800808015853823181610779386663930878893825884556056314059074930365519187914921351319328315180621551748091601 + 5714910102916106131414571159732353736678835156815504392107562506650484480968671954066774178137781734638792008562430877641109527 + 5369362810620715036409904025968522864824364325482506902964133711312038294053559282742499233287959154156854383883148516152426070 + 0230923585180985083743915234845529953134912525464096240500757424789301872897111680226897303301395426146920411464973830228585960 + 2828878183082532630135919486366960583430058092282156338048743819662184574743797715878229822611358535700802659064501248149009579 + 8877808967697355352896283886616902601338873980280498803907441157295597934158728665206373488691687917104704283343745205639622462 + 3315755549989540644308207351384163575736340700335343877848915517455194885659684732058284726257857232622941934453881121004726782 + 3002928241602670019659934407449689182082678896433504272332382719662522606641231869982252041696766531509399818750721950486163498 + 7932472000788041651204426873094409270765907861252426634561030946897515784875744395710037381070458145660220907030271894709835605 + 0606375828713960156150750275120802286593052131450659403286977242629895839703700510410871815684746087294738637398861554742127265 + 0927164114710800842124744207418934599056137681039495980981311410777428870205405129624149605463522859752503128770836084491952252 + 2931015631747347657009129018143774038849625686108045440606651923845534431071983109500879593401459457270781303275371634919948465 + 0387570468949867854454498257661547651091256802128345749601432500529628510635061338338862610989893855279059054348321900538486115 + 8602609964344200881430293688135456245345432239342905412584133371544661893209862399991442865006457440325878578391699643241518820 + 0476780634258919055579958686158323045730786320160920071950074973087521728400869220442510810405620758553467843454120670874658001 + 4611389884432116865691971525430161735365815156176932740053507703667082841676421694566703484160697073157865364859324160407900243 + 7848340394578239725877088114075619051748487906575872632940285638137907126466280399912812673908953355586620975122613901023009092 + 9989300098497815617534003740634757576144040056489564419015441642507944260710401355749819839918602861170379515547533183230261689 + 2978159531889967729748526061427217809996789425967856884930963977509421860822261926488518659963801830737928324899351448743506636 + 7739373703546853709971163541284486539624807396328266253157406157316793793115843617866707276779926556010088380028395990807722966 + 5262595518780890084621315703653759393744008415536932695809891522083236025326969192829600448033930003810949789949558452866508165 + 6709958307107045609075677759152351429582355756238261042407300818561928024091909129169346687529817528488405441096301840942497835 + 7939846806218683995681953891663100594898796616302246789629809345268814966245162531052163166438108697094692065750286916247302592 + 6376737923232528630569024819762238692074089057479592609265302063789788269041103846131589957468529143458603367428237467202691677 + 1164704135075482622437354706246898083995113224930951841406301203169957259318901636559771075096487643893444519082342460614778341 + 7571486167299822050740707597065176588093664070641995447134130614103674235649546121137008292829783010870775335672457433796269838 + 0786000364088666248224822824647357946129181563136369891309362023665749511277214956791187825832905762312557124459238096857752088 + 0224756578418586950260891776975306306690545499717256072289157907934175802791666439540405671709869057148319796761025632922961188 + 4317800666800783644393485986576298736917563650897164304571720738720115271226750820847348337143207594067034889090129746637573061 + 4992035733871695023603260755794332051946719932307664611429871720394241080075351265170984927835215008078524349098428854934511014 + 7791275210894880460866040577708447085440157107534047266197077167838868317086743808903866856598023308194718747427381845326367182 + 9440053603247145332820937897067937394376812799936768352012215925676355028026697201409962671443788824047418146714929473243964178 + 4694097429621088759426437344831944205038778311615485599880533035443309753228841592516038076111818420993913946554412796041546011 + 0591550477943256220239415601324460355602248522402154416815822080226505160015237485088369250676462054718340071691237191715854643 + 3754782628510988470286589139121850755775569961153502324797466418949716647077195388880488321524207926209705534645689175931304390 + 4293579894293631845176289384983754244067774813502510037057302019611329180738850594681778906215406264239719011424001198377631320 + 9407877792875650325539404181214900230679005444970369243950847777718535539213759142124477926938032002586130641694624396314012506 + 2378295522687601357905408069624354294555654221781438340067666919648970200524898545019520189688682193849864964964428853699551465 + 7923565501350073769051751525297874085786148453411032926127268603914648170142127584914619282268063761170983684501064629044484389 + 9840829700300902841805899697228329095218443610475399628627070805326825976451593789370050027841655892248443960659103428515769018 + 7131899325280315528312838930296738263099442057104969325259438333829573217299432626262718217616786664813337230788868035555543551 + 1613365891642882106953566519548821305418260262459032678151796367238313756913498686906585565640299870573937524634136703149075431 + 9289249177275626622021358990349141206245802827466686634188302681734388914438573274476670571970132658340810522019108097685976679 + 1999547679043388007539431538024419806104005321474063902499212939182657952169737390109212206767202350076020372910741798343053860 + 0796380798378956338026387089364560910203624767639137927998294096484424294854533260048523991232484163916572752125119143647479084 + 3312139471300109845789877486922941094495320192955690413961709171195278169767812527830359720778178037462244636938901054061989359 + 6446495700380140348116004473224522745585963020017740642418321329101387653563805874445580561212083040164396327873544239022001568 + 8221316129071405562026280838341093594207054207388991782744751735089766826502781865742057843922709134454840546015717044077633360 + 8884079984504038495190808918953678045353356097676798230492279289061735280457857280913457619377057884683523850527395740839623992 + 7553178237304616708890828475106185796221210507905405468874982714460646413397054645663825587287675092464040250385703334315092608 + 4773590965589763472535194103574470410955536365729704648777555516672917330870335268784268577673152078292448804242825553568245947 + 6215819528050303270969774851839361036143312160025453398613079612450766506304878967542263517886001609950018287965333798559597461 + 2170641880151969257726247627112079520687196427192459411452224132231427774555020194976266757454256306589376845325708061001674166 + 0808706168526831621497924679232450195651965661724083005213398910330404632324992737223126731122399064939390308377239660504899222 + 3551818900906904056676616710573047283299775444456072812898768689067250392820375890588789819477340760813736549269624861064751893 + 0906163675906901070688176210778473069828249578452605511950224714556564390138087101450788624170738723043479291100038259738176381 + 8078282667536765535434830984808011662048300628237758542292327990288591220497965448597597894673766538440553768610799486540893085 + 4239348796188542060619155351521608241401936444825596707153268722768490308653700045149495791462321531911996176024726025953987339 + 4599085925561530429435581768120454911625188723603840101001827808010649207159239374191781479981311865586606666121770067310616172 + 7104627786436327756821840719455701887978236563257187943017156401785911149438142292942970899875188032869983742209547431350943402 + 3524068403178617373975067637980111980036408360680020858787573852832862969725456560160112278450433733839443039332972392923338691 + 7361417128175114993261450629674608141894725708171510038678649037487846100911817687890240766440318417379790915067480509929873884 + 4192563045095005960884279637612799513276543500165975164906153877957210268650229031342852943158004290795716146485254485943610979 + 5527495850605424448537975358841328894172810067249914112763981461492106207569150714303562508512966364997576085520454249415595925 + 7749567920199753428291369733514893066123672937987655345561072264405494064545300253825630928142777746597418333809686090132329222 + 2347190729828800374979423249344630750463633445579902195914226451238506679798785890126552693482294276302768079721653123608475225 + 0152265832264604743532240505688517479981918489770686750786602858928368893549157302414453807821089110756269039234757397043529808 + 6533482130565176488100655388961819118126865617901005108218775489706817843329452026358354168685608881349897826461107138466301657 + 1298673036456454794414764858082769061588499493558362877721489608505337579335664200621558841720543957496547716133300368539580407 + 6422724558120550176442233652100893764139597343252110471726917934375351595018103999311490022927771281873120822851829841201522060 + 8271532119297676915199374389042651216528118441258413260870365096855873207948565556782103615860771982841168346920959540519710060 + 6184875439923588759440136066343058630113336838104030510817176224460276957688775424874821399346650313045479118572616668489003296 + 2897490483936533080760701381789308980122333755911815060695347160990990030052801534871717538234667743972256918252210649169228903 + 3655303333861985799802708736697214310308014845445976122762735834979387407451810326226050509201808567673064245381176975037733147 + 9657194682720093768010430501297373816646166065617291768151706574173498067197264972548166688571305758669319121229890115185819057 + 3103510865220902456203344829140970552995511866958564974902239021728149583173073409170941518663482580344763138822732758130711321 + 2350688930344799523350604942490602629624759567547933020887009924743050812335493964555189623547661668513628841842940808414417517 + 7886476590659571641831046458439879022628434419829165109717986460127979081642839919400368933401267954441646768446103515126565637 + 1110171943300926097143589488105661141081024879644220948038639183302967863702059520939356184545779690411373217502283638534283105 + 6427345179711846867068806487631152636131101160079927489950186169690439565446479010213897921064107507425078506360801250554414400 + 9449471539328516576998441231176991412965843783160858329264144663894049487064693073174535162944480509103362252131259963289347661 + 6448977729584408680822098278848838996541448014927561863895692613238880261580223887644439627676547583170203035028358611234118545 + 5113424393568423046116537671317616837784363459294529414397028767453793820041115557136079295159075170242753593066820395440768961 + 0357417280340583283641050541304196888459267811242609025317032935293813444330705702581551660482757892548218860632259447912758396 + 8759325176891928932295819377731294216097307260061594553902071464538665097894582707057397147529275324299057601238957576630914051 + 7741473646777114825234899359211272805439289189063644808522711602498268477174042815308766568204260129647306647359885729554656976 + 9309329125552267123498982148765832181281490321112798033562587148057414223743472931562572470841497241968346307379573830843375864 + 5689803719011022683494640589564528393539106647783122400405858218032186185463041208001667912281578057825422723357469418158669943 + 4135592927602852287576618966571253116928765233133651892018881037343848794704599894714843595981667962009408311650894622157342917 + 4255899203623494824224271003677968232634091967503097880844441755720576147137952557139636719564772738964156856519335241825543143 + 3626415788714735175257556917344733999894086186508542273673131627361802049868502277018604195271807930087879067221107134172074310 + 7958546281467926023449343568661101832138815620051349600621939712639392675220715111033777811540451328852498746778968470255323001 + 5507407940398075053567751242109569783310327198481187906287038704370431459121242392319816826310134418784694594320070284603132253 + 8500952612124145512973435903996934578404485074378319984371754538530064680891506823775364453662506914230333187130946894042814136 + 0265665148790173017555028894292865406694173385138855281737615651927882128657965562089006870021634293021436977249028055567123606 + 5915024874219893422458723773331806018064564044582475437209765195603359789772265483078502778595048000442697079452809908661825491 + 9974005988977051807595272626225779862046223804794634926553502843630881070875123298869912614128545778960915871587536819171698115 + 4134066090737503736509722416899089791584075227377094759873530554067748069082533106208531237181423743510501202120010884006504203 + 2130661127717575197825945847274376219456565491166146558949366985214290031939401399735403160414646904595040915898139346351713694 + 6324612167251656207707087624536097155449639896731425226748776831598133504224173609907231060039276944120772510687900080346884581 + 6779168745096711200457711019042996058420593520557512225066879514823155886446534991145884583182566717602534510076749929656585763 + 2645365584973687585388329644555202088022989110607367050144776537693714417352526613252012599647340542087230486009799844093446266 + 3564846704113295525583758182164662009216216712683832484187612989237709031101278092921642250525269665257513687371728284688457875 + 4269555170494408895577906466689197972679804550565920918614809933468304708581306933698168463484178291731316450813136298166976686 + 7026547610376955852909877173580002842485362728362791349023862313373489864426541187364755041770087263084268647054320360965911322 + 5647079585282992247752748756022346611926842984561046976951468976647765336240687959117772104657541464074764281634923169020133548 + 6986017692163536989579104384975828200486159266813636401205178471888697579916647226641294586286142850042407781409124499578432265 + 7557633520998487338874304841131912835862129914096167258884138035045133191763280844957441725806050932560746430226219247549692154 + 2059549946818227720943211781526111003981250924876459433602235222747377311088585283118957625555745513105052583294040713888376552 + 6312790236548842295363447664682859100743206688687480099078223631017589800121679494388116457487107923554186562511797306252062729 + 9341961249268388400507893558690543848588537117611908256806356375473026278316829039260672100995233732139958201591529357001905122 + 7622440629036046952745648171252074362090378664664601861125598525510174413032785951294400218362705244805632366004605852186841943 + 5591402799903315324575404129541681549710964981665090508369906992078809669693743879553048600144250375936726479837822625004211533 + 0078063724382242661885925388201522364426479724179540766386042648425409841158873221737967588237291116048440934261723138640261227 + 7668975572438016377259095768317171394189060199749631603972553612209575383312005377253743770387375624576792404785414546299669225 + 6702311775340274741303788836209727482858012234498189667215083952930215080983474097496335600683835003845218991908331419228161974 + 5844861014709438146848025778890120727743982063500046236695299463240688553674143271469625051120980545361183599015488717404464199 + 1417923931690244544999340897859985367002505948231379127672256195312588278402509195472407043750082438215262579893876014989408706 + 0852865918577980935645894147403286685964996381094297648429648506192278067863183038777421574419694387317777907505729693297708412 + 1477876485508630104652801640230580883493634454785840756974806839665717736338880683347432665781835143575902380330089255654038083 + 1333574195103318490380293307280457872559202823396902837942959887393577658742570521479101307298105809134466724699237489092865507 + 8231986011655928132234768712876079867027010505901813055232448036254614645338353115984374755578779894249199293331904818734171378 + 5291198257745669262198453729172996916240029288161181812810389503650167962679364773038871747909175248874112616641407342566234542 + 9827656930274121781454100476261391707245667711266140909114058056141317855910068833712824192869630959336254369672357008292856548 + 5323877306540282063144065009953089367459505720096157841731259977506672262970125862602619551379971955654409939177527714243403057 + 3533286954907536500237907021493132000340867715658050587581466366920687545465498963798769329374590369604149184427380755601882748 + 2772451245387121398103687673837186367345979531432828052838695364605611707914643359500610696276887453665009271796449018655863587 + 0698238146791660163022661497107232088142858713995181413650802098858185207125972232613318849001183174321522406825869523281989408 + 8598554632732565974534400037249824032956321514858885348539735224820260572526802963756049116642833599682551125312131721936464816 + 8777244479719589766354029439548567013317807112981262942768196141952117452742612964786718669561362298781178596889656657857438059 + 5923903176580798552139931019374192553986137461354795191944498128759243022494357593594711086051327159717361960027267213667050902 + 7713620888965717050672864796196500874403820011858648932283473719914877636081597753296264071668416201048071423687724652867885227 + 1226026168424754948160701743250583052114587429759744035821120491264623002950973529144113414105707200986835221503669020815368719 + 4301615723202468195623453039744894794833018107887889921748034816356630393443669846540007477652862272296203141137911353369865567 + 3701305132741529846291547614776780687562767296077648285050793745319685122361946265802267010089656480989090754766793951985030256 + 8873911333836369977427224870430320356503521006657767633627578973429639446804587551411591770027775298708856911679457385890346605 + 1569544828599021231532143176442191013631066377985711192575263159095165119051577468547654466026788861257476052155683756383480477 + 1570683253965182842006010673097287497172850525327662453055182206979693937570550092128731857505346441332074707878996538911947435 + 7826422261424373910786428920393564290525228206911026303685173218951588837324122530045948404629473803092607834231045937648966971 + 2638900097751822798368796230240210897707934867384226561665436456581464223307579261127638844885560109562036790807667670390644417 + 4192581432555251427389363044896326951734847648428400345150360499669512737809145524003991223977279428592712065139442479960445332 + 3942282183806384991949767715266661401310060486291440972343510267352817495541237489262806877081824812836064827724828303648923419 + 9223072015234086234796090436383818568296143232241955872923081786551697504279591818923391084950971313678554302938168053766302337 + 5040295146817500973605556893314901715843407186937767008367308307925199801486021624397893053770707845409279496052311813731054362 + 1647014082822566848815080638989025226353949427396868720941862068805915405636344175116957293867502515550210403185422186297987101 + 2299194118400856813156210708210682041625725297454205612569506042325388570654000072012600316753710747599029554756191357595113351 + 9406123252615695607363852828573549803486496914881699175306276755265739836369938313041363024110056929623864023133434302918217876 + 4012400092952627260881136088985623398889677549475347950880378929158923209470729028820934081657587476645444580153423943137551662 + 7552074556799764537114289715930906335072549730926411552458159805302034148895295264056331531618830126090300007948842259905560480 + 2034810936658458335936482208711459668407533754842615732173788255099444966005654249703291665433879743623245887203502319367176453 + 2055826854912228554738248289886125490164761646368783638608966701408500405439745351176591154838568604792386814062201460103196028 + 1704883259604470302949798965476058273811653448846315941108597287428362004683627667421915628743842382745845960365444382205614441 + 8276093407998769926806805283999661528492618490261728950220171409852969042576745011296912080496971648424710213822281461166346433 + 7954055459730823465679899905176049956104235683646988019468094197473567154076726095028250041409673376986848760985312614035795365 + 3541288526820871183022785627606776202868249144458419432875958263707872906136295450220559956136362126175679096582857639739948725 + 4938942457166622758688764402917253914836669353169972138509951712963418233559611193066044779423979184123891151058275415387004481 + 0186693532983400032989768484986211599974215771878040648121115240600011282719832395142348174280309789242173034859607865458058836 + 9693011226500711160574222437812022981161460007590617976243921827767353835606291414448435195278815539213466555449489307049996549 + 9509118537609881549110785870137427018215479109414974529881125038407426313589072435487055670013225428915901526956102119247020213 + 7469585110154725916486236087220807528982687428584047123899577899339622871539124688449741918490207266633825962457784296958609358 + 2301098947514645707894405697878233655395086728296961354861714139621104988822145498752087551938260818588440041204929785479253335 + 7195002791628422640170129886701270065601981205842819128758172220230767271007555891989535523140754390046908600193906165109046248 + 2903714800754690075212414752414239844419261581404644710369810146988392192489474219249291646325601976712417376991598429990116224 + 6657841194866308789835186691755481781807363317310203480516610021219245717136441915610841540149737012207330154276656421683007775 + 6496393167312732418345038041143115847682160487308598451735321809667649213873941020106124895016322422646066096706495173559340273 + 6190352286444996698010567042083025249630998980474746852300834243586692391358290885793710964591096599205367697354040455225748995 + 3808084112830212575642888231806203048547309288414193348028410780142000603799742289999737003393558049032105240979729430950416734 + 2055001806906934446231057752350125761310442613239626005937018173389749155377417284662314193484961591256165582045826903566815287 + 1770910475516651085946142895420353886980271498962773028208448011256576219469415630937607816862320717646276543446021775437024856 + 7317728070174544541281155663261784538153312462326658626789839195595942323601274570763560759947639040733318592217361764664122267 + 5163497922629734181478583586735139172337995385407882365183581289857390438660661367597010604158349602523776584737697559311077546 + 1232290524053006728473192557288773310853272463002083064021874545276391652038777534156787659533007696087737660972241935746823998 + 4820797373925070252089423136204599368358477176708061478789645953897583587905165644362770501568086914083487441612509546270070041 + 2710844937068669762717114936914428075765570984673461573362652998653398467217253506007120061287151708786386990808903587499291676 + 1722239692416177387037629004556867021409013954231954955946248469232703827805268278720272112690685704443311442687874485358911812 + 0696442461522918873003473056316397138103158503920758588244927506442635208935867088943853508413143951321019830428306333251201396 + 5237490053651269730925587281174140512120043151663340911938612562084343250088788816613613533254540244890538135550921235569055235 + 3652159735685467737870844804342436795620955533935479356452033442056822975104591188103222254197338188275216408256009062112739968 + 7134994798879023357613115067249723046493042657115745023241318111461450746096281739377465898982050597074346498759749836646750845 + 5435539953004427145646816313257688146440880667736243466005411373421754461366941715230523658976477672479751504847483760926576034 + 1189232066364746161715297654667683387924489405288055983423309925216635045159783671997425077719999713937624968743960815866938439 + 3458042402161473455431554634378956977066496820341904422146434258908727947177474383440746332129391825690966243498723403254667650 + 8583588769346353411734495459871858141713721510897174001175951449320360912321580651780695549218819369972998610310409490019288172 + 9334204527475060600189111850610268775609506754404225935699578359127242186303638934810994186504201384645847184324944047027889017 + 9180203944559928543575350648779851174917364441299737433952437533215087774057147807226819191868491441590442039396662591808502513 + 2164065534579878437699757090955883471447031879403082053258427608568820018565147466627486801491876503507730663614122066321703246 + 1913587358432681308736116815399127159387589682764288441702400713256228014611237877207779478537639968530764623959147519370506561 + 6235255735630858442517033591935698933960554844760005512206225607812740106611830794710056776637176558829867814913080368920324943 + 5410646760661322485781048142156629014814968811323925705022272475371023640394527122828545405831491808608741154836760565505004928 + 2033787078461763925201661733809116559798197426225447373091087213252755823492809148960852025727421510534412088471340160144342242 + 4053406317407103820908867515275579307068390637321468991384194322089645112923727349244540751951979469134053290718220589958599078 + 3285805403257089050405641613610899794397383496324785340103859171172319440876039603408630922409574370487373867533449326075083340 + 2983815868763252323303322070522064853273357744420576029234853609842229699640881843769482230526051119476446187157115583149336835 + 2361402646872012433986880843871560611945683230864891757700569780134284216871106221826645632387373922861192629580123373279881156 + 3429998671996373176825887742582100895464377776504251588052739302345778540285554961799280437565093922440989079226166655301999596 + 0886198944491737540229136497483278400920360475905860689648388002698383026711966163612310598810941558644533048630182341670726792 + 3224790998309426141510868353814679975103849323867287287851298934668662832191399524482143116612939771691776186144211021701423317 + 4793327096193585617231688937441621332297850907599875602232326960040073326201864681000919760060752937975322888247984232424151851 + 0809471069558103959275275538388584472907830398322459954494433179596574461777867507710018713571052848608078849868820600263934936 + 8295056327643509778568235977901421687599218957335038414287972297917509776356464814745628543893936365866982215021206066423916526 + 0069175389099655621827463771703163016234772278712340002459468537149630573879420643113985870282366118625694647368265400040980694 + 0185330675548785458492267177712810772887558224559469934081174511045410475070695699952516120170917198086628352522241811643698589 + 3432240470257950810314775679834800845473620978487244838484905235351184086387166599707527028976915030731776500593580501517198631 + 7221196580395629622683771151068414253703527355840765726766691589948635031125477445246126627685840897423930890628894585553998214 + 0691851299476896761562326144030082656664005132402228246129440862040530711922127884942717942941321981606132599740710622690829340 + 6387805954414104944165651355643971413515987568344486496225929165033526273702557885861628429072595508259134031569932407466556139 + 1855370060311355098279801028503699206359780131940779590143641110125855998712927294283001777864930865688001454553164651367990176 + 3395026397066375956526282504048669461521946610830298850923781230518236171386053536666469499692151678856847055919172630657325178 + 3046849923385707165827109497171128710135811605592578271326373856764418443760349195924655728319788343802029428671675457416769456 + 5261821042279220321036999746346900717107895012894353289951489320917708733388530368251182473743527841343292751660664418023250390 + 8824252317744508579970406643025576979363288136493464811540150480851485119103480579103156985795448940762007262203877811330652870 + 3204055616321408250954812676138625194951030184386810613892670161995606664768252471283913135456955545480933087872315934450481826 + 0110599619290339021324056958678493559294456117665436489672772960474962839844256174658530179997209334133515553960451214172384426 + 3123165163841681474367010429491835679876709672710839983993762107872490425945162980229932665274102783110995818120564672709048084 + 2232035395926446390712487234338471590552947684994788621710474575654186707905435367680711475885293815543060949577152083169955046 + 3350028292251658928286123588620947938740352179851517866242963626384508167950485172272074373493999323206780786225244298185666999 + 4138239667749081340443940138823062129167164095346506708209137890234837357780622504863833649209158347489730999565991588612008781 + 4664217286110698633018092758084011823559493288270590581425742146586929149871453186482768470820080489858199024057046533515257475 + 1359038127174952081563588721035499113638671173404164924825530484539148472501653910385502837523160916070082537168043390775386612 + 1436923728210391122200372504366645991744778858443244990595402772009992024820412617754275410349299293608939703285522116131987750 + 7070475686255460177418547021473687579971194688396164244442299931146128832803904423667313289561781005593542663645306028982529133 + 8234121263247251924212841508107137520536152642698580769661242285329043039771966387613256643214231439403217580461965950616775878 + 5413104246474816660429811639531866004425878342745986000581091374331764631199000564830359002609727849512990017018293163945873976 + 9271235506027321498393346844536657245544343198147802739604119444238511848559098921026630558834845589124777635275843923942487146 + 6915026105020117228571904488841353205308577369931061433915716936274811913573096342546878245443525669417786920642396110509919680 + 6739657651695868636149376334284237799146008295879768907577994879004415279621922483186516644311320818173589692203657526672858471 + 9876510782436209693056682744986249105883882516043932138260023370268816469981968622627487020614107433825722570906101692145161092 + 8947476576936475757290736092762279169953016586726757242391235235637432154172158901821960951603571049760362400377076037216546585 + 2735502157822565784279289258228694712999190257163908804541511707522385665999422960150232894155188313507493238330302410605425296 + 7940101946087505879550405973067848188833812225296523952905032878875050817047074123446017999571197850004230072472112763344801201 + 6857142063692961406887982913011490273637829211932192499375592176104274764580285681098203860236999583984675192011342612589287803 + 2211465020826460764614937570329924717346527293528447660776999654426823206473097384092520163892337570587601913303602876478051786 + 5272016532080322083507311689593741698084734458418980219100525429302190098183573551213250917695957795596851135451614813138939428 + 5194225250639639525068156399214932189538746207985167145356511964074580667075083175359149568969997574350520456153735083289658446 + 1455560636188297319680331471565963722123437735473357325582592487841750254758281060767877781711667628353861132757458093517522296 + 9590937580052253974622159164858580322392765535712215396895455529996073185392085906968002802221878982904887664044332656986715431 + 9536212991471446618363328764237863492326635377747715439634427901843465449556160996406079848698687609807559175166455209276718369 + 0962150554158891455114948237812845566152678283675857088563676954226626094608713709080121062121158536561703886898127526222898762 + 8414892749163551177217490205399965970236826061221918459810953818518538232318451456451553658102845761329243527433596909757880804 + 9825158812532083534774503272169600063323718458433952873310136391419269694767849055513012348666684447456130828029837154887287827 + 4062509382360859964541627147185929761392475832974190883249337770970320052156457280268514718326951417528373787461693447362886601 + 9802384514195519930363615938594105163103928246792737359775050266251933928460657553568168049147890604569802307087230082628479583 + 5935332407364708394968146809867463424837289762388992341535259500067286459397511377634976747563308326968703921946360640378185893 + 4569961338778055670213869684862788995924625160473819440389284613604453202763523485241482845106528449769880720371645531620509281 + 4202560683681703431369153262516802980502196714639887848169937613326674387122996761898343353693436995583214395894151975156893071 + 5332713363776927366695888962587179393484799105075109946348286416315933464459810857879632369155531524704654845441581407617245460 + 1504145331569763505220832523847632508529957830567158287689592530569297300966404712183597770247546234814056520028432048220079902 + 1149483717724666058290549158624685899733135096369862966589441778195807957291623190196664952975922610237417399523101511538417768 + 0036082673459241242094083136368293175771615652653244493296672289353318399016588588663275146926170769838811055155231491519921092 + 2671555423322348703897548437846131134228893160392027737396758641632859270434645917320325207654186499204544521705733245689882718 + 2041837354468721403869880661989984614132154115011011100068745419042193490192096797533733270459341389726436281948139045659902298 + 6287265676207191576589342058985373273830354712920659876843903556929428288343172794038913384089049546744993546672999661244015504 + 7671119447680097893124176344032941210873441607294204020878536819662836852561652631058964593184756766213107639235733279668108014 + 1503597944873319896726432783506968518844581130482208284211813252594573116879179483819354129815885419312761420721174077013349076 + 2090575099698794920755209276799477214063322134870825766478922887601572992873375806104725864045048652936083491870937541080699093 + 4276983494146036588052551210478424032928358829122542012906258904015903858342990969060460111480318597431250609578131562003677515 + 9113189915457840484343399644582165727880755692052210886524470220995792925869536099894161015143779391596346691130912281801612173 + 9319631208845800137369253760266414764140198516858735371828537522929558300406662683159046086394078157278265484925694452296859315 + 8349237034176302850857262350204638637311808275176159745110236526981407472953488387189243977498778789698586980560479570319641349 + 4582085067641332005668306046922050438876194786256238539902378554139808224133740244623740910175342259941720827473284689401445459 + 7345697903120299815105938454414060402797077914470248272961589951135290709800128402376384567445478103311791196342258909767408438 + 1687450542289596593441156541948105976556022804241843599203672068561696047317558154471118174352593930389361496742548511304322359 + 6498489819476221747377877067530863799486747795199009866503783070729160667495759546595972752749803505545796148381282603736838562 + 1116947692218975950285800049524721556053629253858269322416639882955425601685355611062823222776368062359326543474366782696365362 + 1876190167722031024686917347027779070009896358771654643412669083054810506078866218417271851286420021860907338434817211204686529 + 7526344148737332091666585836660697055361931941977353720336283268157952341498338628673162826343734542380046878989163995116270895 + 0881257474139601407433704222324056930283355591807454770810061687372318085122818010133000433045729252354366007849932042280735696 + 5414676249451280636930231638752958380804768673433252210159619334608464253621441055450445428123593855381938626029786836437726558 + 1472864902858611995686957469529408189014561042091105708978737612763064100403995245584630738467933358860436751349270719679653915 + 4154741684647123464440327863242393005522818718477064168160551024239993656696764829360125195215986845682299044548790324197334138 + 3620127277527314655388754016922253350206555973782560191527034271929722748456430219013528002841930398470078939445946816067765376 + 1722243978849829693580351795930973604730338879610427564825410468950337347468265193351290232895574144876817631258161159766300943 + 7560827667474386459711757237346751568066838129529407855307314365209698298457841298119589066095648716960974765231576411494919727 + 8647954673176727645450541867878958992452684388452058871232181090099976607265059152633077058376469186824930991444056731009872982 + 2534991973200933430036026714058825873362205723979737750638944916727241098322793656977758591967127159597583155643556576943448135 + 7155096296084695428953865082662825849460303226866978634425536379072621988021237204615220061198468810868414563936757985215986294 + 0328355158636181420325206501518296045012302259181045466662110690600154986730477840865756276397313811576274178347247630894639601 + 6488666618858920723988680761139802965152715427776544103393791345032803457282545151397254870010332315293514763142030945537580212 + 8490792796508337321795619849060108983218521200268617175020002271232501077412217793566906763151880182142093233096870432790215644 + 6497520222357920618391446425720257029473583117356819552842063897560547456381395533477059429635070000008137772848031720176668971 + 8337012837324253697188573699623123203170708166950795276999966009577648906818828342730326847639721034032786616971040641824194318 + 8936005757600971054320025253057644372313238443033194219596927715787049581460393528422411161050154583706800554645719354006707835 + 4215727593152764210346931899527305466845340439034432649923099270817579403876601746194619933095404333412889852431784452755466843 + 2088097487158522551752685495115047141137278634729729587648195891955992392424399063377394353752520259570862609415201408164480501 + 3544474831228092443689968228780611679861586419457086393251353177701671796943515744580842421181721325756988105402798156643588821 + 9778536795257051681439799124663145890473401144931092912457976024515106053860305458288529123695426810921506064347775651216836501 + 8629179794286699832017474082041208054529672919556607496647432513709724969762646139135868191228785586347557306843431128687158014 + 7106456703557605702232569911033196736598272397024373712296482733842097318351505429979256730289847489156750506335880609744614597 + 9660558924487542734143121356331540689398560467085012517453390341732092436780513934245365179678624863881161450471818695381011735 + 3612453516034902143796136205048511802780802772294479133906585232123112871839607661282061340027850740910859483338299107807956460 + 7138724118583930096084405139356471004624454913317962414308274669136174812224878197906201370412577330455805945128690650516949333 + 1730291821726950196206552159924266720782365385611242853448279354949948923432277012453511172303822029259754519038931979427529263 + 0548575047242616318508715072515332204278272517306960109310804996719916332590161894788700070468159978743034429043329057033741956 + 6780889499085964528861899269034340070621419803779139024411147795371750105312955245739852543595775978340360773771494478163557276 + 8779458235824687171901362922249920581085853186181780124486013927395708657432957030172044779093473433280766667409407392636463029 + 6492579411705822845905066201120652601308459859010659739650561022388466983198156117882306744218369432413488854001765063909641296 + 8476320260631331607201248389753502857961661494677170435281685503191366884817616726638971291309647117085069726218509290967362859 + 0810139343653776833125734038676243930878414416044335363929863448842581458674823745747264416650503948061405425537368655356993636 + 5246772266327550199529567399996744188644213516458735587639817991224447177904904043235549503266714688854194981790228117033924563 + 5461999291173972450770635507697104176866762020802521790899644748842731393628432841194003711839701487245460386154522697276378209 + 5508101058683508523829079387008807816663732920071304290119836347773461806818814318630035261732455767269492882409702742637950576 + 4599609444549117705097045766405200220153090927581307100167391516722145681413981100426906534790499705750570830947858845925010025 + 1009651634984508835728715571045793550385433404603846489058904184111368085059460823145504327889561854662565906194985160507019989 + 9357881999324778923494272780697498659881414033472270442304085245770043338219929173021287371666801815069695486701740310076529915 + 4608279080766236606674170110085478654830337635040537744779366742642067739517988003498779451425063495418123468371481260706586708 + 2700839483986172436829409192485873721128692643705335631914640430691426436305173498220746572777225402080014675196382731227699368 + 0086136702746607717078625347234495013215002090165872533540039551264212687781885399476155438281141614343873696580481400589706298 + 1705902722746414058890369373242227296762941970919549616605978259694120130539911344963309277369189903126883321693536398430654697 + 5704737347400443449757566987270236468633966314353505101478851263083176174429030344023607680553018559157482487272502931014168203 + 0929253853547791644998906236759598501768018124990991199353184644473283908513254590068607924929473380232470364424573291631346278 + 7114456427076321654054593005258016944651062956332800845969220254804995756234489111294820165405880256529733135691041245584370134 + 8553075127747556822577563288536391683930679292906640525736392953226223500696613649419343205087984527799731174525862937043354377 + 7195787380049689624114711568372766827743368052980829823446372539589421589808988393401756593651612425875577606936738214349475949 + 0181544697505469142362834711903740140759734959010974977126438624042186356553593244884210506676336566524109269413687671228874205 + 2896686735795141476730158554607522934103668703053995570782216706155323744964613382384967846986182100960586040580173953854307263 + 0286768549279297394586785263108063892918942908459235186623403809969114153282154910435594392237358132752498428484045697160025994 + 5955615832427009939764606346259378692931215536161617155986791397037887173705219219646647075071165536665651942885935717666403172 + 4276536421804556864922554676992233459439755861177568827029918375612999063128068548901725736512083925758415949098712083242055096 + 1725062474106111957956927114735687646594918046204634711666975260667778901437761819647914937715436330233142512856404865653199627 + 1291532637755334170692403451392823323540177224847012033326608939686606026939972956526341007272336243309559194347525857345975521 + 4741600004754011316928740091902596508371266808717732973936254941000335221943249074812743110404969466723162046697491974991225004 + 9085942759791031775731739206062635146158396893656161608173687371708987211298821225045306367484626014700868922039873009889166761 + 2541340395518961317950998826785729636172355473248648132541946680948357368185423797382627281741493372551999786014593359188997484 + 5815863362546532185070737662568520327034674676319716730206859041401224197894669598892125005912741187360523778711460345399659500 + 5019261584110255017064950229895215051849707546749811603776445037494938571872346104053773024040213974077890562979334359709174595 + 8333959703819799129975411673347762248495046754138982930023526377690018754531518740079491735091275401960400702618787889510076010 + 4581333314409607030057543494344952121287231730028937956224706941567517833092451729648212810249480493474654543033507398453170912 + 7852221502784071535646166335599143402394637641678513241517161191111016811759837825114453186940577300367319815188600287295217212 + 2010730508881189649006207896145313350898015140508068016693226343978406558747353752836658017965545008809220423091595161424950648 + 0496642867065050893136545829132837570390366632826974250747266589629788809643453838849392317508541173149110672931572489980731531 + 5044656574615736195246481865299114510211631762807229391764826087155637720268154669986339615396192306621947657967460512382581862 + 3895441416167225879629472693046552479446299590678533650004819143386099678646479751244788463147638567925169013110241886917506841 + 2313203706796269432481996570645174678020808456857425673026366797683548661197668493887407113195800476443548512276825541513285096 + 8842881585797604763305986235159142379357301472286513544030211227645270193019240287343188528847284806872333232004379253392212209 + 2688409746134847438143178885250323822851284371547861492401669288415720100963691981973327453125586959600245064339903637953701615 + 2157845883601129857682095395770985605599007238545319703595004924079346833281510603116153010794429037127659368861617341676777914 + 4401447994414721274888256152671021736338924549726141907269816501834171190194745666679544881448528084111510223352357146390678748 + 1598441987414496519030297478102458680201205753852279934039229453001433839642149793337137629917651258040708764206181523433254292 + 8502235049697025555092849971402076674867464110183607528142090872909056796241616598564935589465706229822069262366265937628292137 + 0055816249709410284431305701461181450452686881595061600026629505373443676670339321519731346337868758756244867546936430600344835 + 2653221234894262976174352794968903515069018957828772393070009300269049849197795885320787480595346792949215526978359438371233230 + 2573198395480105527983836130766181207518943018866225650015829519188519988960108721260257064720088842555685468531102293009893766 + 7692694226464861550196190446675400547348832497307906496613188251375658889565533214610868096123194257835553142178169804139054021 + 7725637998171173785445603097719118044612631181543666841703322233562489202164880099839601175940461517268783567897496005081890093 + 1623476912740353658966890439792885600281612076194740147557413318421891935617196959684345685434629547787219047616918564873155095 + 7025393340892141498709286165315521796432685307146924561201314330411100254047950443336104515273461423562157427134079178986568513 + 3037051173501455568382307906695636378996155638857317043809314274578391987572790382804869815651855972786188467330565714827922500 + 4074893387854201023525918388726764794855730871461446351512218023803177488574497502040250654764531910469820302411970861290475346 + 4505685142400586418253034395353236203805450253479017801928704774791824048811941055335303586560686324885362705510247805420001343 + 3089154219080968310703760534064569831009505236913263817236675143668487294264949278958590434251398242365729091805726174530517140 + 0036394729791915199963247134854987262729782792900430729405932713576759938708525288045097625035200406357341027793528833641758308 + 6352067888617175431411674423431768301646476262241768575619045274936408735985350498083851711439785845206739316196883719103192098 + 4796246905383107193048562525408958439687461541231738438567101188983088993969984494129981508412118318349184613817013959589269737 + 6278309646817389075935268193490507135536415367887824086765490270943493340352420279233033265958209197334685770879485799469719026 + 6501644826983757753799478095020135205854302975462551896895597291920140799672078608383168757287535179491461326280401680688209269 + 6878526040144420355891683769364803589616260114471471935609824723068550467740012749917856656207461894693384857525476785223522600 + 9913533038664755944016342494625355616351591218888135528544319832829890186060691211822484503271002284261557646472978467535245524 + 6548210843247451049422320528853823425570998217119732063096360026534131251690098102596630502775298567714836475115745947762170767 + 8887884056401989307352068428168695321737823154308274924885994114161224059109503941221400198439058269599476104839310697936760947 + 1499621302434101869959148741723191678491689696644090274728115214408462354277075304721665902694379966811617179086736989510478453 + 4472180192689505631132593579798684787021607827033405644669077356547531106428251322335834054519860462918400592332567647993370324 + 9048351300356674084399149618697303904545693491523593398209411550081390607196236295352104843258693200555492607047645055200473684 + 3904033119579621911938196032662442953927339169769049079015529114126726770405396769752836907821633197786728940414757447592836029 + 5698177775039384194905994353296325732870874582783505440992449252246418852133705888017732270642203555475460239299507823556669568 + 4584762886535479770675275444567493237009137069030861149601485784515963297935895153471843170037858613325007001549210631837023209 + 2986230798529869904729567059889517914570160421964137879893497645563877292347055745496295096825111567999357916375574494934291205 + 7206470066816931559279891084092643447735267681920960477832257393262206090265312234429580381825327805715755696980240563671249333 + 4975196191021868367044398019078519059684387790904063324517862970957096304027938042892083911602143438683752393325035772333502998 + 1316065614559478287404397163400580119624302865064035828659428240183667221604845265166461282189820016614382937134407772850983969 + 6172722824726265969836224691170018753182037736393837492582066024393428721754417142086323296047227886511163988288746175386143366 + 3150098340574634288363424590978979671688129464997330011306067549875063142531548626552657667362582081599069751262734236839198246 + 7320831408674583797739325661435931815687746601771458516299735930183747747803369077854960129285952199586802721391111341133770000 + 9781649076575876416834626425635920411598588075542620127671675851163249442163030188821293485762987388143543674662920406406559708 + 5939935563329383384304248329695829758747483676028520127505271048590567171170009956748249750276404393523654234793402435394531559 + 0252668408043754647206021991183069125065854666835585971567158743285135342908676173306885768974453965943775589652707957703958897 + 6941205372351396701250517551254482102589310971175662401605631499693168133844709297036538928165453987035113124871313193061665449 + 9276802658913609967848115344605249848453532699908586062377147315012593156326148344297014110306443933718879254374138651819351013 + 9358073205389217401007942156414789371666731131537345827743121944929460937083473364444624266082970336996459723671391030112788573 + 1765411908158890001229050208942988203575712050271091972655376675898080722954958732806828573013490785204118792568609729781493352 + 2380302146221749454886974990613671789801805162408638634096879268990438108120689272991357553079627023448340790990962415597084280 + 4048096687228528057040549427950909321059124104059954691594133361792928522598487445722858314871353602305792037504518403367795101 + 8791402885580812697264727719699410880547796108771833960539902147827417638408675493518018213254819498104814348795878620396366601 + 0903924261354725492168290232167217374559865613331033632981304605379493456181688182582298294804821827770454840207003173905889439 + 2319227785834038175693137220680318778454701304164120192954225359327542167556566637258412033259709183354710843065358146305555525 + 8673917622829080548174920911891769587355766435165634787328419281721579009044997104872530471989859299305155593643127267879722422 + 6682290955279007939673997760490906289041187907827046608623932479656002087546101920096135789193088482019418559812270396482968185 + 2423495240985101912282160197226440146044901932777702865325863608790152621900419953459804469566930950992382020196553029673452779 + 3436610407681610128962456711300906610774647139359864663150800708313215865508716982334525964257676579485350065609743793059790523 + 8492723526317024179966715344536215615681812917282255110526575184184812878258269018344255337700911624857617809339928700208173945 + 3637336636381056356070802698487403636259922727330027710606038599582455818066875278487848716217844022297313070587219989978367370 + 0060775392327016214743079646392570709223503152196217613938079763344036433088567530057235155273916070612559581478927578508356337 + 2980025169096765222953776328674278356394573802596587538549701911336821174109269755308129020228887624742741743790423872778133411 + 4050821812671715448039700197323622949979651733365312936187264385591443824448095216098907529899820693216629857601750862463957125 + 3142033473651787251598564785166706147991399595143208797800693772522221250290172822723884818192653997830457442015732513857367482 + 2434227934816021841461320189923052035591521089170168079786149675686974463633607305584810474242944486308070058500812306124076610 + 7715099107942733927512136192299373968619398158672679676087995950860231222104112656659877314698556942502196127845551909712373108 + 4069114461731658732633727592893010579600135097271095735648535688306732518715682620335083055144068477571815102417990371455419096 + 4513648336048758526599148974167943082379478315281923441623546714332454634302169701041016212788185513022911448815223921787570792 + 3624469067047527512170727298754069896031789622645772484827952155406739967506695954077541651367850929296976343602998185574427928 + 7941267068022945446692718780586230511573764935339043083147537297266971720289420223564631007244922385010298582167405543731618295 + 6806852318072988521804655880278600099719660787055120319799397720389095148995402664025461591174050670273042539667806005860061500 + 7207008027571345636661751333090766740919387017591058445443344334627123396031143577924484316316865139392646603641126628696936857 + 3077564139261564206167503001531356981773542928052096642681673223984499732941393025220000573381152245673838328811500670802459159 + 0948542799001533682410297780373013799791748346265940949566539377367731087302452174028989049580452869089162990037685957268273937 + 0880681561126138584261480022891283215404751141789014380796409952816321543905013512146286826522138659411899727000462608467450535 + 5880091566261256557011783504868257620770129211977999169370084785384096209807922714348396458806443353193445034311369641072095970 + 0556656033549253864960039890721015883335372132680590369609602226419085993403091634173432095151442616233244407104672122152816903 + 0104165883408627525444104591380562545622183558159751831249938218150151310276941351661814981521482974647621742382874619909936820 + 7313501231477817301767451446702735705428503662442130539627888646852578831768325107739301527824363969429357121983438884878755269 + 4393819179422351389843662394835319603450398553466130430331252873486799616761474948216299677793061438633632338236018231007238273 + 7068094772817742176160590443426997804722265949259567119852638283512544860402755698118178658952516755701578554245375512654131546 + 1929058509678608173068953824208364147161581285515961193245483567752314654578018433833005722739540799467152027333949229966280869 + 6336730057716861143854645697201406300653307680945816167555425942108475384088151314617817926634797063108952284581676269870141278 + 6513049997339587705695549544072595339278305253913271901919825663866146612507671581432953692087570028664604274026412331620371074 + 8287494858287111672511595795429201499531492727612182441663719617940686643391436311349735908431637719847434127985592417043341276 + 3683439281027866311263196237695664936547654237370870765012602749829825808040000867227133823847412406422822451359747985192576292 + 8080745720999988790691750589159999510681935221965279452806039652949988754070864815196625235801191787296756531552141564212907151 + 7193959478339407643118308465039555507133342674876808586706138734909756613087265895500010160295176435656450676824231321652261709 + 0364925287385399527025737739685585498448664221812361858587254459582955070942164513804426958941634994463722930608065187062143205 + 1510248350334956246451724384468817066713416535078509857129529545180481755289335535116009464206553367625156566677354615817653859 + 7881465671702288772143540937915254400157725015862757578041600213873551218117006116952755764443062859739372284691117745149958234 + 9088672142145404730278835893039966187590126325943635642412358143475145374782213403246198035026788070070178049812453881844272867 + 0338668401687420146135473027030982411204915710337406365921420685513130184588295184291465724202435316806267038332889397443572598 + 0839432579664022013756612378573508309364105293988945101718659897497738253028464952712017100629220365209543091962896609529479679 + 3205960596777307708890129013560513946330763313564335478005273643120628824046289255031118424365183741647820073945909472936879735 + 4620269579622752421433383654982653678424583328146692271652411473449919421964392617935515652881545262048907644967697133592449864 + 4910971218311134291321139032124590602851436712963785978946343853100496072075735946195731359706831946181264874128557978861454843 + 1011713617018211148846555458691095625992954032111035185714620653734574566700313717404927859717431081627049246861417661324499234 + 5786110524543942705885896839017534087003537095772880970962648591315518710892525409209474091669813346069319857029093908507508520 + 8853954861830714292944628596393329384568570114810794672937003168548384708307820733820193722197605410037476744326684584534487320 + 8506177470614128104032179365484641505802789779285846461790237297261018747968281039195118146388862647365824837138881138267868859 + 0627387322960768524871037409484459085875896325439489116621528742302285368082254073124593119410595219290194886865353532781155425 + 6809698357496328576273024691628485594217747112697681983376999200098136183929376787562599199562809870612840417370015973807170130 + 4180345838072561608049345847198586105129570485513244519517878528919531649387592676465860801665435795014078048815567745274248672 + 3354246532695167434429089502120887783749962531689888071529106417054905309204892456124468634666345233412562908228212778433482865 + 8025350198646920310690370174859009390241456508358264258699021020277939851249666503547743318751810595431556900870080845029269395 + 5024287042925036023658377259430412863334903203075207016434236014370755084100466996153432751138550920390967655897565334875107985 + 5140055633415509862050689677756134057716739901647883241169162784527852235725792016297971735177502489661133426961482215258022336 + 8037402896490266221826083726250897311919802495381754225581047474087034884706618427848292889662240224463663278752931604522244404 + 7043755425948194930791058610151488175614282166409617670305934153837246327320668633959913213103337798602482509159766659520973014 + 8270324793209592396753604357772106280615543278837901728489074421806486555551552367821526140160754356205673704266414947144922428 + 1799358966488711764366695558613904123247231097498677269788824167860157320461004934898696811210735916673092405907643647942161633 + 2879051334510139198581358891368404052755328890835533066541217913121822938905792625249238474950146832344471977043224365781135389 + 4792241156268785166424579695585412116561708898561202729978503519790831983242726846466172154727854320602695467825448826562117055 + 6892572380716177090374320438112277052543379149328749706362112028296715205065873069869487739216648881329625482801871208985853567 + 6373214964682547847971295488976163394711102004330268920420740567984995588029489900437674583804505907280376076761512694288533949 + 5155665472119733684583254908202345934203146938766729952819115305923223221786312083916415057710647121628060022705929366547804604 + 4979219068691159117673733260174579718275355270622127824048810725346461586407079827993239800649367405496829848031012026874839047 + 5453326819721439241285068650662264327283806902040744362117833297041970217611203752467289267570303110513926750426867300123044678 + 0552826491452886926336136137608744868267813981244854176639767832954709406334434073383918878421433694185303125198608436174948723 + 8232804838617139276458679276053642834353480357742672915996943482707728711707722990226821986645110256211853787080947091570985448 + 4530019597199416503606666321373773776661468897805635174486648284631882284913728030703703554479870389738113486662451982640555230 + 7993338222145807140991352100542338400006637591961344296816299971822252698512532704506078851263452743784059409504687946969377470 + 7050536882923788373466054136459774772814292349043369279413441771827357318562815124739087054575308713882488227553010491099772197 + 6089909596225409017825449105685851204483516303044569069782656841637982677940745207225513250507661349031619934115869792030545534 + 5623878938475449105483656355950820776480123283684344289877071474158657289092937164564108821983834915760732145489786160801928029 + 4816804046415869731980026155380698391293302660706933603124933543082802974288753245590234004708950597141938648083597306991959548 + 6285742091945356496670113754904503990748375484181907762641311090270050878330341468974330973619534202556739616012441626266016429 + 9943182264167678058972498083665971330560261159232616995578303066019814909746442924781284268163340228187122534568268386331093065 + 7152421562633124939028810156815250340969816324770306713467508016775028986746579511353296216202084745909078793312626258806625843 + 1270211232086431110376182218366306020098067244906289836262668331857252429211967620796216066094322098532350592071668917821894836 + 3845983140880841145716906938062904326623489852177531923802141898083667738472813358868563811996856141869924840103531518902763682 + 6718003149619307421590918630236184183948486678786725981990313301354204177947073223184765980604578217913950986068011309908008603 + 0928467335337181093723613708048071495790652643180583079182628211576154222901059273081503840088736880283912228917857747961420216 + 2166551801482676965109266503314605693500879290753119500152110927158165273225738493344045059814681043424105403563256277265130147 + 5602984870377735940956944951929383106107020907201382858387070933315397423879633043403789726957228735509198228676824257307906832 + 4033785332705686886894233935205324983504447579271074658738235607798108047836471901273736322254888901735575902110174004577938609 + 3402493343952267342344754443371491773245869528553143427384549726736187617570093360565939837511071410896535571400200988988962479 + 0467384270228802505542012448307525976842449031499613137353277852822620338697586513075361354863064717799164245330603052561106892 + 8842259346260183856170976867586760896719736933276441816021638614978497367736310097708762890208045248689587229972592272876387473 + 3259167318440772369838882122021007960375389506141034220872992638686407702750133638151910546511598120704345383522282582904780462 + 5442641858108090041720094339574637116216554948307838544047344475741751117118100567565238848037532377180455225898883679663375089 + 9577142779120614628627441392665993338561362305904130927688924256501300629907368310744468665785794738752761659537261334710214003 + 8036648554081009787955952496618722107214483438085877494384608581966978660817589075759692849806559360759821555215575625537328994 + 6018332837847583031691963477349319171451400074031373390713717042745436212897138228273237021196246257873177739985799453366628180 + 2105213797394649680881845019293842601907281739434203168302170068885354441461289080251599722778415734193180238772976142195797481 + 8846734820754645249343903444980443492288225807913782286509632765370978666435328327850741457922220028478728899676269184885886857 + 6241211337754447826883159708571545245319208827655835686933251362672810423079630739434073408653288828495537708526658804579257936 + 6272761641480084516721023070052621557056643754854336674557368573875689625068313256900499409409105292963555938180247719262631692 + 3370472297661265053196085477234369632895929368519546792630928565306505801718550038387422423219452220411081683199640562587649457 + 3951837878713231474233482132735598466639480024677257398672432796607337555329635538613813318615303256000562507502749357845826125 + 4701181391450803850270234592090970559917694412710413114961034587689766035663731463069166460549538653431143701866309605231883521 + 5130066101866721176356898240445132440597653755333619647577387320361484004480200635865792415170670027337193740214918631143418262 + 0808586953125247209833845490228639118624854066699258124848785165048528440583631961380212929557758370252911013779599196305478822 + 5521493745858166529682225371969453760228060851280399420192708176554476472315839318021751905690807649055065100259488774569707365 + 6158697507308922777896716663452883986126333631244914987739404979553039259206951208801722656773710392910263349735278566679339104 + 5235852402635719195587338866742022182421541295397761869128302452896058848115769056351269147058952464962337808384290518791915445 + 1541410356265877277120453080537595028913680044162125110791583969590059857305994592466475393255534238742387386696685456308459612 + 0685998205305456113478494375669069867507303172663122574416432766684294168665147860680796606372059541989820238442687325132846277 + 1106867923762001975234815885590982053876420748926951108789589029118783643675464846081587064829483161231369554788911064379449191 + 5812396650186976221479400172298188629572727898176974211003232401377793666992976058114854815038333629709686365618467427463150786 + 1384329026943982531591592399085803625354634016228493888015194258739954993856952956641410330220082208258103940975869674221124275 + 0959625394390538490258630101489160874897384983747423071388118372125410613424612801559234232776779480366009970965890340120701045 + 2667599636961907870724269931710369308622554291093494631427897956168577372077593727180133140549717498300507170013965255252092132 + 1737339475235603869117715688789198413446311276950893765017909814539886259628403094769733766342691082854440546058895772248646612 + 9197218961185262852748275379196855788331061390003979168135259363646749693751540875250641291188297420332987544882702271806564544 + 5155345846357272505381130365306178806560153732924148036950818502559878423925856638459435711194956693467002588044226649914787035 + 0339515088331009475687588955523954567747189933073011102332237830656095392839856108022616789694653613303860633782147528467869258 + 0130375935586298049775383191407798098669127243484570035128574481514435908283974501169023065679639597582504503336586846159045241 + 7077631278309415202815413204154287337150040264985085284229097360757947744868068694211304208527582045828778373828218901884299318 + 9750268301116713110151838109753966293343621088077855224277949045570521139532153236249008822916991091102238861514323117478408697 + 7155195645472829181908341253643812659814915997068241585467987778740169901860636348467280424257966646686476472265113081410661304 + 3489215851493494198992712587668351276298911212514851702684901497030382245009336388185220072052801963314343348536393431861793824 + 7433750102437336219240711853055477575713689475760799540383502439038522399381791672647025184537779822386053913810580122038174879 + 3818754166719135070632269620576055650986227950584996452818776818068696309115722467830916362575260788613336625118633863774586835 + 2178221238069038687341161131798367556148830622561463128345189400786005116148867892392990638096974925106944221425159061603022670 + 5524790379877915422325982255364820388029995625235481186060304010456803568052174332647747736403777805245458180638361448671813038 + 2561932270943099179760490101865479784716200934807733561691561384108933097340199742932516818080682737612322848740218966854945307 + 9080116601255117121383041648878380955264484146894062161454022932953200141179550531168588724355886537447858132714146647197563370 + 5582470235237288151308759910566681678927176948236130886004032182125845977161600117740547183580925791449145036400529238606663420 + 7837033717084727015977259234033008100455368360038870286352550514822219714510463917848677542164460976523276256801252857727025894 + 7130094419267655355009949375142847444276972876916939298289507233195397404513990497114810662137361054915518609388753530456478940 + 5388394232615483120266638817714522427995662494049561316381620397442848359037023023824190702655956805505137789130807808295750670 + 7728487145979981298300914926600023112696314252375455071809186812868701327870915067718357028716612327551252066278398582389353164 + 7289773656445897637637801900198614044295973498998341687324987147175709042706190580765940871231724558042584698396691392833921161 + 8657047381454227627618374146397069336202044856822409754902332810974380485722671719214725867693990943072348305834409116868276317 + 2768386266640115552548464265203598491327266098674766891714414339959283543826573869249667218521183972556730897770799418342118136 + 8189160219232646049490114563802577964294955901129433201250836705921020927053769046687178122894793267915461627258608458791264898 + 0219476902780453916709467789696795567878369111867867605857135264741583700268708214119151342234570678050700247598575853332533925 + 1642635008587172832360657829315478456525706956941480551250122576528755981779071461911390584857611720174162647873804473942063599 + 4967685799379026281672422049403080588839491839093762962697369896023527084701530700159221622072624944257435732610627292851813751 + 2044450251147619884660437582513822729870849508689036347657931033634388064328200140554626737296767003665386040440053850111272335 + 9965191238699562685527207327106427173242624391995490667681457409129351701642801367806048618652102824703936861574242876103982267 + 8167136500949575593721265813173669081199030452059803613088300447991271804667292549385675921231605005292459008477827396828396980 + 6509840801282604124983554742769070687886591529251914833953844029743868619125159895774188014042708540332420119945175514865123729 + 3692321786307153306613998657737637076488435978265420180472674598878806315670458550057067811482012301407908299677656750462270208 + 3553454561634700149917505664871758279230385607072819176680565522193204640320948453398810380708601224770333475704117532694153974 + 9739801831118688634434296635463933483606562392700839399728340475392493400599816097076262424865867680957927823749646379318466788 + 8207485786494651396331129651303688013258032982874538569357681541288542572016965208057337584986821728683984473782485195031290559 + 8109594698571552972881573904540885927360173123269475341745160895931951290769944326526035760450300948152494775976334153020903866 + 1739268973385061826289687149889229189956753685868472054090051279828873221786295847959246538258862203254463138510475016160891729 + 6472588945675080220223551738194925153786626106262423384260557370130433634861152559973124770729011313810073811203315002214957767 + 6317904094534761856637133735479679945651270156668746266850573869850630241143818143990553888552953747865302101114447970138765661 + 6050111904910844217007312990287283030132792651432799525258590083326102644255354794948740529248987597130140253327270495396985608 + 7218279207220544832644649289313013019030346375149234023654949206605352146548635130815666273562950986058561700625454917451118233 + 4591089295985815819108775507988478501559092837715809067331448086286924500664248339776158516774620654659269297333948779421651033 + 0402389695369287676425439165311946884646996933164719659142031175373351707836712648952147263228223229642458870791042562919539663 + 1663280408606348818705021370639699925355411336760403455952690546859354756234316710656534265824067538349235703012760994218438928 + 7331947252166763395452202287514396143003916184577374680861816449247026988630652041781591100537950521820855164931956884346869156 + 0167992341341885278124354492799177573677966259864026035120911925009272011711402759093945175436356249669782240856162554344304896 + 4307297970448548637044676901410933338328417297377294558704310254387943692431491233869228400552419559003867252598836554809147959 + 0400912691036342469718967629054695345164844205186330491298158594966799688436822836744333087245877645780438275466738783338029984 + 1522719795609161172147875781283157496792619720043728981895906145341666050986634594495047649741152246939806507306609930123284981 + 2105358148148398274033567712304765375367909977448660123752729616799410712586037852322616433905738649313626209308187391551045434 + 8184050603718152729487919051152176341217780682835043432591401578282222377677030156609712538101741280977544353648960619498088312 + 9780539921497865045552480951265192490326869876857256607893887668594821322177012473373977135212994227092237257692716960309499930 + 8387530951877561556746885813088050059098237284649866946622347108029066952894002584214015925808803683837814966224683534722188788 + 0980315065961365338422640630321175434205379462185984915822930473041804521924781482514510231643402826027992447752984590090815631 + 8885215984427616592965846360943654237762984211426187791836287528989189066470173789608783423601639354776027707428728361921725733 + 1713545761488733797112097100438352878478186093850974631628293903780866218943733017611561596620119895299713346283509695880279900 + 7056694123692100328413045552536384469910897094450012862955826233283495356986105417266885152765210669772149818027501922143072697 + 5044288331991180937483810266252299436099022518584143328384527105505463981298174129945339074070183868941494344473296478243433481 + 4945558387028214187495664309036767910507538072289226775563326183770144119596728765797237537898375774364456608274929793323186859 + 2322622760682958787774419794236441627708513520567224931868094563846705540632720743482044172976408519449985880794628778392723979 + 7704734167762682724779119792543440260650654515136102295412021984201525761889238911775278953009856036983484297176809989345351898 + 7538438504892134535588424111693601136717057553968849287415515571796218046474942306436018172239215803280193264125771352664266396 + 7105221455394922182238669063185805229847494225913363125711170315190206996126469146603174629254473614090501455991736786538113046 + 8157168667432314271904818365481089200297683424381896431649087725330131885687876217074390326660020019876852812089717929283102567 + 5370154297245853419804188360942032243192631168128880436140877705786486797146832449934263947276552080089455965696884234934971523 + 8611893045023888017310198960086212752413461499017699656702018998940525757023063840379418108573223175879013713671744193748767015 + 1169024393509843272061563781622978325016779395605303924999369153283788827391502842037817134058668089767959752756676201396896441 + 7712715405049463369575317556974267677998279848759269048895603544096481338768211601218741510541248300317436674252540127015114391 + 4834430831243295519098671812863396000922057166207709070811235493720931115916983299692520931163380069504267039634742271991229413 + 9287385557045725218161176454965763264083042136444478713449129334549410452033352200798030615759042237027156709457224173930955024 + 9440754327156472541302944326043902553561785824204549770748860453197398189036670911169331773914895138408417009555757899645501252 + 5832453847611197719596117303718224745254716796559500451686231076822545459079358621425609803998655831572289152307921157534370594 + 6716617297863540993457906819123068181321563782640587142663699479729095230755403564453694626863314955875318305864016967285927449 + 6751752585208130882471772146338918033811645841373896388668212294917320582400645793013617832138799866544853495551795042553770974 + 7292062075462511235154219336433250111030971448383048960076039173673865773457243289124490997622252180509835724029497464904686356 + 1703189532838988444479300672213603786659157307392869303094005510273480520540799882625565441527626460538592793551679614793917597 + 5131469474921792991086626550504407821816558283404370799177646663722782715758886649389166252871185413421418269585717891891693033 + 7009640276492618793739187876608008054508113875022453329081433650929497189681068056166559133270910556458288747450052550799593778 + 3775026817449250262071158797005661647517869545017156045641434181332078515755353689003930497030264487465467676524742489128433074 + 9510101337115987091584562788637829217924129844325702143952753831115106454935897717213086048464400730491846668741988349250815009 + 0460642398157894924642248578767274436367563791950971068099635643161955689433389352445513881354534070645863359289997626236597102 + 7422701275758347504612869999447090197900987293675125648746188541872170309069628366658720207642452150511782301406643296921604925 + 5722148742542704368310731836532013521833785510008023772247459847917061172721772791747731176316362682231389997934194900072780568 + 6833294401022288062004523032063979096666714062815023108654665205678873446818506366372748896978903704125253114795333767006805633 + 0409503844899480726742485372066289542014116663615248040053134473634302073503009858583019797024883588714394669118201212140331049 + 0801167094699960082079962007695468661043658656967418331551197267388919434693010620339366679098731235659707521841235334772751876 + 6325143950028159251006278830542343903327924750282184108026273734472327418765244935721260982532015689685569244807990908472766627 + 7594072557268049752783928609937336033485545218183637235406635759394992632389014311377829965838907592318760198667367240484412343 + 5995370105199099659966025879437447340499996959986818273399469349454086733538293008250823125200112169460372394345464200255398128 + 0278006855752348475839798168839058164956107248521078548181749550904031782397298429598863198195066959241173235250539525076363890 + 2434406818995447305231609382502170967538696884871023912846712870860599713914006479152902091530717543673744437190057705732209450 + 2049303158709878586595288112356673888760379702189055053773161541139894881284696826212357934526729889089168985110486922861784281 + 1480496657855804936389615128385812000095228481966854328817796490269872553734151219601055960998715934877799282526137718284428232 + 8638224569717329657108787802886111345753795000064618991042853502960039658407299390014418474102137277340588865538873397922966731 + 2915504391345921079597753766165614369426311302871553494239227907927104755401277811135239511652090480469130728548314080193845714 + 4662543498990058418814498281187250236958894998429926084397929019382124044722273292092351973221932689481754974738766719140738353 + 4190409245555651289372817877351684664080842342410487693494611165285252514427042631380484145603968868053004939443493512729765220 + 0119636369629430093021488300230179969441757666478935315483114992540843688913867607317956666306088259979412209337113112892142162 + 0522344915049743379719646407210766405374162220565183535557053495876729008927029380341012939110046953015244548503515867668213581 + 5545277258914067549098676802369675716209629211229823278440028400844384130766676038181293025311537464968008032689589725571813893 + 7241917831784954432887951874113610869422570389407469506150472467208362227227524708480496950010505902724279188045395824562149045 + 4536217193131427845613009167815485956442321803951137596941709381463070724725318338865720453796245623311051568325407640234609643 + 4950000863730017668562367944404823933355943718044346155630933481082791520987136962663882167172001786426520967022022083855046918 + 9948462347102121864710644896101448735320408682918327475914042821856145185407258575043429392954988610306816855047216892742882375 + 7607463192368539597117886391111127498537601742711656094819081284338644518509840706151881140781291037342960935079170415736099697 + 8170547034180787962131392617751093115453333934584190242119875787080041916215989194964046994229463391170868877473670939015394600 + 4967067863801616048208692428984726982425267929231942089387972467090049190181520316912402532109719978404281158192349591335918000 + 0182827511598856652325488782019351042712700704721955971553105284410000877214479216605042256842199795133210940783113951447780445 + 2845448586343352856456977029480170139895515001400772533947791028664521178270989590999530566461508232129548565121491303912378773 + 3186958087525040737796735368369363073980409705399259078085185801788329795473492605756831924612159181775569516279264645527914405 + 3736227582287369825938099577236266512057139246043733096797986415476742434871074557767615701953628932757311718425644125724233706 + 7173052386737821682078985950554267597062731307233678638341260916391599502956775154905191238402444341035490900454688563799626952 + 5147641961470238255748645042116320141678230506441721302812017771332190399762353180889095100320685446894708468194573746305094928 + 3469096230652662675602711465325424276546888133056279141284661309882996606616677713056958440903862720614419241163546636652676601 + 4000176045790898594283018168562878609386243501149259496688481941480198035420169390431588952838073985685288362095448469635565752 + 9472291341301030094187025146867336563674988987757598438413852630025766068250538948297399599973328446303590662904124689712678759 + 5558918453683884045568116648619640982031099812596210893142179251292478971547413993326289821580230193948481450670535256195029562 + 4928975689440726890177460501590676962108712941853309133182477027909307432937071388936253714931106477057738446899643424898539007 + 8940244387920877438974129853648880036120882337129881652544245505645048735775452951748876363983239868801033134946650378020657016 + 3701058033103724656733182793045707161803086804756890720227008032425755334349001190669627279911430274518624636020186433616060892 + 5795048614649402340472644254299779685615196268626556186825992241948964494636129874107575230767378691185971658847979564205979820 + 1236133846548113964258787812605512858795064801453710507748252434757524711761598464790831987938492943750974650361247007836117825 + 8985069765244610015917016588371467517920803422724008738355002305222843175513547415525425623310272808519127269635589538855868669 + 4866637881580384758530553032050127301271010383021829168699459836736308865544704254424297016793922754172114529453114659796809124 + 3421197137282279783180092595776656118340512425979400729754872785822827951114365899638513626864234673281733350488813180030409671 + 6116540261589173059806435182727298140303534088364505375974117730218290182662177594123794279119735348291936701406861588485281875 + 0383388028538445842643371054045990749985217056001543711456417105050188186522673179186319252532355654228417953034579705914850138 + 3589398737652268493665223622209314271095213796466114005222254738357264490629049957974234088293478306962011737255628545244120278 + 9242006644961491221804556688452952473719954034253935879343918188942010496090705258446852742963029458182305909452754390287793730 + 8783068031607497439341603800503578168008017096526972920750091440007773022446775696934539156855822636256531074692478856955931965 + 8800823547223548709312492609422799167744315137636030763502283934241170303284109496261288800964950861563894408561284405190045969 + 0236871653896771373931349637525093015261721424149322538581449425146949187109336492808412768678305259961228548229258526615055933 + 6808296006076261647807027264924130647898638203490518417736498838185026931804266322409312178542687977048973852811639981510309567 + 6711783212313531503601350937924384067635440627869411288664439772524317458074685185346606914709019186196743715338064452022403271 + 1329461726620692353133812940387503225279782302791789101276394351197294472993751698133198738485236134603208512597461992464092534 + 7712409812790062450698418919781788475967301395142101015147156004348821394973951402124816517835984222889123201533407163528809483 + 8878866193884252627688867520926767781102452754391877549372235240772045942305940402248699505448319900090404392151869967674502128 + 2483008370299951549301955588790277512316664972307031593695383033586616221934522732614016251454351893271188672805879216575868904 + 8930668992950485150931537517355790279447532793020359504907584544928499659083716918240980733762266979363328381222043500384239731 + 5449783313063957701679502215046202754515996947849788011011244404372242125949053935941173427778943061308870747330558976279745268 + 0087442866677315281344307628368254568290685263159851300491709072441620656219856549470063530059686910247545618397733080267966459 + 4275923776467144475919672663054261638444876359385278313589184049205522647886045588220547740175271213225571694335593813888699266 + 5631076970562565479284442184748121529273149320713280238168313146627141356684124916604998541431548094125068927278902251637629771 + 4049873854233479495273404123122985718709224211298472591495302249456292201698069758048348513785824572699432884088465158829077277 + 6601450724720706904135791943277181797939378581152182984849501639363583354753791712537234399122836156611327530479415218232099189 + 5823047280117680731777259023254262177630139266484401163220777646941723211983561493087099972956890435877152661438838138706007958 + 3871525096685339470645850417153350859644241363604522957863652066029739101996436761253594694922069548250943637910124220796682359 + 3789021225120290908842849945791566951268040039302726617891236371450848884685584694857899475642048623621033883942963333740640913 + 3413392907322042998743788130668642581010260731658079311951196515199970920919298587850590756579979416052745401954692899254629962 + 1834576186290812892686277778078188491493029363265052305832102758282145333131211542287672262899869561233857209736661910966320185 + 8640618069436548861856298762841794920426604496493168277782652390652529026370866518863711574378563335650089395301480857411365309 + 1062855694706861343683613721473054277513151272875708166067829305351279095564881057460121748427296483260938003342506900294399166 + 6708351271129793412643921214770696882147428525507519544681246954889801321262715754608536636546303081680171501901796848282715773 + 8170065360748835664225539865399039511547738151434626699419911223518847738407528346693417347838281049824633463358386526323379557 + 9773283803239608948889044323843524447778250704201869489766199362127854167469574262448141201863158740882252497005327174568985690 + 9629170341829493159540502281159419978757497174339132063688621315745991750554750919122418499757801567167615195540686775308036772 + 6813737486648360157997154949184994770910737848857708594705159108226498818076724620595499835896899658135344576077658527954169440 + 4916163367448740109143119472115171909713176429892100499193749017654102572161123098799425438195950481418848253249246794538567213 + 1943648585194380435794184207380836831419456414164714608475465257187830071751668999365832434059345210749956754565801799757863175 + 3687162724713568040156043932976576841434569787909011626375244300886516755159434297033774573216110685196819615175124148320455479 + 3344419757198679638351706919063941845054040199124828713172593196435249592482470220242606177271518431150127043364815791934444495 + 1400008065520008098162065199768125759577818782918099045365313282741980846275621548204708560469294053250492025107214712766610441 + 4165080021198705915210786508550601653226551217888163799551833017968067846988341804528031533804959471453060256667445828562593413 + 0316539921143167379344751397929218943090424282667061717675506492829683232765044382831375540458280475310930354270466628024378573 + 4617204749069035253813713597661824629929473681227979210717594546338035842018470292109616982725985026372103084242143325201934501 + 7628437040946835252535863570081482725836702391432238382009021257963849956941583278276159017021059243802411805222128391491555532 + 7118276592277047948538579672067937116293934455417400255981648387252807293008272125197089405857447395662820745517911550198420495 + 4817641036360381588057889324736649206689772293316553388319983835732003282890192751493367420760022776216834345866178180918425947 + 4046762929816361002114402224273088310438847474234192226897299571581711857975564268312621600137920668387355607049886008638057179 + 9349209580226030857313156556379575691164723527464611358492523658913876021766102463374095835678962118324213355237312840525047153 + 4458386832215216090846608267034928117933000209670619365236847239547649406543272314067052926849866069213065858041288568227157782 + 0323889725674406704675299432615839196837602006707700866051572397447613281818928460518366859474985370527579091269025122957262918 + 8693066533952054034279975214015256982660363796184125831239795876267900616583623647519579472331003311428117914837252346650454796 + 6978896914173575690746678387000060698232734806725458177123404206650082946025871125219582890983005045333389163168584620102734094 + 0208343185195645077429621338459120990032615146936965171481121547620265509203707449471143882951101626839387108073423291107985197 + 3806694565547588080124701297594558579857621291153844744163973871845300036486064506978169189349641947450555475680771354116721127 + 7571370673293744335868791633492268450482890329783462471218711903016708619390949407758233183647172103050542587791975330523548939 + 6895867004702083992837053115350359081392183348123057432804437516085126480426796559419343457573809103554769814374422319272987621 + 0493741336702343083547043049060106406621621423866156744878463280624931631638757753907480473151395705318815364246326098575320029 + 6546610394497897246218305493409122075422636049647756434404729742804710870898441487104017723846320578576625101570540009682146545 + 1011863982645118776769923031005075048502898177517353081584252680645039932448249490068383719149012492191034530578466311073324350 + 0940022141946663679361628444591959010381878575634668757912852707910261260983582304441366347012174417975464831931140858093450475 + 0648068206853955526969735294213923796512233785864528730934169006767896899020079186828212231303729771906306615698951701782896040 + 7705404267837637281673906483600597132329707232579985805240515664780686649377686946124141035632716982723408330472426681691722063 + 5719449931034079305356439666263973565128713593058013796099786122163872295053911196817120195135137786906005302955333296169099953 + 1565007759742421563846584208111412785562612780177121771600395311757381072903942514964351796547320888609281738762831301074727155 + 4840914538717807330571774867536594427640229999158918266573255879619306849868398528582717693006558964074770743956975947230605506 + 8434170706163547151705112191666162854461320116071520338539133193324696905732424568076770881016026396766250345270611437134977029 + 7078829392513262023910437193357139649522860536333445198136202621793588265321546711781743395796073320028953300954811115494631443 + 0358109781392845465184944557313417160881340633391419971812545527651450314512749202620144080637491419201752326439158460989691315 + 6502021443239860929638929077452949976769441697009577432157105021271893283919677666379901876413440307841861569738215346309784385 + 3775582600443257869423701993595504734055924868316007937741523410145241997102735147790121190918364977637486443176097526249923371 + 4637116062887697972788560169232687166734847960365006931173635513798426534363094553967229788862861423059133919581108100325100963 + 7530945856385218994386045042760138610248296085030904585153248074916348965900743636913197206787899808540051760130445456596005975 + 0082651589864980975976353455996961471089119847766125021188045871260940417581575204228376995886410553255809049908515562710519369 + 1760176651046607404619158827695196639809040360410321347276093208667279377323033464221881041272072298115933348047136279306992189 + 4449900653089574942697877619922022124081013931968320543380925350254859461377805018823478776678186127822712476112142520129506611 + 5360537273314488942383696459647239094488670283840872805432523968819547360255856276619301822761467290415157270983258323381158842 + 4069470180647648022724489031315390330623675246416531426538288357194889582860078070141817901349890459635960185352818352346101741 + 7844251807909360860529020528005655952345376045413861757127236316061244993838373872852044455049706576181912407467785016013363013 + 9052782242469623627138305243693885375972159761715793565717369599576257075617300500868041008633881912456191819467065232604757474 + 6257367548773919654525538912712606831341580701967173140576682703453195979358288347264315572356542410824096892368844905848969800 + 0225531033632269859821449136659749178099595609866207288912288428688139123199517309089785003185562015618879502978274246919977195 + 3412420395378666741269488926730591786905587902546167052955793049551854045851796515140844301739953615780488764468845360750173095 + 5314569125098157310473890637519564038989130593324658307078574903372187794019987998391252363359372204089006276213106238012887639 + 6663953749875926737127213800088216077686383881272422931892106536521390323291590624983492836817664288184016273391511477345251544 + 8638673096407867791116469531963581105938614830552680798696429006418115851082700139624263097469936097502648484256024821946642846 + 3261638416472717635495620507090713763983290274773473746283045337514051847664087913092670813304318998742601034170158553214610079 + 8880759198069479182867513797991706527425937623927208476182273090404608783390855357409578977746370113730628533384722500327769010 + 7964841863629197861004282115308229708980836184692237168958174288698996726561927516939282475998327300490824455643829853959878546 + 4078550144875137620442196894251820235783690433882002285566789090860837373159507997956136455505729693351610325429624900264497493 + 6050282912476085926950954499140111563620447106769829012752567207785593165136710295523078591701424407957863045561973215300362256 + 7166661176552788865443610475451627720514979209097163741564119254519710530732032781304320231265321064373366029789454524964576034 + 5731838949398822830420671258681703806386818639376155723888774861742977966282701086517327314375297715355669245126118723701881276 + 1224558805186365369295742263213010659311742471260411491616914473284160243356280450620150570408750609913288411042993040473195864 + 3965363040687291139829734658431286318462224708522925124414942719604612215357576250193871596416258769483377169469309016314582237 + 6893425774786606424591335564336597467021697313261577560777519605605111465025332099784940659090512446671447989183060023172745349 + 4463023117754025492704298169088346276715292811942385607520313996627188228077675005968319409041724080200894220147117291796736469 + 2838367610734769148543248796176416656292040941138404572575878998139182976355595776291061040689581132913463002164503763638521768 + 3585007037968899533646050958305472231296473689572926896126127396786068936357337467731293075452760614111507010520769025993887156 + 3025256134722351463444782906552873128386686368275305328178049328442606382059696387241124580313700815579068965097895955058791706 + 4888785355196252887855666442682481926655016587897905441501499624695729356509071382797002137717002280304447105900656692938689937 + 7373767636755443505506466024295128010399690845976961083809222125377563226037530095320414396885247587842781981216438439176626761 + 1467040097296217610154727986310524824930119662672041177376733844872215017687323322767179584613934704188382812120901100084067248 + 0055261010703792927114582278798343530536332871891286962151403775103518820096790537756954678439988840466572934380472009105374277 + 8745186553258777370952969850546252235196298235316976663904366268611878480055244838332857644576178557847556193922108941720480963 + 7310291886872239579954842039199219595404202222951474277713284211951970030467647252785199038918806323250107496561396165925992981 + 0269739665100112200470147709926216131752562563116766321854129961314938822821859829783043904077776487245854331065090150597583869 + 6022034598022521394602277250974332652859372516801989113143038045232940829875622476147452690929605127893923207935810728978176813 + 8336719184987758081413476270877983896287998313373933528191759149653154025750363065606417948489184358633308380877845477894994394 + 2211461131853873156810302948765499385999974459433061226146423964769287619911252503115962272972255899290410107199334224556606196 + 1402532784763926313823670409002705225482185592078872442217786835593632982577282903273472588503956076522785281354947952227775013 + 4429564170373891691353053299293858952840011672714332817264920331107567378250030393312486800497701640449816183190591793478209061 + 6696515680454660415306312055092012435204898424655900246268144415272389485588150485707845045690614308427142660270754614963190500 + 2858971388307084324374434247865554208042477256400063151868591675576690659860039137955754547923321131572573666015058716528677560 + 8082431519645786853787074095747644469767343409908775777981556502295146873300678603062293673505033125364497124824045616025095406 + 7796338540952910648733467788030865929612271961440794230689497348772551503718356824778119200166125356293580937006896521596909494 + 6623286777262305838866280436574493459341503722464731387299068764367690003490556552997864648359791608273875942027789979081747901 + 2820762823681177751588883983434913077317012385982082727245344446265775140411273692313089468167013918322825570599659499017461253 + 8261747834117161824733335000918969440857899686470868022119901936951959497914248555296472517607486195543086996762943719289544222 + 9801799673583374329577712601117604429044210658931033348348701101269055569381455391166077387776701104476767458640618577366620088 + 4812671524372167827325442166901095131227009588677251478248615586184246419258110774327904940522040756539440861199193515869861850 + 8664636186261176234317788607818904273283245654628256017166703040583397980518196864696741148650137946657712844496351414683354360 + 9233785042626900594870398424394786589093845861107111076865742457098507103631392813148996022790966610376381301013746723765671101 + 5599585345939628248728616861490756773613146232759270658252490655694524473642364799716984131253156192355158951050342077829511934 + 1018115413367504225955575347257464735373797464835594482025360169817251469418319729479090655145106287600720398462808509722342523 + 6277929810316831402715379663360019513470321307271888286707156176722601290897267704973159272389968049881611196311224142002818283 + 3935507653397356468132051961271044279593473480413318195705016813924079917284710536189206698836513833423232062305170527285530270 + 5930541214728728710514258849354991541204981028873011695299038161284051747700208580498162480391834623057628739847088944321070540 + 2131178112490366896971016249779880442716420462976316622931349965957507940779710818286842266030393060843328131735676772739856028 + 5339433698747921036431228649318038784378241814872129036313002907877189828316605458939009159662654429547906907634851960924867766 + 2725144295031618884966653121214453016640389429569724950019640175004023672074204183536974715285043574870846234625695507751624691 + 1101023040899658835128880208200979236233784480432079242348382094125974376887755928733596001730428491870299057160651502141598807 + 7529805201863368482438225714843876867695794742159176187308623091428831090441762886002331398279108448588579520003248961018841987 + 8520639531359520492110038481387012497220545183327686786319255787574425654228049283708164761318908288816634942299623177967850311 + 6808287068903794688768313922352685578188040716704660250946776133077382541811421559714303292759615754217647905753791800896114429 + 5661937959933192849164004778980526700005624355990312125795014118394734147334017327033918908976463421944496702296931260093163478 + 6866390898079223822127023182717821447021210719486206672090868302561371850042810557962915762631762160188811564644765871940463260 + 1983784957124576912722518060888269293020694751991232003856484645400501387457614453894654158242083061986108255912461168024044362 + 5023757063288290577909452112558045920010016969071712896564748738667312129264760935144195712725562634643903560619975222875598092 + 0140266427651227095088902077296483470532188392053269670883135265668245606745264278532552540957167938303029227319042084398428852 + 7212818706985477890259174108784143029357600406814727037979412733984989889987109358055090912357026404921211609781959966663957665 + 3885309358663398776897062600124335478996053317484403001725157655044282776168453835403175508740651996708988152698983678588345737 + 3549561496006579864153172902480324325137781423364931522958523431287424861594425297230970169266435951937028485126756644018421959 + 2100522734881499893473520957404272588614489603694208305341205355969403603944823313607027770883562580199458807047182736184431355 + 3558566826776678787162145637003470985297896846344237649664211727912542844807936273529611661291547660198761650362176216275159276 + 1697273051970401823436818435327916444246809126780823246257873146180484087471375537086616586114897794676638646530157453530809297 + 1877141731822379123458355749374949833686834219493808460922026220049948042459289931477172440353720942293259692771867444391010663 + 0596114677690135744062023310258035439858771664427542203238516588128327906442218908975480077474481540939986337760369812161668739 + 7140350695399428116941903267710113882542083290951701275369344655927910523637037185426739245384522097331905044898640671070017500 + 7453482207139204385313210256702640687353020750058344407280878423180101848431141829884177527114462939147014281506261604724365378 + 5747051408867537658614820169384534962462911220360124367460201651929905485919878430356918185750947336103425001412723806012420037 + 7672418158298677361496394053891368709542765466425399242228084774006250993472472890952527381058062695609973430135097018848485375 + 2721910797057123953879416244095325096151158592383520642643416351496904866623597785985406941433201519864328401275343395705908857 + 0642983563496035432630122777955167888076028823131047975325063367604577001605053104073667764503079932854743114362110563627584697 + 1737450520589955785122525243234607141022634008326290553045379074437558301788691892914015378729774742647378096844792864200227145 + 8049477947243449894011256046326611511617306926576503154750985615770186729781372043096871431456514521234719945343529143211616132 + 4060930164560164022219102032312173710730634459253495956116881900466752536260684001258460015562183214690371015163609148581576715 + 4339672054138260157605312889148304084301210593319661500758836115820325521753635857005220500312010112221791048318710925629489360 + 9098118884517110952549620567550824645268745886275953112452963794466205654973301959016969502644339312155829940467386423970146851 + 2030422710629305679756784568188030405053813130034967510951876362126306529129246017456183221963883892572064857246348841309902207 + 4014325197777088687588337561652558142332091500654763031260105487352116429628561906919380099545877339112314250562226830515084041 + 3366554959465306038343578751837494403196208574534790117389855546409717054044483042532146409499847066640874035730246190276785027 + 7784874865116514506998867941821004659533959527747303526874272093224628939120659783314979799979608075209344316698881835617720838 + 6440603777916554902557821762272317634207749152011454338456295029524399535728380230269435936275288518444494136138485427687743672 + 3697767429372731488197371169546304182440802429138205900920907076873491237616407487249087243231746614255961699354564621444166710 + 1737116215657118949418096366707426664676852506304031637797388892083081543972250240515279155087924413491083737598642466601038186 + 5943501997584026886556269657780895221836455524956899348998644491412008841758015117023754182242908647650511196372757530427844200 + 7126098691386230123347928604422159107062602585844839531380975985325229120484080904014468470157441597070403077589128617082084491 + 0277414078111008949169676840880976444791578133697866086476338429943906280786246925904505101785927908752510981120731146336711732 + 5011921703942318242688882518650473013576715256957336272842712546671709676486379489552317943731327342059730625728957322661925103 + 0879272542563908841343149899911945430473689164183260890378649854294324088836226655479509126988786763035689227450447066454969580 + 3635797692910230406460094517526461454920959082159212413377990917407487877377494660930246389887432321322711771671714018210018244 + 5496909568572645176488382324921312621177838539677336553279411765862833091060541060811106495286938550448561214644311877956532326 + 1372848285800862888898722477263959718622329488994306400315469392140836614515990231729283982778367781183582185203884353672168533 + 6002585963544294141850925971586001726265376264686412361898087738304610666926697454083310088708743790359728974336913706461189057 + 9544994601782264143680659072037087516325897282651078850550946582804440990613134903404213391711941451230258293606634693846961977 + 4294296739368718314807261871407488388139897913896057193551518458028526780686105950168593279489650803151515173510050942218207014 + 4440222769538547178501749374936219442687195706297985586916321673062155148432380676822216859833618467359812508595764374585042802 + 7090291929148830504311787542972555491835675686001439326827409601590115100758667523079283454747571560861565934370463671494879471 + 6306207613636744929606340131323412825985507087453258431275338612289333774848983021189785244607159387364635876091430264215902551 + 6978625947059991073203270373760209952614062079324674488242868605448441131389947105750784088354616643566884781392969415722350013 + 6876895254868693830649346298281314621651851243964761424180528331393082774872122268180557991527876049313013835528942921722633863 + 7994555257251266617368145187318488777925218911343096210380569645729516845387191015748935661281511118325824054860678678241487526 + 0561712487759666786219959935849355827031795611802441457990195006279656115907452353501575006228849649556626967066612451740817401 + 3065700444272921097020103095032561392189274167240364636985217260309148382438375007728649942200430100798750588348282135626863041 + 6418290958339960432209597429802884987767056126860829761197583897408153172039938420304452769552704862796110442336483929988890230 + 8411149220304441269312528476234638082926201849344380193272700895522547783655344727512614476846755120115181365390739989354909216 + 0361827006206843386504436443633849307138803846456656207910374387223474485947474439419270873842802147250905121223284959187002960 + 4561901942869500550331725452244098638243866570298342595884556094097612128702524209824571526031229091793929079092201659156014426 + 2569784663225002575851412395224946857021846888745089626571792624047307039913201999491767773809090290291368272189546699726924662 + 6874345054057523806453164208085928558404937408086499251394158950058605789150302667994062909598865360566447853006716951800116507 + 1806892347177795837940597487685027448543886249836281858785204813002880073746279096873385938335081449362375954555853598273582800 + 7280197984136582079744511307894765629896405494228558457447110951049222331477610433641974978714281803792968381573777298819652746 + 1797088044067027854938520030542484156979879022746379761147066454374087806486473993175758842146367406488679492927645706548068169 + 7653106688789014002295870215309142445613718219291306854675259348422471093504331308963443794325054200760084750801107789128152322 + 9003923022817082834921721240788410357242843286036977355497738812382673303415071169601837346379966066053060156517838544048108090 + 8927903196351477482460887787174517966173931425526452434853205934174795153124436599267973662874006233354646357728472499860554504 + 3649137050137288600334652169002894564926317935052375328874723351133720379648102007752831671041946276927861278960706248758820299 + 7881676548153486303936365019720006418330263108526672450012829414081940012783530554845066547004930367871816825750941800388750747 + 5617499751970255706526710234532717339068075364068621300856559435412791685014748892438638038434662792832126729610856601828058978 + 3609505162338640897172019393757051075698357002384746777463891780931828353562474692966266497051217520058712600221078906316845512 + 4218942164849049619324701770389240864171286359070468568203895572380950389773235867347931266228357895243861158024586703415416725 + 3286877811857113758575603255834974713137243819997694752214133530728139390482439967896436662426005413536915227299430206070281748 + 2197090522718698504657769582076344098155286933671656794750871593655253531647336100969432683359373204499872727545324036411875127 + 9266329520011965890398156813860326403682885444460637962832683571266360623432333340007962893574859386016733773045469648300215724 + 9360218780816808197711206028145267393233058010562551036732947883280144516446467977991400621686114194941533328336858706301853920 + 7975466727102526807928730597288066888928449183473417942716701022737828267407136547666947638756923213101355014521544864295487342 + 5529807372773853881156331115996145600478892095295063408262502214227819442322854320893250029815358897498644974831455098851752144 + 5217677466571168103885153319146030362086428120742099054171064034691470505077333070394007756131235288630142015715989289401952345 + 3238751872112411965525172279795754140090657968922574492232135102357083597107656178253770512768121887161690539858563177051498031 + 0621143235328817027584926551312004300826256116914067938452329926333908173348351478521275486940271058902772821984682443421901374 + 8675029994765542582556780936437230200725353322681947577235834861538086815882331325782379515826004655685444830286018743065534290 + 9009226484124905023296329465126310425464799999137557622919308471018246198151834136297559364600044830857980861753679005100073906 + 4026810600660421971978121050945152770853655639964897333811108395111596792046176724058242259398267547036042717629901672105588823 + 1701174760060091817941457573061071686086097383906657079983926029247083644956175901708832562604741667581501354921250883246878076 + 9360121868675405580012858168094642670756925814930958722345840360155035939830719501362830202256115680429221284715437831407183230 + 7627384360887381611002122676157337577850291681707758128451482725333215128574377639863228270429176470896652784523071172226399208 + 5924717495388805188609979501739528551778957144375491268555383034743525334962407264117945701829683575948250702090310348063964292 + 7285038571762987494406954123411340680613165769286304746181220668099890216085869650378284432589286853709759806525223094629118994 + 9108371459503424585162428035918267612861106220506440110173672498423384456764491877643881942033565719022603374698498258614890281 + 2119544835856779238923121210216240209691871364625727861760840643200609817224777039142791222829730821468075117365482012776292615 + 0287625006985324113383256843550124431381565006783532108722669073077586017057966762263289920449445173729525567088605286164318499 + 3802234646726929017573814267132203009806257343348973659561216577528599490870752429375293883854127262090614163544620710283467000 + 7574267833171812189998339587827378487203820258567218738257171370030553714438406356225807045913475052445364294909346459733645424 + 7057209974818106332836072380332490777736818456915022774135091028181738711236811811377666386715288877847647340595585098875240481 + 9197215476954479756497624010576859326493604058234153493216522641384431342823687635555610194191608220091909666730522341780147856 + 1119537820044774998504706322100346395055393450296026673688711639572331613882591716507869222690391102545737433635859812821586270 + 2028121903848368987212538442391618102128444213522329584551212886903253244685970973210284229639689302832127513289597893485709871 + 1139101840913818162477340055623563542434178020287614160741421605723686784042526943742745792272929328869556547712709877327596063 + 9107408768006237961652791681788083610784715577214377191666576416371990600318918309907846332307177843177765073709224406749447169 + 6733725726008450978073741092474719053157935773438091672305982444490248804288080650618594239161482780330596854243463318510550141 + 4618707611170337857871421415147893285747404164961249246066409955331826510336908541776726066361511390478520619795261534651528646 + 0029871423726184455790317017373341560382122160829511677232857909382425970016570928985722750518023888742942482674353399294113016 + 5851677764630543407742209257890179166834894877003624901201481696534056706522332095998210032002750686323425734736641298781343895 + 9906317458124808949504199178481097664951999312281141056844360268819241235749855328929404804574246937697891911753442746410513511 + 0301178939436270473741478421267690206733306236983147974561800903978683929049444127508643906957999471564453966363638317098479091 + 5695590670680910148994003236516725327853434675592633044599651978504490768012904279502213144296250305384458215615813612885360699 + 1739488113025246606429350291878905105006718514335177675021282668693092738324431010591942084632165356255063331639570681777622822 + 0452464599884896996261376953519588463160916217402746423924422154683861260191652961898971705302933158251417160490178433853439776 + 4496351983750730650624656965901956261109512227868877661440793378743454026849129576683511149685514643006637302234104714172349199 + 0650873766138283576167959756442091757660353703079228843249388294567585567331488037468607523624545996431350612623181744202876623 + 9217884841612782253645748182653936757610046223059439143748083525756745987386187135434504743166765496977544377259895573270803669 + 5233343431863155649799928568730055354198316775389815272387174921789883067246402571006054994197016258947251698092729387460016002 + 6222471188835586754619063338314127078684770466144889169048987130424673328124774962008878054843463980934491177848530073946295466 + 6092983987521059016788973113331515120050882840886284842856803861355854867424082016223127983920367739842939341557083529339357539 + 9152847423135593002663232861455632334026991039822394086654099188131348343461957860123922177650787602787823148319677335222779269 + 0688837540315420699495154888659745629289164825587079409113672585691726485783954257060693018031835646491154074592682796993759642 + 1560331745546205131052821650865965767504353088368099838110467887791087910699782310016063819056506494246788726522788847044002972 + 9843063757395851013539217226262322774482770252168515327930783086524549572291277963238718919614771432829552926078930464389873382 + 5165503350814374626462147517304790280393184056104578516266158383058163824599464967401146483647756651293496532192439439145458877 + 3334882919381143165661074051363092147447735703148534066554968559573383084492917940343234309775642206678952812922080261015609561 + 4150090892422827778476783958648862075260361082863595155851728025658354185826522324370827070485157038772970922137249416500335139 + 2270729610239360993359408455484013545432335012129825782822705159183112780581412024925958595707332590452541348227573704213342055 + 8812698543571227460191878467610741003808872140196791243938096775905061169632652370417102797369863591037024610630210903737953654 + 4650850571724314687005845773201562588529522607481288290365062000530992710204626283641702861862037299641210309359904939817933700 + 1541143632255817063903213640253364698002930217355939377060114361273809860644552941254027110592936933650281526566113066201345129 + 4904443218069061051090074486584977672087200091073688866301081198367118241651115030647481869824608967401802054144740280994709964 + 6714819600988123781424031251846423957142678675252652218273564424036686308763026328451858255344930462603371376203101104448466961 + 9509079835837547622180222314290215064732353288206452347849664411672496172109171750484558066698591320017336090478613367662057930 + 4411722606999341112288605914814611482715323396030160357274723566603030739104369997016486251468461541345322418772128759607222696 + 2948183785699572384084816055776039138878581148811752092336317365102276231176457487558011884744609026187961229782054619496985034 + 6425095624545385534119498681567553265889108179726785664829530547971892685921754372850536788921833807429343926950424016846919855 + 3908326069100657803588698889883675042505627231337237747168653314558267673583632726264839565017058848634863075879312565153073799 + 0321367266050720934662774520376532661682212427124263069420126600109509081952403933716651001460064949865799766176759028464538738 + 9741038058065551330442704073919666652946527397570055939551345839830820648016177629571594906346803356773604688620184511211636838 + 5025402557710775296650014515224591309232698067998266520271098024189399721692010614452489061642157793190304607388980065831660161 + 3865371756663396962706440110406172511579502225888432146828231479035598172810500698253040173626514931478221885791112009689705108 + 2972286823839979161832311952971045738890113686974537517223372452946515286365656547601871718080007574659696313592727664057554794 + 3671238913457833340723922452738592109309375009714705044237276003225833183922594035143870946960395880735557105535062577056078657 + 5639824224660978396027300014663032753936090244783494976851962014859592152013834741021570506331633866559318037963618148063022083 + 9565507482964988994686034476299289689477300610763650942914931588839058915298408270882723496065586551944274748829842524532900569 + 2950174215698554483745941905548644387438215825109435969023495189379067472134512077000118600012988374494816155364721054534508820 + 9518525904194943790633186346738672276318778362232864095452323156494968062204689793145701834333799109246633884847638921045253621 + 6777489268860937675801194897856962853781999286279373198884776447439334574892992495036091872659389999472183722596570197112840487 + 6940178173947556103657708676822035069381549630078448878860057242455764188710473335746627500154960475546070307022636234086868814 + 9329686102999304427635999138246997518586345169303923543680994865014159368545564362656579126189568984209672180187596509411904289 + 8400290546843033015441275084455799605870040808860666105081155326036596425585507607789010815662662324838353003534213828215099749 + 6262731155067666934829202231823905666280056341904107277513506385716411353609764416145090669300953084810469016331307248958077392 + 0982572667217714967858091868055542854621721843072461742877828288780619596753823464439165581485796328231801786913442847252641526 + 4848655976411335420584575046674979122655105315200347515565901735274063028061587092460808297171218521824980966675211293241764354 + 2938658446761945214970070404972488238286005305727629688975307477962234711112158327154676636619409638849544823620779316735831746 + 9233723105727772276287999774922758635916582468201648663126732610340191585232715185516172590941978497752196971596838962424314214 + 0715690795433694724565717518703035300373548926507910938888351542625042732566820561320308097626791527666632661894798286702091403 + 4964320219506572216963601199129841376254539941692757336784083929771858734782219556315822673159169808692321828354292775097642159 + 0335559611733921504268377474272853207366325430567729920137620204884173222566965027114331948190426982554186105784631841860371363 + 8033508558384267940900957170710292773682470738089554833769290979485707252598489360936633550982291403202103393568639544279214517 + 9104033203529399347159766145704434677301867369574628242547881760927798205454869510642633732888078982477565192220841911379788216 + 7987660031763621257245807669247102344394837687835695594169011679441270384265326170270019240149525684618010449694008041756350062 + 8151902440733357075969965129856431003770185569733670086864031515027203169324745948550070082363039150127359144961399154724592013 + 3790327961179853157835883754649149214290489479319422066362773172577179735157530589191336297098156970651227770438081844185734307 + 0727046673630137406560803707058042940068228879956058420026237531511228698088255979495039662974032046384364026969019919437568764 + 4204578688546460366354226690592321231974552743860907666913839079477111780605991648504857092410645662298682793993079551732419876 + 3756294405429570395559614676089322871628319405115443082409818445213875343993774082306018456892013141571878129826624772129903802 + 1915879655542608031603048228973067523323417771894628549592585367737979812887089684899398996853836990904295238545782994463736003 + 1862917064901509743356712523964887969381684280627429777002084722985720739317294453681605121270099743339673719320682461749376518 + 5235629358000506017419756442938714321316730985284287276160530781176188912088650998156658168743552720877268116184356043543445755 + 9443882656574676998601479646029201608533720364834332155558897088411735201080867283586900504743773546108777074700728937687647870 + 1677493272605889337983961765432999426943110889282768474699096119469883217687878946342929523139815961885455260346054616901453447 + 9942749715588817104901581207188857800673119328816832808571244811062495461360073125883981969697016073423707659358263862951164461 + 7589849154636259255662987558451236625196817855393407896633655975124730683842916268495164065502043203437031707489979618651602416 + 4877537573726160052953215845080536556910640218250727320033197474127755187683283945624270057808449225177808596236183681916214308 + 6307674309759482316304083895463219733480617515657742063182272951154632706337489064696789783685482205360435876431996285794642684 + 8643739931017169670588941204387320679922643218218094561807636190505893287798227669018730741719908408353128973453099243266062517 + 9595878873331613803340153742041195527735780444717553915355354609332848505998881213100337678158719821578770031967558080136888152 + 9826258075448305567391906666815695574763625260042694682673443923778013491658161518721464450500242508138338760627120693213553580 + 5553946281220024617384962807582191448987025563460515052097885240434443584003120884005027893320006209592895012188176773812824397 + 5351207991648894581591662853877103686069327469518295438143903554689747912914341445196157967066587607931175822601224101946313543 + 4718020971952950496510335972370616351651238578779144226177776993578212091520634237018822715136461197024637982739115303152147863 + 9502456279815158271330961578383078627663170821879138142148906444928946168505151984176109046790336568113096829851051335078064246 + 6953240969636903319954311768057533966261755313567448194782711138760563765547507739230406557393058730942539222575666804143511119 + 2069936646276438376676948110321617772893399556260252358509335079746651069969820285929369016951090713864814429938558082689945968 + 1521371174145731236232976467624651809029170086344894245707746268123154057519935873219521049882236870962226595226944947282873198 + 7819821085451992801895188229558460134173236266804505398682944828070031878272264470195089873005628963880175293100970223151449714 + 5581893838568192200692899357118035029378571475716773858918510887575125236858310172913692992079179964473799145336381338174573764 + 4769245956084317711076182507252518842194925936437279722455907758875435914157274173921143663890367325067229935879996805150485626 + 3134946076248319258593699700301770098983689499295660906642311982752703674969335911328913636983282731424392564971128071529792186 + 4653454953851844259383149899336223085116998954459207141602572224661191223836954928657358541085552778110770329785385935394034672 + 1848527104180913477755119395683294511819189869818050532796513348646616780772576901429766012659310230873210004958312011164035296 + 2958092156871189322732011639055425235756904126336215793291675441374713359747361020499385226744232860514052551561041374928704972 + 2212834863497329670476581032210400927271310708293108228424935554688407632484416285274174812931270321948680850009808218617859705 + 5759858970411718249018834966145654061840913712087092866138009251429104683711023685469060131756225674409696442152891897372343886 + 9744590632172501257249804338242668855862458498369585009073080663432870189779358421204658237236159348444067179731646552147785093 + 1487302286960634890703793800583916358993694233181958170067964772301899115902690629049952516027344747956086526751455372742400915 + 8338876525824289493587802849949027999302785007312125533604872964433845704867828931952315117389601715858805797176205231916978863 + 9771708561966315440823738672686475996359300091791133612159610896088743156170335643885163215910168604808694162494306049091846493 + 4260246980990607411798428730055796631495823134395302589335824515261468702425017396399121744052394058025204383900792732372609031 + 9971700068769073722960546542881880186840993544233005529300285659415785115249158554970710339057479784757811267863305208596232681 + 2366740530644754206054437467535946438364093779279894170145358386159026725061074970741778654202207224942319105808241561149108640 + 2131299570746273126264570482316141085118510380774029845237350007337531371596475771574171940133305454244596824947855809667756017 + 5149174518393308544163272712602730988826876495407743839625377436405836969824290538418225557277170446225596736304939253815552458 + 4121823510749511107366436348094783330267428964699228112245771169272372131739184081655990835742337126629817378548166241761588650 + 7681892302838328396599913751062470874471102029977403036886581893796472818466025775981658918091981433719370508505357431231485600 + 4066251794397726082230815863792863498887502338665772599923859722198014368910671442996024261604600584351270667582157099044750647 + 2453319243126941865196218141928398513931210505017908632678271906294188175528244273588712226403525451579574075491526959814201424 + 2165992720884571403675858895697135732268260556618466022757708781513389984131289376166641651464163701439701648503883511692095752 + 0809953098069693344801057772787094818934098518685172639722513866511171301116371082267224802273430384579466957516125344869179896 + 5481982401939122614289521472353637017126771394148320518526784723238206085981641590886685015768028048372274104457267692145673344 + 2306442226244080959840391166046824665212018683995806330612693877379188175903847065416666586796553782166003940513860649019698449 + 7839622245401117642004314710277578314230150041129278793586315748881510113272583096733556513373523207978534603403670731996254473 + 8688617881383905361473235374450468814839809922748795968256897565635364988983320676159901781893744135189821124712699202769736139 + 4654535121453878305432208653573696687720659331945282280482164376466643366264403854440410004602377849435849425047260830549050573 + 5901354141130553186089991532215523080159611047438619487077531580624462005235622602720033994742060589665151566143947383285531360 + 4404189049080879563477017517544794830939312853525609682809863259313640891722874703005379977055110211171023836236430564193209703 + 7229494566794585131912570254848123871703487763830158261455284479338860024826943524410960337002804517176829321597236274083343832 + 3895863444104818475102160062282466733057017625695711453552783055209411033854956586687106898952724582542873871156820426292736090 + 8900114835631317986947314833806014993742344316565623294563018259706162592235301529753004421871816938486470617127313453996556895 + 0571759514976034692556387423658377978720336611483511537576020419517170544073326612329641870061597096528288442406290336718658618 + 5351965547349291678130305501394296379111242594063885471825143788366715324130022316640730177505334429253870301505302005277723169 + 3916717817342560503418340716556896773392571317597234277462755462162266315055085507027881148045053452399408688937434362014420860 + 1395787899840181514485743703752177228078579014380638280483962491760489212783979634460850686798659390084425828810746413759168217 + 2135670387347630269927889910568863392759999570308499518950101510541542088393000686133918165399672601047703855590903413630319231 + 5402756885639965603367270976348755948712799599490635951531639604227412641095043036804481527401401591963544493042050777198305908 + 8529853370862945970036024025436607369800687358272778049961830381455619066198750162208786259673987188349784621840620855238037708 + 0287160171661419657676846666977667625410411272514035315874978763125830094141664498713238305106795904657260444752711842879767089 + 2429466318667908141926838367968922957966923427083942277132655834855250930739506120606993470384477050842837546690187842884625651 + 0859078343456062742869073421013869747003592646292364644445549193378529859368317830004107789688729965524376290149979489394466571 + 8035239664854439337661491633430612363668270550373199092404545748888325504908156365529288450637845828980854077097067322982777549 + 3141023341289995552305686646515529412648513395018325323202158482204644747543553961230472458295893311161675174437937559470576749 + 0847147233703839410907356117466248368234947493218430919253855840473886381053247491509943700747999091387943188137392889875056078 + 9027561924408681103294230082697546064172946790782404069187548612190839473120786175725940158419889526634026805571973842865999326 + 0264435567708660940819192568711718952454625290701063992984178907184987617554072919582117061061638475508286749372288750484810591 + 3758876219081855315432362136232140221117526750802434000370402808679995451358803624973049460963970344708478212627401394392324314 + 0737438132749076462394577606428117744360361527711020670066707010174337101948368515240770186600234895342764130573542724774509423 + 9073624026312594849755836859839861773390790206872160912057185754009883091290659157623485315161215679742322663821620022079418138 + 9512292856680689427009039672717710424584681275009917377139164236516131951125126982668253717705356666975977684408510117347264524 + 1614244135791303269397434529358056292497647554306953362312956458703923199969180084694524758403500654442416064508250070732846804 + 2519174085201627296034372830011366838603028175377849633378995386798621551863828217907888881997187873208215147973680227021049086 + 1003834843003895903348617625671797354229539053440753237068065646834526921585552402882071062806329627104734866652786788079565348 + 9629790405359972301542148043545627855421437234097522244411526361848299030888697549739412058687417924390455152178947938956747613 + 1220334555078453153775416863741025226449115088431256895031662080047877074330240958104951191074477627437218425259277775462127879 + 5330046177874455391020429152325102772616525806909792370732670726443060748075990477694277944732782581654693994482617923050984272 + 3673634429035216620140695806733909073383802026068407079504394523147664262305135669486209989893714484828370038683949845972371071 + 3708115456116104837959577481370904415573625213784335620684326306607428751455492651914598239687297810388689807875911114963544682 + 6275078866641136241403805509431449819259498303907303571719921144438991991012377399643498948247855847742996423485083104296357966 + 4819771171509939007698439213480827086866218725106376148904562704537146213203839362150271333692094168029380425896012121918182027 + 2363813324380838896838697582331955348538206296702138518105826516120031079298034769024454364560040544650658193748994518844922761 + 3584004325313624962617797426518359904557846265454464840046448902633251444504148633006804302389871871448461320891471777760471406 + 7015140209188781023966520963877943044151556490498938297548114159848752913311985584190436463500622710986698476383835553548754022 + 1839528400463687701674829536257273749291910270980698644016289075485436646251865330303505791679775487148849253452040305315948402 + 3145765566550173415234672570838174821210069239627979798684879235063388281638855085067234894023172727303768990495108093511731814 + 1483336663514861984292197260930161194717688304395281475857151745194230301582456092278030099203677396095385627051965960418965869 + 2854504524032911241727059077016541586716790096641727786446371669834231656716324311341476302384390592511402123780357675520817756 + 1896892000036214095213174483595939108751482199845439848320000109938495152786801921343185996467957081886861283697079441114823751 + 1013835470696140967938560803552257866025556771879993212750495494783316985507407134125075415195171213975980403552113090097922014 + 7515529295471634503543767654884408021479006972212507337901526368761975637401627838535557010674676502841359449244736451534979277 + 6386148785910089568558317754358991974549956833481352102962872492406026696207774586778061183616357702706148878186924821100084521 + 0786007793408177523760641643227040330556706874975301831960943949711205745890553620154847773954039608277686547389729917607939287 + 6601065186724585869718286730900507361468222773067014813540248318802263981782312642062065066278538284353552795463948608367617264 + 8710458632884006689061619016115234211820116439477889276589203755014121466655765492211482958675286327074722685854832241409593748 + 9721061962175462432000129864627652688757814948302475172688435098625740068901878583888711851475071264973226898929358873311316683 + 4174366427344989068552152924708427538956427143878190827546384412926545762544478791156448578168011030464548344644597978114749995 + 7360922452061081711320164728509310349083463549987726136205083770590452623618881507969241810844776231293351721107321616807591790 + 2550845118266461695500217220306235111000226441822451555820123914245682646337932826709632824811050296875427929721177340139400066 + 0537242786569134793043366211458572528023713869510543400208763370329672141795438795279424345734151680580842314157723144187850297 + 3691971167907808375655388036762185591921761050859435693988855587355710680373549562866421201047569372572737260475884900803372055 + 1007691946206878968978529598838997374929069152901229662680626003917658157134099448777326028788327501120348629153653344792265032 + 6789665338488546383152814125714262232923477122140534949024472459646083579525928155625268840134301323030935772657800235228310313 + 4868298684968408834649240926318299142611007662477773878693177513443928825272512719998804017438032952107625783388477428012876908 + 4309202213419885445857524725380221565049288409243087159437144931986513177158450201360308556789291053726105045930369784581421376 + 4918602058560708246713982614793257938660065153424340512931090185661823200932451770267967499779255156975310512692435013776152000 + 1110183674703280644653992907629380068789930715341891132020648458097673681456412608084277373854376969813158591776142390000280900 + 0445144418946628205657456424237128264942955311965086380583598212294732021966933151948426543613378750502788733253601313302851775 + 2374366628960975291734051077636704217339955444337088817734748627762386830985963672836557693273405067738105684469127912825361938 + 2027506449534260776940737096467772483868296281393345078755987162674894542324936567113913899614190563606092238595769318736510014 + 4601609459626193748838141934701193459914056226332390088463312165368986927729066528661188656389710831973546586554245180984726395 + 8820641417137341791284188339243013012221967809583302454529489453970560570507033795822714618813232104921926392983794422966946716 + 0917599289793082450351085959141123440985146982836878988204562375158569611940037966919396385952791842444219407364739497415459949 + 9477416265026706394163032606799526520617258416558453349947010427060666346412817629143427886670549081801335758913070396959720115 + 0666704035859146354165211453275694040361967505403921624893044875089069215309652369723945012113209887458307287755360555234673115 + 0255440161315757825615697585801039525106439960924827488627325282298838888854341592966844608858745754258454784788330547612148950 + 0874980077738428750262349348089941932765130462263947980854368723919615602845763694707934084120416138718231554631967803081258409 + 8981164868907222146030105839525610946849494940635627162577865021292617220051659027789888586435753051650333546661672096178778980 + 2620946901150871449077949420947077759285135192780733116251997439655441528374111538899479815498280668657556929167956071921060805 + 9030260608320606358567118378046750979991657572292125217943471649264668431650823749458443029769965695844134676138947512285494656 + 7911546964476705302214543959264572361084543166660831362636246720337948370592526588629297565497381903059061404007654352003582699 + 8922075574627020723499343655693848239182605712427393497956424335482790840429881008002039906918138130808630673506435738463196394 + 1030007563952008786387120762737476786971644512140825923263748032598127575949995761019498818566016398257609354069772389656925099 + 4044422726596923902940860834745051450250943536191821985629944194928632102239101274072099618807513448554296724965250996986364924 + 2354577685813636309146827729776859816069210424412883327405297035176569137490665953223528983078628177275666747947529655966331575 + 5477299131598928984485290428357889109417137134680518227595002407302611193611761790018230013945563583265000510580955975339191446 + 1619521324601562573756521193045609645344126519940152032470378539517720502293336186421186366939997498341179560168270447355950110 + 4230306307869293075421899272149696843537151044956328729562855283491975528896006550623263787552206307775364239158496535813468780 + 1611641802461249957884380478543784809385839965522996094364642447223105495756896318541934272292804367584843894271046287233761298 + 1709756805199283313621618096481348781674012787506990084789188511001769795898381723775624988249883268986469361054705514036409475 + 4042054305280705588082843156563390558519428096353822906407664058875561059644605482196547535261726903242582076817607377960964154 + 4253860999746516433043460107715275174182573491654972680242324213294530205657678192111601960601634649905585928529798955700154076 + 6676179068384501343541631038132044675296273720164020679619589492139981245074167783663095317254579357724910508792547067262588017 + 6293884180622784793929874980896521285454501177558249542530377203281315652064795385736617567836645686619617679168909645709168097 + 7743521550856066318163410468235782415369091035062393314878499152138458241235674642599783367386177248502506902767835896501146443 + 0483794093371674252980588779386498050198274197464907995529503130294921702208337296889908183028360175355797035085155032755797134 + 7360019231801705667141478490298073274830800662389220682649304818227754575701335947775670426238672520023046096705399683924718657 + 1560373958818879850684156471739380073353650802319300382801718291634025935869130174150899754981641558303334317282125650661935271 + 5092493350585336373714086054348812631829949972662091014907535609939068169965945723736778889287001972766703372105697934518100296 + 4734257102525392916687039288087104774233931626636454683584533774360103845888157407165794111547584642769928525653912147278806542 + 8822290823497972283964354496248019949369662678090787983018405519062148805449317563743875081526769207312318307346979280704726453 + 8280283626279949899078861531461602097441638970306234787225062938541682486544091938804453769368426982357391305981842832099966845 + 2217356720554468128605404764499852161966456502338368106620715847133295711653095826628517163144372167241765382757784888551945323 + 3293984824292108860635484259719926152739335450946748798660592468126259449417195090268999500256639254414418461654750409028017288 + 1675306289991237206693384004427250238261655808453706438418460194044272886240166511333039026240609926117492662156547022216935277 + 3798683710262055280473341604637975853707715733359848491914615475081846941708688479067522988710484836724298291195075742855018190 + 4581874216800089134728449476207100847781237572690983431502108191722970308605570690039979318708286697553630513952137757229594209 + 9413803628857147469961583711007745023208883952507321209502032469098964348049914806057645578293300641835023243516073565578336233 + 3421265017714445796604621284137835957308268098924387669789495349357687107880833828961898545436375036341306978848338980923182467 + 9343222636188028392447876071807038373006670961664292112334770077234449906744690005047749541517081971030139237186089097495754677 + 3197112368581263984569948101844452284212008325999133835851189833940770803601768180655910037983634430639371254776873860967944989 + 7762428156063656052457140048976461668407455298961839410706956245596539166362271685772723545123147978715000469199290892122691240 + 4878440976953031234401260269958754462435834653516282136155912652234992770322924693740152133726104201502258366755195941397981349 + 5410566039278422394352444668313290032035427902945347706947962717669034134093986739640503933965401015646443482046077453432046184 + 4739388878693555231586220110918786353416678121114400297535390976972658914130824675010539898056712966138526147925359029678913230 + 5886358316255011245098615464017615182438190446564591019394412368509357681569397482568515821423340665852760995420364289038278484 + 6311541503127681976206070117236931568310981280275285971795790489631417369196648946460067342315632515195328396495936094906795027 + 8224055001487992245066819015245704964683485501844381492046566836373072408682020849321689488337660828971885175876650163928646965 + 0254578793821590283140178222280457619069765363934967602749676534057099985483967828656474230988014165618526645571684624945648693 + 0109665916508637725280874977575865530242997110923401414431409335639376452646452851515568924163798404754643876369338378812431753 + 1218315801760060263870530314784967603071899867258461326183988209146000243519324558810891158838383484826158948667409186010480817 + 7903203377696988414945216232421892536173370183150633896237853253925354364816894136252089105545529048726749085139508534886223860 + 8148078797101770523716078377874332667044042558325146665083596936734559299430024125955358519934955785765198216278595449870598677 + 1116539363983086722722201448783346777178486858969772190694450961667734803002682120934093453206868817575132463247817949468716367 + 1637275206589839665316460804048412011573846372603155744795091025936193454883889805228527990919468358500076576823231506244498699 + 0027621847956067398935694606560509614067216464874695482321462823676120479915649013012054108931749591716879497574932046754706928 + 4550965358813639986179681154209780873107404530149950214180601478806568724333935291072801881538682786052141302073521529721130768 + 1636835808005913985865949033373364692120504151732972595493618693947796782831116462924175961942781719381911750675622713009187832 + 8144555119970713260660826605512619993205968791014438812251863090080817574324870955751027471809521051989383021792494139844493682 + 1585931821612292754292414253292528827165768965683611240737666722015320896218326640019860760530517054982970340862863680710846055 + 6536681595996347954437568694119184759342070677456835801973881107420392523103849305532249049602562479138323295711575175876515640 + 3486443061013741439479986438866229511864021882422370923187276377158037668029544320414759066219016776345013936686773434186071692 + 8652668214037751054395752355562459984977103091936105931037362668574357365575540736744748684242434859190554622399068882473374610 + 8580093375714553964201167764812992676992679093090175449230495342109288752328986692009639151993677096258635370756684860954291469 + 9964866699458956436463452444822527184213143978744043079921280767307287341419726065990023057954791661193301961189038570454182768 + 5099791381798674690627429376704901489902412978407791536768610182213492340739402802196624950327768967894658802241237435134810216 + 2644824029820305111520479567245295948221720974051912855629977767969256584700072624737697630748957013069006968156707232150642177 + 4694014156265815259320275858444952794733981468869946419687206201356067556770447737925027827372686022309398793525531551762030508 + 0692322520193661664579545021783669513925271024381519716157761278129858733071273401229450196329877841294994307214799190419756421 + 2529925924690763185785959066401191385349387731434107358942442763904987402826148766868356311114428295259838898928666272489020921 + 2079494677073945124622995106365273958525412410850501502163733379133554803716983972906533166904636077433873959124786425510691812 + 5600448283577862312179623155268824754692832396408303848264207707120544301021495705368104362648456117090809527815889327217546635 + 2343977389207774815138566905589371213682572216665369482458860895527700507201800331270809726620829481769123927780354816652809008 + 3857604203317914309286408408516621032904248756858927009945259813983765983907916658284682954733130678932128039594166445571290526 + 7783506576165023166951251072092917407173251744876214934915430447355544209919802690055207660666887916247859978935839016078615261 + 7480703460843227445195199879222716960672528809567298037159358077924188280933697924269515298429095424116709060884750185401083226 + 8717064476124069485152260308142874514219920880901182710267169211713742088964956637523570820108183570127357202528608391772392065 + 0183762641286324428853776063863402233453633712505217167155150999046272831538702513532943824820006210590058738974696140094824531 + 9112496681140545311761452054846654072950289614507391281868179377997604366151409215985425553727631766796511079991043874131555557 + 4848466672408480575274846878733482332783913190570793476048801496992752228173129813319287139570412963303092066006377899503587208 + 2004264846825219154033402067536124920004600149381068226608766267724446119288301005499297409144197426544971420258082942394022997 + 0140320078386067723015618497818762945156815014583969278200840575341177014900417018827299383394638626203285185921061940008032865 + 5962478195492396384491797383201234602669716423445444477699550016949258636112731978273213688262995924599283114955724957765374843 + 8311990015515249068920407871121923281094596878515199867380540740586492915851905851867276732161963585489156521545932776243150499 + 4592710682075197276504754152068206668838563346968654451648904363538719952128821973082368544846718432978965867108316589932428817 + 3552163482893373255049569753046229304178905562057146740570805257427023711941189943044300807285165026750415508222049580394911287 + 4596021173135544782173915901528349195173147664807647330846216356295629295015969380040305219923049284417801673254103299322068397 + 3943524404368165203936926893260166313850279802117822440456770151714171409778904837544726372346574716859663114202887576413543801 + 2969116285326615235890680734637608834483184611588075027596448992877129841445196831709848480423954210927050978003235143506132046 + 0153071245386120635128957595884412738484038627307517440237760302728984006580096280602129668935036883924996553872412205753013658 + 5621357475787817996023091217050008449865559719579810787563038126520104376758261418798236153692393962370203265309058313384060120 + 5031974571476436448786217419749048851015183003367752606459920605017140928435866977820091890996541266633748940714886983142086133 + 4562696779266374687250665129144508120768763103068669726719903362264420017240549417302081941962780048493798236161080017811934325 + 4744441027688831600256636793504579543928756869184371127623452884135869811364793667736493944686083992892480103958881983194171487 + 3993112528998853349337977120649249691278774025202103634228484270608254195748299845801769708524194520077695532568068092195962254 + 2329576931503118880223192095103946522402558163495818627264589763485690044385772668639064805859345298816707780560479994433943363 + 3218849814933855133187785331003935806771232881004238706522431511966088657254108552621744793383328388740747036182217129765309790 + 7924052825089429554499360417535494167874442982520963688982831955472793462543386236218475310833559387701937594241052466519691317 + 3120730387098471204669336934308519377296835486747153400369971745719675185172869103202802955453713945706425356726081359191431362 + 5436861304614177525957519069526164638577548380287496823470807113570761415650401959363470580496567502232543408020661206474053266 + 3120249944908567907826123413136257067078494146549111473184473022022655595636232845880738387277254397911665634549126629364411401 + 4035843002062617386757564723259476788690970258752656414372739557004284974159497458955655696811845766981760932359601002427208626 + 0779143969819344348002577455948300927630939121921547040685880544649850641595729872650264658050333293212488609440422250520307515 + 1460705203029148369614787086632962281691805758071437499284040866802949156450922963941143029043912074471289441815938231327288667 + 1549240739672667607945860219999638499322190035348564953406860715951588472937396572245559080251322668950418605324345241657646723 + 6681600989234088565629106267156100053645378516406056877177467623317919074902879430656553383602319342476881970725454244483233156 + 0192568263169645194866570376494013537343370202553601755904593727729559768993904298684689230055250228064310566719259142616384584 + 2226698070135175270997371657677443976168753242911675302780266617573092075405498205119010526964247236701457645067756244640039560 + 2411523124866541301070099168413071292074360672744530325093983003307829914552999628543032410966968534244029432252498124255869721 + 2032148958117324274615176859919802414958436537913396718375158773684001583339324493639015775574550405787223527127839505198335838 + 7873829779466960857655228261450384972633464601331098096364008012962199690499598210503782863578580915221775299630382906076523471 + 1033617798236208613493443460691499481184470043787180389655899698166528830636916915480716417683921961582857940369278335021557721 + 3570877773431086041166388678403654768190776468384892784896107473099172280071916265352211077124176187206981633533447143541466428 + 9162337956051462461244081308639454192982414597589520706270659960902459420484545944118766172576927213645046647438580806130370976 + 1679386001024741318115842266812215689927333532837813069949968390429571894735964678235628716093113797167330012932695772923859921 + 8804168783787089493714870963570663419696958001331927763315516123670935571014222651056237882407840332672169785104960709919825245 + 0497455776366854139775882322268590872937081090128717394425875756408043314452495438785765312873239203328867278937236653265323056 + 6042409906538241575209979144212026252259767618647784026916367882392586982801406891358315499203056053321982052638011533498889270 + 5665573721287635790869699668106163302621832934471963587290594671222971786422361537494624465628017639194877871599798228379718225 + 7432584741479817366719910925645646541846360875945358928938495570674893693392242341873215005147647843928108951666723535877703443 + 9626429137239096178611195842928172193314671253797016055524388530347610194243157336306488458466944807366840872517364192307199510 + 8872554743012955139567705170988677634651238832225827058388116110755496007697973600003490415480515644505946637930188314840631970 + 3992491991103767989877164315291928453885661238942961179632807297112992978760631966972677658662459086278724019257889314597469958 + 6669007755891601840756776309575869340114031142955328946684465711503263349456097268207290469828978418533272473362080110971119500 + 8033630970428066315841260643530102154382783569132687157611513276699429626479061706898110708339849619210276811595853043955446869 + 9768070537230217029438684537825935225327148348372819431279340284261370618005491965480298943126300044774337991256135794900355667 + 3657498279192720768668603975934793465689868735015232170607621866439453389115795388712792645934981304662545764256708338815562273 + 4841652997648921227154354900004136760485517640549167386012657306424618486993618255961405066483542868908453734101505226047480448 + 4390654153631921147807124887078770782524389315313338172327932505555766712042126014521672948387933863420403298182271156860089870 + 3083699675349781049946715849913203260143681249018875435801318149856990157414011015651215483550403032096067120964528627647289771 + 8136660832504574374548878451558509361941048418373428464399511971079202695299106137651197289051575362091446283996841312766684810 + 3676236989934685487277460614965631287879882167402767160319121856718994264197563392677953816932994293095294646864998371569945650 + 3049112960977618674809680978004704430920799039334511606915199457270782728770389854739859266964607398443304578468934206463864162 + 4020319901840360451062762075624924661391286802372025413278593393390727656336661248466535685907382226627976102440776444559861524 + 0166268182450996578449973258577137477283861283683233635300267518223499975003192269667287508860009509128730943175015750710725727 + 1027094337033962463834235326303117245639527702316027545974140882034976571260270032549979726479017186330571896766878727628563084 + 3735720519280562035416027535373646170800608954405500868661244053278717672230128154298018261865339340499855937060742071802179228 + 4620909442780453001381207438741771581539126274686674694429903202199824281873555557550181182902700089108021432193493732079872184 + 9458342180011256500005493355500078007350011604607303307732963471459637499551951642174991940916434214889720629725398539493831562 + 1757418742866953045608344774690257090125548479597625280633090790836185148048976878560947512134108931123436802430288121604450838 + 3439908217353866705662826605127180864607977834354266960510252404933627640585873170058624018410480482791416937234522273135497031 + 2172788248827330880258621512418568877495834091216163584166603056260778255791670347944634914745463656259805211952460022859276063 + 7062821874356395565274839950114991325558841496177484931811683058289009845398038339874364587482418953564120109998982642304471400 + 3698346712015383293895452263862425925615594845734737899372976339855075694671913339207356770288208509103055437248670557197975416 + 5731723926926739876475885511154531945948200793682997616742493659519964588297814245753251250515716831733713917292045440536017047 + 2326213034490494256432217527368652272393723129996987975280491971552239548286262875444742346718137588580994530639159848308302488 + 9664053981063208567695237243202681506536792559295775868533828506782791916794818915656227027388965683683700700077078525885858163 + 5667625010472277345606381058073451841188387271842197689932469281333817846476853011214737420944488058943262260113307982047560323 + 0376867635943376210756229949512175221086640268169558374511241311647850185329038766762763270981601390818540680562189733654333764 + 4491518223112590691196826611428935302844272864063278173063473168207705976253698032183297470010465109985370388667131449602003018 + 8802699827748011182168113988637297474486522040228085650948530427329245143454181410142916723537434758973564869412497956238710891 + 0653015424586307910784932154517633495234468902775642895621562573878654050393509111804824221865060266482583193591594511748836623 + 4094703884414114132180304529532880233548615595688135936066808466092184620343793991343848249436804401054149903884653644876865628 + 2718370374189505315521628763517179672356494682994180239553818915110898807872150301279550476267769560111595428023012737770277809 + 0983429088572418894311039932871928790123994971756838750348015397853262244219489154464202472581023076365814977799205726076421849 + 2244581657719291754700709306659618001196719303854922152332583798578459941542447742263613733064435246505660395020395510382351759 + 2371191845917148718985406337649548363315059193935226677398831831786300690640380203874437098924585872141781137278459673035181084 + 6868095538827304671263059227883616117642085424440799227282508929248920781388666797060697845611588551792908329555898460456707821 + 1192043306305230972108032344493739345654505538181410336224627870081996078504793311999388842368948858806146981869977786056189228 + 1263564157432629856155576816827336520937607635620996781728277895852539790604285849253279394716497232033008275892868545867382681 + 2337190119883945387644191032300914026172189976929618448527119917727894462635110227775485639758673866947701176216601761844984677 + 1541725580846818676211322948610609824222332361334426723507920844056410476870968277509960759021044456134551342168799278225221031 + 5808026746515835625867232790523509089624770846326913802756163972740615072842822135746471264238978131846218179577994033108366459 + 7209194492748333961784669338759539252535168061991620450390411453076684475148292681430958283119646863377618784660018401847206388 + 8164592842234101218973444204368622348477154717654721601252474279965258123105673927507866232148031414671644959483263113289777725 + 9536506697075295060127905565119738004002490249111193299408907722018709064690369235720344207608369516256550493184611556526526774 + 4560017960261564009218990204461419858845480963206874732488142599183336196461705771053123771553268404282868440226650446328616213 + 0784979620602852570679351917990832385632423349482355239911158425540111723754138128518596135522138872178079847769857439148437200 + 3065506422221326046922349934844525141835749289303921189806839691414799095653902814723672937020068076690809012734952484971091424 + 7531639556490305149862508189711238391327019426642515502558468392326082589336113833462268524671249515158066960751008937821736410 + 6252414527138677204351141055246475557495876614593229376289610072418141564580640343324426668169327302426458833085549654617933468 + 8091658367794443766667336494599463493723421496560610375457662742614878721712215614199388402972271203457264117746009414601292472 + 4908066830822438120188614160836549308604180994779262747990121233555704249867768081188552478880193430879502515548138613493765732 + 5079293880539371206967935767115987717076965982796395512686484284292191272158775216705810765026584234552773076439527278292069704 + 5164216628992440501162199298685532131413675395537593848742057924552014924010292705113677909421661221880801679108009584398377793 + 4121418969859257717214261444608216079650826208617995799712962734646420115576080668425510442736110574190180643945326397724337600 + 9884581544962427545759780318699856274991305713483502351242287264905051143111943618139482715140793163760250713362251924403750737 + 5001181429052612807248790060512136898354370778167327719757330132811615985502470639866207141577372460429670627788129417134404406 + 6178770653157619944192283152223652702640541977712224400210339303510432403323032560310805508239002669348396267104479169736023331 + 1565506146888751623012576320991779119855864177643274705087893960131150916233068282254723459661688282729513190349028463435804527 + 6845488200397241399013882436401994250911820745822241059508913459645459567274421896167243282273985655453126249904632199335837792 + 6040683797579452107027216845343063524780614029426886935760791257030864245182939630838108471908303610357161096840181118609152193 + 5867358422344899058837359139467062379239965703229659786120062948805736192330007221916713426793575162507137089954539396331620247 + 9120519760679588392286105798236021559061854045122019266108300186277736886734969411204978788065566311792204801446141473355188648 + 9729762487738362702158800023376627553944314549674371461896299198497056817939283617350417487984379973531521250384859390378780952 + 5278728682099899168824382639886768910340224230494671557124611921288793461227571446099109231672351187529971910075105296077357641 + 1730149007222759960804235202582288759192771252526372328644840575023003569331571124411309306137954892577214909905859437364845514 + 6359722384817229880817656694157685568966235098606153131789136445509767178564237103959982917552413501317717319150118113725281168 + 8331881891680259180368288807257087972744816443005083134263401722243486734946708091896751081947017218318643507133088446490502898 + 1564672123742228001093857696640500357335628593848961899541997547484403147074041514838330205353223636545525633021798226061157975 + 7577934224848992516208537526305362086756191009198436224096722971843979917310448903629548517759776409320845391838217575441202030 + 5842023675100545856824292093806577194777854067803726567456782139496624136800515010149246416535077787552986449619329516458032493 + 0373167808153255052885634740314278397690578953752487856466779556596486994777425942109945709709335720717497273570846620327341193 + 5952530704523306889233492671665454303269886039975987299656234612350738474857467451882170147036566336312226535534145167519693735 + 9607859559588540690534618223279700864577721437927651039992456828233467681820892987538385235563873550538138831743319323285816092 + 1624406727909111147099641441681559414299104318980440722709754783222151032344202663364762643657625463452804121615256537142718557 + 4340315496406729909696728430969897055002939519672286841554008064322610667892226345008617230358420658804502966997298469146129669 + 0210625023915241926959138868143886129423564883883556915150345946486026490910420790564346970440390087533686122782420012907572301 + 4721491005031549006749404748103949153294842924575427991607317267682247725581223721840333859898813958860082395329629494670433269 + 8089333321693829301610669436388430107322213493559809633043551047784093889175488034859221042528763690657356439399119706918708269 + 0081737607011167672164816311361636636595718748621290008823635691873373600228901339494989909273621908199424676593460415730887285 + 4160520455923507310701763781457568843470746581847988497318956296776248312754405407533119008905656107514741346097573287623338123 + 5386718227154603611476662828982111704301478482540378612558078862521675877095588029121004214011721936617184276464093409939658461 + 1979208081789258362592059412017416272899419903367802069424612928998858612300695288310086571610845555893261171864325093713786916 + 7319139333841813731995304531194319105663469219744020376897814143833856662869242932535917521586466923358318419175396557400347006 + 5043921771833079685531325825310432807800223715751775658072562091646020835717475241682115604301178255769370561929846716138929898 + 5795009540103191080406839616053879828656176434583781287476876321448232920090228345539065457933826027880057345811966575002039185 + 8576153060956850521311077608763009793771506275720974549550420722202837108735329754654396372138014747847396055096136010954168085 + 0509043015950572569270166347532451603412568949379675617083809175396443490772874366901432037667793377607725671409709046037414839 + 5757807520296047868933446233650750653295440658940733452331643306076758589809542688132352958487696630197185077693771148210415488 + 3493366273573202706880963127674882710949035853748406509260478202136097703296547394474710548706092731416204930859887260446245253 + 1707539941222225775800658254639655291940922607284340086831234164821348634212665200587884346716985605251686416602230060503804746 + 7119373075229566064030462457605177717171013246215489918839015056056006164706313041702800263980277171617607329962257981016326162 + 6663813052725497188713444974040320318581428866821251405183260930030389032259911879414867761739508256774997369921307923003380224 + 8543233997255243697045277479565692227756699494957952164631865806868110331658332715068585534381871375140656787606232565908699795 + 1127161017080656837915924804407883971278108801828959672411183897706979458144168384325785293840525608900932906069101189576035960 + 7746884054099676741518894156142307630763897600710799726835033615686726465390861737711082117067758069961050536090277623500309130 + 5637631551447663652036022243883777403508274485804348060822361386569981574710776219228289288499523332852532323527986372935987772 + 4799128874055082677319044677884361786887526377254867769810507962743180135340211433750487850964619355570684078365963703331785531 + 0073682589254914802156389462761084682583678912826358978335933715271645287806405047356166648799977142475160038979372628423949010 + 5037559719886724670132444119093240447382541873564218599313650731701908225623880448841585926824993839038111972019595929993742491 + 3846935441857871521862191302228658206156991884533871767438656661539104499878809823997230034119838267962065754111334791148146756 + 1506245754838722163589450414720903186576980445131544657545019758753225527419416112605350003805887953770147934624442363883801265 + 7711965724693431682894274811945992120534708309601562503539815868676726704850890815034768784240539682384600476706665486329906626 + 5956050270087533659778978762952993742209890928275529257391035690977242967921950083594415755279086778292240063613624273000623384 + 5061387982251874414971585573609892535056862802605728035065909921406395624271235709374930413322182966464210152496167481038893673 + 7793264955081367428964822852138933334974506780923885826935088471472828950440677885279984646325294353993045156334916727728658382 + 1917731844388737433964393775321834810791126648863902100900130682254900663770885502300591056044829585219310561565900983432788348 + 3993621103753371559559083065225969001381490024230870158740460349214225265354617541796726739208926003200650331011617584531364466 + 6446975200293349558151403162258385505474942322796455463090381985898884153879810666921247678344495019592171989327800934238087607 + 1116773012813841761179870425820266292137052144431441290909627977940969824030291459806507439794936788928214828707352139273391574 + 6029232735235425403035383736905446200540026716844974571516139411975848154720481565143793111521425975198184192780712740114138327 + 3438200310045736349450654856319455355471806503450945057852390828051199118282010495739738213447341204668213941183921897766832892 + 9512957847613586351781261772535091586107882959218997758350989715296118346024725200133884012765597340862400507624462524830866480 + 9478843365776113648646455826476363854336443473601804016310466451767185956320296981753166811182992550179769973329037834636002638 + 1745421142947154461000688129964181745046963595109768527672990383210124171587972151958957748633651595231193536560491908213623383 + 8381825139460307549572877031135183947681591383140425137518397676071788098018785187454915609863724531998066262732015118963304139 + 9818630925621801216199389879103728134389152002296761687336537102178195168590959317811012194485775439363610537061412149495648268 + 5576817033233193054333141148999572966012541792116109714940451926593836005748304065707002129553500879663495665687664101078961830 + 4255249811578737819490016920102133439336759727576849642889727534022902117660385461887412305323198051682727105599743797538768483 + 5664318936157823403995526721241574938566862585452228404066914834889748254113822291330168260243598542768358287033612921584775608 + 0493408359374626915181620402845179233550927620380852963377274566085358451742815682206366209318504599243115355217504587070160767 + 5099926458337087971802835525020183140934847289656680603935783200084783016975906879446974951582977123093907468193624294378414602 + 4993211036037539293757401608261712055642333911428904305517543773653002323722539705273891988338327482438288308063770111207012273 + 8875724448927612453412899117913683062983270974383158999932195926949387111141855398745328636343443301765332909049991525667183004 + 6179446485196106673286301271613059516541037127280321853066460858041150601008945716021915010720764523897185471929927560029444239 + 7849437984569538042541347312104898444874295714765888754190517892771505925662567504469022216257045253341087785885957187833718309 + 9972288762936380366686950714951282499790474803745721728891585856096753079311064364081796195123806475478622506713826868777638697 + 5194143783169339034131894869316961917794611019135131983101366014715857076410377619181633332553598229324447853163042312520962414 + 7850854551539305001687198329060780010579189214774936469033426991594801002823836027328068965959941131816419243666581830678041716 + 2062179831972241107526467338284038440066567441767013516710832064119073030278681905009991848241324570216334414105094116172288746 + 4795251857046503954973485018229646234695366724410250031504983138843493652944866619750102836093665932368212191653037534272918686 + 1825362974498797050137125577095725107017850998954189361286965048355333973664280494182300562942448127524039989758648090694962142 + 7512994410145549835156679857014752505125401506747737470958447208937721056830032278112608932324610937928836512547690813007773206 + 4386958625254464154906642431853347789932184826155599439488217117827733831342079710541861559451261895702289359997911170346503767 + 9160582845194443225222601665399912946931088757458941216770145834719498890068834370787508728005299127862046720974369218083539582 + 4881031377785621947067985825999914746359269429111016243690638440462655472434228579718379181809439967478754245522265321625889814 + 7583391301685587265357562950095622866121830355803288828241373074939869852539741493888550714334780322503664271906152272539287229 + 3706056275918240737054417094100085374094932331005897520832184041773254725650156202489186855782648043533132404772816727073155235 + 8593562217884076811451277453364735377701544569033315203869164836320799479709306444027657854268527295924524538225997862678112859 + 4570537859634341717395527618756161556420569519217630387646444203036568601265546935410843254883517475649241288633895824882290087 + 1279603976070610116464640212199310166444520867245963242449012132718994226744403248200981139871780434324112903659101791778621066 + 8744850384566117283317344846157583437411072049976031321951124766354609384768681179440522110424899002915456603055956128713981139 + 2086242661312485180876173221212851654741063402662853918748324706267356051777749583559232529239969008936507197332763290031477120 + 5741215520375853751719868036345389495144698592395029595732821924732143612679143914116460149908254801423378398341400612840255578 + 3112678009802694849286559093313827681147182296039209347542924704088172807791962585025279313952354773038812296501897230865202710 + 2464335074070148432312036647984428094369519448454963043288725321796755075626414550577697084871002645789785381682654641241100283 + 4946700365473689782081952042866282556327651210752194953923594323433725250140138447685850292340132652464859222629234697220377811 + 4116813834263078090553178959891950239969717708797371397856902146227502290357214553371450093318491311749632101080525636146301695 + 2152016442288947698443136330933042135184223974200115803798042702098262975256411368585240157169341361695851434355296732786801088 + 9469700239580500443632308541309983452163906017765379912144038775472527920834490565234287360219977902823838503195349727039831496 + 2028576502159755428471922748239092215954614499408923132851493814161260002491760119779606365853853991681827617094579573055586297 + 3640678920108595929213187711839271941417061119448282180155978731064884982006841462863880420761509974612500984423805360525276222 + 9057118337335912039094779552592972943649024122835147704439083152493402341167911887606112405528052285968546122798145084807566159 + 4304613049097528789015322647077710992450848025235239429386820053371823148160964657760192249248892087179211556970604610852657330 + 1245963067779593226119382101475675796217312455063935339967592594066075071514347181089457321147516518204553844378465193273590500 + 3560863140415397624008978961463819965678362699058645101497391867248986869781266285523093686811424022579360460735505488281520907 + 2803810314481228865478572362393166113955034570401397318410902932552817985751479490450351950758398971928389088057335245044158094 + 6904347745025056517093981246275608711548205826384671869194152526627350920208727208140128575295910227390194690418706771705356517 + 6784445719916791606648643520294851397681933118673503958741728387886357271190905065762821681465016058740202568162846967243295973 + 1820495748778970925066926664077661706850366307799032827973753165199895444172414611070770446635902894354703969177838887030507999 + 0792366480532040444153327711554056488308633552915589047332411364711058132183546270866868018652349880999177379420796287072716088 + 2231884404962985945388134094475613555762253572694848559208422137166239633417739879274457716224035685193748560132590653034477542 + 9227302311116220471908055555125965124068362598930072116668063472712158786276348904469695948132587468164071579543544049342283942 + 9611661683770276849635190630772488322125598419492636769106569145188958898006930644639421498885045868655337164693651551682789719 + 8113170194159795409724804157277970216585110875118496676005194638884485314135820103479833056690555003499859437927213123666961409 + 6776248629614262117061005539488708741664752240716973399951870993215840911122617246729216135676971155075389185544568368200715006 + 8136621653681348621828391620654330376833126244814473075974634681828022721817501734663865372891778488609175456672709780494092424 + 7509035477896901683836806362847630551058479464889625032860924968434340014421918549778761662492676219077042005549667470710873708 + 2649270641258444022173705146602820338815565069036316996296828717613516424116147690610506944602495068800321856748967379303431711 + 5231537094318273489411666006633698888790246462698166129109823556983405782712006150780252324827311704109848150151626541203089319 + 5293239066624699492800648051071066181862007268310279648019183315312315154420858012591159812489763989269552995744386956174038764 + 5180720261104219765835445462051189983679962609760132661239453035110340712611783326617205712026077627868902275865901764502746369 + 4450386186789754245435591998462910276602998139642701382886884245787698610667584456364442583085157908011542453439257529663938908 + 5226947020891494666123742174916211157087031239651884379910014927950876644487562604700114503798045681730239237952766587287565756 + 3462320891328376981719619778327669975981463699579856289946252639770341221258397441894692753073255239973756891174514808164393544 + 9266128730309970612623389424292152551017956433451773715730990286170012828117563840968654996015507568606746254308032751484010172 + 9555122523637838569715536561794279389081447703619598960381475663155959964617699927258813445644496349054324074619586132556815203 + 5221901221258703935673357600398356681976947446424967337708716326590353253394660639230448040100077013280765926948098493319213488 + 7738313289310543436800301466124075949448435224583670124694327098481119456888840896351512543815188557251685118660772588456625224 + 6115002819234894874533900222654850689485882307323315708374429887345170183105778321445910604513739852020875884337203588872923125 + 4481043241227156956639553841037732426965917364470043436075190174090995043087977394594850901991029121373900633832712403510778230 + 1122190232976475343331179295988355035324572960682589565916578492624347219825791452145522290660285362795514899273106419997278153 + 1419535386080392454227188259532485710914908620105317213100011817889875764632911121751593887025644393163109071422951719422847110 + 4026612711274029089236246041114948354793310083266181854689070097597525414068795108775947050469531123122537281180760454160254035 + 2729212202223251132035733428110959851887971832113712091873626429082924950281013969697115103891338579818898846568239238607918122 + 3944336153317752913161793886424178237035722936447760222478425805766217641600209813232221230340238786982394323446453582721990048 + 7389193916919980057221104426235427350670234767999865432553198312811347361703697530913350075859737082487587469312736993623735804 + 3544483515704686277538264527506961791275819582201516681389283444580314635355964056417380225809498367162186604237676145482322561 + 8044600252747925830317760868421526571377975782889497428302869692743382713250361972424374300944696385157823203594995989063758674 + 3762181316198228161833937930845505733610147834846550265056669736693282801787541130363631664735877621678425882651996823896571197 + 4895759837384473598984792357851123553619562828621778670882704444499813426092540279529447104250292800981220546692084253328082420 + 4664284555514464728238600094152484535233997991752935740228264651440639886242409459644164822259574135218995760166441434144147387 + 3498021732532747332097779512063273078194846290742584872890698856916194513341236677884416300942002054144602101645686192153654576 + 8855689629475186087358536061769600329981635356231999344927571715122048450556630571843667383074529954198709235538731487573715687 + 0984316998018946399866843104618259659452795653432490384229487374720689309493558506727485555071518696965289338830868013877431679 + 0444954460337393289812378506420855357215741077375742703669752012654590715324153275679920752247842054109194186158654335712157841 + 2806861505564373354176276173563926841713871053400626160801979041772088503472612997224598155147542728678254353573523697935567654 + 6201924274245126686318859488923564788418058568530778365444195042057133158737326264356888205129275667061366349202778458019010774 + 2825177079603097543301363195546845866777243546459927001122927276132658961336248692066215766333309788747162494346240324193946246 + 7328522607444197904276536531669234484641234327006749709725328245867037809150903161226855351918234564454937188245329779811527397 + 1625377992337069927288579727970280388115743434164021261444485502332859966787759877144357204976585729746356637542057830900380879 + 4756314028565636147037500545330319143265189233753100563686689461353510356901840785161069243491300815016067752040583292254841464 + 0425017333645387838654294817531355494569985613245897735076448718279104158222119913920255342054852667882224523660815046839280651 + 9062897569747184612738179958208393387812077029581124581459197624411283206076395360970022007778409057996215320186949888642491834 + 2577588591174250273899408593063983438617592453792302359558473005206418002455294336176016723332413815891373160708758731967049062 + 3790766334026767123109787766877375184100806711868340730414046922950551256206928850545228229670325982658231736019892656930961551 + 5274543406306956723055597804421123472449821052046299950205504470231963135543548703265039753201973863356153745730092781664650899 + 1020617263114480064430348590768589835423732129147820366131428529210137664442462332795234431300140813802687903923031421483099298 + 3305606503022918455845722586154193433226668761115620627747430416848925633688922763380741392673785175993422375485098655310345526 + 2853130953848078288453311632699255400113689129756388559283548184844635112023417531659479267970268571040812683475165664822794180 + 2783222167931397034746003825257822695087707764404029816076797619920932960124572983887919479900468345097640119343412470086673322 + 5063459185940735886394343828328918625032505938760162817991123725871771735016474675217009872180054875341819281047070252038306775 + 0743585397605286027482664572990290216960312219499687628442325704541075906118067163819053997876546874075941147761887253181403133 + 6865060056069818696891296915545023370983419980885799857058396262667622091719201948407642987224698259796247084724028705854417594 + 5103827826152310417357275607217586307830343393236258610369278200854730301259212109525027296782910788706655437239982908254923137 + 2959652192735329005701145454769790852470342092444456431448859896236135922540005403226570654335981197446157556763871319983952696 + 0906069491801564153648838254163601062811138002404571553190646376754817601328289018602749191681199089353060650264442584766903530 + 3785962322135501816792718661619323345882587573641791662855806452191640690223489872037123172150522718319643946771618053874607301 + 2342704599377336428681571005102144288192803466969307063516540780329331225964749753260124769353818714585772490856102378132713276 + 4346236542835966635872778222659462346707942811767870117146806978169322604045750387880280187005012616459999816635343308178563646 + 2604219260434304257671433967264369756269802345023491459538543248359901859356108205297353830910989444923284454022447613985397264 + 1822281949178892000423296707942037651472365683251029280064728588016134363373058610506594311454908111460545368768742973357987311 + 2329670499086760430314104242828210716854904379725565610986919473143807393666799098016719544449077169306161547903571473642324181 + 8934928646320239275117990276319738648757543739070170895539210951333884142223117539519009532014319073300363829125825739466521964 + 5363386211310899141728954217940413318460520197666536176317994465965648033515827854532405714333529319178360920611572195490491843 + 6452281693971710923703852296775814957821367584399432406445144322839651572894248840082293918339020670715780310479909368596480688 + 6791949317913799774656284904153563675547018432823443924016298235065082832647707880299401729868016947630432394689913082273372425 + 2712968598557679357916581334926350397464524640833937031346811806334561647348253048938805411658427143226876519485429485016393766 + 3501555543617126115194082213265703065410803089224710636262686284845574699295863975355551722711478618786950261560124771603773061 + 4778106677024357003045486275897639115668057170330533010873096634039731123238801834051871842868704307554039712015191582514954442 + 5218459195255301650149970279364690486331464065970810654696223977244841051824600951397161627678662117382548039349844217280375193 + 6369806374093253248520031657537241583648618465123745039819043766572718344368140639003289414418211436811709774570097952888487167 + 3212569840247911007598018387084803647762488058555511319640016886915147136497977845568137947542869347226726490373484609221240787 + 8115733543956480787117884715874295702599005706164646884593210924736152784838359510894224199377258864940900115663844969555460182 + 2035968818201814843503316301816877369650620471604903993852843829395302301918155158237168629501277731356144310878037185323999107 + 7016895419441126229181619830275636225832821520441765441532992753638148826237793875874434736200782222141244213180375828740996801 + 5879711152250078980107885067914386728437059276590755707069830533352692084569773933300266007591174281283361187767672358396078896 + 2103537195144138796197574043874859185879649977538344432422677102393984939164145250471907596342652013494773096173424264207508962 + 0637450827987698515011845992398093937196147180755217329303542644463406470700019971836100495535322254679390620873420862364850762 + 2242509562912546291760696517385259786276250406593124098460913531494124669973775469757781521279236307631066606896102762073078153 + 8737688554624301439839538446862017884613896797755819281023174101498754986747558403862071766932594675733495440363990431783540137 + 3643542527592425148722339107873667468772709136145667446671572809454163340131116640859776867285040887038441378816294697995941474 + 4072206008606547388536544456067257224875289444010744788037863160664893445070574937489602184055019861155649531412106370948013649 + 6183624181311379076807905566573341779391313360549851142539899794930473883081910943750299100861533261211231956101452244671916467 + 4790552691647255291761946345206897704211085378644313837821311423673070233392146600975258580259558879486034230540380014801626096 + 8493966397430159495762611418791059378501633459275242578770822154956094389019127421733416568122031957966837378624113082091125501 + 0539497663700011903785013114734351822728368447618541431249895153026462750771721023669565811790420914410370442390790070707245463 + 2527965030066432300857015457970368291786471653036513592059650961230415181073725654607900007084498257528783224577191374901431098 + 5466092963804647249090725375187844347347973252108137441562290526430827908072841935677879142427224945383497721669674256500195118 + 9408447458584058076150017650238543964665522204847767119461148283020725314993208318241105785737923682521127890161621980525163933 + 7752816476751548314213662757572297632611588857400086488089795605852388674435780461993562784936271707018785480608983595358835686 + 1627393802741824989025898363620676709684659912421866285079664625171969200262501658717867654051389804050637814037774619076628490 + 9122449665202107140311875578301366613855230050319765976709818479408721612162782387682958793989254712472790259401394162587792903 + 9264559273820216137804057886666471549044481178190332632113699758788705141611700544482989913381964978281793867160157791927781162 + 7442806842403069859300613325533104981898816922110133255013384334075830779759933886533885733793824024671542171085144755776119332 + 7374346360629846250873248611855740390376331086859870274251856769041575442564535703086946429812945653348220186072122845016274001 + 8100158244663714389704533217051390472696914158612218153906542802690978033894796544874039962095788720080152937661496672600961913 + 8620241055478925684985952252838411836616234675852362577897905957450930653087681187667293254151875334644179085362678160756183911 + 7978254875299875225763061871403474457110245655385719997304830996169804380424203018555208820048813202142753962116252594621406974 + 1364681806031729655441460904058555518845771287158086951978113218142925356256811479736849256168552051145501834683683179144053582 + 2064837061784377038174422796078941972546986123715738128334902017019689407784830561790843652346745495974010607663653352384636987 + 9087616048769273749416367719522093035127707930211676277159029972485006678648961483209994033836189245748110099847024086616545737 + 2425064383233144306141397196556964739088709046393835346029594675076399505634895487000914867003535813058158157320486332684663652 + 3641097021982425901903299759975001000185954507785071466003606303822049570876073457705939373716255467071337231807741213874106729 + 2074354309025181421785407070622306037112442163872375219312465679573739444271473076859615411141496918260111756219972558400237414 + 9209218175245343776137887607783882100053568632353169828579551734386860768832081473967959877027533280331064368843953279403791000 + 7265829914895705780556070716875430476662014009364335116363868273301526498001345684876869560767489114942311375190271613882803603 + 9073891388696315073189212242611726526377243973277573301675482213008892303352424672983354043608654230919446999369674504952411077 + 2313808555572186833151976371065120343070868637724954931470642187595688232146689299510744666262728998553432846824564736716304195 + 3769895001051711590090397709284289543423142627611293076964116196325536683515731394758243179761144577336943990391686351744541117 + 1964012423430274286597296893918822905314758106425920575603004465793377045724816176059995632780349523671266024041147016652652055 + 0559141307894322726836380567121144490621939523042182901839217710526781776038951549469639294413748250130589664480237146063632821 + 2784427615240187672159066907559581170138189996990499287132279332580644422377771338142338877270406145886924306247277891647319839 + 2650622840124168882146785089864582520075975814107450314378337065910303739372347881027629224527453006767239445485125470798573294 + 3280112665923668502905138798645913537592166171499662307256909576761808318862002890184471250591748083711310397550032446473077789 + 4839123297739060737950671029462682374736375690549900393153725695518603231578972526440776594614418742798429193873047497505681792 + 2160244025080490634108186799676843921536142621408043650219395075800794132235618687434126288996783749492148526728267890467762275 + 1151778651927614305188542555589072273825319471951036866487051470913760762080070986450018226884129812856690672034368570260461972 + 9126667808863381235489349849691246557114377306076458702232805159967351257175416964221955677360994319567614203175199799743819984 + 2789442446232943685597991603590204183390799819475475321518636276804097467590827293001641282750302064255269776064371623832516088 + 9048597881455099698450226466082784483581892839976853703691711348479752784919013613635237082895964344395914096977829703979539035 + 8807651873851261763689740610852384724724967281185663138373836249447037268804159569417135422054907833329936731832253007919797504 + 9682114913920055259992108818897312911322686928213632559659016546514207889796765657343025470035022686294498921433293889021982807 + 8817906539189722113102359692407543788732651010055394962852526688290033541790486992705883840600079101359528027208567808930305163 + 9801041923433800395009066327257582729179435202758752590945790035180893649947139262456916818609204478389874916889421571462394032 + 7712450051093466464431798727528046026835894856944238434402423528849559439733559946888997104896406027931037956349309616326923736 + 7381318701427430852131274547674285844624653982181746045743742319196948480723763005752758284784444958915729789741525394299696626 + 8012218598270213765952492120607042939337977067878086380794314818747633639449994732495580724511274417714861329582888877331906442 + 2523903559053376560461999356914800460953183047966595580074070441846526092785101396532452282664986312641571216344907286853277587 + 1243980803716723402043316042450038929890705999070870015541470833748745344879737850504389676782666386423839519311757255510240006 + 0284528532586136580475966266604417479884520212063362364900502892825693493079279816397630592037794996982087214380723458893748385 + 8491272727902175551882935376152929301347887913314101691264776996119552678466629354884721510455050616404890619695271496162337915 + 4545341965713318896843475698632445949069586135305533687841423447686352614650216106958803696792920165610566274323872801678178779 + 8253568664915132158211550322533453124118327929548882623091786963905677622475126883200587876894319717512008420758223683547396925 + 4320222323998014931144025979173468123790086139354433220062005544015035220976182446830891814234515809043692298378909223491021578 + 6069959232219660879097232566121384126364624848136634056377125102029351039021829959177114631501219753707218086851316623762802248 + 1243816089430429483661271140945607300465854350055161784219266668283907250544685294916674983006906835039612884905549454140955379 + 2940117682598404016293743763452820571055836767681621549318648097809089905651411870200800086998457828557152804031061902717793951 + 0887454608619720066585775426385076124950271424460822511049331848391671487328356192926497422819817241814088663154002962024098217 + 9444111199203225196678001748854632792810817288744330344130819478809411416720197937516411714390009340089903953898652786438479523 + 7598508564858904067093707855688285940754985295788676773297431147947757643127210193954685014018553421494459901761944702436530765 + 5554085843289054481441810390185341385291272744398367506999297552891321596456006697431455499740285520112057597547672427356435569 + 0013578994633080338189924814677511395910036898885609486453589361725442884886155382037285922038189976648035996103250646536792347 + 1883418355117695192895288397176362340054382375638457044029914555409870529840507997093953867543753807297378240486101911704147190 + 2990020394219301141282427939313186733000711509741075546302432127423255702951507832353089573401235669455023017949653420450062207 + 8315834094959817998047438269545055161942585493293325815723771181252407447320553420868080424394122133699301368250012158017016770 + 9114429395330391270070591803725103499827663830583921855069504046749255370339126443177002479229837662039928889147633055859281868 + 0939693955047378469672103416236905988750384823305338476710533963327706820167318110473623797427088982971507090747733464699600155 + 8097749323633489883895572126941411948413387610953411492455863784508332803867377054591645781447379503035057961144435257072818355 + 9192774536491861553570480071143726445650506118482951514380572367117987602662371433431531020944047345411439555055616659122572444 + 2538272673224446791161100046059076794348690288664907501420986291128393194698926073716590796828226666658940692534781574652080599 + 2296719356672708630298340102476096286223198315529342168688227248665999468122934752834636542066357602969267253948955801596039200 + 6907553929212877794229661239340340054507529389112502857484240836627584226292443778415389852020999685448069205241033372399261985 + 6092552080660661596415004237982747843962036754844362941207857067711980933061648692291784758051313128780610506614569982941900763 + 6594390851938570829005416110125258734178056235062424322731777215369780823020661620803238711218728587137816612075854867828598400 + 2369696331217866566447853409278304508453286888356285386844080814982619783652943626843027594633000036437577975836948042581832383 + 0948885007237584172710171695745820012612068700229335944852613395850206862454317862915465465928827325249777743488489409096560811 + 5495911603990067019527969794975740716100732404562122420639048240417867412633964511077857983711654955131598842753406211465747911 + 5938576990907415666730959973171116867930776870120598849297289380213982472240243585128799882672536952585668000017332908127868142 + 0055033948608802263653030525631019632385167453147504582749896613855370979829552517051177850239757173815628192095505002356755838 + 1575006377951552426189315697593571157901434403253801500948115475871805154047796850271348643125694619380221648554282326550822126 + 5246972276283601394823321357823533983734860648197127606415601325852813899044500843947933650765212255657169653289842270182408561 + 2963795283400693969427927841410518920229478373496996799858803689356286312942605835353285929732637824507016592351551689198434905 + 4524116354075005325609861714463374588743076763717669989113993414649241279740839454455938573607498636902929162122468763846383424 + 2179849115762842803410844590988059861418931490923531363860515702620355825744742928541840867928398829472206209785674120570623101 + 1132410047750617625576007081275570045071771592714539836172004355577617397790511943990307565673693827096029990088810389666652957 + 3079203667265148591706387956264742397674809071114000619637965798572137055721279282178439992636758230593462657176883252897846130 + 5344900606236775949063632708480760988922321343844454792539062870953446557548709705912512202634518627191679599405320534739710674 + 4862620838291477498931509821859436769537924979388766030614053473312195673928520927507333262772931790461823017698325114264269689 + 0377879474949535999373402143435358728101597553950835828260875850446040578864121150552326559433858342085551900119266465442357108 + 4145382952202338626169521528905963930174893641795335885386219002691641231007259917968036502863440853204735639598211642320126801 + 0053580536687636415170048134719028636721663473814357492351910729926031799390889508364212752500797332425619171871273560570543315 + 8050888999124989277531284920879308536986968026163965044507397321505480674446271580916011349473678101309289578265591746813517726 + 9127557909914237400136577868957543371638044740008283166851799275961511059368672159330761617818453900045874047935222126146402161 + 4101481561011635460925901510238481810190290058999387022386961480571796642806735909558855831574016730200955930521599776711652022 + 7452149234766310409197279968867850647491580237728049077688692166936015804308350068889158066597960097627065379539367797830770392 + 6879895654050303365324517468233477011666079944449521630351405739029720149442284020545119121309386081120398471736260643772075320 + 5115668578180735659993042798673877885823921120201277569914715190894516855160960884928665814998466370463245773786729580361126788 + 8473676321663825127148201234179810956242584805477442480418075610556509294721684997709018216961441699698479559880791844442850980 + 2548233794760268816189190401306088756408880212519056730724214290704225280819394151931727397286420914387903845669497115561372625 + 3358354482836700948199493625980064917823071542164808097350543961229800125334834517703864655364546055166975880935305435123088821 + 4029969129548193511513014303632741396672093205336941776475040363815521979058565558783096959704099250216961508907068930707743800 + 1178228259948098596059380680409565881553234195364086559565498076952409655440130991639052974945372324956190156780171629355058755 + 3717169015464986627001032179838523927735142460855957466743630432390818286505306791995379349323709241837876168544133279436428880 + 0351514453291951960472553858319673428002898082287147987459621016579844258976392337653325512601241626465492005157367458123795393 + 9131757913676253650480410533013952331883655576543674109012844727933443442812463625615079052305206439748070329783436962037461924 + 2344960044770585240104572826430912626099098553793285442582298302002106108601045902079657749391794040816491373923940544837370962 + 9188063701594180602103941124399234673973525989100931802175158910488942922514429931243842291939057260146437903218286048586526737 + 3095726475590315515951883606439041451987645791724176078005404488548116509110488969805623639698399122683827452715501916665020036 + 3403203657780121846439527513421356719526606981096988845264774034545984754667811956286997210908649753612024363260420418331459837 + 6454363503953069085653959466382547762654112282647446898596667543948487517796676159860624750118940186171824534509979950086899125 + 5534857215488234005757824538224541774649888325359087056984429790126545819871211147018201409980430263764262297169187413523924493 + 9520167452539794941218775260774423444492261204451489938948286717754151689428746487424118400020813014135629700319029471552190487 + 7649753857278617517384047446362214242830920706961544783469693002591616096695611398984815665331683937899607935227857197308530722 + 7670636468635321903676766861271780561993826318676409654225250617146887843176296360469702345236373355189175304203166464435492803 + 5456942248296553684603690989598415553795292969337585462669697131930121000520692716176831920728412650435826182698878423955991084 + 2896202227362420166816298936702205787111522693592087473120377589659651412246131193859654870409149102874068068052947526362484606 + 6206499177988103420772046456006763763163890633653756586913836205106440292257489426046140931638490258992453397047593430476263734 + 8271727426541847240045919975482895895407596972876222349935866226855009736203327632117757403576107132386631830517560425145954967 + 4982163925157138555939635994371164500846077564198212229817459032427881591645290463697023178851238007473163893076170963474781460 + 5340106261127351887331618946742533731988940154583287036382074049074320856289664772105865760586792346984849386692407381048942810 + 8539587910802062328556477423232706345676834247983911515809748455837801552264721412722228887311117555317778442883915233779797479 + 1727978384302123967727306531882414560603798977850417620003458650086712045078303090511550979287673387880893466154163854646269635 + 3674694578655904749986580598395421685146833662087197374056652325798896836233778806349388223093547068287833955056912724333066803 + 2847637229990901535043145484946473452323017593046078412652932709449735113175295374406245481235052704111601101677970510368326922 + 2791471564967916436181421827384161108238141389611296884460017859614820709694863977807620407661790121758211278587753750388535470 + 1311682212671438808292446213587823526675524926735249896308087156166254699859676499961522597030531906137578453887072208144785351 + 8861987970713845651946125749765842589051394459161283498525078704659636051445265425124710568264660637581231331333166906616781773 + 3433773030784699549858220921642631039795495279596839707512577767723632096893086622754554818674187555230885034907077860457028892 + 0456580053379968368017945695164763479833506838952019851181545387562584359601036032261663315698690958554540494006314322814695152 + 0089934480486704619783110767294727013349926542271497056296250118282426029001430520413060977864809649544418723152448749796245164 + 6374218433638081986774399897692332350976246009622586461188714603950733284096247572024844313234627483374886751903785440297788166 + 1964624071497448806005939877571581081852368682713329198774704389508439970356078811686024907131424792844471710419031994307710495 + 0920647722499203428391025133284362175932945797352824069655533852410541721344987923656955005597638885921881748026281505225146701 + 3234051414875467310335184839402728147911090604477636334326355603404083470772369446633927746336105082555084803709873030579813182 + 0797776807854225896647327655002411099428092825155001834564019066984990634531216819521296497699004639732085677368728818595315930 + 7917485162442064658421046487728607879599371289976088757626588362451318559683586821768061531908102225442474938214076282479553260 + 3281219759953705660325535461460598775637270570011648848817233301493712654518786509665608881437564458093540417006933366539835720 + 1421309961668710980725741781573712344943061720229290458895090456489735933725778071381711038599743236066437961925604705889777444 + 5346018484213473348778149540609702140487404833149084935132956734625173249282732560039608351835971014828152667004296001672327334 + 7640982015534543149522949001287972675835062998825649759593191032854308472369740597155188057572429051521288244481472576347709112 + 9082197142126709759172581677046792938596869866773476159806997279087695007866672568094682918889951065921351285356324461616422296 + 1936662836367636814393593918150500159197921407091608653457518897602784067757706017281722377124420704953813373267377728149707235 + 6165532554189463034890275736530147346375384892741034329027227244542906540148716547806611470041759808947343102903725834811540237 + 9921590940060069893953324679767980790622906014798953371116800849894891003273141853411016879477894602450403366892842855960933978 + 7315523767557595011955152358473653019805790165086637876204849356737581570450280098237545014539966107468231674446113357850428012 + 0791096311925956512226765013630421811573099687378388596324590465120594475232654312603704526616319090075205150090415360289991719 + 6209585520294606187513003055352209151687938901113926217849214203137326771247519247105616300171713950372822794825746012319922943 + 9070419207282434237195104895273960005868745134822958234433238365905514670266360172103212277318139495451964580465731804042546085 + 0338167338157532972668177758079386489083653270128069387600686406564818006155678752863600080494279043355117187180589834925431100 + 6075857929007054805987361298779916735419742025429402324367885856941288459616727309405216361897524393233989298288583563658786859 + 8295608945048628864124667559446303925571884604451666719475562297491635918267804843940029802361638899118153382320671609177821037 + 2582167131471095203583988388775565537112236568527071226697464466863969482609071992299656322827744545682290545625251014139439495 + 6711594101773826530320065101211025715415340393938808536071030195055575879765597974028194836866850448633781263352118203830334159 + 1911464166497757327229347266491166768994040887477045432967042061773419808596553435219059712816623298485611786304164577509711093 + 3950559965553312195375204426888631697136007142008473612408896359608938295800221018496826509159015008898585495437881710932385623 + 9874188189105976892158996129334251306053998794609627074731940358792016931428037315501950874633599120688188498035110487709165641 + 4173410887164627415991784444779118017795312676797160939963018529923226506062126935003504945358174169319649592822030532548902364 + 8585536437904001642599877592181317351676828771494354438414987542591562928890147892012194379909967644778402105597291718886776458 + 3150820435297838229930820366686733000243384455249980345366643081949584071763731857162948259797374460060553393333323596509856155 + 2746510308210106138913961915766655928022321725147254596535903741506128248245569457512888067134893515592196316478265340857967148 + 6054837822399734332369250046782008884610626357811684106025662192613352002782118381922758419491552146516596733810475017566505975 + 6253444244691352274570036070483313882748278795425532524034702609588633374333913295809727607310412619066512211586460777396607177 + 3167935626890486882612342937895694862011472784369829386553959207681859657350791878067764914715082125859929851130735487337849909 + 5973912099248621614115761320919410184939653960557823675647875630413749948258747675478750350454945866579601771984960798194388016 + 9736525221109913891380740014791803647462175891768280453619965529263318350088005137408675181210618289125588737889391858187625884 + 5353369021308107059796622691343010568879776199002760578714065302617216068310095438159704609241785014319825155619864292170880710 + 0495180914933316707105009248960814921465681956792191416760665299694180526760284922837494706424443747428740900047510907222820027 + 4261167178860446527279234457781216359164057184535569399549566971774741437839602392078186827336187328588770123788484074481402098 + 3638667122645479534954458961543608733857643210245423464371257036918768143627288762652953247716922315676522443004771243444008790 + 3924515546743559568892457871009003770852048769643235894176832052809028875813896140562020415910166599360845331504914716199418304 + 9539930208848580218543922990732130838884473458954810662182599563214576790823089949536669626168272941913640024171496275351316441 + 6014586121604715045014833563011298445249992633905973084716393755263990314978408352185626630254184110544304520462563363100889663 + 1480056209827971737404379030390423810733649879094610502529510552900145205746169635070607870308190199905737823014183804945008242 + 0269907341608215559877018486447313197581053179139277368261940240899846162645640750726730556726252880111678045833842135360488520 + 9452683639389882051701960541518755636274003173728067144992243393027569642308110984514593826650393132965688544590683455796310124 + 7380252617100440281579567534384005518334110526934315682916800234325208500512344342386934373532140277510905603770493859349394883 + 1640841298979540048287075269187639921568678590871873233480612103263772909669941767642148108401983790040311768132667513845995891 + 0797228841202589730512673576721011566549518209931565777081305309555092032097475454967752699515363312040210695622598933787975405 + 8668051227922162902176856358741680893763627061240389531754672702747011947735221029021238076999742096989024601711374129582948446 + 1940517877834907351003862153234670764674347412348064152632718218140233582465116935278604919054339813155764852687263384383689198 + 1258507121750424356317899666874328759136117897322624713333775442411946490404548479399911860814088039900005338783292400154353212 + 3215026566497194921100428678498475477212368831513037002482731701747625115899231609161962690257412946823057745227816040916263135 + 5553936624046126710513840693074241292678003250027162357678547764315313001417556750343221645935609713903330012474781806462752509 + 0087160096352464233135718030584278086059148140723626725159134239250134423251753319043440628036779710209805517160099782393064078 + 9318218498563579335348341700906218700126032521018782542069807548617891695409073329049001835630809969460708500370067751685336992 + 4208076385552541906663566236770990347477457147392506695455104977958316161334777343709329582406111068678972797895379263213969728 + 6469519015224118923867472889765223881558607274601638396572334489644055785283085612422941306760043896876352796674858662547224493 + 7581545382840053688960159322695550231110088020621219817091426507061324686155465441741816208389678694769740607167732243171488972 + 4513458865704194161496940570841680853750653077515467382681747134693802486964790650970100691348806372555667204130083389487834234 + 8611747863343669889389552604708894518837779002018609033906535124466043777729170830388281007572831090596749539330676454829092268 + 2614980773184238784409092097541705502166871511835967598046040179529035245968990886914099394023190993075959231506769917989928255 + 5078404017663690714097396036195442424905417384596337491669874839339606038090162958546298191413554764614281624619030688715839038 + 2641999347004416078674706237266340276545528202969242926658631976187485588763571283416465910176657402769591804490385811120607894 + 1022069138109039758566977843736614783843237277066124548095396035264485535383579339344672494958836028783883577568562124831488748 + 5036220302308126851203910148295691777409108647096999242270479109438402097077523126876642469999412297820631461204592271671208573 + 3765990012871705693020962224239694872611037068970786438641717866334183625110030788667653078611800346467240202316395411589819234 + 3782933301188992583378339987527190128332463154672014687853873904582770103495961273158433396887983077621367280840979561172209874 + 3749199929332536186794255922364823419316096604597225233951718116228041916547239168206812159635533832324993459328359641335851160 + 0949078067861678051433564861906686233060038981581529250289577929864989790385982845786299381823508035058298434160670694386088772 + 8589603171909191258961043702444348933790044242468360895051180975009846570524502293795875915077460542906777905339916008769533025 + 4696790001285278712597004232911565273828035212555295118585512821803987256554356248161862945364958160311031123882054615472804301 + 2136763839544335242427199077661794515629181187002289822787279783807001282765862055208820154228904904403489678312786030757766407 + 9614871264207972090235920749815254428999808582182551807788105640461738443833466880592889986393806973211194934814261892282034345 + 1053682892737737957362804191027861071649489484546703968499730625323764928679998205513025454613668271807284174919717885935584552 + 0107677739834015517323287238318659939175109001778305487593186279160892671682768468572465735391214037913879126299875773890935302 + 1453192783717188719965961795655288342172822178539274975297334507529484119848624649135862288188339473719284880061285948938876451 + 1104549929363155396273207050870222760506597442331198500643525825130190102095717730285667006432704158844993996831311067931052472 + 0828794534801481162296313627002145147495573308897739685396596733882610495059540555269595443659894160127867987587635803471525887 + 9824022973580621392509031573913634949593512565298787398230994893915219176490569710003371534856099636970419816555736516423169506 + 9878869772576948330900142931880528301401489012367453237909670821957956278129934157555287021598067976133621454184066239649408611 + 9449658706952732276667554753119961137301412966671524990966931464264571223338509226807775956572226631814170860570478467598493299 + 6650524655470467246688640367290038855618731841663664529545949374735107916410687959478366394614227095766286594581538618985047713 + 6086084723895749993359399578577946854255073324766404400181960974843071723540051597517023301307855898898894953430083847202358708 + 4753978848939024247917094291054930385042551054372444060172056724142258138979831515270370976027807892767076899036493276499539268 + 4888375835344223898032733332908158386194226863203069893727606532739301723911436149446573440019514355993413403576684311443713663 + 8296174705195869577823179373277139184472357378750746123040139737885926265459733919518384739329034183096218738593256149149459218 + 8744604285228489074099091055498838353604537087151030264581202847750393201247650508352763633370859358894270796201667489608183108 + 4803757550419070833057341387873914307394706611793081307683075761521436160450412298883575182283341357874191269212976379223012176 + 4435149804710266828206094765772134040146772381477199506975830561360349698395986931196641173574221626045221904844792851097031410 + 0140901477445628979104022134212056527853288372076077175566962012356161842830489257088195443545165486451856025672191097292162212 + 0064993358872969642733510540028442337052528489493327308542431944612538748472046808937048692371405185247438306806803215040744971 + 5863180250517768423942955033295423284494978569038179153339219650484893674393537942959738721683811008504606623434622402463074587 + 1057835094428515977317637880823368056821605598124838652727786262421298250352722448869673429472764531868054225289565474229567344 + 3983238067434669068143443350182793359210352492378691479389127933138449974060689160199725860332928925347596191014918077016053014 + 9909206404814481317875154662284644158413522012241871567063512207157398398808577747347614035401411443650498361772558269985219726 + 7744531085141281581884696688318667987388073192993652661160923279555067568241657394706279105517300977887168465546838484164576246 + 9611748410338839797298552575152326071882814435353560145135335186607329942289657269580962404267932188572721339477733166705898691 + 7946378873728294158344802516673294879896454520313415594420541327407109273815189756012820920103635963852069701484919842956064247 + 4874591841062298195410390631359369161750834793590724525846541010552709961171248502344146476896644307714211419632056930049968152 + 0852013636597020207693222771451991722621240083418836922565030460173149090294177983564964216327697927947088353859239269055188074 + 2400549504774664967997419613371907388057256285629514767888950107220270166626488534296499500671373046737811115964349503266901011 + 7846949189277918675793279134349974486913260503583373441600579959916070999842932572749268240452265295033063113981992389359199980 + 1807261813286492446582855762770791231541210822077548388510880369998042947014204967053843960432445968862263380028288322991265906 + 2762645433260880544005259370505499891003063278739034550726117946384596067905756389481622864019774830490639904899687312014368603 + 0877598939078117695418432932115534755404639291467885726434445252435059379183430846339103652602297046524638381772417363883263654 + 8359730049870608112690328069372460928467332597727838745244400830648941526818883943362511766258737811338084111308530830389543560 + 2410247474136168092178004494614768123474893065682802068994067272461583528237284734448787471492174143726629957921201303786784836 + 3419244084207146670255645738668183101897287707313517219103923810981141387894446864639750358126083692639837682548305250192071549 + 3436195357834369331471914469743643722462664355231433520254139779344070714371148189113613561574794491575113019678653016828154505 + 4439128393642435861391888228862161582205771186938296499633571218847225435482241772976029740807151825694346388408247223423817081 + 4171338859609192030035030504936231948955422469935021643277709598491047020926862755743386040228384976638566676326191183360208322 + 3510862362886970176404175491659583359746924395962009940383204211293131363439339555697993521569537948812781342292800263161257581 + 5726969821251892647951678196842942528264097032325730950425154233756415408461741348237674984518538018983212811201588754756679009 + 4778823499024627173529601893322692810338013854983738107737211008580929848242105038076828712411467725165215358148210018424891037 + 1496776225022474894349628318466731097093204838845621769757160832213029122420309244726997275518899114578190401052089674878889558 + 2150627813505105989559012023523240177523105542484058646465606833626398767902073791909228024464129808047176621447241995834760361 + 6052017973982660323612282677894938232580284277106494794233888932365369180563831962638387127741187828046331415436706723759407894 + 5180894648613337149931873741726031450761346316713499884971063033267583243155357639761188673059015634957451632776491096066497095 + 7359097724129074389636668836328680896804756391700054500433769926703593431467797993796585602417512809374217324038244052246360155 + 0320127339112689809171849857331267778192107524355671645529083978652864384633410979534318842451250352236642968028403645196181521 + 4118883887076525329129847815663385510560303081843081502700312066224535446821931779450723308317216723461024137619749777688133771 + 6860925861993428345905718490095572908986315074234835981417267582301259888782018674341030424958141289788351602467046638469818924 + 0143824935249223588362256342022083873670928848969341583470612068807101099916137780686058304339569283167254333748135808339800772 + 9845042645815548051061661959342234028016893229602886364367950621055704775648720419681077874002883738984453187494339471937282961 + 6185757617018491828131168967624272567910874050935111978401025105754755523134728391834040088198125315748002405260114662632225537 + 0001356522238346600683651153474644012974963965580249070955634679932657691126596449770936543341015260416997826513343646145044283 + 4828874167962259991499503673600129164632862005208870245173240873585329607224314026307889603968799682624300985376989091014318333 + 4168596789573195113960639290119776051474016854378309232971533989042184885619296187870057410925857690307120789952188315701548184 + 7815816015467871136014863206025674274535612873638378381437080759117487117954420502148760971346576864484963796596882357424854163 + 7278776070084196458814159988413439534481041061939764299982929635630954177993909110795537307351830954498765311432170571984412940 + 4866643127910829515007652463394937334032003939291631862785106424516937511685939908344347334073225050202328398177347110978277589 + 8801678473026832588217149008639268101698714830248585119117348101801713106570301483277093069752495633755950440945309944552577536 + 9617526174545226424763055218268088790352736241937230497521917254797890205799826169553805927031554132395993133419267021828416925 + 0588595739388380595646159745519694245103070425108579498054959496392270944865180508024017295767451162258748775694293117545535076 + 8702772928743292051022384687311462236447455075709507160040356608423402093661525464261088741775321017969842598962589897299430978 + 6237136476697160214138655273076686746008630927947783830802379210660809805387482347921808311217785296709410669748246476297410657 + 4956721962293257951828094615247811594706401567441027963919853253912294488061757086648296894406025064932611868738979275806148213 + 9236140986639524620047147846000572917224921424609362686790157846221057427556655153843449488971368941339909014048314921826442675 + 5366378038534835924469785482056822213525701444985254633404597205774596447015868437597513680309327466710395924280351223623339183 + 9261759487436784234076954133371789265925256106206142125748755816777807349896143234487553341181444300315188799020606387261852065 + 6449231339989879656134113568400091770993505914272783860814830316499113207580889761456971111735531955653301180535329421263128180 + 9593132987957417462820592468596242875901632353771559986709766159903387546786798526051530972235857175987208754226458183961092508 + 7166010270941368051527588903270384190676373547534758318035208065713808112773649467017099455130795910402044915843292687098488409 + 1937469715418217414858420673158652244798733546985659728265347906685952080207655697652213278741491999837300249957163250199620558 + 8228542398195856592161847035652366519403982135370687548941385579105164032051119406009514327346290711302155896619001736994882959 + 3637688922930586118891425546901071630399830689323382607140358997300211646909715463890915726479319114588493474688432142961034974 + 3846092487931514115420051603659542019430636869539365331821500084544038227936250365288930517356505814134292254191756084661422225 + 7491630641568207270697424777290522332626816338241009039782131614678232351819731901409187134000842000166738975995925878926795417 + 7070750968877352578247753117115107850387026880348329157736320326010941179590211312594408978595708610843851283204781916328035469 + 9579425490712849875219973084577346692279033275981940434988363957383909743141776369454560267346747976256694629456374012164182136 + 5715566001611830336152118124700907641876141203182109095013901373890817946278609009427237417191831719001170380251629245333691467 + 3777911831700858846402803605902436628175309291503492499557547037759922326055839219601687167716391664999501580752878380637519910 + 2345655297190543682328955031766959976133728834616422943753268441547260728586436316967787919247613972239277147037959837372479832 + 1264917138428370036605146743753527478105136932962495735773676134552135849746496312485051160777893753074748519890909181403083444 + 1019752269689676763134331558096188560591351764633604225395078892173960817806638672836991960044167937282088675278982806967963563 + 1646009447412568269213391779579827953653829284427738902923460839464242874336523939561058096952551188341759036552715805796071087 + 4514073980834947668053426086988984219335479873558292410478690803080693664498437799009591988658726439726875547569087833595254435 + 9375888306479510358575648650751703046541164954438171217850843228076528589259852655316343249086105052230853543970799873699798265 + 0497165101239642555970983822927664186264700494353584434852254137560612395432178721562325965038387864052788810184396252265391565 + 9637587742861000445296706995627451301787108835157787393998256171661400401789319408568582769562951011299994449045177879050273430 + 2769638085862574311449284998834663396793439445498698446119611616703979283028314824805123683773362437290195603306996434216889157 + 9746240352274295235857973544138134283682808329702423798784675201114018293748073782256043515882634590777226313897991318556273667 + 4701746730536780180098002090253702648694901490740529266632381315672027202981413355374788940709298520432491519903507229198264330 + 8070148149525433117389602780506057744721609297582112109576333690538110175139908485162827329907610365996630627743121137187293998 + 5104791573207818901442004558359267736381147580646586301522698902268860041597652832411905302035950359208853670857974818287006889 + 8341316079342584982610662915730694074266548963632208359785240542883719157226848170269734749166834340935627403531307648991671361 + 0980972555646214322144321439065894684434469993258702669138171566031352957356377641038155398195278908409758982420498643103410893 + 4371601001168990355540734973104369357289155288304862691393888938344400557230712070949783924178880475136899894295722616103660902 + 2650480054074532640486048424756932242389804525662345983096982594522899748828272298964877383316038674083325253436014966605240140 + 3856519566975050055663208955514019483009113366052382153385562181732228724721105677879336134186949728875130780075511950816508916 + 8078373724394599222427487550133729616625008462045077201670397039714132392823230257154531053190372696559721189464062559107218427 + 5533555275076610788085420797340154399319379967237990930040901555785674670104205199936906742420190549652702261090687000720033243 + 6220111323366364001766649253557628713894497231901067623752708357435827393686138195041002675760831950319558894058730884453262921 + 2672277003207147557184524907281442713352109540367339513087567600977008089227949901291846746947778742548425956666175882640922513 + 1341364992092721464190832131115386139839119999152547728030982443332120739263533376607896512917871745789498861904805336640005368 + 7658494769549719799407250503812834345058648333149043237321838262779633765459673785919568562329102220327192186018538985265090758 + 9891469225677893167626557199385256479464450147340948798817312917938176509424351376822942297600700655298360387396846679746727135 + 5585419624514115780086956162546737430419445855772977848266264876064891998070796161296726855803937113862539594644902156882096859 + 9369735292641205270247208512449851304357935258980017450069350537303506725253901558161348011161752800022469320895146408450548005 + 0250792460158595347750598522833094847081172052676835161342784300572879217498951077354750791561533069799550859447965317570533329 + 2215924262194811929293333565918894008757945953561673129802085846175034801490539407544733104736094736753035909391436637603434211 + 3003828547025999647155773214469770001753156334255534694689533941988376812539304881256890976599139258146884644045613614613975749 + 6800289970404751783592624836999186310592737935219914459902710041374388930994677919752362443845898391179354567028930335795630336 + 8505759963363966237797610984127231223565214326257640335015223496586184791131912377414208061741646388077399037761412502229212389 + 2367769534630970786705110465175915418118488516256049569042500049966228999665875815493320452276993289094558376973109778079159470 + 6740493910513290939463082366133739451516673396242163998658427933891438988618879026121788841470475041492666218138874169322768351 + 0357303411110414929271994301686020384849443986791255124503432672170825267728337655437754688169388290097504447359015466216468554 + 8192240142847884347063706580178899765888936207019662263339819670804657575316021484690040614562949295841542317355852873318646994 + 6622263158780477778507038872483270954479088649415292887077869603719840994025710565546888311161500807362774885446004022146890733 + 5176307819234962298055575706826929453118700498832781969398229886642207165799263179818071674130902753482145042794765741675062383 + 2751302275326116756435072977812989216925193208517438463427139377868288067976273977283764655073728859395428187073500573181560080 + 1845833119022235738677681522695682631533441089840982284202257527507809093077654733824218731845673599302802574363126193666185391 + 3166900131346963127277355530406427740614776135936937104096485949875917688047955787215898240293170537866227146364747857832752126 + 4669645223062976703005533676266421855057200556768903274559944244985743499257659816488004923631139517399183550005987669212203452 + 6297157628559223790562907965128004350109267209905657347407682698178194211365899319173140023292544735908289515011446104226422300 + 8502054721545809152280155719799579471628904200160322267901551608506906168294064129630324866997658363940456422902104004108177137 + 8611455694956943077268590839116881863962149614279260195002902444128093061737269752861412765172102748566330731758569318211290162 + 2118077432186424807711637317365270035214176328074110410477259086405158562676552653953649314850972984909614735542131768665131395 + 9130318975369645829745860603018652270421321400871933193989890358079853776989047665775272263249474986926107253991947206182591757 + 4325629926598371530112760898633445089584186304063488458578614511450976053503391266403574144006236271752461276059535144816112805 + 9310962691558816998084824217608875970240851404516558899699931821439837002656912679683111747809512293159335274051955163666587739 + 3902386789985655245291475443305453851903636698632422663873769701394003436882941095444088054500028643416504275287739285414766428 + 6731684059779922460344447840778233714899809573570342484286950672469381242333715669289828470432847009362616600780028432025743033 + 2276600041430073716292091375271727222342465787797822281415644677410001912257463959430983836963509288786612692459635796134586826 + 9782224784159961526251458006646854715817922665126779115397720973464372703397941849152840323345005890646175543131277561028472366 + 6526167561528291467123805366888888939086346365110568387291388627679455761130295567840390067905361907699677554800553539940686367 + 5318634933920742765367288875699774586510799452591417236786364826083325845867157040527831875773026806940962750032015566117391953 + 7493598975572064199793468603272146721884132503560554819191261369489899329392181449153306365084506335645635211479940033483680033 + 5666857577286998209607341637144223997808492861427974015972123407497307671199006287616123632355515817115708130939568369663610192 + 1205647133800994070282776117664323692713443344045889466640364601504907846992739340462456897562574412472399343745023522153250853 + 3330319212199788930516095800858918371890861157149091660451404495244272634139073531985568539542425087248882661841548689414190274 + 9339962909966865014181214015249254327772461905399600921043142492498857240896128334661531817157722725029302364254696461600120855 + 0275915123664954327692393323944686811113159039391999178218124646929218008261416648150717574114279175738099624550954907847794987 + 7571438595941848638134927452374529897917662628583906227103605014116793319790628080501185855732090732338304609688113595225239617 + 9130230309512350610529542991215174872450882806867068241227281773112095423160023040208987280292016395893990306260033588936149291 + 3745658203217218584383948667226718968580182712181973947156555599253392240064780457939033740602796118129681262618905670233538489 + 4412418271808065273371380680584774737632471892264742468899650839254371362867805781616736426407895133489629389395846145646724319 + 8489210495984684333844268191310832723383161085211929007986759567690696951893569242504292424131665261321552489038411809330750578 + 6574010925786704765333558400961864682658986685222505394734228960816617397028634600968531515638569668302469579752350128387282475 + 7078834237219808682337835724461339925697109440081470255808977861161896407485691000442893960515108700590859410043250399284457162 + 6826005017559754965121660973424054878627050600950197534543970583792709158920574211453104472613133226055927030752116724686804441 + 3714997658728942284217722016417944347609973564690519305766123183125986230197933675112901682033357194516255841107152642532141304 + 1057671755594723253182271537993425618933500230542903348744403011513962182314508888904498037845069539547674219152154472098348463 + 4167698979868847784276420293320039606112408368549434641654634849595716003611837153708427260322734964264330233981684490094968636 + 5842205187892994596332543353231430273153910962730263311288493948447613898642287416656513718409931065308355871917064045665758537 + 9483067464396684153711784947324331651250593602460374159868530726671454450164268258494437853338327466263116015842104260460184775 + 9918327983152500807062535153855232542858746567492036007943220587038833257219577445237712255513226337182088357385642452970244677 + 7796979178949646284046620756567408638628381588842960380640158418933607236535455721736245193350129856456748190582611676103108397 + 7474868470568488770868160856619425486013084529184753412392811134951027143914884376770407337322922148422893409126222728159404831 + 4025970172900887552972543571216650363430374550536726543515591505239084581125341961497432836939375430662456975979411649814396281 + 1376673671354389313333179969625064091561856231653660770117134131024861451548997992193443491241771601133879416546391689721119253 + 7812382563778834433247309068407407067582779720037171842393136498269365501469642413788690972515921121053433102407538535462479581 + 9706575053071949026852790205126415890557321745536935615519559505631029223517371185086529237733348358256190743027438758336144576 + 9006414531022472111125196202814342278375571427110180645405421603811535358205031055882679708681076022342218218061708622772715466 + 7014411937404524372862470846165036293398376604107823885481595132489354330681978934995519374885800444029796119672180751145597990 + 2217635875626883098820646597303117864519547801664674186453314965253480085119898512655154794357106383983041271503641895125251110 + 3512252235837181461231288315033867607629725036297297118913502488196313074376766607719647753171764776345290627421411392489636355 + 9367329989873888631983207743830247822211335192876356701620415814984875713241717521999471919347104942898869901044085358319426464 + 3886932632919049176756333953836633255259101098478704964812325499313834184343270599669768380535271527046781188364512125103089728 + 9085400532850996923140563913725057699601728324308946983801623506065312434754540522710960789580013319731801582815683477412184104 + 0482120489559053393661539069411739064074531226478250805786509477678364657275374151794004014104036094940006833641747026194721664 + 6223030054108461763808112515000136243498515799834948548188322786124370768805042850586372228996897524679407164853720521651414447 + 2045659821087414454414430804224189873085215197748925231475200893842348103097879724089151789730563882183249354356129862099874841 + 1315828776287414001746118239879779806183081196189658013775774856212674965726153082362347461854112895332344854176341904165597409 + 1213515137476784596057537684608135941219538557595828609988436459029859804112595309586038750020095414785054256852539919216535980 + 4484140865975650257767631970278524142097436320367062170812973468859967284286099661751054315067110058820945519136720185944895374 + 7742692644036659798892433853855040190699363942257261289132684570773772398269153067661790938476854192452194252168071064023197248 + 0852041937859186893599452942342756186406516322350714595377388609314520833365297395472603829432190992959559426685189491282347057 + 5433185143289951693194250541689460837628217616946850778491455755537650206858581434235195035172795441448516354831307931147174885 + 0450942348007827481803050062279398301950579282155758680606572572109484512358059858330484516434220157350961537316843651345720503 + 4380803663067690067136823238680695720389449212682650668097530448778728543739620300359368766106338322729357455486494754904098461 + 3264642960305581246967575470210497486665490038206044077023048630121578302316138939937893860519106763145890200076403810118822241 + 7107639168089983991587862527040150737165433796689810859573435301169366192576251898692883826389304101824844158348543802249127582 + 0669598166832510431109943775944521732861864105283325341271770704933734103372804558821648326293865298432780241079718755089452707 + 3568107971104085428061715527742724933050823192969880425640410593395489624255402189258495659521212800172822796344882503818407485 + 4194972547530169348356862971069263077075953903800152306693089832494384056021498593498576727061441507427007792270872575143948044 + 1172788991936383893646302947517752222941032857029795292428946787677455477081292410506859204482638074930525197495818984377516119 + 8708727404823062734669585099177621030117278743659596151369099005394128728746425149879168020045121622056893025422397438542352826 + 5536557575335193916360622332260209029723091397745281648820143235533928946294383911963312581783465260511469849131842805230470062 + 9799128949323644060685917638538635211442541566486657515013727896653746677089071768007544683389875228688476415065723679786222857 + 5615573863935839938823973115950563644124889855629743447770458847381603667537087961954383608440966294356327727154342428403717584 + 6135719365304945156195903748702135001035781887797234160617684449358873860897697192990886253607384422197173334101390229305548708 + 7355386834242660296627412137907269283682869702323709426719706244145140528071269497974044139621935732608883353990706800769609401 + 4117824188478783409286690916041542923147052848706784080198351893505523979781915688089182588499549735693880215954821551279637108 + 4670168752285459430877011145545186817108898834243886734027847064654587388165854257852169040893626949216503073312235415138548138 + 8311486748387427946913806861679281620866414231742557923760474181682196182819449180979395793050862114181314437692082443568986323 + 8048322367949325657177291617359572925594555792044926031542356556453504106573058251613848469630469333674263842694166478603019606 + 2241419420107086119951172130953831261301246015464350985640311185360710868324911647982596380951605647282292847958812174415734380 + 0207875370509633314857109554449234589264638078127939118196136645009058962335018366740029205503954796978369681506112588271652726 + 5224125202089733016629542238144949897132285324338195131993745529968240465385054246763922445031407439625787648928055552616882109 + 2793536617404132317781661381899391556171029177272445009604125493001682989300317084296686416290208482553512764370697922889547543 + 8188433691033017668731418898412943576673580084814405684350547059200277266867531820522833168888834691511550304066275553413432816 + 6069781060072723977215798057681530374205235352090719032425665651313169145801463663003622748057443073337332287692516062915866474 + 0991144941963456299854456491439712458220412985735998277280486665724362417204461793739331274746630407706323572187551658131522029 + 1128985384630705817449509424373236680198643102398192723995214101875334517122923435752591437827690137749416921444994412824571229 + 0933149859869844034267514737213635247382994476023098139584524288805316943149032915781109345152673212416893459588048333327424649 + 8431499800476711779747358632413776057189971388402676768615975922425552726845845057116844980552680355154340958763735731899549226 + 8999746969039035522234132566990886859367771300359825363759150761208120895977530444860283076544729935781975800213516901282765869 + 8578384564148446021966192696855640744733543364607326875346561423047230035981121889907856300901288650704791837601613641976512860 + 4782737185453902550739147496508870329447551421595794641391271174654998339963075546317914475664543351090858707240517793471880344 + 0532832780888888968522715514533732512924561999915854959906252640056974250958067417634581049729155174966017949852499049433553005 + 1013570953208696598838952288133824762193269724513979589866416713036164401176767184475902330276700096926543877198993766233942302 + 1558731482683686439823710758826362624215320659618968974586082717778992330445630506757688512508423035162517304559268454636939287 + 0350643207571320038261933704850349754594287810435189119965241800581118358691680807766625340717143030794170306528880710869836401 + 7542021244067320014248296046012617744009265286583021536650506535157160764351137973007620114482584140630719966828687210278471738 + 3972594767241483050839240086921327315906881022442251582254034730627668558044239515436332898375100074941146541911588915186647677 + 0697122022586499143860386882839929813751234590790881003673047769341255221587898768035294711863803910391010620206350075218304635 + 0915512582808181894140392610882201933416172227163788895549745243551406730258634514282881847090763083210060265428731131498145196 + 1501512625884967191270103224021116637844888067197984181082849059840793925774486252348044423174920237439188586936474269289045183 + 9546757728181045784907692074408445085975750656689918729547020741600264958315888287557582915125013916814828453001978125724956413 + 3762013269830490722798916645093224443451891592652341999436840113601558507630551284115296518475712532341410529593546552381421688 + 0535075660768315265313017230395001783344059304089071262026544062275821507449160749765605530180854702975356649517426392492153632 + 4462229922158652059017569592409947967925255644154395071833612619360534506981545280294824268624971434641426791536487863590137885 + 4122860079882835156235088149203967906043976190683635109983922591971046404170885166646247578979128875141127938069850765269247014 + 1129866849265718274907637855113066201183196338524085201233097892015346569822121339489136356302467977157281536251430774161642528 + 4989929495806193845801738597980701228751796772240750395477795189154079611747433960930484756810247462060407330702869333431213592 + 2584408285550889731205066850550890247663800179003073740079409662955268984464235081016863796902152306425169108972643255331837648 + 1846495490902027499953838660575831876113795963871581292212984733841932116361051031722680807069640515568611052917719380714508500 + 4730368154761060853591867016650935034777443474265562879400822197268954342492544791524055284219250660710445080227842874954141063 + 2999165237216316240588784731941187402326266210523501276042349025855852110771327522344504598981978041650966736224822421754899433 + 2237345937661408885897695793709671176319094949111986436639240560063478917538944076082940836147591761497957719533329126550091001 + 7598999755791735199200904311392506066249434460145555306422386713523721542555336766166589674039359217816140532997872100172694264 + 6085462229902194135463330821695657542854346332891821785703935541518889566865952336969577854576497261635473651422862788436766766 + 9330926718781006335569837395334762725138935227106710853342363931868717426383038886351253414292607302835343171708502682390162568 + 2759725885383603903963134803626246023341697535265756560586925977858745569648871684971845885034365173610581864076735566479105747 + 1316975221277998480665738247654385735782940591833339656446094875845628844928541054371377477189441032462815404076598890156931227 + 5084047857098057061549088214576495134500797236087647217879151791731034614882352668503598335757353547259171118367223224526235321 + 0797097525215466425082977546510079918770199122108187284931098479825643355771575695825936128687263528517399780086601002282738464 + 5882108977367740469432474363253310136350409797015594231680654761034810033039280285322415385168502267113255563957206593967018787 + 3765499022319437900072126982943230712423709856742749800481145115762174065774560039072882469409389283337021169962653600686979665 + 4601581997618072107980461792417647044978305789885381659804666757198975786036139854382381412304035407153678163339829269303413079 + 4804720639771780250811522331538529037693400650190090078194406321327819886301852415216493527923345326577327202798642624789731981 + 1262413264233591997549583133381940611046336903584987787247990058376502498817637376736904140547566821566316367905947287384644751 + 5776817509537024183629053964111738625804577685331848301319393405578215972673272833105126341165662081776587402862223607527237841 + 3028857137505052452119497280084550108942293030946862851209526606327291674235480503744471700882929025765105260116471991605614081 + 9340100683840148792620022922546803909003134351687693370396127613819896251128556322124687119185535407506368947843781106277912265 + 5837860085277971472343245356960717599185735265281223333386501908378356024658012834775741482445665420888316355875215276412206400 + 1493889817668204302273257693995210600140074382228307911629842034054862116792315868260039297702147104111933826341459504324514560 + 4753667010660505615221578575743422389046538837003732162433830910088895626144829160559920876420293005201234062697339903600869729 + 6354021869352141987691776069755076073591529011311969753213483772524805097648788519425735403544963778868397356812064242294599252 + 3007002284988957442402223796792807680185699679494949671140500739304141518373349678385232543712822588498429151363366914067465545 + 8768505870421737992314357883218463757749966400771061631074878673057982116800200818694276568644501192730861238043718483873582182 + 2517111306024948547742611078204983908881805478217286398022649611447119014425201196572509914583877236045184752832586045682283149 + 1376425079937583047628837215348969478849396716756967260659465804416943561566523910593617918317955498182529845524570831173841723 + 1739036166752846450279902298627287438597800774942709861167238037011909085160508767640035085875297386568223167138576660874567993 + 2749444684052418908020211162253183694144723421354516311236418763218072849726536005435788876083510665834462678112083821685346156 + 4979778261313034734593447279308534789267778320343662336147199781647935359075816167778411424508493052174895307203375091235720947 + 7206632108909493796814807157234843620292819404196257674170712616419318834035027854762640349933755746419728237290445935893359476 + 7972523340752476063451026561953128800722191374241698295085331249527419993680680244353440653002242129183827478637542127263140061 + 6106361246560664390746249407209413785337414934577733325155578012914242942249188259728108681483189855141297703781608717770284437 + 2459983080689617774602481236618573771655193699359105459132425259318658958293509205828433466503731104595644550263940782605577596 + 7182234637562052669040625972588934688697821675314146092726738283785184154736418695256280074985786382718815935852352072100348316 + 6798709996334119952629721938215622401513286500076236957073743607147857811179119661766817565585334251822559283874472847953361475 + 8077368484549177973605286548826253514295310845993496549862916394171225254015547467894554807332772219846678815481086218479850253 + 1557723569466563274008492657223419903746768944164337126986375831639044695750746490501676088871281694494821017358352031765251392 + 3419994305802489285895038983304368890483549511884971605938842543322203428568381657097437964153561863023468226697072309642108698 + 3155924019915150179568158859379848450337436841515789553391587979303261228659176045375192003213895824215877498665997186076059865 + 2999137472267175701076913261675494050812219217526275916261893447733447516002165559492227300890776947227359067981526656072673696 + 8601098495166116027734424221556221472614130194797807299983947972112789211510616421380969053402247170620773625487954585201101683 + 3246912051329707460282887222043348831157339566467828142441386949856139091307353393247884498427787480035549002968948796358423112 + 1150576199110861158548115562719716941558388002376600504843363323295796185489468606412792484061811432762347078760084900402466948 + 4752997880608034066503743367113742314926769742881109939696550927489876774818149369014784149716022391683583701555271412269098049 + 4122947315189371954201913791790379829165934721428116210038908501041491200253464990161405881080768468552171131345401309484164251 + 2900730978305956981781132350165898118101889333020350831669690402919195278513062935410969054110767363793161548411520509850489790 + 6317140142444713262780353377445709754525526526100220931420853524029521161445026020859823577131205174501439000115119816705181410 + 4499991523210057790779337069784661258008182657881453125037535965670105347302421579889956188914279278573529309721593121892469205 + 5508146256593369763940336135259800659809619929794178470062048041370071430831208645554427627646035391559292722312680898801625334 + 1648967526716449029810215023304697906807519889979105852637730516484206305531886474058371893246706713362439898050285759339179316 + 3759482577410685684593596493926547017312369150876917333521714609230709447558843397643743851645851153700140054595127571231949538 + 3562024855350127743440468170916592187245116700044293261821848456699166330596624128415577062851344089770503995251522564366175797 + 8477766635255068732724822778949890633417123111391309938080502220545229819981424955190249946666498348138015162432180329219887241 + 8326147305998052694691664218432203744648063166741259109591553998325744681167769329433557902221338261010505326465825260282053606 + 1089081066369978288230079958586716934294819087031912657105656191281125863299636207713663767265987214971817617524167760055475985 + 5956659161052521449892118359418646820302358805073751690270525811449427458601574354728795417080178749838253936083489079736869589 + 4756040554221482987126925729358987605986625930694194674956898248814661136244491613548633391179640626903451535330197156879634503 + 5269657254348772763363513450959859105237330221730828709908803147787150002260299247932869706456162552333441429917744946610133738 + 5165094570822740809419687589443353580562603424278039485215120717937567901150913213688361129548604982677760158365547321585786532 + 5721986004191270987440236388972839714531938869537328769699467486823118683325371541953906389947764104960444262942308606574783420 + 0825423274999976416479179163665065444342056794814403615470874263539258759123358841581177125724615901000777617590704389294753780 + 6742419699812742131364238655136167729098672287631443854160975671169256136755724718145831652290376122821890697634805848496276496 + 3900848450956356316829187800619138955746586281240305331127062820418337136267131988611645101253214320267600642044789378308027813 + 7768142101816225544376840102775693516634889161775441232950103285109025549587962218777853283361116377890977393111956211092720773 + 8166062372469258701826599477785259752674604446062893635372304334593302933414637458058589360745838888558751703330971096452276811 + 2564850420537564339701047323195837094030546459418840734199428562634836997313660393990033302759129375346102025176996197579767609 + 8872870135828449673289983810960029335233706075121561262257287764860415827304140209641297619500143080704997500176861691643727930 + 3523914550868909381989245660265536145050317774721868915147125702074806836551953216452075481799528663908105214114354861340552001 + 1593559589951778598427586959614078571783195940556392469576085221648989891950185568932203712798348499019366215767685195049047391 + 3677450698912939130282894253043150590674429032380702463421683822229640128060377145549638924052619130706857319423374607432012118 + 3201722283329551818782298921051193764095244804825793425784091160773607662095205922340014721050275267634431286245410339294369403 + 2407761928636596422414810603411396624762992445889584536298033386878386163466235099237586521069756385945437909851885956052776101 + 4551892967264629771755662186507262378960508623998075765778878560332855343021946501189553259398537769291592769103084773248272732 + 9106997275950792264693136508466046590049216555344492329753333502148103978681698340982507624277442543719542272924397318970160593 + 5003643337652703728951291818235842005801228735393820041591928726474748137284662169580644065969190131576241311478203049648965040 + 8986752392715741495979561841249049222033021019539768600866686767034142327899022898431650915325022449300084738502689817549514938 + 9360763437700859982761849014720209991738148978736994931574590369983794309597034958260372656270656787930070334337332515206838552 + 4451175037964641122624713478708404279076794770827862704532161639277525181767823672699083856308324336587319988741595847500500923 + 3042463864865181170367979354550819973787820266099597727415684485159423697903917044701020373206808416942704276522208882269559354 + 3048080200899219985092787175219925954199186801590258882778436766885446862979938621696230463254471930200991285622531815432909506 + 4494465194385245878424876179842789271630946260267264275467756829223006003558035998437034034758226419782837401641627699056717218 + 4254906820448949384513753027180628971432660348348526219339979967375196656324459448972917993637121707012531419527163028051764969 + 5795056709264059459045347065077313003930925374715251843125468051992798115117609874425243624614071216341941951333443769594712905 + 9786422961702175763231201440570153261798473160575498751716552119467779736203318520988291431980397558340560735449110931384906041 + 4425505790631864513694023511858116075339628625002969403915799344384754821079679161200533710912237340094421570796695940926114650 + 7558163384552078162151051048460153091046870543482529259775071328325205703384361917997334121827387863984861026567298429845774499 + 7024151222382954834390823993921385978213128615164507102313528814208567079688499912070171914927156859122712993045849060653099070 + 9429307166946990362134229731057708239430020956417601592711428461279614801214510176796114831132813782448589275144006367262952407 + 6718941975166588281116323921210724119843734085559061091993083658912394337924185488399990441930203011310984521684045028699686488 + 1289068200800732284238439423123562064066343303384293220311845805205731603115472146721163687728630207002750751276592100892794448 + 5346713601139175262412572458619231213504622828349869740030359059521925593845499598173510818770588358689016443776827808183107359 + 0509643523301353915236067697449265692352443278187907371809463832094767055096167823904552345535023947977150405485951950799761287 + 0296312146861071422545805752124301678869184550494728174693762162879350214577985621448093757895707899661121270041521839117379026 + 8409726864010205799722565483699810469720898682668219634727965108320651761711145638969114309423068089263623838477654883333920986 + 0701982653061769206880551891091640218809670563459796391962611157072335109465122237619770084725609181414534082646884976727487576 + 3526106930335563839568672131933814040405238902124634964052890265269753914225841472646860370300002991439661062411618062909298184 + 5489284594499017553239845981638823575689673477128445661568350850251951827238826810782941625211567718831490113495662231409070347 + 0761858518186015339779421490664354210470217380607247145985104277374945800693689645130689632481933731656998223732805590077884069 + 9539065740290512427091282228814664586680546652097563995149483899551962642839270109575078586841792310434801955703204357001468021 + 8203312934682104375075307914019684558657139598128081066927393125488596174624606696359883862043330061635166484866461998328167370 + 0125977272761404461319903866680344397363067561278546743044165247263103505646656505183679223334371532724158953424891372755170794 + 6917119468055808943262561786048361427010843965462318965409483983665658166958859076133376429071237660115286920877219457193653148 + 2210582961962854397595552344204221218872408837841098089244290975638461916790216426889841183579823514753626176299268639366257142 + 6938938279494808076759108059141376006848614180404742864748925105751439953802762622388768762467629341123548099684486115445621424 + 8751508911757378238494838354486964489105407120238937324611137021997266296685725619021335556120419627792798600024754767811910130 + 8942964732151281745754352094851080075271176779020939272053185795856508342400932987956154784656391491859464794187568016580758549 + 7093803490558017110343856896961686184727738060163871518042243290379067462803909424058805017311424240997471204900355661374314140 + 1566736119124005628798032033275204642554171747963659618881718232992872787295516246973812659316873285663747257448232242034285446 + 6562507237663679024109994426672469847713139656813945226527911495634070212834050520202668179078431355382392103665110926728808163 + 7163337093376914471075674332970801236470473885515009415164064219689152465011362048740380213961234696943727976782304542628115287 + 3743855222420028553131853842508021542825305338712873483864679766747424043976484573734764155416545908654414383080932700776375519 + 7834242892295013548785979422302177591758705851513681511359120504187140172485698646885346881713211672798953029529425679446990175 + 4633893183134377338289855331963450809211760110920084232081216223646405738494934518180959043407239414117561447413964700328518217 + 5433662660787097930154056128793373805525457327147412372094936236754711564146018693671222546348461125048100620268398154557791577 + 5116486674264823893675387799935762509658389400995246436075653037631158518006706329179420693907432583221559739906432889568752110 + 1646689708083793966601961846963380825939768409816872372745312253381435289673316700861369097472435861788080748455563750632269991 + 2394913678196583770021969391869849166343366172108313828891776494450171319520427070741615104344197304147604907461161478146821535 + 6970220265997137270733854244424832298730380713169130932100655564124041223879414671509531965328454187192449944156019761861229509 + 9043786409994994408835814038392730289274231805044666470305971162880140578631950679277309655392115372566040718447348800220519568 + 0260472202194716089247619131312603168906540268723365507831041804698080034582459501938467511494620080710391206340388730610940838 + 7326118518322238969330571001468796819573761190336351214992854388628577544497438052708919701742914513344327189122670316147267946 + 6390506784888882547755768957113718192319906860888999507544967824165514074944084153555022322181782516106164395236293833936377054 + 5714641021392941796626276072711028884736425391454865594302431453743809683815572479844749782164523410744380979378894640742103628 + 6367297859579910614284261237130263461592389581599593438725404642412171244089574507753692124870352648825973497683300706972608091 + 6528879643690843406788232137812536357500339309765626622435903074816275044864634059559694905228929605192781404349845940406623980 + 6885914653705063359510874305420852766939519431522048421204491529430787666838710231728773489324489696476746687650429532899868255 + 4233440617969212981294448839630057962261459110072028596849512767604956758310477460111261843845740348872559542671712436710774055 + 1508618282454022497140169566835479909506224026572100667557407598641042136865104440157420255694196211078208396396117860451776365 + 1507239834904105526832362883413042406464314583874137343256081467177503191240584039921334732134114272817444512404536172921303844 + 1462051089737008115697275867129401567569051007638125298802754342170903145796642346081652330045536281219892265708368809837219879 + 0453685864744973901237027525243434738854537803039815016737120599127474654581496567442710142699846446910049480896669404203340348 + 9346689990227089014642019407223078337725269644715473933462904642091284492249290308972584444368741981346317066840314608857364424 + 3692842182371137943388889815198380579665396475153546930512504814795832691928659417816231253704717088404598973194431677726441667 + 2526815319204901006066476270701860537782781626529137506566276977867530476935375522834441559090476111355166836264357254224488482 + 7009126058180938597916312502300245038383750490075362057823728327394777642420436778059817272275806207554818391187127829756177915 + 5110816584935888048243109800031765306763187568267294316288420157299418121619714954580527036028226556975389796598626288986624596 + 4019814997533165299992337612192568036796309043358811887855691200355299547444919142751489527995336846485123932685995757878474429 + 6005599839728025790953582536623365308961400544193243119538823245141014368431208016452105852057876883877763572171550179791872562 + 2500356597670124887859667877622171934055903916486360738831160634956448169247221568037938498171280531058898708454833291828495747 + 3109569215216409575065435532987897643346725582420896049058159554867798859087403090846590114662541568279219050551516019161353868 + 6185483127396494726368946515385004646852626975268477683334752638226219119476553266373574505398051454753329418244962919295715945 + 5344724458607009080560091971792387153222793929070066348570583467465266923727598378490443838259560132593811322661974372369019403 + 8458407692595863178782843772482279508788218196221474525584418608306184633515880367399229446502766746947115360332883675953446527 + 3121980707768424272697486172479450164639268792099956499632892432254994295106673987928794494946432347077043928557939886000171261 + 0577050269924549664323393933836052936324274196559262739026908246179444460993650264121746529145829029909925451248158087279201429 + 1182711132849414035693613289891027291528838438771406387710865605582990490514444755922132927296236610194750925496351082081251878 + 2109102647103389955876851996958955042517697886815050668367645651505615553003883543425993431580868653965842109551601532047774323 + 0249085151080461985544466651926919056622702235431604488689367549402288274733008707563604434799848038664792491456040962095929365 + 7278999875589390549123015596410656975040860435505974009899756364318118677742869501641184521884257988494124371969275324199080350 + 2143525889485226056728303512644071737922673006177865168448238248795782597126416756968158704999395137061079007456174899879867776 + 5408947704672811574519430929617541968994408425732774912564950806181733784295540418756875998713610000715279835936333399272549796 + 0046618750251923685648324487668060245166359869535034556031423916249395766390348943983259976779662337330101459084587467420377611 + 6066406518226332392745642377882173038406100184159399300600456331777383902825125059202230966872433187523955621780460854740743440 + 8412271363530715396852912523334867927661153444730211881314493834485030033457029175684264387115709617680689679312093978999879040 + 9657869183165570826073481937962858496613310115706782423102371799566041214554100144472536538085009196821977429400245149738069576 + 0816241320499554734167424446072196247447636657341202004109886635882777290094614656786148313850718338218604613751038747577375251 + 9117319836426478794488912868694112364734778843674655117850629082666869083673489067903986091210347641126774671760575626609401765 + 1008118532396406153376026525242599592034858556342525818569312902010080131834952260460690347206525525021427489641699256115948329 + 9403478796471636735520877378951136546880804020374976748551718084257630575582778549740221982719791953968237118454633169542490322 + 1286802823239946142833722240859834876694232965252258418975725767245437772637447581851118844815831626565504328510567619469003430 + 8292609187732000353612944093829468343729520826414837631688769850723905562968822078612443055462285102551209743540366646373935564 + 6195307285792520347832027057354006551256656817339152300843201008404344101735346974655890347210090580920518304844457209111402489 + 6224596631460367862650134161563558944936031773882670339156933695467888462978309028912902276648283451994600576418116774756356786 + 5472438323418087607827579818345851863545677098783823512135936630219825008658803838212318120192887213931109375285743757983871070 + 3462295993623789324823077363153428519235539388072977171154971504655245868325675529422838022778549930317329461099449011610221962 + 5200838592621585186795894021330350557903923860725207306860907835414568816984390887997385942459848064357524983387010427408109850 + 3373256185275744974070989354450321389766066372305525693275351316959271980719451196548752519719437550201627682282540860722912254 + 5801613469773755028551251430496692677302091408721986707132740326731209806971448849117149983546378567141073671063743582525928527 + 3697803453226110613863663691507092125649804560354539788548901908917360870034087584677937779281144785927759366742473292064354073 + 9963717672138768910209602639579145502161357030053667109664830302862052329208650435316813897369377235565986275115675225384254363 + 6761344873607397157287860030945733938977023836366529156220217899463330627464716487783276767734588772780285540219618726811099276 + 2472361254288850026102274317845905290678407546967989656293686796378605109224367092391377532276351514638630925654015471910946545 + 6893284960359512924679289275759756168128756913637757439682764283483027618435659261867805209746618113123871290501000298928987223 + 4604230631532001258913408929361874112508575772563457725381109205712576762498230243782724863115387239822706836827854691589225919 + 6353180226120522335706585585655463329450214403091956830465201717296254555917557791034667593584676865134148740185250129625269812 + 7681527901091326113048786722462348325784769942754780702258059604458735745233803955056030921585788629283445553041509260093245352 + 7309220586489676352977698261496440058970947266199089765873965038198042811288461602506269407874212537834374031596895817266480252 + 5671380781713371554805278200673327258182545730441250958579106569242653773093761570049297046722445961242199585137608405012572007 + 7828486850550976212754252064205756489990487555478160661135559387233240543781534504267534308047400112433806739577979094229507603 + 1735652617764383585639984486995149658650155492118012228612717608699086389981358293860866276067465797190676060353147557719908880 + 5809608466540093565672420660893504333126497209645992122475383330847359820073574627113129012380682929130905963299348891171922548 + 5002869804918377770158242860178234038771989441187910348213084777623351555039769099812484337067510542127104020429900993982081671 + 7709207109088318832932845793851072838104821066587277352066221192004565750065851231562111055731251503571280787745188052871173891 + 1300675988020851714469995143129598445432183378365444739669948446307812357058373524561004834384315759687175675721550162755500065 + 2986343436898030807360652672895860427883496016032784149587776588259863806298337541233639409877580883769111783951961729854269967 + 1601823981755766290542611869833989750039385604668769648848238807861573337182702195579127745245081404264493592362053024115769418 + 4107102716492675980158632893016973041072334043127798725365792088221597132425309628489541173280546793641323966773146909247868755 + 3819683658930608253697914654878640066261793324512623727802178114862630064529284630973855427311675132424529284212748792990550668 + 0736093271588205855246000014782826243591602482151161574269309829561758900770381929089531747951679154943426373942743857678907201 + 2579391599623221851200754933465381040789651168701188912204464482208095449667962715138795642341183881460864419304811104815352329 + 7570162647614550188694961496075537449438462429576197619766568228578156257291119319362788331980002153009584790725962518357588642 + 2867301400919047583578998934993306274019943104502333712247027666654628326692485228040996686989047207277332133939435024962426111 + 2800118335388070264161106773949228910777957160444174345990380796529948251126974186339060998840435346432168006747571320370538154 + 4476893884627071583698402476874552862205711529686822374264860104226019597554331616506435529408791452032863624032022777509172662 + 2387360521387922188586138212711962601419570169405135474539424296757638201501368935895796012267512214174579198583111876438042196 + 3207944223864976640314026742675529342045001292563111065130367748865114709153385711357232421423093197866403543774881366812947410 + 3024015733350974607130082705448223007580421749047845265584744661269361681112069541859763264352543531462633691003101294808859592 + 1169692162436061367720119759930066692678060291627161481443668541634202666603165593913992477700731194838349007676531720171279849 + 2751165267818731079924541076614810221037738242037928099580658966017244137214097278777683446450716576425458106456674343770827281 + 0396856995901845858069688500739423611458585131275613789773338642449531843526049135797567793850609374983112677866381777610197584 + 1531087534395262206112602286543697479767208631357778942636385138053327121554947922895001619615466561594121066079313165604153569 + 2093692637556395792176696765614996657813671032355821221008345920651772816571893227375691474134293122057079026746734194976675858 + 6656377492316720744820927448196522955924434793647944766092359157144753759050894426200065451501628415477521405487862719508590906 + 8342026934212011048128231645702815266555959471653323962526192450377377432253217447538860983839942343996469379287531744331673799 + 6119650763732836889688973448048471041648065382987440098529987344461076331072134069257926150018448979279801859696456939951283072 + 3364756734455969829310248048507921203362218977909063710162344883654504743601191459570909322659994691353369156210663856657262211 + 1878353636597017372001364702577584897453891661198546393569651046602221858825228640216854117340540870937305588763063713204215566 + 7246416818039080901692045886943289879346943533530756863194707455582283075691686089441132581902594229725501704594144338085541945 + 8508829844172609725721048474190455937918008659794137613216237230265268215971845365542440688734702896182248548131537748110574617 + 9749837159931616345230389269791318525672049015765330922830030005687071010042562156668767526231766645728311230400611546831340883 + 1042438692813477410787838927504883371438184111986343392632454033632895691282059130126453347410816312739668264804223203706756562 + 6361009275683200524885847104957823290376975509915625274519396770442677593644815139040216252662268629183385844801360269251220612 + 2229763646114181877287927118379174699532585850694835097303121614336315830870465640665166803477820913104310061050902102789844598 + 0133060603914382154852269620976632642294770629603193082836985616373167078617561223317446714275063351779922957184196466970884767 + 5219496051735919324804049698971068904312201333312370591154056704186542719979874616042547422134608890139798422893654424476506469 + 5309445174646633737921041425428020908437429638540244462052129439971214228921839562115695079069371301404828066341916732725724068 + 1929599109824380789046935363381838679112048207357698712063450869013602851026654755608800829647182811384855047709407638244169874 + 8711156655539521674331213489806723157012020673218852893220562275184063123762927470825532953422135931696172529627131694897868313 + 9146092529763359061139625016856546857269473202244951373230403084240273596615596144680054956193346943461881907308435567570589732 + 4427806006379233157431109769793014446131865605460452718401487086503103098553754737499082181376863362004474070049162679495304786 + 9908319411586467759323529251895892937674894302534759585448543523471481019079407250526711177578259561097423457479183321229451626 + 1131371780154610377491766557592293428206914537775417828678921143427727968850975607814254333398412178045797967112746828184963972 + 7463947060005178881443883529993444944563705484864960478232839522887114302507061077267547873033859704180182478601068253214443547 + 6363654733262110562720880713693267188885990129857236073837004378034866347649760844198517835526780984480422568814264124396245788 + 7422184144089713717140409869475766686474514248637954570906655127051840364408955207306296810118720773449322716315645914875117890 + 0847277505961582786741295462154437342373825998662718119420520873688904858163025326891259732777158377960920534957757187301680750 + 7127332835591365255818677928303920688285753363566564622227243735455708574607542891965353908456436608550001451776173990862992161 + 3829054399301597187964270168808949938169540225900414534726047012413120885338161369990845308813286961059592718025627205221770817 + 8092148297686870086401035932812080011392424084497972356658952923082172309746025699168011915919281009722984056602687718337362402 + 3027398748877048907651150695381083835937725004446873842854430149618594741819924214123640276762016797602129360641044263480412772 + 3710143070992584709931252199044234825397803955966283897640299886246679348943101389030142066287790993761176511866201467864299707 + 8525777612726675246376342834401281272453399310074719106459898269090225065025922311415205451670630902470074176854745326883762644 + 8262544278833799829033118364917993352082125138925496717970983928091600634758984244372250880458595883955890831596406628913521186 + 6897853799297275638235876552327431216883341950745982036695977282177864189708565950522537254131161076036929940837531981536512451 + 3213748658129585636531039879081929302798794268346651462737129452506002968774313717689240477017446831448952135158407313634350442 + 2055874845167569647361541785365745319937172123917988776868257061731415878495755011208403654576322652419771761741735204486134128 + 1873586980474608471307789365974467503495691071252149719435658541818854563735190343177059527503193288117651496365565656653307241 + 4168177432498780914163093904219938645313613562804544457122557236850377399062589146156364240794704626265205228184552480787389528 + 6002548119488363978641919486071068284491204688921592270835983882131004647117906646204653024128798598225163921424999116659512574 + 2157407327085931030684434640191280950835140906873052295703366686157391470840100604628128222870118102675339834080247719766902753 + 9516075696286688385617312294770633537786940805769023218236327039881513937432194699645278901401806327344576080861704678059497048 + 6871189362548323056223946109945917378776965980493422695153032621053464957232674797346887230723234348508681395275248458966927875 + 9336780663866116286377027773514857490216582712388958421219481975628619943979311778012113187699153459212550397452631591800634557 + 1884225357321516913996913776484184458840279457439252830670922733976854064570789902403772321837879511792814698370553104269506613 + 4608342183802630938543364752477985342180204673563980704638103829760160093636516325877632052705116775395863314477370432360214625 + 3293602222611238360052445923968119215574068058661794694301159396049393023879006675439325347420522015724464971518661959121953285 + 8043528468318108109054413534510021714964009352370382732039845180887830146914560592175998791412497342760924247174793888155615218 + 9953136600515251517270114445026178472065320103271749951560132315486968402879259134348096557033081980214662985678737805295776016 + 2082425869735558279582276249486763021868424618618158613101945224876744522204200404218768513612549469324132911065247448884834161 + 2715300790048270780472694746992029478410340286154036701148546125752257415749783382221561686531788228065371707859970836437758369 + 6586934570724918966767618089617174929582836792685611937969070528242452974277966964414407164887044841543253218406757856518905749 + 6701113102105341541135759678684819193668388121785636742894877294681466156143067331027856246686661690573758062813040020779144644 + 8573371736029851148801112116958518768083768805313811181481300256743484459392633904102235738743377368774016975057841718194084994 + 0319902874585606893329741100525933056084182554392753427931707044407179198386674603799910970919558297811591565044725137884178871 + 3211448717893811033719443147078575334620516368575812396883003880411447512133976398395409888756416803178312866623025053382610669 + 4561353382089346913344316837392847914820218419836561651969690056195804908190155708078402986544580149409461279682788447362287221 + 6541324108089851136771616890125941444979071358059045831564141967544312392874032082755961068514362364886944531733042486972382351 + 1947537457345366294923388536623305727166280503481566200274732091551547741549840732121496504900782994752246247415294786133670139 + 2790662270964346469038082957923935596601670431239525874522807293008957620170868585946546458722568195100218646703049798761457890 + 7207291855021167963306163201383620528292099344156171536132565162121580753163039591601562538194503052311054883261440201088776719 + 7081508994123346370534091387062163390235318525916429277771533969354167555829004274478142845946719915110847480617275074050516329 + 3008933084371763781228021375479207498806120584984898188493731541257384657224732160257247009445015469067201744844463068899016846 + 3400853085115213814503196501389761175483359326430453738990669485692964833263969136641748087708764716019323095274097377414065683 + 3262060508094820191682139681063256834961825192399541866597766579614721818676700322392895466758698832928065782064894903472978312 + 9760920512587884215163543988536526156574865982745337953096380337326849623081010538502752692990846114093305595114511445577198415 + 4534258782640418619628264506406504403447005968106774436451122846867047076694261073542029684272737494317052196031968617018760037 + 0005723042928179923030772189645554654702738582913437716383318676665447081003973531059059732707456286646505439805283337167567513 + 6867755898727425848664558154624878031288945357600827739272457697556698844756274091214882872082839937589030308224565293706216309 + 3727537228724168866963116807318580861851195574160478712150379828696545006021644250770529425526279645439265900826286791538135930 + 3153997389799559939607422587882124977791743840140703583207584629133167628782910497529520542920062933572958127405711490497737856 + 9067474435390875739488758031979945416769209293461704806750415570467527973320692921500611307072408238071671039355350126215323195 + 3397087786775809367683818985726713074834263187298828458889483102002512283284602983872325517586754239568315454503146853407356331 + 1156217453455804570907455838506537271360924924818686966590633031323668379608702859282734283827376245634390166587981939981633250 + 3412106433453184147582934702569648764561354607002098617356742259624760387826342970038831595863063739528564750876654025034114351 + 9541719290749487737141992118412804491779799111981476193385533300689670528815189491502637221085072487226634588032661043056759668 + 2892064967147629869694614423619676513067951679311770744515022309616589783655846699918308471661872732172650395986258940991120106 + 5144184865919978928920815222171229181997238748998964019938552954342118630154574987629428918689878418879411760377091395290416344 + 6885105521575830610256425097707534533542028808834255387318107287078639558846084308180272966744285679093270081574095013341117481 + 0825712842225983699546990461215024477130525988490880256409773994103713908818390693122587907689102651005737105310805023272218302 + 5661584786775396459681434880691492087318430940497979741425101788956553140338175653002561188152737818909816437963790481976018401 + 2333796064755969606150287094100220527676969430567702969130345130599373183629780646448254004373148786027781444947828389799036231 + 2370159800594514645060430450080996614777495906387714719376787944968432214762676658329959973122495250133837956302119421564977403 + 8812738504000258149359611948440268119800977088619535948947126735318099451090706379617772423943777604512120621890539370786597632 + 1363253012488373680482054568974446439190725621429231276569324135313694462859720454323916583978487818838914751980359776090418942 + 5309412448985837938866251311974802939648013868273488976753659392241870912692861488024484868367836148433592247524575436350374927 + 9969514974899115014452925807661936280550953879875740514792224284344537632692977097082883985126798768022555743127429841568583436 + 9127480468310694537875735497900079126170848463529624094796935948030072227221587835070990509651876620138981087391650544865276910 + 0663274772751898865701481848764433338510687274568588217413099134231887382122648096865873338497066278774094796953376828006000126 + 2223991886894820013487780739895880221686260123953688255289857284508367990146047269272253817887508457566736245360372546074724620 + 9022913659536358863270572069247332195356175380482645548420742634480093147625717187780842180713151897503373416116801897541549813 + 0040126272697263557284035143648280938089213881029883862911870694532327995219687847437429389232425351493591671711796587562791256 + 4017430425461987380494086228031466897556783584467938250558585791601061306591861372175583299944343371927286490389555179774602318 + 7872955211264709896492762009841470583148357109101357998512705454425930076065324016499469004837167664624659717653859578461687235 + 9667310959423600740682018043806968632350609113790915003388710593533872466670325086871976600837835610439552558719613595783702236 + 5280944927395295859052540423240381366808883628148042644568662154130067762884915257137995873057791352572012021048384019627522811 + 6995106927652578556591681036413486142384921333996800868230237202393167717311762878194321699747706337864446498735182883503516810 + 4894127087101054059360113153040095596503789486674685811347198640008673703554343464924312512011781208631600506972544379180978661 + 3653914862578195810106428140030210938175294156340298752901536901851573154592330206774109827394766622168822827213223926407598523 + 1752287994131637967328932739154812431240663561508299992489581255396838237199970478414918524473397520840434054432691053868383392 + 4475254299662836002489198880413157763837585826054191105485073144949660180125415108179810953128183235091235263489809711965370068 + 5618413924400018858280428271296438533254641173714166471746748160577329614446433367969692047250196643164558060988866789634419083 + 1976673569829377798715474066924169354140929130742194843186922903877261219583485904128878654906618865153383966440192899927641018 + 8533161119710252096705226091491715680664590252842043928311396400578644885931777054299394359376613317844464091496561469756448904 + 8685184190096699452877940339075889148354699442923532123110999704074604303853725375307368452619373244845552599196580274471194639 + 9829578543429362536437207266353476212156141077734490396691958840205815483098775874456262295189398128556239354143693110486242701 + 9970409655619169147931181826146996933740442172396548865369872311637351974239103479278809874040155159335694067867509786798916993 + 8934739229131395268686186934227620999682967502345755750450754377980375485746895673108969778424574385778481433357869228670933712 + 6403853140387575318798294898252560753364466868740386419346298915926350400035543680556378607221479519818692502368546406996064171 + 1053081251212324305626596587814428006013451031378599825941680949090154726066128761151070261252589982556578267160212779194125716 + 2889755089191961889036525987804900491217472837363091046321293846058934856253393138783914577483067599584740608242898988136077107 + 3871240659195668412257855781781704566864660291767024614816347476774763467463583115867939922590382680508695307915014840948963808 + 2822134512303137695995007841922537885648949227095598324952993245073100048846948118672641286579492473549786447729014913418849577 + 7115799710686817026544023974604506965289044028358314166807497671714007777434113787389629694840769613243261303424414900494011898 + 7392257640112536311638754807439431161718219269700164766558394503991923942217206220355994391249150834799995352874004008637120732 + 1738169836253384974782709569139552429502554327170357536474522232448622509720551967534903770682965229229310748674655279819812001 + 1013488426299593714852536878758330763717657950972685023529624029812092380027913386862035092137102088651474613519196497838916967 + 2365712331332348797178741500614741133803176085015200716152828860157706088237891249512432828832383523202673780925247731837609823 + 8343543339820274706718254393402391405027365642281414672601521735599554959777377014041823630157212633295524276413560148004499161 + 6041268421639300061742794731401962219148955309257726102832738599350862047986714418077392903665425072627420761149419742624568473 + 5903163798089327161860705456299199357142261228683379549747158444438483324626130181126533716219751215937033507622299908730009529 + 0388816251038799487192843352437014500990877413652618253793690269472286848421450299377527429839922951807455986611893857644960410 + 6747097789593097432933016398117542211434597285816625911203020562919342940284869769635598001370921459163969583961849156409633978 + 6058253598655377264266980145151402530578841715801191174134703632064724433621375404185347776838645447066321662228541280092856110 + 8706460045506764337863851824656889505997963004840404222919355019179623835893581428684583324979366713626899343900308968866457307 + 7217115588869155277775561876870949020701337732105962145058144137569073157203270186719489063643062743100706189008644101702506879 + 2134117466607949382162669449831544904500037626615605917490932121868589822502449721652777432598078974018800021624932345792700743 + 8772537472143251033025302537735317107162425743475413816038506301465925279856675607449722802889718409431120703912286958510209941 + 4868004080038983558128526716248086993854257004538122139718459319434617070817759239833696965506062568522567601751636677225399970 + 5772707421791629107161650375371738241195109244751411366251362152446624847548801413381446956815082676765934768156267696685640257 + 3337783332137332131442737895629161974159375156476294489620941247396447219121871778030180022268049183913926389862808328015747496 + 2718665162373177306261228085712460052227574664675638031209424855973371465310593845908878207798419801473033533102851536608498988 + 8594650062259102571664509669089099570629940328720500583665382040942904077679708565306833479512196713193874213822763114277561821 + 7763922398020531727099680865423760176807414153322182938644853758445162559723450312367220101572741122819976006288279862925391533 + 0609418074163954317311535425632639460543917210847556877142776065667429208580080239400632276304974925905306867007809952150307911 + 6324798067968629831501975773028726696101515750158909358262168518496428350181893495977033603403728917956907772455104980623840611 + 3585603421384321409739580272281986370246357840985885096013164036482124665391931947880815558360671475167152552411643258730493458 + 6674212278514790724079384829207583320586965949581600859999150201711417012504831581096750857003895316139028753798041233239967350 + 0724838602272073110730847467620546382405164306488489590470927625949743749910925230346070277479842393578994351426637786933239473 + 9758486324598916254826474547605389356962763994905059896268073096288839687527478615702716618454224618511400537520151578922366430 + 0912492025822760544865884599694514920137845684369437041888556762598262707248611887100015044910247510922363893211117566916277207 + 4970896832680655065722060515676245073680441413700428191825160119923053062012241474629435368642857468208602093702394160800952368 + 0401643954061460061469538963715677841733067884978557675498904356226239814257513498478706711931106662782912959490144875688684392 + 6427801429230014330280067244320390813250002494116054667882575684276220510978170909405937360209445943389405620264406898441269151 + 4513961131947927648793953864754056606418638015682203461287515973198501950396575668694970608763112445843545620657603445132209084 + 5756001157040952762796856519600056686459818285012859365932754153307811718432937457957972840218047257233193928872388202493970468 + 5745171294650962698731398420701143198082563097452816181021021324846599968746630383827244381072653879098831871344995918422668994 + 3440697357810684087609635992103602934958412129332726402190737073092334237927797275626663021730679412659760103153021222137031354 + 2561873488408007135940986273685629006346887762950502897998328704241551747655409051903344700915847431066705228403387636950645457 + 6677547618819900422307650673816956131536670246263056210725538571359966918216630406962626983531012334568659195035619701341684239 + 2420112802529724475156900639848021386946999992189525298915178531829794178899375316321752347503745229384277622075513609101448077 + 0978966580118766906719339709431650123507257526495690738543102142511117335171869720713914484644191091368983835287599510980274549 + 7253035688826486175835885694607345249760996565501754434755643707038772708239856393717371875268895624588946691881982666455004955 + 1229157575767360965832607989363181678043448764770403987112238108580504462888836301106969202711436540526584606392030520555629817 + 4303800215068042550679859587110369621335305905151798020996167677493237088394878180209234115765088470219122388293468346691575131 + 7160108019683761926270404198160152789263213718306724711634865022789627807005870451606075994736870542860235641292939358601690892 + 1281304446363067443221484815128597038007892955460785907630142069752866701460026126386319238710932447939095864553352289508365136 + 0314065667002957866858488765937097697311458242916562733459459218151551894102884025238852720369894804551004088501646041028776937 + 6071040163745909418176019453877965601147459065352750105116872007917183143758403418504559900007858465882670700927317278238845262 + 2057864431401330101261675645065867887669270980722933655585800822914522258771084932227437807465603988558837727049424395413086192 + 0838403065062402417019069366493917705353727605973078124319419683057212743574597310780151384502291168595626908520023754345467963 + 5237595147390251950945857498093768496867490339391087595954081288707206848402637964670896124834883491892023218043300933428536303 + 9038575918527245239784697127935511565993493329345587370301152888215360283868124687096008034911588337723498130857892917083893566 + 4326309213195337889918560482484162052931169753291241688638438611871045719430309380350737659700684663483713556511824284273648934 + 4109675537859830665204217999322330504340383531423575355281348688917399955785319877102842092110480808916641344634371327017518067 + 5976571379562477291805315122658077767583602698526304594638663614898936945525476463455648126285604724437435096863798048639029149 + 6805684460338235182637901097297785029718931952225347991353757161498388530429639352729227333463916470311358261242265252454882149 + 3713554069757475756235174202220726685159145970448234073615786797869189321230621988473892723703610057245772568034893831333824268 + 6384329807418457095553971699330059290079181553384702995369891469896964859336812164228972258241580918221240870171611342340166996 + 4238496467737330476039022845048701321182330582443048269767680094107459509184801830653831569366411726902088279531793681281083241 + 1389317145760821195180078109186551396173257466092123382087137757380977821227017398905747777928583603397479220222412134551964141 + 4172433396133877482307354312025003410197620920424049031355359918529883398507939057731022302176139038905017200234464598134643926 + 3776455852500808911518410528880591214453698534859661007977301367112639128608957724121376845610991533136565527742397972171004531 + 2169236758277228509207094221732914621136016542832442557119974462763405873279434363734315812872035133971702886820591857401769365 + 0469858184126033613406108887661308724723319896168974862654713098974773391394034562612379275030863451007736429954454094411166680 + 6170337864185847270755623945219598905895923685556701346236877669819713556924060508835912462997027984549870490684576221788467996 + 2684567926478205893568909529013411584469062508988939792621227026970772272619563307265559984083650571137624804538833124458965412 + 1535835911469765914801129303385752847166878267150358870063623206823946840223186885612380869419340578863726545596738437580294661 + 1159345796279619020659424502037780228138063084481952522217422192474814460650570150288813492963026126513178935693001157815213888 + 4115255308469968312956667592729481570942886979872098274544235236610800153069537830562688683755471055934166523033112817689423559 + 9188936491751459321231439471707842349428821745374698747871010980962280880750506886802895843191246598782044554283344177438872823 + 8347722755763795357915434510354216096329858917788023158970394599943300789945002208151468416849121549451743359325575523192943247 + 0386458822265636778073946364464754663546374429692132747455551460488109624863176490317455770854516391720009905789081791014745242 + 5441057113825577288143510443291415701276478572336349873718556812697918623782132025707841689574266907977935843620901112527314879 + 0138974051576176017602134330816942995720273624834286549509110307443436271222852721817459586302582019304440451903755250893098006 + 8714580715983710618302573323538613568787984646210126690769977327196476888780472811559022322326994280966501214045283109750894159 + 1238724204438864658817267118920298143255297575901621515081809762078906592560699017605054545611366055292052387838303773046414151 + 2117880548683675747162798543936995265803158300313026522266732130084089973850929862579530307924250791678839458713648131052866542 + 8688866589649054666206289287368847639201089110726068276561807440633436849032550737263946103998593920752309241137169715090564726 + 7992366978913349109203408811669845313806318145335482602504586472079577960741456598112230859758567892658655917499886892820156294 + 9269289344377943028314943737975747440225464454099585770665233191895455121597963497469457088101021828673050970000696324467074275 + 2620213720505096912466481021388401048520027588680889621938076715558063059090115474427731634806419367474059903683493740456083416 + 0419258099585668206386510983923399175364308512576355916179825772896253917529784626455469847416203745543857585138629447495124687 + 4926957394763419387802807256844093371043881188012601196274750577103452141865582262123425456983325248975618318937642166941469448 + 7745531482212763608085822252151342022701776876422939982991937310338710298056659311711100694774221511805463875602371671771107991 + 7622297042918195524581284988624821755976081656742322232878212092814401063399047757727446586120047765852193643525978220488403806 + 7694553355731009082341963145016321622315287166497298675517840848325124707270827181601834343475566034855078916693975601380159131 + 5691081048224248376219969516692299552551684485812747394911625377626308622713328149116932634160209525550974738125918251287523859 + 0467965216958213222976523551707473542482226303543330237484038813545187688169900375790194437313184877958505335015185533760569003 + 9313388170020500404223350587859029392425277844920011385363704844190916888907282100497715918895587428711392085764058004531043856 + 4805593106127448601646584342013400666164278454947086863410933724954207481882298946080783397578430480735942749099815836074939980 + 5829488935963766897295398693976065473334615080031996490066697080972996155867227149556928263586779745098746381741955988476480256 + 5145688238158921108920160861540066499070337742408273263858244236306539277333029376512623358171655471201632148566471544471879593 + 9921214229435926996318797357630113668084683534980450540625624914828693276400997437801995497337699991160179152196384869788686202 + 5452970283364847951628816855350106161884215992345914720345452469417460755112437907196741570679787585797744951997013243245883760 + 5291067302501955637725509930308800308821879902449540996764882569862895237545484938003965194362900224359317192536398128214213941 + 6161982577027434530385173942460521391267875161999821213546453369930955209737128453903802184733420666743600784696394324963677611 + 7259796660195828763104609417030954701404550411856256961919298349416990278446333820166279192694569999689157318159650815071786127 + 1409252775006780923895660512761218733793242701073753044161926851887250329246949307610371367921483913476091276544943910212219648 + 2024883815854805620725646102396569531338296559295702755514936293184048845778213281077499032309766928238274933799920207837132838 + 8210747670883127249029109720500900846638073842072735692712299242482036224417598293305373767651397688387681839834164347629159924 + 6849912340362293051521285112884702937904971535989594393302698489020568178389718625627324020502329354706893589619173731210032692 + 7043789553739208010357759707009160597258827438739048435319844873364203025319025627611147486361041079291073784131340379802864271 + 5630517567000455573262321447961724157507366377593234074637396775521413915860857523966422306759381837353927621547514858375348648 + 3907374620037626404876010563369584978900791842626728009855287567645993864184962785602670934980414501849977057712840353440946698 + 4146385141059123870591051497280881668008298341992956096236493101498703482256305064373982480667690632647788868461225656591267014 + 1968850563894509480587740368883124473858275653505054105229249423142559298770511499954927552803754424222038587228379761857441343 + 3593066522032907759239532950409720855609763959255411331452747381650146615224156577229227092417969990679672022642682488460230666 + 4777284684581020086703554379926122352924845140673649610422757744893763657846499512591483929572896919893136740342514388775709356 + 3278001195584405224574340518455727489287475412287946187833805383833415237459010850315390550944653852931708140442412147400013062 + 4193626826135963841422031213601650476649922753686929704940497664287967482680127644394472418039840709944058706759350270065888771 + 0496707764123239353916969348556102234417341754509205481354601177831190831135133718891421262586922485229955848858284322651713550 + 2364211115463126546765721277139380044647678205497997698025656179147544409871931320460204274120159204240964415234469912669043171 + 8252385686403049790333736390573303996823129984313927885511658858105668489196273816414521496403236288238282761677474764476093781 + 1249545053006377773498004690990118213356171931577992909398589918937522320753583797192061779831406344206481621920250152295078939 + 3709843278222111715104072968292537550135689257500851260250849491755576197121702408117922267107801447424437466479647604658838505 + 9854374828488017805142065771759506637983062326803172669751646781389776006196509659848336558123328010610366919010236885546271093 + 4449279473317813512456203547757437510023295240020059908269371826627596476653671730054696042131496333128833416321765418914320719 + 3406255777740484368806154865989716577772954696365667763046622581695081667791363935783289021366520297269972594689838903064379670 + 3971992965532938884360604600128828768832371480402617473079458005449743185395881312301575878592825423836990732749119210579499565 + 4964414428994770524920627355735483099389790803639808833122768311697123316450497548024460387672711368021069867385676748771138907 + 7272947208705814863061836555172890754692453812368615959884812383294177521377885043762530023437311935454983526848574910569784985 + 9715236460972266941105456775641088939352379849288420663874812734503948765928906653066695278788734445614220395365589281481052985 + 2219149571492569121653088856413977750911860290899252411873082297287513781665034941515671551141663335672214686872998009233611673 + 3252445083210515790502427230581525204628936179674886617751355536540130374691771589975236704266655393863956951833668294842751553 + 1066643170812591610511115847160870442604844517253754311969780356590045310298592533473063715395834561034249527692096332630663031 + 6094678693574789972643719059293336351890222699519292906160704354339193005774875964485745420773135852897610846364640226020416376 + 0078821325017540745977661794444919031229533952549930041702337654768594140134838827623154832919375367293846998623573154781662214 + 7359805369711475680734455906157477769170543397898162106347663466476684547058977605857152935135397794083854436364067424905370520 + 9053319467618246985715935346228519691376765059011804822695041370567668817595587435020117179808441224160004516561911764361051760 + 5279785887324494559284533174001913906340668600486179364934683183133265522486775587610826495582037876134991475823478304604306409 + 3941979376926208894324337577802341103192284179207690346815460983649049917703085665853453770292030524017689837132097566609313622 + 0874696648882529341619751279943169854047021416531564941329234495433297775450795376776860235960754121606226960482122943806912723 + 4403142549129181418798689888112583174439363438245360666469436690361242515845002333293117928704700704567851599171947638983428803 + 3086178172887575667595570158882926151846562563832038255451988723965663322118638716096644911129577785347672668155756960077259260 + 7016060211620447349613366392265953857687262706207804671997611538526738050334785125634177152240160503249217159499633364839660140 + 5489512175142718110444335510020717260552562939322469369407097546446468340557730058147393474938996409762845800786386613781180803 + 5316893398694618358236834304108186582233111640280225864142166804368748966281116139163914774116490280764125236118841244780654205 + 7528194334785274348270807743401184076977359005808989097790847628594537909545137710117536079654129720175240043680499382931315617 + 9670385576675265565821666921824539041489513174876467496206200652157451658908879498586135223489695875901066307973744711118179562 + 9293554881752014067237144247792025493783429506129044867060712220683356640982811741139549073541449462843252209357539966735713385 + 4766042719100373229390546845449462827735583320023428894346366740071025652090167656518273656932135482003817661060458673642777968 + 6301526335239349282461856549816100522037177673330915447520746670914149246304276129215650553527297720437502141660843474787824161 + 8981954968443818080133345527259601739419841565729583936192031325311804839597158161812415269217752774138988523259895019553556494 + 1375817110090726843596408461202879175175450080051006863993971804570798947994555625585878024069026053117840656838335462247825434 + 2951238989342425774096587516368372195370856662387116086488893532196578602234813604266303300411633704142608233959411992656817117 + 1078366109359744038481314864313226318060249081213275603047710120330297564750748020015170091244280923403487005151336327967793644 + 2590644710984063836471814396137903631095128763841800600303330827770204519245855428525596893191150792386804495821205935562805056 + 7587927489845850917488079723623306056569190541982982580007185500509384196528055437763768159799054085157690272308144066104571631 + 2716691447638059359782976991714931875589838509515317643963169052633209626064370311932621633892908726622398410656122098501462508 + 2187341550744516068766043103052788709422923668066123030675357066234501008353745371362353282261896383609682551818558419836467474 + 6386821883063127753430057004971408049021180273353275003607608462963509731380707112452702494852068512020333193164120541304971821 + 6414619855917522699462290111082170337250489881403447602549155371621815281167692543542521085921503446688385053019234090686216914 + 1514251753750908058132963706101498627247758343884090328099690893144318542740931341743091728225255850843917610568152776796003007 + 0586747600603620622562637108763020672642036425806055677095355709416205188154703219135342081900691181922293308472380603914641966 + 6943882703466448671671347942866066071729197097929636191832480851465967168936588557508460013143074231989501890259153468168582090 + 5106944931177904690443492972535629421878279108027478056702348421231814228319595001969285380236108675594104178148223368821682505 + 1013423077468134180344202453328649263556597230333389978398486618230751510288831048067335293062077986298410020248356624260186784 + 9609742549854821633067526470397698241682366743287992123678759953855431672859515457048320102063982700799641338555460645670603233 + 7227510683690963888209842085118318517866633639207568611885740247627869030070367221673493120062595703412511430540635725690733531 + 4166904720216643652362019185541125336279973971095473810174484610634739482031555699998920445667293351815342116856019765913024721 + 0204685598907595748165591866024787377707833163733227729761204199756529370097242687722444149797918578951904826714174399654373078 + 0029695243252514591043935308120948291772608227171634548103690625246068887952914933102467669452782090604646361027594958463008648 + 0606043910237689889945195721316745105694059044358961433889516172023390307325162841023925000976730946622777686367139699337140288 + 6532770425227279669614506342121365572660042996371513972011473090716295756052824631404973053818570282987235859556502147507091296 + 5784383703297394066201455976072965897350946662861440804630035111722516300582625065762906422553404492330383168345359661866546635 + 7755352359361297136322168309187217709956128684689901207140385336402261861792474715981622821266358097679527860080999492143093132 + 1766368206837633471921145548103904997241216165904015409300725066451342178028580494490424756975699571333186681161146526160888637 + 6435676017243653308531673583521916536301571057843651379516536378840317706213255198563089909258098489728121633860286779010828363 + 4431604721944445862183599288814310892377084499055111017374193726585680550914726436314439993180521094601524845475777232173548652 + 8838913044786662722923315829866963645973025803566829523066407753524509752981118743428995908031509623037684132020735808440759714 + 6831533201518779101708294838185079163952906812726056828622166710833228863087344104415454342957894082410432960146722394394312810 + 0026750412265305432804678135281250107474394107101163961158631241381326874456825116424953228542574854725058161235809819422717951 + 0530095666016377728309821374273950714947770494099333703734720428753672558560341529622248519497385032763976784920070775745998492 + 9988103492323582802831123529566020729884479858348071107686123450154590877464099472518837056085048970237891379355375854402767816 + 5730632914573233372640655739395224654373166501801926999740491530052469701082483441902155873112176686047852502749353152358488650 + 2570177044053910045946498496953083595646140791798652856797075918041625426521730745013108556438270557756261535076617672897082024 + 8070822196216776547306746987791806776779912117872036753101249436897151550298686891155685227497724326515850755173992122017730073 + 8834834453446142095731369167693716173639921382555584546233080228430284169771661090869805523170856183199180807458939980812347666 + 3374034628848110181967055896853894757362330956181597331342944383294532319770922905892283292682026888125967189041997170645906930 + 2816796708896328193169753615809284330192400628212014852560752820595983573685822703155361815716715825780349446395688288981323009 + 7068534005360767613192042797492589713014221879034298952445175191916602695770589539510033643533276163270684273301159972772079846 + 0851847960381648176955810985408204753982844887706344041815181406997985867444440863020286602964269777581948956459433973575818007 + 7244153065545137632239977736639101263396745129055793110973443976621943425823784182900120559207556057714294191011934647831514642 + 6220112071917364308442903062123692544853904143920646475613405698807838684964691297033599042267911174717943845099876701146499041 + 1997737579617455507368079950355247973464185824287192636611840482334933626092039322468638416062106707636638684831343949569888001 + 9056473674062962705649948566947590595122246493016055906506275120659977645801864949778640366697230510631836906881678697914437413 + 9851293934933351435860731679561845700615460829332071112719063019501427379839759911846192375852475742108532990355637732868083608 + 1981670764831163220456625777162284911174669042984422665330847096514572430663915704539930674009046717718308791910081803605092076 + 1436167228645743999726495063433059497403336540806399989879727825522625780324646087140141119024144101040594738802339934675234494 + 4511331339256646611464785947970006064997210981736418145964184001849876673693526718038480153571548117761471182638795979792615062 + 1795579829237064976093578272496505322533909223281608272636931019121795380635442871500788593701642237770643966129586714071750006 + 2259558543726883196265093171148297545202455060457641437680621020678468079454735539167389894892674876922877875836968284903103240 + 5190322659532635977759442475453937445078305277952610411039017125942798503797185204729242079034555967093953206391753749025286545 + 3346586896166410527904055884469771043579999692960199777847808583456813215611676699557144873569764821207184084966272170201919310 + 8492812746065013433267691323002027533207826063607337577540310499920611687417123621076705455447051576454279273880574231655581484 + 7963980271743134112154087260650334248257065896933807620141668762775373128572470229135441642876072741306062133796013873900656717 + 7155588355012012778870617504567123068873574015355543463865010611682540901252618661459039457810933495173848721472502301449759789 + 6250342428228956319030041026630301654869718238658413832351916020529083012909954188736775565330222063260635143292678318707172682 + 6306362489099506339243174369018743275045301435603437084640257826344578993743886263071878533536813315686531934206065891475930962 + 7256078764576049009416184871748648772794832357694303718710674780587401830972226331756569564368514137449167545781329158975242668 + 5137011302637382277771122596368810380574982751431852882121643844964841634725254405565914232138014950212916177841984286676442765 + 0130766950573613943351861223297588274240988343477886895038747758639966388317215304568124673651393253970716618528199527580176531 + 6359126988671940758748887099156058290162393017636744749307547677028026325587696225823070273928497980385751428178855356190336058 + 1262747164602205208071416052898259778064629199619315166088744120423992672210748461774575909144208599043872184758764391922991513 + 1637777143251220955861291729128344859755814246044289400356284088474702731048933137147907743901585132956196475715784684303014662 + 2779656199507816022148661387875419531355613321583333187996164541556836852609250800638246651009398874732599973734012124894691052 + 7354320128684821812105410562348993616339745664287363950112497961551242247169256027249678322546929448755022227225938009677843721 + 8972855810687812606653074585753478301824708270260970161604946179349054120962204468271996990113102973342165999101606421899608935 + 2427496334389700886512192278170872300796174251105207296701976843139085003204747190192754643836301630137058164840301068688355227 + 3959418860712955101125551436177454788270598656333682307048221492143694319890230219738438292220497263359673419823698673057872078 + 3013408623490314068776627587135426768753482653895410991590323095157887499728772798489129923069618646593123822639438579269538635 + 1908216328408109211109195709992731650405613610224189255235529994289098765621895894667201782074632616819297670322225038809119550 + 0817943537763128333901984566290468707429051150902489063403888015248830107015875323502758058360302496764604163625874755344905059 + 7334562477121670573355518606105354751505482715112941146764597746549856497547302376364513456936736713783904762299121613461158516 + 5283407076162674672773440443861453333470684691925760891504089347363035836279580135355221825821573398468104182485287843330909617 + 7205284306122028970211792875328746564733992888131805747056055043004240391649557442465694153748887961289838987106491544764907052 + 2500872325568857502281229098611844366313487869502518915819858430987626410127129066096878146872919622682973073559229804271266907 + 8295782206872660046903141337058447164373782585028140797785111578071196136068281762757693333793450310851105370333208052458896958 + 1725889330426145518489875923548346134621897254499345669060138933732620752098808224545684009099318550221718273960774029508377011 + 6086360263760539829227685105382480409473035021789956560069988221518928563686053953426925951987832850158619577369793062706768043 + 4352919017742582830329403068368693550555003865896903349651288061511525716234272382256062983241592888339539171693959034050993111 + 7316775446918119981332285689855871890517757525471516688406003916733927585058269512316355228173253797483394637476145877140830653 + 4449523419101039158408708904430347733804700552814623747680680614331040890499889250979677397459532347731846180044631683772954511 + 8775927277284478472403620186389038850970249719140155845452372844321949705137084066166954690611328982193781479003940799798395822 + 7036309001309751772232372080817838422988947200353430157955341599997125428100524596360021893214442902724490483771053395386266905 + 2526553722458751882973801186174660169500936459737553375965211051557068305755252365586897544315025598670454207459745656417390706 + 2637149880243542713228217652476736046313897745886197441813742086881967480415661410956495847064049122729695529600136287474175290 + 1793795271658672504903869428016853432949018555098626397052181786382888682206907544219009649133780351002110388824693692103301828 + 1084255129975610497399774428514444229695501619744314654316691842636967058501657387850037557822192693461604997872810120193484078 + 1690635325513958119210187262311486075808664902577687177132226261921963946973671413085629761815694454894584772804358916692902290 + 8584983060051303667121308176671074873807110361225378981139031261855126176018462516372607208578426174357538994152717337719252523 + 4278036428830763724403099207458044021754910574858908048715320547117712294990028756794510860977637952837840922253254728458600984 + 7883825345262132475931206135018623229949112586397174487649066363051114417355320278795734783658869193239014023523778761960029033 + 8695026444117478979408146585926902316341504795145288358653821833800650855569985787340203101735816503203866669795526287437002033 + 0245051742430260486282155254132179648064481192529358125651323989892545661828432074084630060930677773108561342125212783387281955 + 1156534912244337917835348237158665382209292463641851049571853921423174805869049378131731211644957860891749912005458383867541676 + 5778772564492822262562399502030821202632651082331648596186198421567114506013473886361019711381249854838415342169443696628858178 + 4018937636066081000726527827443126701548588875106206226537909295887328559668190334839725133746234608966652449462868965060152769 + 8173777546154775498367210355738304841393638757271541666703324260466614672029573295838066643359099243819511379078208545782984277 + 3894531584135582441443997552974471433572355979512626259310899921004753808626563585592085956971397408889173848312206978387162122 + 4249778224435541775834672279093907849532605623442929414275448734738794025759189569362602709330104719867391830325898742293638318 + 5618458472230917207115381643121156657396683440299320861523898119230249426608095966989749077626813445096806473183743262392826169 + 5141443017081978141752639960290174384446691905687453519079674615609648441987212131402698830771368709970102768419122745998384912 + 2946562140012561122001343127839838295167741172616748608003211961781629115805578417306196780198449660660896672943032048541196007 + 3488478058250138575080356458275864826075120035949332139371412714212223138848322951784969631050003335580101622399775487873990978 + 4317860282593236100733831872685638869277432762005042347567404549772458118340256499688632865717895145858533810557576307974444603 + 1928173630042126038543686101259940626688530747112695018229893249219604395612728537717051374474126617790845613836004135628746556 + 6994181584676204860202674587876078621483635083475446039294576324194007589602377577833162510613729896861820149258590200450670657 + 9591153201889299370958865743889668888080847094554165557463441635078117012681280739489741681606506751718013927402701136203548044 + 1780167360508315641369667116901861812842526826720765686979668702075706357523197794146674984683061754983908320058757429657215020 + 4621260027453785113729584439569855185620374311773708057945213037359358758689719104605870656508325190409944963614795797144191442 + 6611412529823091494357371703456481103154272600004279607488151916951301067639113190114505272247774489140541745738078452548556834 + 8106748866753253878302577929999224844368660368702977874939897082451513356653811013795048262545973632043664542271741351318143337 + 0778069182951962287178555694626059563658908945272131830094793792647180018850962827338479100883010796179956428416377824203799082 + 9473023880877077477396337686061036427727779399244945597262198872743579391652952681609513942805826872165303709494805916573728492 + 6294092277154179951451094865452721844277717466377028709711650186357899779470166784063622634966195721705046717157464710442807466 + 5804785796886616339545161571917895816310538794711393196665470438339980915686578699904466139950097093535760550147855823745768311 + 4727439998296384114816286463820007469707513836075275400610242782096499770391027100262738743742494025582717951675320717526395925 + 5770688225429387772370873623458820190254941682623110262393319797303540835367273621810830554446149103975368995431078077876936297 + 2405529175616664747550451981407708416427503988134127731468009719622521436517602196339409678849267725633683568413854707742239684 + 1747116986005191343502956460687122356601160408668274191052227378815062922961362392926820216609198684542476134407735883221896780 + 2662260497987146574078784874203657867733135048405416920171958838688884627100473968981627006284094098910015991752992842055879818 + 7034398681569535649106832499610645350629642323049347631261095876814181084980886779188444300173631359422796869708950194760718387 + 6836733703618557086120703365229061728453720426186389529699692510071571231710123347703658534972106524417884249218380254553097325 + 9819799847270574690752534052463450597318916271469886310284525865231260264874522733678980911253701800076986898602579299994595517 + 9135488779985085378045629972341159746040904128068784460666062698063117787215014912137720162075250475265414449002077183911431414 + 9809851736195297213683107966811862847637535801414773082875296684360754325074703853487298740359726050853338447561139214515571992 + 1029599022890794387902179784268370369360935567144903247409435981421651841889958031240517172069175107596477581973881408689860362 + 7400367259185579353010164869469689488102231791643828135531761198096403804156803391787688285965553218505121457658933398225058406 + 5220283029470788325194233641742163486977117357701064964101876499830666046451739488161844284719262317454589282938926798508893597 + 4856368375624850629404156042966360434746200563963426632219247842217835149470275034357811087591708435161482657165228727592100816 + 6253772836778061529203496032750827006398455227451857109564867169437129073006140463432201664058302222335982176666409479667581160 + 2936456922664809261586171438046311878472513284135606095783748274074803411461233988794425470611010249655925624921046206975885663 + 7903340067868061097623144373319704434575514501755821812557204930865063397777392798291309341112700415633886191910088310537801960 + 5573481392684970852911664492959855735295070104374454536083712417507044706607037494482191236686504544140731669546789850452790174 + 0904993356742978486159542255719565213826027717277534463338027027906360296595539148861118855418724089346480767402189286985762676 + 1005223076106599446960454896515318564456413560395537757983458843931854126284677517864393826744115625918435152244510791809692478 + 2164405990650873094086602365842140190819719314893955030230888932507331906676191911961689961891255808931785984896260979975690681 + 3253727014960636085246150995307788585817654532411113862158610700251523142672098671368947509829930523262641611496136611155754050 + 5927873322526687970315921879739844277763573086829985560339421326548635360045717801382027508629836290928584431149151932663653210 + 4760858192547745555268997678117732829237567270192822266668837972286266876280740550930386549524048812443132805094528566843643923 + 0552200604353097511107833851418517885398565041104987050582967853637644070929822812409158588536557876274185029987107810161351297 + 8488557995995493390642962339468082402922946581115285486581085810242830297673687274512734725802547502660334048415579446341045330 + 5709356062023991965872528242196958896198910586431524813751700975464715731688842846588438403790663597080684309160359805580967928 + 1809180118084899386382440090650505696513340627765123157216132637785703218992306349927445013022757227491085193637218705876572392 + 0750092974015461540416097560544979024242793468547428554110331500932107320102022511854661891492261408877458706999860502548130498 + 6089719190070430700600786193146021409101280174362984471307624705342744373049193769815102419864609660529369826990237068799451547 + 9880823550824400406858764215681272127616403736552454898294728046365136835488231881807123019108941139138735003722461424915329488 + 7529037321181887616470646776506017170053425836736636947752180676382271801340633168596956291990586642144447067879824547939050775 + 0702265125795249993652978449111254341598591409462513412644706330823597010310419837016366205284525093508925291114478065520543206 + 2486005489914656200352331842636430195667576175939710807407359823751196926836356542172998603833007594132689750457318477364742581 + 7540614426291493245957654051180243018629278083258315716499682711339148507426602166172200768552170520220563426401305349960660512 + 2404338617929580850851496148983728094122155851959629735499313721174625488662780908166750428714979229469660586277142190041914098 + 2734970584167413642829413555542927092036718157943315563661250374551603827984602155759774285156429894221533968500275418633637182 + 6560220052859607041833971976550951076186294969188109531953615241005064465315852535875503380591519469842863315620903120851882868 + 4362109461838990069490474891539380133820330011017862518437725479693309451782697543824505868730424985500423739583859994419014638 + 5084805381905175100929792755321577290419383142651436157340596535511027236705949268189435276570853108955493181266234603455114274 + 8408563281709145363110504396918026400160693545535873614031123523353385515760396989543124701606521301192906747319853776998158894 + 2312458699599599230972023213413420672303278131983854442962403875724144311681960596932014490316204359247402654596736629024793653 + 9839221740989926513947745565345687824749236841443758276831531279631822480088615812410461505184335496692743570654981097859767887 + 0148513962240941032376953093608164659349988907238073209903158402845914764726830224719377417036845150993399330628686012123441747 + 5919614485617148484720530134538022911021657584302803306902527053421247675384565988567910916387370777305148589468626006026739483 + 7159664152823325316769176118475149162428707398939203649766531576459678350978394525441052205823105345184421463902500121849981000 + 8288659993085551546441461743163304405139009826361143974328223331967419739647241073571212327801960556484524118468883764120169524 + 2246338306775029095975369446186770386599660011384020498379465046982275031718873753405808637548601707969197710675661519594764281 + 9599700671171430778834023658375047244787074487357323294015535711745803913257607799601446000833932736200689998469969708376723008 + 5081943791810860552689101511523648202214658112058332928346393590013555144813066914194030280115978731407804149764646197662984115 + 8801177359464553557557965020150275317953374369713023241680758235462889780964894972416089799047047809594791811478533742030190073 + 0665429844750818754679057503636454736605371676903157540119156106676570191787583727649819947468340786574584101743147082806534991 + 3657977605543416424987117022654696293608374996078959363230667155054631271871981115488592293902083994811357408917297410729122498 + 1862650934481731910956432936712254764601612734362801048040108459535230079759939514256093409449391542317896091270323008227781776 + 6653398313274972684240408723778161592189390653041468423088421653090661249171357282254451145484842067919237970412388771640682294 + 4059821256052393643115972017853583376641290368154419793622859038067932722073228138326697082834080833163668963795873824307443161 + 4885945116785653293180979216652517189039102100870721593874386070396567484340764036310998065513336640289679790609291581823883333 + 3428604720660372157112193405611757297738411485553283296939642822708738180393410023516446689646065368009275111140421244624003704 + 5562960052258931350563961074454414104687746794788022658055770332756970270739126216170694306943534685894930524814764997593650416 + 3008384543733504706776478261526614225467564069116098586935957253917385357687398588155803265872788670839186222042335779464643037 + 3618994828725096012458832876031499829184389279845891008599618731986280732307102787004526300770299430819579608003697211024173693 + 9217086377524454012913218100708405723232921242597498783314818967648121936298190307693812351239182876627690699979858904402641018 + 6156985750875948360548164905855940506817600324843389599811157633619677210306664432514278405659673075559217581592839918628085400 + 4764772987507938088705673246656764726283775492007659316410580014942504090614797117731679264296150069410102991752421283871178501 + 9088021494611622294962362961658529846402973311983387998125910749644155422299932240783260368601058914444067830424352644504379196 + 7142168355025888186137900382975205885091374237093915396552747486547739152007548268368634296637427030850473757422944218387854757 + 7616183325502874293153395715965826837360328123096242771948215374071981140320994435687149135694129364024023152186261051421982087 + 2832792230789485819847349814552874874835409931161612591863141976920380812857719621635320076324767599038119716738981834869773741 + 2754959867605262800904073710237512445047870616662855713005574347858126481109562377143573312098011061313182520482126994274243272 + 5944572495216446034342198294744331850728989442478427239279385418283344155306850003896073771784045248648249808863649089110085745 + 4935039678346741118281854023639235666178336524231495974905785711915838245296715638301791203620715851604930385744033263165263809 + 7601373980902035512868636064609722029939023536705525076519976556652492714730630698715244783359777077548960439099573621098774644 + 6788103237769355632318040401274560065924878241545893694505228598734431875252964572555463844283713282670737691866931493869606535 + 0416187164312031460323292595651046052380878338516759425813027437945468646970166296000101963391062426079829338723963248745406623 + 0923089990664161924027191610177696764629811421643542437939862866986835556859764272302075103487218202328441244550298063164681875 + 2019867260237068480077811032787819165579411546914115220954604696377168121100888419574969311251245311564544879246746582842436916 + 6868613732260412990938531237301911324073055318005385120355972354500615925738636280898984348888758911483752216818128353784893125 + 4877207978980281193491650735689287510067435635758992016711009033554062927257985428856499572775171602494384045603122508003854191 + 5729531014485818371423575856151555802439384687195667542811436864469460636476071341511650757925855405897036006697261458329928553 + 5460991959983883494783035364470651652782232918135295761659407906592669701830570881217510435070790362298581095301898060905173789 + 7646351028988526172675924552809872541181626761125500157109077472362508995981523449708391893239705562284235588614429905027555758 + 1619134181392874715654091932556140391724453901036282239744719175838602787922700433547863998561669814541630538374359332841359124 + 0642132589359772875036014752032306706353508991088875094683831897858049315214902256977825841683325136398731544129046064024590934 + 8005838235188541103906355513876550842936138467720245485620712847710339766152168792765762537490548824247757795430623230546063661 + 1739498737086961685166983125262113774813358028871712079307291894391835363168962025939984050181882718770421839433587670806624476 + 4755044069459609604971745446900378189205860081010611662569670882836262612421135453240273781870602310532514360568130085933991129 + 7924290416111768289187834903766663006016528601174525638099383915633909474617753311810491476284105443999724682875652267118724896 + 5850681695306617855936614324554272763867627188224507120915540200480120428647332751636414058742508052557803594703673781795569627 + 5161939368398633733681924028671740682293310854421624725144685852406527972897380355105818239535806432392343196805358469063293155 + 8819559114109771559602841216196553885494830284200973490048941610619985614867118986891106961906280843338752508763555675909702206 + 6241566490588598271025864796744098875607062200785043619624462705052447512034382219094774621478633751781359662848610200184361678 + 8704633729839925740538038689681271982506814499991016892558765319948519205733093865854380442216165127136281006009985719211033451 + 5874590475603382790640233559612673482775953839089864470737210616394894296028059828241641608622138456309335058488482647911816483 + 8528577480552717173959823507749229677977069134280953275629509898562844929982109573639706635205828305920402590508711781395835713 + 0089930344552012906619817966789113931607542416094931145768127062728799915073397115668423507229674038044945322045301649766598530 + 0236619236986319774758924493517372212562285619369190213778360087721105343106507409406716723533090029620699768530871602210981580 + 4900295631035231554608058112293217835929574133906243363911069130644679986177379278388410792340109628431007635443781281483062060 + 4988368133324357435318270787600078029431686121284484541827394881261897104701243599451161363480613963194743733844807088688115634 + 5178871803932196297861340370803170767481272576611956494376594793113965439245117335478620700378039639755713637510132362926267306 + 1973846871626730910248052978143950536530975380151232887509932339881071793647054810578672393058114957563604971882394961817835491 + 8978209292630747251522017252062343300917165930874691119490642832557026684811610939173618238354559097444010525631775837097840951 + 8326182506155413337881369137900095820346248710691175947937982923048432643166491650906416257503450243786283464120124419550826667 + 6090914463028322098876359782808759824243499333411218847428154348072847658504046701534863522297418259623151406625685618209367317 + 4253745664431692653592530190665547218310374995530293912340336697232683775175851639464892393461388136647485464789810252552522056 + 9182156878387604674503124667923684369744370052287701241975705851689429509464670883347575783846313229293967680582071694204051095 + 3321006971958449910630372247668837211034782309154572655303854890011708581736868651280877351904031869989741999700057554577154390 + 1273067298313752548096207203603148138418750927315375729523637857281549085842436944573932481003443446922848528006413314412427332 + 1441821872672191871420138772481289303458305298682170739045298765824678050356023853590500427850176428627107627730008396343350473 + 1052326101498218606100898713263447573551827490516947668567656571319040829379674136592743558516074455124317265474909140902458087 + 7834541971992916704455016525869622512851276565353916338983507230882585013003793323808346566693345857527479053033593116284574877 + 6838252895614149905894777313466208709968773989472894570857815422084908815232548928189324969136065895039808122393702760781384523 + 2929303794620328740393974372454877708805842222813897741603177439187185228877406834374147233014054610369299556729412885884560745 + 4370856078387921623155622787671852014805409807299060561419288539719819906697663945124473843579383816264514077377269614977581685 + 3394601383138607507974293429184042736065549935759370359893007688911547744095191909676349245026886870781533913476330551278360831 + 5351259816322765307961191402595778339300322026355376338266384698585109900534462235764152505801492032987502080039176402011160649 + 6015860540766825761905783450339596728965747988413885573654798343784315606643443103943694670901175274103478596479365688106195479 + 9733596316022892971509096088392032363480840038385290255713310540683102401152243848292964926264212842555582110823197263253672828 + 1062515708221923559386659794495097841198809034454364525085442636233669203446069926961726048176600711294973993391741061849180079 + 9806127623797585819585111237146636415904332057123217989550966977692535517011996512651123910136604576120833852264076101548649068 + 0894752723723477938861483316019471992063859736335516787664755140329957520633060255798252299793172160680450787189861312439796670 + 3913142052442456614486902320774033281367626065329089488796925098543116615817296515061149179999137691128957532263158924327442783 + 4918858536678070436088759702284980929577025191565900433342638171236644159755504144947154030057873677997786393398810399270491800 + 8872734106335380929798217774610094691386997739307412068494969134661496618521118209935954632189343140189392135323738890270473225 + 1245647673515237131109490917571703008777281273557596852732435015863930630266628924061119974383584899927931767742330245961719796 + 6852379757973100072309834676038484260260899346508201154263890305770366822928200041404900931901074539015449894481478124870846606 + 5288592940348602075775045536917167753748198797428454287343716300518081003013742004598309648467119358078992444950790157070897622 + 6178224434793312241397484872165819485491096197408141733026367177440768594738187232231600889719889461459739097869779145699996070 + 2192775687835295828387187709692569714086691619295450894879843196267448458847228413092057333128571855124524447189613776196209305 + 6242914540023653075456224110675459930237745861318742551814072907467664681202170417286866153184100097311858010110265935844444511 + 5209497239417620919469741474768380931492201661270471587341653498268177621359803201248700031595849957309397980724999380306103922 + 0556894331856087053327675958304000445533946185075415894264871473185811965493131424842414390488954096468377128994425485984798739 + 0196159676818515225003292466076872625799134390488404188280002687542570342770954127173812843410476595231005479765885421327808255 + 2605242865388848411850848235973559236245406311003883744452617685164124063273300160172061005325886640047067612731170493761853684 + 3723865217540793835273126631505051186346898929963194134815240955269409964826180214819749886514216356192979128714223656587784030 + 1612652380049586827710856241890765244152817303616193799144244842589626119110544403111366867458976947676427002814778923808924618 + 3631721504060950588384351554676808360758437911729833313655406741373502411393332262640744499827573245395519111703225362606878417 + 1363409383247041202382518900846037480203513170344097014906470642027432914804792692599759592956926861572014354287205548305433650 + 9938363167455625445680112095072694438021204263665499289036436205115409602435745285690360330318532747799997172095972559600945294 + 3849224957526742255789376070484796163223388025899309472042686406132560940455845848040737742829859477224469824421878404438255777 + 9153640594267832855398773722288983227094747426234571630063269545219291207342356377829705537624593717193629488670483397161337722 + 4742683466675948276596206085950351177248268507712030644980189541847011659976997997291786802803131893537147312873666734632318013 + 0962031832358588577470495716330583413563622072795533159442347186921867618325791765612531566938977664106322136330634216330706485 + 3562792846227123177501866289549655646263423972314841727623087546398961182987448990222751356418413165373556965561892665216006475 + 0506481362115739578595809306613922949438046074388531145186498774188751322860892046433870735773039483261252104554347599292426213 + 6629076659887419139215806756640799939588104500582964705062365481405718348479866775939471858338157222844571173771380330117254323 + 9427611277124624517129218643055712610406848999072749557192128496185603527876575966140152280783898310639896801498077008734557576 + 4949349263979842274642964286301282439502057095606102606822710846752651420038445554041921101778203644249576817202379962365236644 + 9000537778793090403522534841735088671708809700351632320108127651758914457761194719832533167517277944390073544087779452376879039 + 2179620974987315833763764525622394287879156162214632089232065378247731638836108414730685627306496030775755582279275263164338314 + 9850178620109230660864047257606734366763600031327072575073099542439779650618140023637464021494877439885488556217335419454669846 + 7274436451730146692806124202594474275423757115268107978580315116832524063995327727093500514697813597360878942124695394787220781 + 8077050800020141873083229149343719418506939350096709806686454834234546620350690053797423042331890117409969910833834635664137578 + 4222569085314829230694422189066171115029353200770994620763730497186499678980036529016196644500138184587387164123266827728301061 + 9140763168998745887384781477877234025340780171338591152461030018239430263211801503428946233869503372300942372235304400820946852 + 8437399467538616927457301639250511729312614497619431195080809960619969552298634956256648869707957943168309430154835637684617202 + 9927888920815679261894236713565064562156846670872463967287481642034739020192858148286147625951137420641797396365115772980951219 + 3655403238951645285818609634851118279549531888817205406539748497770277166060720853420241694457643803188820531391415953932633187 + 8096429698574955422724412934129163958768439154851606366794537099440778504483170647334793461803467077456150095540043989710581777 + 2365201968161103470136827409580883843970089911974172408580391996075540014445987053836291636308746569551411995558157351658739831 + 6950345059892537018933018077820506883809089865363951638996552650340293111131388149509355326175519823347067351884531383182623006 + 9729692983578755541105852708900437725294440871971817004794137742625651321002377622365955498287088740364399525852759257372235252 + 4593851734614428386795483124618557640086184414899615960895693770722697765927766996280493365204591488466719654529288305662919475 + 0122479598904859751605583470001521191650223688479671370454989314043303051942287523649808609527628133476925823025842389422672084 + 3056608819600468295745423499468437706122458751753728982506585826980159252966514250379765257256312249132321573973154317443215255 + 1261003464887189939919598811711885508553376196973665253914113359871227784508364309872766800569364687529405313394507842277777341 + 3335595614255964343357224505993110214988297629416503148121404268247459966936550735839779347369294370575468296662036041463516505 + 7279136021331762991558929156754763672783232261635376259854674650491435829901582103560659803340084857348232939069746185793481086 + 7001312755863777334623418958360382433258119385097977803059882470820602915102809159265450380632894446941317444541503087066649605 + 8796169740654134032665098260784549928283316353597416172219489498769356834724310846396610790766934291348253075369200618334478026 + 8802831163686839169667839421840117736653893219551959966388948111069365662007487678001136916755953605936920644573768537311349838 + 9739545132806507773311726139940569054566559814706558048797461242055138311352937387308888484537481230253759123043684421386096698 + 0953084370435253065135920609321712138864781756707944630525539032264477854921495176982483322151742604869890730064964430072465893 + 8563889642871990807691809483723365775240608384031148556634799934500723149755352447233079304887498827996963939978814660785015524 + 4422068594927829463105462477608520539620307156466022889708603842952278355035865136962605151617935839688034493508879959012432457 + 1797597440197984699879058451944014171742351115567915351330880426124733117964473476818687526048324044778050824433512831279314278 + 3544880014006914530017330247894174199038635755809673971423695196336512713364189925640866570283506889971990951009729565756092473 + 7989020444450139152190142450813270776908916050703362005761467814560672206433992898775383186508883181569920382329721780736328572 + 5963607248916565843748383716251646836534350100847190837736559193434644723784998135363197913246364668420334826697708573880522965 + 3263484959293045146013061177283236124170085863131765193651484251463844732711431227375764646336930721004123585223994485289918901 + 0583029668150873954157367992526151571563606918837234329358185868795166989340614129979830550547132857672143145949742222265113600 + 7440572366306644814358767338023644569585694763643144805041668167574800647065193962831865616870056333413559981420227280146948103 + 7295355536699420073390947523011459995035076225978883439577116325646324872851036992256964558891639573786018094493982547872559135 + 7129457262838894246866292831053823350947068553550051302734533231301531811721807950765452389323781067242015285235015915373253500 + 7003661686534989695171145431734885832337556123063280208162395256598378269110597151277334587048349487450140097618803853206266757 + 9082217774055830430004211027285925285344275476747121049534781396260863522010542259349559050699781590339007899734612452403479287 + 3191667292995301649109040619271406402727834137378627737752393244791408796163577067403946973388491815614922007647090321324522320 + 2949712664738909367012483650928320008049914477514031653686312257788502415066119921871956279807885221949190218605724017500310920 + 3169525625766817202209440542641629818384859195018848363928308881901815336912072399651202491194626625193357131514851165636605801 + 7255316665553834762495164950088245569336300767957000036188227515262775800565384194139225891768802813443198621045801692291233140 + 2574872647913296219947966169138393924496399035916640976364671914696565353222749621284958305509352891507065537978150518314618840 + 1953749417768878991833661315137426428652077503145679920658786397955780176167247358992933014357557538701378753423037285649046608 + 4668877807427263578702242652781568611601647436182495270690516771196062145719412914253392449657363828299691513193636571040444936 + 6886803557429783411232920271165325523458164084362409904470754437138270784982746722601116409545759719688367256037780110379647023 + 2300356518881462544550334413932731049376257074071686920169237332025867743966470152553906187385400688773328478685498436856277618 + 3440412356699057087611095963196908710039931495043446625996426055839433344899946522222609944936452224313579344290272586318016202 + 8993953982184479368753437594218699447584551919428710623167603425460525558734552005471227418138809891695708393142992004433396157 + 1641364290874900167201473644758505077028954784718448987507776152112958786620272578580374033281627136838108776465262593788494546 + 7335791534524477898748563122556395894974284747735359153516999217809354333772921832279669823385048414976444462237355621384907691 + 2772845418405555209223672772048928810050444241654554863085813477997024445507615114437302354148041362541497074784257678291599777 + 7178588655224708624898385615582303156928858845044700179599109039474166324676359828675085010955238472718587302252391630153958817 + 7714350463980300266933000010667914572625520828229727411680133017980270989103849220980928606661613727680746076907445089175447948 + 8959804988970943750240542329725780454835670277149205665534383835852603494258686925800889072070906952377561912949333090450610435 + 9127584427822125708186685340454898072189100248623017561567872674357247419856515640720894591586135918230623264124957308938825903 + 8565660274882658423962595807578322116479785809616786494557353542161430392650520437776730973491703217016387298185714704526578560 + 9055899627055835280579204790473134990779700561942294557075688923514759353053304752653692669704340622777026507467115119994712711 + 6401990429555126633982558874714554382951718476795179895512968275571839503381782370343773457772170386412634133151122279458473043 + 0293309378136412704813380987793756861154395548470319616928895806731980671468030021029452883570696897386186564749939824907170573 + 1417717547255789991707004411151265689787923836241613415526707758612724058279277154586299713815047231145490533591839466123670638 + 8468716387126244026336620863493031193083664955579994896168486675960587844522828676215258682659462698160621004514607084416783102 + 1449640886898263771104309544234611139764719954279503593908340282487665393419611852384397377672021450701130079538845214864162053 + 8048887383017701836654298226594900075026630240187365178333016065699848058831083230977644940244574444820285738121188435273257549 + 7734838976170306869973081121181660448148530318134255364556117593964696552501147168845028313551613495459270535042160362667658266 + 1546639029308273692114824601121738207436726090786353640928151613146720401120659236951025944213817893334993036938357931276755092 + 3794363877794105698247622335925064622343924657500773158672876932260234127197098205417204884907008074223982761704004122962430390 + 2332227732674259579606138447783556533770663844706548255581644643545209413054398521429945056259218551425238380035190336407512204 + 2377559578117061565563176922758264522313042429970112963159461355099505172026291216364090521544160711259708331105724128544891227 + 6832428920554567726830569490691102432470549042227057932067103955101428247157515420358182404777567376342028775513115385366928419 + 4241634693879583625259038169292585038330173637743744110426172931636984875802849325805759410994995655688205543970012859415471525 + 4435409455307673255925091284402380740900794676435449835586381572908519616958395334196299914509777009013685912584824599000928046 + 3987500940366892833785739644668889848240740024168650731790637517228616861342434915208852629849188021280517196274460956387434019 + 9025408507685643206458885320228075047871187183125968258455419735129168110055303698970042275578099161589116560991845557669784646 + 3366934559408606275260397226783303207383085083713447307195484607017198247596814686470103165356557218941037264416211493596219700 + 9986983198296827970312097410216841561044999906047830934706495494099795173682393665158233220314878778675703926172446242051213291 + 7327936388263057744394340969867975674336916032235104437222484250956772949755115175068343392125983148796915268153189466560134516 + 4505129238068974615562203042384229709458199180125982048735704933556566236123385106774238252165050271569657572461570289000767894 + 3255121682739504137653843468184029546420570010142268916658213975683507187608005044348538495082520951103601067607492368878206287 + 4806852545996927533787451480123813559737763425204966730971472301392243492249231539770928832609537982396509758149828504617903683 + 3852759316339548366895421554002413138488562983328873969801625973328318967409411308340716647240522981188392227872470754156065273 + 9712297766053304902554018245083167928441148337025924749085910105658941917341095233228980927774840543348243226033787592995988515 + 5229452832882947701986160360761878773430032426431930521890318903440689202842760168592576826646125537090631410703061420763990796 + 9492775501530308620829606600311339640855706549659904872171618766544922435708097161505981598338090549562866490651446857290681656 + 1678808597459616937537502211249586561665053229525645425138896011542471614595178170509581277828163045626690556829964393718215591 + 7053324203154477437019031580603162546890080238913915157646559489429803976541625693989468806549155901365763128179885048681463067 + 8903137465669354155616857417689085085205927330249024040964205952230818210265737328326102255377329508350857922236822007786665553 + 2734904576394968648887628638128862963608976988414917192020797115239688653336018428937106985737003652208275177709699892675605393 + 2387808386702882349280874532643852585858561738093225119093657885192947905905747402618285721157837466909047447734685099503267111 + 4222155360968520550560237616569205752212233789555461181069785768415048417477169723562149137809030351670058489971512620085540222 + 4298243051299268952240909211177826836030583513734437502197104884602882464340255753900393068054947046141922743129752936688868680 + 1061375462364377985228292590232948700810225069864185759076897910654198361668411325978825417457852278989472721657536588031658991 + 3940469338205826791620626804680412258933163753767218044848985297248760060861868407223928680948167632232230076213403901155993516 + 4300489987649264460199719443525675282990880539122997731272161031062934060033770185574543151609533413639501738216215062848675971 + 2177118188977585453528133388279985990921229278769939253605657684059131396416486258985713207176129279519783451725740599907936598 + 5468202247459866994978249422059052436184697608003427416719037990135361500297493876720017894883453685240892163318994013086288251 + 0775391987748089844439257445352687468561143051750745275017026626096588861151466861293340177217020485953364933966278607508804835 + 1628141832107584076506487704333155316297016420320945282094351104594402285535278391969212402643994113779520387919087141691462578 + 4568389047366302665905669107740203378971862242851210284195394536420153604497510004787197852478898999690840962496286253318550921 + 5915870003274717803413556085627698745281531034825477926175968946204463905051355885851004345422507537344854894128229093755738123 + 3106488353902440267975241920861283331388536648597182081274348906670754514090626662608509624737135193693712779860188833406087992 + 7845555194352577902505815561879589158643398041086893321684441920278495085775044919835855368307051779503838399479822915036806084 + 1432352323824143885623247262050454612927281487774810795510104248803405617391180050263987964438216016361064912733157137057008420 + 8930414578064185485247400714821333921221435324501439994244285682760117301820424406392510602828280562393052749013520039103061655 + 3173670884438194788166911165081056822054430147218290866655074231005149200684080014396687574505239932587314443974144267617007284 + 1527450743968461168931869720925121234258369083166801029927251949358618661922498099466741377608784560458426370545741910023312926 + 3234042028371733121222497619662259149254047701278276017559926645765011785573767542697475259020390524937117767929011666715323342 + 4704564242794556338739787095791826301668604024597313082723259898622680965079684337190731792129157208207454560161440807617595099 + 0586578102694447320030978034126807967366576180034644346378206991116172450484663474175770472979363179024738326934451423318607575 + 6711140559239053730606360957739329179929007703740765446432207582934464258439308670322228705839599858462219965901802441668368441 + 8135099406701400995240439771871466473527799329781080913941715241663698683730014850012873125772974693072458542177139084387995864 + 6568179602365017697198231075678811557245910639538778108917663715366214082022315024791477373317009595760696873073681125441512291 + 7907116539452577187506381898980888332568593365733396512784485641208492339371509014105839017197673863709466309379039960962534849 + 4750829188061091962181509528044851805549096285740983094887975885868844208625379458016822827359147295255429793714493083753502809 + 7458122759750053134279494636824383187336514214679539541415555708799139748870593845560799552363619897719534116667792275265497323 + 5164505983084622666859401822913429103147582979952129213026773147211467590148787858747588041796556975884830210299871356341343674 + 3017622046748766474496658478936400050960631692047289817971683454103138868538745678486924385845403439475522996310311537377432294 + 4414433427221551082351019813726625491301604743637648323980649889708459225496111765515476857080238229389480546313915805440388154 + 7128048414711368158025433805098117535633079017719775105234085215317610434688668866637527464933292899758107458405969861125706230 + 3650863400245738680980130673926472854780296246906056457846071189797804208159343552552140320987399388241880735463419185645329289 + 3725491818789741913366698889863185159632846810598378698135320769928269090296785595628838126516727088490704926873118733305049981 + 1156989564178115063843077403158558596361694573121010738084003904783088187504126348616809589260761446819325657369704310082822306 + 3039078554378698516122693013852039986103065748081512292985255853944982748397274910996825923066426171066912792454508578589756672 + 1894849971820554276778681262205130604407309897326530536792905116831412406644096303796353324894146354102174288891383230945427806 + 6519430441043631674771677332934701069341868125297788424647970576482950339536231483156528606063230103167532910086072700422834732 + 5003294909621810744051481544451641763277370208048653102677095428677725528287642449117886584959778219864346164599848968697364087 + 6751096317004399279893854072583230132666460132819591435600170059086840170914605351655306551416965997517899522960511150518237562 + 5960953398400790636904166620422410033200069198453455057858306095484024517953196610901762809189095112424175853725058162186086849 + 2378590573214575182954920757796313474094094261522041549359071498710995391605164191319908953433331128043052410209542459403183882 + 6967512166626834760387377091334566417667045028443096775043889705526174743033818006933449908412813794430186357687977532151972724 + 6459437209781961727829502811704779207375810741393525593812033931653583330049048561114949732748301604240502210577065589268424394 + 5485945220569893838677587873427380906709988368671130490257845675526326075411511740051320570135507392241324306058959038656611327 + 9867804575762976412063217986099462524791020332282964702449941371619543236717809914141667173375719858685004628965511347280443141 + 2110798992334306839358051076527899985588107686694616660268331099137978416904137377280100977825535315137051402200610861241845328 + 0363449860601942956031660094586702469467050513998615147930502263169980700379643465968570908871332692146680759419252634341789329 + 4178175171299653546801324512595807182660716928201014996433033979566075147588628538125142107342090640143892070802843256418010103 + 0456138779092213905930697158012877976499848878257289818896704580464918962127445564050766970246810568260512090191166877529968532 + 5482828669997339487166576516726609979104834674845622909875424783106655102257236764736990686408975204793086071837965911886835119 + 0267535380044835507754251971519271244598217325940244403179333727723642934577686643739339224195755654907218801997476469074206459 + 0065138464529181013506268966674037435955704351830301533242369638335168171139259359713958529701206344946001165594755646272160394 + 9247709545287060822576712084519151900147438436096859182537437687606226004692040127414633767616557761740535046385163645108196795 + 3057714321815816843173779617852754091940306380163712243160807705160943819438940855547343479788687898931661575785126108832716960 + 9533193667848378687611829528479562728893899352573352696025950207316753012731502558223567081292045437196069989946207141541601008 + 2746003049129497733856902406986044430147897422219852413496236136281848127325893646312380454532608491203709112537348345922832907 + 5956088319437370932773128721138395583820924421370173711672367829016504396575639303752597289231640106298414733655039838766441635 + 6180360982212734271044173784836239476693843516863507994881855803639383910953492384867775507310386199169825014966152355545690080 + 3474612962133776522839849256217894365224998226219581308883384099107152737580490415337430321380267679764659802341675603080689884 + 8385214883553973286697705130178868327520836907858212929553123995458539418552809580075802670275820221517432874193060009661810485 + 7635870550202301972338809565930908660230248958179738819097744222123891965883613360999839391218647211336772299291193850385713932 + 0223196991899819000674224598203238140866873922543961390070945675722542943959098310960399662895718004978803705167927661114684329 + 1353039351866220611077365279049149758286033094828313328435837478853295648033377121231092341833142961745552118705722131187887027 + 0630837254454720024736805497864487627874608261900388501662821043624883721807437900259240409899471051510920617085099514167842832 + 1988240186121860008928979530309334258534723646976027619874403865209331775508112215956780097468860667994721263707215073620406836 + 6148969112241707992551262221756342003961909547272415999992255159101022681539848421608837594935060720460495066842999521680449846 + 3457737254497423194650056810264127963010085423288394333781451846227050135758357730754076741230565869445804248143832527389323252 + 9790762908682747953438433738621860423268309500095630988326150834401786630708761812852217486714179905608190957461442085387864531 + 1522476382145618120242675473759696978079648715587754580423057134915914494338656294472760447616089310947302406703031809581038470 + 0171535968526973835184507085581755238300981407341777890096801351412273999921818828858705625413157216884807494772810429053662454 + 8619996360469711195123911341155232797961140155492488752604043466908848244534955186766472286479836154777737654804742176595782417 + 0442287907416054215425872961111123258314536732740500399960690027024024360050777203631279476105577959878524421999307563248792796 + 5348313098484066077132466864776966488466415145151104355092278471837179740560502130988667962911672913331290100002597980514807384 + 6973148695771873711809347394667364106588642004523762177909283034839940053425839430616152779752491636974036365528618662576277264 + 7738896628379276240988497456223829719984420682404133841162697625994660783140799400756439398245883415372300490612168611754778835 + 2968155785628016494964773780830380372616577140688533547628672148913272007307142811840952334174750520152544790354169079912774158 + 6160810488767205184519228782587106677087830138711937806611950216229418417002136640356986986424817853470899640679854298647927259 + 7389645808720792658628388654675620007991152874617887911936239398213102595897949513877377839509375811277492184373982237380291082 + 1922598786894089615133138929724905768857077536113336665514173213408958842847812824030198485744051056380839435865339196791176969 + 2136038443877769241444454895223211664298720250012371885167260344691881420934862218782035849576910341176642258076960704001222187 + 3619101830106431706477720342582912973276053324213930842322321478885278765764844239473581443510550046154371836075105045519367692 + 6632620878175338782391713943229145276164648915620343082760668528508249819030769842115080099804055533615175586509178038716739002 + 6375633941128896351976814553047937414266141967344986676911841486068926852092747499580940682140408121435982416523093436110154753 + 3222139045759943847229548540511800241253979460730316619733573541964096618975921352811299052448712030457862855059140594007137487 + 5542934473211875603591035637674955693033630753758706551752052733350020451305012112157194134893565133530552290159364523539238466 + 9616750069420348886409611437053219761816707838644591613686536212537661191394262393089971240329521480448880783267163369576343597 + 7663178436164222857814082876400941903973450706396969842174499622842764650335956819817450043712545807776915977745377365681672284 + 2935635454175721831517097628434415466056776136240049950596242823574086540015840252558304179235526092054789562977490616481745276 + 2672225222323108279006574534254983148801337991382313626787322270855974712894468368216489102586460739019744587910470428744488347 + 4456074219727400675373619105257416175699861456100136151468602175897841754789156021282927447724373220233266891662271346817093855 + 1945491471112632720796456775261728821202881302996527116048267476118823402662922873934255261349533307722895013671219044843545536 + 3793064262773487395195026532854447589979023796935998929027789654646824047287035198327952786992674028615601422606183219879793442 + 1630579923384492024946757118026605898057464509351571155868933384841116903091820066294965297665314366667361460313869589402652652 + 5439801899827848778232404947415524928188533947410081530624338414230329436826968163987544645598294181482211511249572440955572589 + 9020302797433585342712570197932059030880158484733343798115491391574065623327717092645488738835390428206014044345059915068656197 + 6778633319862050630189473515487955936852231827578947650626369925629640725543661083890077620427798703103241551925751730707081567 + 2865799458475868282589650599779702798567688820803000453419899694057649460056145012638522245118862822941880894081107383763766480 + 9848357801406244621888791600769552120182014301160477310095737436308083268418063998275870777119923015945538580745005505737103338 + 7945415897343252007659617183211493332054610541474762203740026194193724624943127621999433384183901217893204226254420212426063638 + 7076158492133875552332779907935346207685056687613427451355599366014714317865416656614209291512293922523145859007589727797381122 + 9946333250403836274494116934757202951674758307883028448572093526467181950556672615580772027423711017988838817957391185266051907 + 2671612744740733351071730789204383122286756475831821553120581637533315869945628262846596800538216358815764391197830622296989405 + 6992508792590965425974849365498446258624365117468171476061738700582645427331625361075430086525639161565604855405377972628830548 + 1767000101633223839049666007882398066097691088797110243675124836228262533287561681535331091157763899063838214576189418367103407 + 6457110670443987985620843280548984156731527065461755656723700576735027138342545097213504695717743645364185206786138748271882473 + 1596890724976137980689991632152444686110535638170408866300049744279882252913535065665891060859035882361321345023887058337830307 + 3373623078064203672049256820541947607511438489025503639693977760706696248117065715718091918113311545970967574977708709494235026 + 3986923221612406956343410179388036231285096894778891156497956823154793926342464675477516471934158222112337889492119504249964378 + 8383359661494890362436075780531143970408529612575647080037096675346333712031003814298042719987791032534165077846901212886629083 + 1031714454907840175775311491859630739967098843327841882994334085317927475102526174618259645090436553276509976956833748682136561 + 9064443423702201811261101290439334315411997283217810869669829733471939988609585312109817796812433049198581074521140984709783531 + 1643172980645376942250431938106354165389537074459078140489244293256765030797030616074547245248075610258161012282504441637098927 + 1963449744475973480042625489273145165780544076999525577661332442838969621507452441516783367746336168024894911875794707697541031 + 7478540879501049129571343735300770536436533927260315165717247241849652331693508424305277324109605811185754598081962423629189840 + 6683599827684293037220931133813347833193703737280727037200969748489983084498274135581120006138983726589125846483814619896382039 + 1059986341689241962791022654106008362005402932907446471177268388894146241093638783546170660638544503679877547754823916693779241 + 6066567318288101759879455792419222471083652734422111018558539534478864130071102091839803023165372816119391124984955696131849946 + 6509143418752724874347225367749147359005862337831645120532349014908613153135844609402649987007336422813208143055617331460906483 + 3354213199998376189921305928077126664201462525396049040175801721488556837349266500704234038852235700461088952452452884233498199 + 4256488814582093977539133655050527294580364706253926894156976648375809383013472871520377935537449640402956782630405195205364082 + 4477841383190587477839953144802218475017581377483593956131465077901385252056389226406917609350544701283827958845981175691165035 + 9675317500791142255855936241556896374576355116352110763482014692288089584642987642868701466081788634493767773533747361856594926 + 1789275548140948127853887574961649444778475578058016075475638253177323030087374164983465707068923303558558151943477905316462894 + 6521653020185636533316557444077296865023590390333185648729621716717902230175881569862122737390334951189041533339830180227274093 + 2241738740799072036341573074248811436322223477169424669409308388622966605065590062245566692647119962939155999944641570918974529 + 1928105019305194521974392400885274260434232105024551451106931113484210411868649822559924165796213171984543031754090678126105970 + 7223691850432923916423525460668413682740557862272946646859452084367199412001020057846809103738751744440123325432522452656213927 + 3644451389904659220831784890291126628998096321970481352017638587386823902603865110497499248782547323024785254006989249949637036 + 2368125490914853885015667449603549765164883918157991257417554348691174190395500642639268158971914968315411160008374937535704060 + 2009275459811984599922767470947284560232970282990047819179940733002227635796160576632463265974978503386125557611307429312063703 + 5284668210801338637743489600143584813073507148578726973558859500688227447435508050513188287747750741584385175252456997688110085 + 3073679804770516059033436419747376347125944073396261678398209865762812539120718854779696622769273119321506920635555831381282691 + 7090364017219499874566644997354338979508197792775841533060988865177458368657219876491035282278982441665265219245626731000939486 + 0475155794230569303711742143247875808031690475413279208626652350784369479556492756708347931041817323940692567675398118277710202 + 5987347394026084150071478790424131834854554229261815024383846088465079695373324503305612702444122591068763896541604539174335033 + 4436269510455092220918525983424623113381645210225340601560482106077382634781965165780342556554085651205866195116920957396275838 + 3995168889104032757269451494854524514321628575817645123299310077893411388042092201792884422861886303896708749182469953549119697 + 4535001242830034769362884028681925364864771844433940737375296944979919237869503095436572944940055711115231301447509402025904715 + 1800925216578304292056694261819970660613390371844516635237968892926502845404165792819051199273212724458326926182758338001776015 + 5370775490948607047730587515100674887605918594533934598837391246334643161422435117919064366778561014958058716726561922586618810 + 4628995498127197780734498354535034114170874670064085395510892816542000534421254922356138052258209965701576585535292854686090278 + 3177671938008077658853731628156335766651218454783739782004804667103681002183460703859644141290605438413899770795832449230476552 + 3025608055188815266778993615750176656164484757488579062995887277096944086284232725973634996318024169760316516668522315338538984 + 6602875499695059755336245084768806035216324561236127708770615233130804510875618781547430556541215471796577953669434492812681721 + 7882550875891690926234268000498082339514970368440072348061964280285302475222074394484586936518612822244399239424272459493452968 + 5181563270479719492880854609815755784042683606603220498202601700410969538595041484423412424024708099469125521786037119075251369 + 1248580037503075406711823500465872772309344548541150892813671393177549861436277865197182621221456420646870403987260426109411933 + 8643731351640151069976036541617610531794845092323107755413601880551863223421905943669090586959614825141812500194544006658912658 + 9742463384500880801343550699245637258131793581488832729126778269174701627529245091838528797596704702724365423027345604418154777 + 1491976930735419986039574314558277854162840810698202905470921161004472351694186257157283632042119485754805929863758038770286999 + 8776957710513013252382046879914405882388509080000643024892306629178763000752942096488188622280178608686752194263930907107345039 + 7700223390484500013939160057722983340948636861897585123716556883603506625380447610584051517968188462287828774879778811063488262 + 2795184513732482674790613434841545867779716565739406351364662664736206685645328526381352909903916053024580749353932896630696063 + 4740510819037498201511535054658680017511924766740460699058893969064394902765714052038187304179100787141754044221407272788215435 + 0593548885409678785621622325583756109305462458590848222639139506641697602853829884986982801690179238753218240401694408881886033 + 7410128478642788707381845999570686789659413433178313527394929430353749262597920022866973734073910557598880611659693295671936482 + 4050137980096982959463694663632299864309583041246448456720658864445243964035849113054975666938514766051492807225377478267946248 + 9230953430893702870077668677812927912187053690817849571057339797969486866950088035191626753948056471063994773880460982770051756 + 3412034824969056166032815703553100561028200933063775986905919463873509475321843375830242381162225467967586471609115452917543492 + 2276619135566337663226716925555717587888015126203959605452287702197704113342129180746061351411545746680564903503675372305630554 + 0286134594910134037086879568380122070111392862199290853114304309332761209262076794099989915249949904726721530928297666077629849 + 4661032688517145326760870540723245614758880946406315180541283633369882854109153204199703802230512566561461752474068428161370873 + 9985206963338598229560272298952476210547736996017303976951734650959079279082066159408637306110242916656383381032701493580216738 + 5913923322753424774114001206375448829014685918194637698592895629614872898525330558761701771138709572823367430917528581806962699 + 9424883011486160624035588850742276732199499002202807230209412116053419259700106808447590894864084149744926170960405759460241951 + 0111713605391910548623870259046900302961074850779853822097709685279966809633918351283533571183917553534326378996150978977861347 + 1050239621857569309671883851470643478606629045329299864518009651449122046063366124913574153087650803586812245327770871382994089 + 7338464051366649209011968493386794592783056535912533194525947811637756396164788969037121048254365052840678648300844862166030403 + 8244368111563457237764184604100489524090599993135317160344204589670504422777317128963386304474615794833181756194674508984426359 + 6271679168658661069189900053139794326069244916803991726466041535821018909664293827288937825025439753702650278433431356713529954 + 5346852690092871593686894605405997962260976572140748476453131018042391268683407218753909113662935434807662980531252367452071209 + 0705634605741863631683627483540085543041836023190103343436641588904884705166081263630037435630150915106908441737355700766586129 + 2154922713467232816471312647563953292047715226865590918846184574044421063130666383320555928376617359704955430293171097080231031 + 6735370005980738361139146789749484206639522950848455336267649778629028940168072161013843975973729190308856690607301961044761977 + 9897723534911105404785432577277586147477026587182509778621368216939584671433875920453602299697242616307976245807249371547062253 + 3864808728722705732544842322660134226278752025136368637744919793216576700939583871247088670783610602247097814787263304145508390 + 6389663947104499816842871432275844541634180937582381422116532840275365272420061136044394514594368541860114545782560162829849217 + 6461508204689611076377900958964324912439197085219708917353896453831247651446957118893020342996847989755084869372230374673491989 + 8433851389135866749479827490565035784654953912616746305746664585754447284795963325019971006496729330088735987747297399102902166 + 1771497470275815103247219843409878702558703790756432271114114625912471360708464566558219993340028146304118900320024587821960404 + 5976617030473732204037553918438169303047012033263099608437162902327180494837554619833899125897762143660304278719895133912883606 + 7761343244919347585259429796353568917054332343654064758967248953925035366120514799510920191615767532119958355777106600079597516 + 3095394058128591553990850297147880385815415033833458376807751479083131186229720635268920776120415936997418185983635572280182597 + 6753076258298533536576760943150454522971260918131318703703785217592559654671733288977408306810194844570204346184368392179063403 + 6769837756043399718259982003405678775173052005969429887545845745194588303371446514765027612890020128811539282517812340583382742 + 1145447512453860943574015365970108349103036202936884373965378227317332374230149559079576915215507294569467043944303098203606050 + 8331961563901986606916925958427127071602998579210529763507751756811409645017688889813292902535048662887095342609935463489041490 + 9736668802244229960622339427799905563413901438749725163782080129777353814116461004513305940715905434522181472880934497720795747 + 8089231465924779558459413345521275018800849869822143818873965081853887737597561843190118386215028657051186337416427295963183576 + 5419828194392698210106536176184087551774670922454148544855468554475299499312061306599825835773673050247207685913286844665654322 + 2029050617375681673334265164512497368276347055093268045529145666800867914194334235145959975127160210970603920222624846997715913 + 3338289728310358326423356618856438897910927180875153967318427145237491006914876971227986916804404786999082347353908985698677388 + 7003592673799641258705037230618030712653838166741113566125031462959628644295056269826492276245790120809269461415827782914919523 + 7933808111352753578305022191116925704616734794703884497922451694274860316351759525772713769181944674741861315056661705956786856 + 8984597543198443392303548683602615735750098545443867287028649374064105213301110278127297110019939173598045760404284726471910865 + 7750264118815211285409646722851047280505065647360902845736489925465867330208651476223128001763893620074546763783343802324668030 + 7948487261322735741590287466404743224701011374099821413313798593806289098955840277566381979282309078179393391191764372912784048 + 2031963937573607333606298955675833689352959686316425308916957187087489102352532079680910868716368077096336327451835608150057007 + 8744303746009770077282182559273953960324245388355803375849588763883535017206175431068707914836359928021715134879810455899706000 + 5908433402194706392948327209167569206279605516036898586828659659699407482487006764800996251885333845684403771593097852947347762 + 3484375963559500648211146100726353736952008101895174614070329067925003079219669004928157370633196400836866091467437872364498774 + 2081484205640426298611707106538905461885148824043568864528394387116332857339440668358439402474410629912663441714724196706517933 + 3644343088909312558175950443352757850056547896271926536743829402725583986356025290388997593791573353364649376090870755738159871 + 3017618967565343354488657372318982952747583634309941675726567297969538505603943497976312767045820564276791044673865996984930840 + 6755211147212352533715490737391598930938409102322563339784308800982635726297552669891177376792489264858203303571448544969284885 + 7207413969560628720009738274631537646543552986672220301640499255496422838738773705028096119936179105477192211718065255929107570 + 3952347918324244189239309810051132796520311457058379135751168560732193370931728585607246787585935133034431471433154073599431184 + 5948122133173804973271249039138486246462418117000640467153032385374427588683813496957187641107568040808210363510174360369854945 + 6331834561201934486343354906308493614367011264274134644391474781936706762560771237417922164625963715633624786284367782142544668 + 7058988605827353891060874777352863740110376065711990117582066617633614262447752203022541270469488891576938820572417323582324874 + 7650494373012942929901692837674976301695625545739424778268284160337186164992467580080040539595408395037645199431241659430435207 + 8656919176134694488026966726643058582704520649434961668466021566505602068958240292321141423966866142697100141650705135865554164 + 6074242737126300341900975693876422564450176547153341379638414445501488034596312318816964962988094532520846350286682968373824742 + 4534503855120241805255426868718961329975641710164649957599487128347011734954984504486944932371682996864451326051197976215900771 + 6630007989276431575068445405328391722701879448701430734576747641331918162377214794008905979133776103351215776077151862759310804 + 6329412106193202180915032816114091690804553056071102324935636935651606678882718350090015499101515918794964067433252126478982521 + 1507488089191785086302341745012119227252927110062837567351191646939013086128950794430586208439605756178768284242079693463131834 + 5134585587442274519690540303774472196006421738851673713532054649167344075465437753885506375501473079004259777595528824429150142 + 0167920777588082886922742091652852786107461336681294679615598036369318540905949328746327769828031291675250740935570893774610363 + 0038129096989223899832722064059115068115632289006675498997130267266081648211647293457692956590546845542631469315045748487379716 + 2520900382745986244596184110700770194581607346454171538723932383294827821673322365898338493511029865949821494463508742106545267 + 0565722884026288308442559359348206336146522003909225136977382087745807490609842307769964489536237904153503877870475885643050177 + 2879720936866676112852941496983745298612873646677215750883429056007867869583163799946103524454641087004812983861736126233920563 + 2682472400392268500328620582825275316785330033129835929951831594780666869418979561874633816166907302039950903765570878767521214 + 6000673278648346135978034734234778737168645117288730828023574501322757674622590092065551189918194137651428146720102471591456653 + 5327338501961495043879408610895757013526179026139024561532644668711391863557108491473051168562266679950416482721536337117909482 + 5138678303997976985493577927432562758408369467781462054517017307284536794110651849922852301352432225552398279721808418546811336 + 5942090618633537593070786933293193872947689557210874049534803895058142797994756021217906395785182382696435144831868446840701054 + 0805866230785777399683174946303367253262058687100298157860323746012789121984620953083069679370163347105957163924550067110548159 + 4041789012854867563385153833627178486269852350526357948901776390770563029842109776450416321004402898078350462398525384367774030 + 2665510818821145216742821558285899523213916502258403631925403804385199376750878427488901928524046342897043307449003184422505729 + 2048478041171475190266068119919204384149581828382571880806118238802367751477551342088588974943077841775978105590373879036044712 + 2582550167003327483543334770578776146465326561660371559249486818965320307377862762238777770099168908851119806663382875070424505 + 5444680706893164832113072218288281376031594555136022935125966599054561592735752631698479935094668438169179747421550309847079353 + 7876386229779167984882703960774028877296085268097204654180082218579776041301150186998163564389835397054336008319799363495236122 + 3595623959964323543031266473552625582982574960453793645874949571464306599166850005238654688725079784506108930071723727021644099 + 9904805562100105780931661247162991156577135587825115134266116050943890998432158388576995701892214120245792294717827415173723116 + 3198902109416772023345787207073949684308452839612518670096056433197360112721221131290963458888501686457236376124484894557704239 + 1439923839664744053843985184599889045003833780920311682293838839176055898856807867213644378338290067096258257324765963896543835 + 5700918940980369141639579109635400284102047501766736959067637462699617150713985354772825179670276479720622682613542577452843978 + 5832673606644924997743952540484980626339060224968813632527031664879549813855034184500405400404100621140495713672255224298990414 + 7192889419886464319914820529555240869091567523179106161721958129392253172606561099507740238957725006168387598704764060094854671 + 3309479510962185342022955705280901753250343720767822070179996628541199963151640899372621594086084748660799272108092321615608962 + 4880909425016446720046143938905942262706584339160340379312192206890240470343647456683169242925461208146677458242299921836024115 + 9112782389287307875231265914118831295892615090298799256818943475243201711378213965480178556028607894090008691361256922857338305 + 7878997196220126636517126620736341433150726102479409458917297307599211520723041036260833938983460239182766740060701211352201191 + 8683094774314359941970056128495804368612258860699432526379799515947600345795062224586289908023772808639146020665057226162935485 + 9660235891943541046373003698737146580202165968722595524291168751596799140752064994627768069683240083731174671310320210501136516 + 3952299801633659008575843631974719807086212606583728034228268635353770341290150958327244666611228164923899770204672751927925499 + 1681865396625682674685451758504759903079794185779114689381923935911799262023419094458049787998569136087163049641052695527707434 + 7051981372339577512946597699315700689964039969082898958542940125278978182609047860935808672479205043611404976983579300374284797 + 9494276685604001130980581987978951663125638076896908522150813094023439651488500315910058707670482621722763754582892271598798239 + 2297480620143752383199993430862475021936852109466853279971476608874530008450195147642064323768140191491557557914372058492369456 + 3210874548598055876505562103390094444210433165591830328725710043504607452200463576289609058990598342445857989436858490154233543 + 8132507672542987199374049904308113523835831443354290371614453927015873910762212637250354565826616538395197156337073925141693484 + 6828640682510305462478950222772217556425645114511993512248969567524785308290443499084010706135805334321921588360262285590883409 + 2594395457778771868965633838538089838472114546447151674569430202509411063873470113459762471547280714167783037132473173267526307 + 1601839698883476534179701757004074668031433379390884724016658551011492507080285489891017007383477491584644025888213433125759305 + 7523532561560703539946099285117454732843364985652611667389407913314960693543811095755855340427962780551780192610470189512825524 + 0348247544916136977309530119407469259627024645454634138436438519986158560867875479423449700625816301245511994796229708771223160 + 3917296084877555076938742844381232454610347414176454495292235478841999037736204668770470759408859717947445502249268193464913498 + 9942815514474689741504492308012003642347161752400872994567873248383495234578303317585084447735662421098893789187005435875125952 + 7400181919019490047282686705057224403673442901199627215721287263528829739748034312624985655044437343710362758307470148179539661 + 8008829134593470730958751998114225068506458584106597781009501241738039124829892755451932663527484529522803117480503191650035801 + 3220127286757997144992978308357689318213671314902934383221575508818519767526663815112777913873690474000419949051472231014820267 + 1399894109901863236068753449286869832068943284626949416147238270002784106062189067937811371979896380361397172738949505933506481 + 4254902873234171699063619785819122642732788292824537159169433666069361612397840595910726633660384383938078177403483650975568259 + 2209368179438159444309719519784098123505334554409147220881995692904711982790135929098654648473758048308424437091906340638974131 + 8784927854050511928452505266509077489186830632833630361379070849447072741785156478899585449175370978549268898176795868437582718 + 3231975833056135924558298656515294400028803078329218944207863428380011023399283981167261222531969361122301223500410734344217228 + 0958925958615134583645559459986109673563012970906230471133763988818583110841341249599399387466204289301186261815920165156578985 + 1991110694748693828675086932988793084291818416422390423728768580762059411945640551530823790024178761601499474873560699371792162 + 5361696020245404957765470178767621215479647553935020898244576640893571391546565492142211775010405579641149396961911772636411704 + 5933641384834122776049822258585947581244135364908556513226296636775905866481756079367435635748095205281573764949264635941006411 + 5041011491795017405240846374877784042033437774313006536528316953327476960247723830386371163515353865121506304361011426783525735 + 5488997063517475914229301557438267886673740763412117613628897204796477231021684048588313466034859903879245472327441120566103502 + 8530760385580859337137628786690355170400764087907594224462686544107056072485919968752489909254263413225447887894153248109175652 + 6157903578937685041336967794345564722166007100607239958562466608483279980200607600350161886932405833906442195659498278360919430 + 9828873150674702059652960737024831945705458855872859591267757719944168191278626072224244567244295799804168245158850647976515767 + 6733614592966966657616990010769041211313964384427177615958783894640954404002730067938048093833284287697173874637222402450231077 + 0815239310564450548270963278380227549898803833625140660969258768879529883774142739151346026790443492061196604908528916004363340 + 4528891650268490704421594911777184311417838640306057034638291330148034732863406008674812263692977851302665645685305101437279625 + 3233475352967519524983898638596372885741145463145393518228460271054338502613983364910024616107499752355701791207046590492672193 + 1607766030654760272868975035371747266369258074306005268123601506826295532939956628851683606599198929232644016608548496393286833 + 0164998823596400554560038697981327950512161089142533974519294883428101099674224630562022297926592367086936345609705271926077768 + 7913025882622995728679690258052758137385077334095212932668418477051379462440145509778953697224292738907994604706710137743620276 + 5951558921066718365814901585239666946472249768608440652585316569506390348051275814890810652375791805564478189249435436637972574 + 9602716095164159166038408316037910403855288603710934148506742938423062837375851102966449162297207365844156933403348477083451353 + 4627498098319599205600533412615626896664838788638148524473652142820739172777284703948483540298530565794965460580139030303425684 + 1565284739336025065162908150482205331120001945515224141600855715524039864305366369748820024483450351626491054274468986093516231 + 5340418952181086209554963565801571626818882174630725995663438985529129315572417340527118943747399687973820656682726051844769221 + 4320926831481382140838060220194555123790396897025705923345941235597539508677805522059012930976097312217637965288298799051778479 + 0908830534451543414307140854781014820685341080782566962124152921948070095677549807088847640541631088209567823713325266131951427 + 6110373879023562027503964302970937405830359276112650695138428936697834271328145752116000081078410010751317037848623862138058557 + 8822703971093401247422493922044598594234342733457558225718617586744418222085876701060696882821515543129744401944915912235798465 + 6594559520819849307838207390295967732653907650649027886332594421647601798566341345946992510422578734064164433073111139225071621 + 6354737391657731503659719583497860062575481051328877369003533126272128322177145084735337788672157007937391387995919117571678161 + 6945608633872227095639320829071216249131553642307083427955811490415705093929385003029105106248578633207939138356220965510578956 + 8875904572434922005652897358604531384916362396100014485333372047722658292461442588088931849935109173016445065149146280103138497 + 6344250852997852406467930596512109372720069308708153172074632971208643949842907827125891877283714403480777088075917332714430078 + 2141088112696908575603884902935424862191062652660730968192553423838776572288261313561512545353202622522229101786236940604077536 + 5420581455921312988453042096323962394005097705232943223301112814607176607418563604729931333417412031473023307632699354685035657 + 4904931609893963364651740622632458671635349731291306084872673976452365611310080979515796567705432384020374827307261624382593308 + 4292701172515433578998040448234672894273087795215109333668233787741983605782088266764474905796649724673659270602807201042559641 + 0405892711593975173584006410022813365106426354541842020523033260675160988528765885253376470412464249071597201808795790920249321 + 2969506372363457771265917606965665281965775472879910780113511573805868748553670687571273946389007257215130433994049155446244186 + 9422294818781445710760638755747391659377594672815933259737267891227254986222671631563563954141355946614955207418080860505944166 + 0087286626782644309557643177400304492693387991339358406695023215774476540471075851900070969889709559625262772196723374356067617 + 5897279697608188221125456894430238474410213921346239465846675042270793388259552491229704041982502727376305057500585797419096572 + 9629126678093091084216993559586337141715599917690951379809444249525710962700663884823083705316885810747054287541385125785199583 + 7595346119985543253389563272070967517963948640714499895302628870263490256644647992172402145011433583359949875045014139097383990 + 7523156213061115787711878716816595972617134587220608008483487762219572353605120083032766155082751752855610567994430397014253895 + 3701919959515768374982789437891830642750960645657994589236832995980797844253496076657711645006752860088626834982056251575040225 + 0979950855271929320767873941275718754278787090305240807928650242101643623835476811933436063479233606315724201732634520101994785 + 8113983065740845934933526321338302277547952641828910682131706421618856976337728051411744765715349602385454916896966865817502458 + 3541043147303624444017398708391616664010004834339935228226187248791543655458437287589626370079460316930365464946671005586907844 + 6467142906481062672351612846421358624595986748030105764102127849419935691001942740215832120384833855662335231988116688960608695 + 2788530799703761722379561161257911074841314957231380008835616333860526518888348729384930186986891972631716493196919384541563044 + 9960151488910951179842583784111062968107086150565586865326760613018375413860020781154310137687104793480739369654379775885629180 + 5757125618091793590015555342485911625792045336449768530669665131967481618933921507464033442861020327590807013639300157233850794 + 0108561117599044904729443235325450727345789731582292014742872599813512719247096059598721914318005872025916402947088829272312140 + 0248866797650825595958204057508507830807476195084664283762933417519142347075582529326241506715718869000199121666869916905668032 + 8723343677864688450245361288384636252992454056026441166941292835836423200070814147349431308408145782824860695919605646719597656 + 4679974361161727145100641660878503281476844268161393833161261969965276371391589006952925603728082872969549646978882403423923010 + 1471039994683623569789873331804012722815466719684852070254837711074357511238693361592620597284807521864906755820794891745584020 + 0746324287724173135220206601559184495263174825463472438325932765982783597938536871848298666533763661034332204209283999095134727 + 8847622479138729829083277482843135313544249094572861179333595590622772221061675396437819003622647477864448706978670376179646671 + 2102601933270120920559135994545418775337484717153198432612404295706149728016561442479718981277683958181059597372600330224769132 + 1259053282379608711992970881977405077810774056106800273103144031624467658496517236458989974966732962924668833215016485379965273 + 8337096778081104941132624055977594869352911917306275484469902456879306916808789684303864335821138065913931420528939044385046271 + 4299368276599609244497481316123376963837008957992736164808101728168540138407838646916364855310221850303575133697274394091619868 + 2713682765289699129061431150379322274699877403663503040025037596762253721290401208216082436415144118858632156119324419976312546 + 2881609371673910343032291044465003849815028985591391451188131927898325558643746240832264615980161723347980750483187867525894824 + 1267916226042826987257806754004440337824069605413162886825139485042850988829975658205470396562194892003670768255291562747373670 + 9234220033570807048609309912547070817083287541492891357818324994480536846132188820055694019487542207004276192292369053562016777 + 0261127578143197454905032632100124793899615216318941692486325853609952184783830755458121912666549923939667928989436426770649961 + 5323045993412285553048451071174802746049476412795340271320920389475261483664749025686760199917517732942380222819936015551403774 + 9891352074356975839408670998973900071675970495889358565662068888386887973659152279951010618083877084169404988201568384833942255 + 3238050166229051707803832286590198074734858215255713288528844554284335600396367554775218985201346513397387400209397068796825742 + 5728107211476180762511967972657147473012924183544027968479506893336809289253531374220504641466496667214723927677602095165464315 + 9011192930379184487659969643233786997863887173759888022579642343995986799605176120033884333316312893660726740709366636155465721 + 8537171701432226276253255188614622965933151059377811653184802609155191205285178705789524447418786231655055288040171432169049130 + 2707936970837574068569629371931407362409248401030806380356720552870356587923391333211272591561747393382939386843280495661244314 + 1175509422804438381892148322240590701277543376729396595323849510597370466005945680426336918977914561211300792916203174309654171 + 4042805192423544654158411198004453353597731647696727421911837745446359133507547657475484034048732290037678198364742205283336338 + 9337695707833044354501853716373623356235483326284612569311911355595616206369186001725088755459930335959640295675396477063274478 + 5056639209721879485672408789757891131387617511313947970994081160678454602320697412448491839531065552976208944273555314142041880 + 4822378866853898824086257862623541730929040197220702007762078231078349736989651940081080724932828161588263934616036801731107678 + 7042616549110273896023934480613769270956663187245804271172698934235574549161064775406631472230169390486643998381840493803484843 + 4432695989367708020512810012276065008453086786966931783819054126557051679306430656639833606398733688366162720200084451796967553 + 5350105131227057106985599834342048762794186401151883770272342638155104883645396726235498798575148882718582404327490926780130044 + 5764192533929612390344710894456047465905143834205988681215996081613514814903908502795919703880401811242594826105306055481784823 + 3081736917550671392293064759141270028494719167332097201455667940386826052104961288882027240309372922868375595753000121957263246 + 4989894866974583276238356566258521642610551259726323252743986766553600472233437943119765905133915493843897768279428421555764861 + 6801273161353076961494549671635819940275013580673219344227796480147357333556424794612960445706828140206119824948840749240399787 + 1573785648039077385334262023034272384935398204989144292167011651539471971703585283557377107933951650497678725581455181207346698 + 4874698339219730333194095651462069186623435369684882832433815952523247766685863473588031370751632910706819521148264821690235129 + 1745856207579350369947762735836875634021204626000569901414064309006844235664625468595115296405455194740314530759379861609679354 + 1263339035301388606388533163722497011371588322482095769750979879436887231718408664779720990691297703089437248834586600555339842 + 6251850491772376275294393458209471528965471290147918965218220499155230361216164967212789860144972751525815583122397986208096706 + 3484214175754929920259118693783510869997218078047468018854269713219002531566539459352397848678904622285083238008575450746485192 + 5035485477939887603964624838580376893177633857009639663967781579876337080786152281286836780643711497334038142643551235377859312 + 5770990490009748551131841465407612077195558195928231585911499648608018583508169531801015305515399706824738442071885239921251502 + 5505962701249607762425096231287734763141665342862391398728642501706701840207749211087529147723821274132607543767155647569233366 + 9531752996646776228330405381959650186056935054844849148234315573131250892996644098435195362019426286916985576819912113865830014 + 1606555436659451432978242703284043412347220692073799660822918397493666695089541486316957331014765996271479614514099842437809535 + 0289392478723841946498232349165923942701150815142311799644394965419544149980499852640646717021478951519649059011872310248139100 + 5511032978947425845575588456445816057377640214105339473284188761415785249565799756251192934762389301520020016150949209737931857 + 8405804800314504366659749363367231268121943183966514746661384830649579675620136873178912503421474419998605051121952540207826204 + 7505457456876976664571641545260379929258562329503538400546169325488895767917670975295980264182906923671943997046060564087753548 + 1274387949977098682446892314563863257816052408410571422114222854885606494860672338931736657657635104187063013087549529686451859 + 5042755850832972022663213277248439000831269961224227718932272498745376713860758630276016079020855254056636945995345396441383249 + 6344700532270890968181465829707309620564725384105716449055864407328703719779390283415257182087348958918979888739066384714906447 + 2478502268884223599964876320836160710993832544375139942095572555604343446400261859797019349052899588226956407340248510969084412 + 2858479499626608853379284122587510516464864248784114135053508629608620108109543831989223100900685873301894882329747241764687394 + 3516073975240799285196283516667224035786957693305024409405170967493899593072209653378675045399225752043351688237909816464332488 + 7045960591955279992811051225021192695063962021956994060992139199430008815112575669363055918094781304106258599283195179624447775 + 8303548637737456436395221856298882133107004338700669993457647426042442520873552718504789607522324772936205923889075833787877983 + 4528959091848677214793256254827374251508317477836642431769535470979890535339665561280184226951752824749258073794415152803073480 + 1459998553825438645486213601892946519503789985188491129629213533576249295139024141113828276369687768834808863007813942900737363 + 7827507025285847290454033855290419493832906414032145098230761761828468254431382777807611448800062745765313713732689219610038574 + 3538625159483449646940178756166257692080479081424585343862543469052182432934925669284445293824171233112956439604122644220734705 + 8884093066755275809492142335471176239144329953772128474695403479470145379846983260079920680227191033324315471442379828977213518 + 8161874018859891048210600302227335518426279312266158906257386817733776024570411483770025016852705510503728654494429243801612182 + 6746947553453295308964010256393213729923189009745905892535754926116629620973613924884980514744338995975237628963272677038960017 + 2316979912101253225038374374358240155041996499533280966926264100171569427093110935120513047386276224147665309331079377719563345 + 5252039218101191323619349210669314090591183299132043388783600602372822313158646436097466384432429894279310347011205483804258365 + 8849078102378497326534646727789474466302897639756078400720546541976326397706257168948381071970398216623030217390426497155999023 + 3271457271229858454657827770335612567349224212240695221407152662225083082143775459834013524692150107287815992741275927112028076 + 6697268153473360409230969649314429281006253608637773637800129431557004336600687209561833649108523766841818697796052616713524406 + 1264023927267188505910887476294511895228887727108862538027310305679469919872644028196540981088809214448552558389500274219570341 + 2341820289505149961074855375132511787200836031120337305514546465652487797619606591322268017233923749079200060539286691098575276 + 7095345917502068750136490067362248249806291619173145831611517423916491683475780750592775740226681145459237438975249038494918255 + 5854207316691383141245954956380735287065353365324788816174156724268585661703068556010195412645633774843480772404581791184447848 + 5983572806554767884384691619553163176913927916522767085440008009887977162986441335924089064521714048589756802500400756006764546 + 8749074908864079527865640561432569820363365495585933467014689209329639785755338623694144042638210864919006966920756182400308068 + 1488418928276481402385931315882264463640479342727038934158474806015143604448429971536086762337574137961555181782018130291223711 + 7647631250366260770657650732694263292505761395977741171841175592881623563088242488954360090722844918014816525013438918815206919 + 1155451667283610662459850201212152183408308503418856279359708202057227744768180593554527508439246428232801124311275672977637096 + 3703563826897681685685127020250312031591544945988953353941140195645214477592978106315927871524898358121653801020581142274555566 + 0502532594831295067422782714984502485832073390165137849670240378837997996971720348493993863606290066187249274244662460276318689 + 0152755194697776938435286119441290637386200629628199446127743622173851669645911455169432495002024405765718643210153464143701889 + 2562249212763374000591086405147643148598332714850654045728093130807693494090674026473297812238167578278207216049055667059931109 + 1802942091998951751764726262310843905210614073350123667768202638105831131108058708767584753018377136585264570210097378501497188 + 9619747156993809984322106521027559385156110152742577368251988283361064503255508785410345421538190771023025825991060075397692057 + 7975279398046115700291300736456549463218759811012712333893946746580558137896237287869240420636891089058025806023431754219781359 + 4988421426405962855719392598321200928497349040850013918965781094541442225330283536616202634976088463128589329235150833173556905 + 8706200507172140856416642848813849966143817717503023224834106896623433469273328907429832511563972309658830234487588093651045739 + 1804318877742597644565913208808319750885352430439083436497378247283858616368363127977363367800390625897013789449450637875537399 + 6640589174553589654051256599633381120024749952650719727219130629373315456037578535279963334633963259335915488696463449646684320 + 8032272830450718870582856393550555068150335019058461099968557096935808325051772579016403379075019846185741776197086257884683319 + 9863845517847573376326098832507232200317675290516210661300649571154879306959674077908278504743343209243187243262639791806186829 + 8260961262731301702271912238265956345814430445731867024044874570864287595912998480366912356847572447005441275362156399624494941 + 9393142035376317879394642824057024278760474627041377093083443136837548371844421180440200277690935722486852916560800667873141543 + 2707649253179074679795746660619684282278565191941032558500021642302377918384225264159606437430918854686420568233535916210590247 + 3653446714468860199818770176822269463628134871277975181151133360475139855607198727163601307481114241837610243765527921963130342 + 7740886414228885927181817969815506430494309276878003524396743847692333838266397442280441863182363662933711077420022986422070281 + 1048387053761801939044385077721021658809540040018134673396554017098633248966461113346771441179046101247543088625644697892282167 + 8354720955462557218106068480057094392968433715936618376234382444557134795213907950353329761280756136821666440990155365084581402 + 3688937719186699342108738462217437423679733279917547383863629404136782590007047571508080094271518356483515978166149181632884691 + 9910698753207335191315666777695731726998145344199523600464027456153460564479006998462380767579651598842317204792886070420998182 + 9896983218119310999564732404427002821382477892511011450905458994448002735795600011464506066851494867367124445888153203962666112 + 0874480478255387464724872537442210377291532518746867402289144019512477208223281547993390653821697806118478800205575150577662857 + 4918888004811316598554705337363884151483714153627256672377291874950758530975380513235648385297027498654040181963476939202925535 + 2944953053399838723025577285199841577289179795119166022276762443360574684698180143394617215098184693212410119796009072687729739 + 9732016373361334253176297777291060712041712200359193577310902701783613655008446771602140682798342306314527926659629849329119883 + 6451043591004466592393679872228794008130850294984708968342075888842891418002758594861642712850414025146690654543853793479725972 + 3268929657246764345075224814644064768187234583627518324258659649632755014931180023989253455291331973610627056888949488127145955 + 4261926089033087120812284628614836440477048559583788705295941729615760122728002946792084729956587080892613331345225489314812847 + 1986796721026437522158295162217239471552249715846680613750709615232262912940447904521346670150883469709041492285328187488804299 + 6628012528405245613161440847234508491425287943434287101928325272535635664307751412665147263964282878231211570769131706300759265 + 7377088066364420743764402212273540338705138073396342307947494852950818207406971919647576428347904811456431944019834650692515506 + 4705138654618320095006319217530505261916581737627651424491878629844356338877632449493703212698711863106207638016952512058495841 + 3297864919576913522726817303334406976314952205292550373391722910736512885151802773872849953849211298237482028668331950499038336 + 8974669281536290012748118151506739167431258730634523888446083432703773451432089051580445107667501300580071396777438663916505890 + 6676388335245038478835892287014370527286751599266433016127479958260673956274510190770236842963946164980795747343439314929899367 + 9777763357901635768971296015139054097237772494695148781717193551641896481882800982585569826367439263979611639005318235314749057 + 2006174408272512048656262525906502452313110102817338015892638328650570498699472308145823254807565718645774486952361348150134146 + 8820513608849516349458467726176340280776183307750894733331062785346417632047203675211923303269854905166452369376623717371465515 + 0487090344893360730368974812186113379856699749061983876927406730979994152222167896194935782650684486995334925005887216364226178 + 4428212757677682587368912604936275746129828292671231661463255473216528603314371364809318568990891647756504476074694167225494387 + 6438298664776502895176225722692218937876815974395529173364685280466577427859435428997212680686584089016477667080112002827762955 + 5372837358048305432426520203755641518748461432567909426155727245524828496289926253694681592910381964428484012886894327170000564 + 0966786693488185832806410657062413915673905612790978639242251067404941406079608751238017548545457392976940768385484687626020964 + 7081334569477079676309855956739406608641536536529136201573794386634730088085065014162237881535086131012737674806790302926845508 + 3849506256608406770319555639552727023819412680964197246748248202159679944624779483651489821124252171233790787024388338169387126 + 1220350189747959004534763654451835109235619957413590127042747161319131890755258681890420398880573552502186079819673130304226319 + 7793578559294710797103985830517016163667215076322029333261233893714376644214340079810529332625249572639110330515277641165833848 + 3375779071080037456833323971305312807921291040172365572121296035080033198190386403786992644365488916964829938879099337521148544 + 2151885079681150752124200634430960212055491111062153428630936693865872096334814997531820067268121582290646921550422149642030109 + 8613181778258533141158145972750085504588401393903967265445772834337987637418600396630528732934239316047591685154760079805548066 + 6810794208813864500809678470319323448087878028803605043954670396669190693495990898866714597544374154361810960387728955757997027 + 3780694542345726440651447280692129044592214402723296549397501233597057657590741164054767713089063618201384926245188297986421050 + 8252358803202927045538322743598848427122577241918805031148056119515867274399187693181758263084888023518690338982779085780404769 + 2424326538477152923084594002081423911440158206786241827087394911592939363042513317947630468078474296989628062484584400644343448 + 6293560419015354447114147053377323271370974957505862615433195073799026219744354293045028357502721448147460831465672262899873109 + 7387532795839583928982541818961799651808690944192536299119649406867938059084796080728700163640618737891537102681397327040310310 + 8646371766907348023824656340748360066056892200614557523317897955392332090329097835097131487719957799594533173582638863081864212 + 4986100049536290446290958993632891990045407747006838784207732735249166707023914891375926737812449203630774188546578985599909811 + 1084402346707970131458723746814930784514195757804466199671002857316090262762516878154322011683754629425143857675752082486603247 + 8761838577711280264766083372187992430863964477324546898292032760669740251929185543394862067810777754782525582117312630882437464 + 0771509220114585291617227270613376384799093204219724418023916278133523270037263368542243169870229505561283586085433377009674011 + 9820385787390786107677870809083528732710164474423943477332838364565199183957564959608617849089060421328797474250989472544417321 + 7919326323563029775076417955118634250595776343877190502902725431786697484594693383405493496141691115991728752796848704617855725 + 2558255581109821405634179872876958166347174474348761073684217931689004048682704410888017280103004988712033725528911209075578017 + 9160863221896162516421424469589930231499714756713528296148018288586763465400454214603217797926981201646940396481239125062147650 + 9840316514604720267572846195066141632646978531870664811024154364403354983561787177052598257504070314131100093324913554509718449 + 9311775701841172266095504345180054522901312438857477399185382790126084433098439433269362739881218978298243657480689874068996355 + 3022781945908762278768811002699224365141074026805076790548873962428543441756247033480754889441799694147133688175673557083134054 + 5661203741867036406194178717036861247199166773801082533375613708479585773697108277538910907988050442661518792070910621436071059 + 0690138478379736786396005725249615711997663990048585261495921831819669914145515073403200894318211855461357229650824823305525133 + 1751585791160648049215935161043755494836647727651069321059714784747155745680573976254930604344088093264307898664770655705644210 + 7624145261014687805152488774841289678583856425221410365164555890159519557132962343799732888357700797774204345288024762788982261 + 7890710552868121263477187455194185399264846143513087916598365744278210315488246993448630198352186843484020444533061474327432896 + 8206909625120146564482691781469049022430111838502858582644125909195387775957182358764356323550045553074686821737193044914677910 + 8204337650424296695493149708468179951960014630538528111508141341188662936175939750414398867506644825258652647525390439239752201 + 1219359010151342200692679606063626284788399861632782010310804100495631217242235430375489322644648855854345633079496117764048987 + 6653697464408607985860924202927606340854610960203650555980002938739009437996650927711204711526682854187368829518663287620378635 + 9615765538591556297112167827891749863300345638363300995749126057833117511099109253123549891887992882557489784541036449471882403 + 5919028352049694001658038819829671235731815415745829048231249060308117257367536285634944658365311943856716917740139982945041953 + 5779687741861700152585779009366027675558545586949850924189709461217199740749305528005166461978008407813915390937008493360553115 + 5834977903061566139099870190655547716966444068581774636647968617674813198281268006404303675453751976888820043577600761967333881 + 6972326585063978838443446520453713997506879344217941897803906052743968972254016142258731934881056702957790715642228115030783951 + 1362425902796546798395679404782769752464205460307818179674687205006891103510168328363308032810297518997174255427908231022445396 + 1509825900031470252867573280977984303757520410764668672441796612789584482854046983756780462029600563288455226754517497700564660 + 7759844224301976256343546717305935453950775711909213261546888518009701479912670689049983757648821113680742909226880646315005569 + 8295567234561669944338275143058695909726066802894545455268764288094686590468443329734647916141835949923568889966174907115365925 + 8847804451408263609187211738763773284048172606546780028907522556324927271519705281526806470352840988271648499699486513703844773 + 6679160425612818347335886820513491773906491628651444000288856405322740614920289642723221399498209432232637228104522990852837747 + 4111012689294616788593607591102956684483592350971102538317426326909441395344097833084048144520705500574792401000355907792380226 + 8347617047251388711302856164567942061715329050448779661635598992241168749527006373179435024773116055832951174916423963970112173 + 9055087726497472517559694026453105136312139238988721622285684818285622456138820844308772825216777711338810456475617988242424162 + 4197863232696784218000746661193362219301917851338032677667264033511098062281872897803087758355321546501532794013889570222549856 + 6115749894285255554690322957000949336927917916709996337643587065466062558943015944180187981070089004992789679317730749848395116 + 4787717685054333694149897473720745326568218218182852236278365043324649884567032268831086174748464582606382556519285049880278120 + 3971535819215057024510844131306800637142690099398881617684362973207491682213220003762765264571054110883901103595485168757504333 + 3733461701846483183011223494998710865469936261566419212369452729547931045469934427223536598514620405179798084202385746863975487 + 6787515125117652836269017536232648894348703796120091034388135038967463209181552965632410604353037772756879239864709539921500366 + 6197228209653401639582453147092770443022867307115583008238408014093437109999520308757528533277994723967340185717046004119026260 + 0327403058251198538854684801262565688227840370906858688450070334229654311591524491257725374686504434311374381373826709761897189 + 6320800720313217016667089641041343357180293991403820786439200978809209918586099663595021544518755767970175732723433500537775215 + 8586605557740559261081287090127076957830333678084994220662406403052293892606977228772765289631860524156764537528844813070064403 + 8457029064238615286786107279460798384585105993306593540395560420933072225512825677840166549704827482169925869109982598418898944 + 0346460363516674840943211123653705144516811133167773396076974206411386351987012791478690845256647926914987854519697980693850902 + 4071039292859550793054081697582930309815712485519665021072773643984757349601035844973218854642152867868823320985485836576692696 + 3566944195916064023455915853671413519744116499257428302391059795726588226281448949481887857567458305547585518788070366283222643 + 4475630384874509141748841479483575783195093285020751153893790442309506156006253308563119939383816229293457633418322795791651798 + 2534236711768923060748330398823973796625511107263972895904532310389295669901143468746002992855700338033513519817927059960082258 + 3266833442506157497412341209730995861476441931081314990884968759007025722755350805078872002993770048685210269397083340942969079 + 3325013293836474893127556216824859727670678446693115589979109778870903809827936806876988266059842178470200459657153466761585276 + 9339215768239697841992780261560272323641382940735693971437349481277136632058838727826902049882698280374121176916226254815769890 + 0579266322319718076679029381516879866920214093645961826097287139995438556892638562807533592029177968784950961959651824138364712 + 6905593271581094882293836027956049322801541013654133342099776388830151131142904625837046121178740403372359293970069573073460036 + 1334657560229091661514767192486484034874814804158436588838115645203542626667263606421481459341052191296393864355597357106139612 + 8983996484498008491962652081920903788269022697096829121085293173454864230335343930546161539206227982332409686050424799265682960 + 5979943191308039044837616371196377606973368879788064283861010090419804092295381096855027541458106648574572073809903498794247525 + 5748223869403535883463902896159174890497470441638233019825678773597770107171367867175754297335334571074534607008535043181405194 + 8795353535341345876592035589428503364517129250540037247550521782811791666374510791517112671288737422099652323046937343991337828 + 1845836116381331085732349956975527066319503790930145646064646988078457512408200058689118375881261700543344729871472397774510391 + 9908840174753246368222566017712326787176851291551010131314349894185604484963390215007002796394968662213178018411586445058609354 + 3648708782366479438386590662421575557958786432758515733410030956830742717789884410593667200352894830011183921069426063462365103 + 0863636445701114598272155058937842933641739192649108654968863927721554489981493578009581287965498827240184001075889430327826948 + 4493294744917241293353606762738125798775389304371272784848161045309965481110981617696456977856845295663146310544856961560395701 + 5828350063875380289041787243953420472517640405923728557572182762701021146981223831971084235740009591348792854248246191617472390 + 8142911427486019533916938360973756294199899650632305767565787069658787674361642673323286198646595884519076147156672045347769575 + 6919034458315451231488534732525157456948587079445950850088410378838535977516348080551775162637211781455681436512037018188409356 + 4896222628077283599302550538329307529265839416312577475209070966536398530653252477467412899117369638571925172776374288534229909 + 2854126939661606237890723618332733028245947026454912620083338662672080884075389624244778233027185136679702658181696482687520771 + 5486768970237811447646114465006645965128132304833174901323446834886512598955526763233636026886751282286763353050412483339880879 + 9146149867375327619762240148102487012789152939324347118132416925423213349620444217738724989375651879154078406666532230695010261 + 6432289704281535683765846177747137478857199113830933135896448323481180075359182281747819927805855289891296771338965010648932514 + 3498778884149977137993362603088225708342761654666600988476000304267323094698652989046529561743798096047380169014973930605911712 + 1555513950736376520645091335370846495268353191373549111643901821633347913274787967705297774512956543219272395543943905097818713 + 9824515005207942672277682844175672734608049189360837751069564229080983682875340351162730595292836110710458156809584248318311829 + 8644392801319979903321539224060850887494189887888933968978507838319574610389051812420770840579282228222004146980291262806411960 + 7170669714045362254284955377287230002812263383500586848752066007279901210618595185664394253569437180949208007446172620486446640 + 1197418824383226696240145317846075038217263309407432715400718235690780656588433075117078422196797078588171900080472556706089444 + 6058081175983404316870378185108517992309376387807189465675421456144616633676191879370638648087281836756096354696164358804958793 + 7175300097350528879964995120589418404250514397730435804307880003642423238815219743208925752113332762492815676234753855313749687 + 2216821005143022212418811965038884804162533171952178272981773050431225972337066809470007006624527746167477143326209744916009321 + 2874879795494394023670916234680048368860577149936343642623399857065876920729230526286990908222249218870734087284012928821855198 + 4892669237695278094261059350844729450055740052868656916863083244548039117228735586420221099748057054754127348342899320517500476 + 4913533064284953905878883623486045020791418669162484614426142342087782118817607434327885376004285685360966673400518425200903095 + 5236853047264130432207807874987854720636307899392809936830966680235406253508899133299685304059306299982669510153104336419138281 + 2635729217127660380760950574877790788724558832203965184259818062945607402185371541729168619518031385767332811305256686570812707 + 2508693777459660048221434065348386546516873503781056818039736884680690592725066422073878336659156014383855199604525567079024098 + 2527847075125720859307217125972603526269724367871881994978039745425984811500976939283305909268477371136914408464862183620857832 + 0690848798245605847434249059051242459537031098176625887386313497201621005955291382938621297556760277294613833001841927601417783 + 7028637829951952641999762601338035213911204478792655772152455046625599760300329777350980475951284319951538433620056110253564781 + 6305383937871208842219397097772665248616270756493102017303010524320362272253687689906320569651514870191751716750048983549016387 + 2503753802832702119325330648883246982515086513140942076923304514033686102637700160768687271319427097046984664384031053585769263 + 8859227992404387206024381418823288245956367455432601449940099288001162654396819305512052575309088805570615034227083337938687529 + 4650804026596773751781171691707686499798853858855531297662807643678150070418762900082986264876734988853277036828880591174772676 + 9388499761915323706082278918760363181675840316081077581226482199990184463308418161663917171550066696858396843063924348798640785 + 1339519437101345180144205804260788988338143185013195486237509665528555982435461459049630103016492555659996037806521222234571639 + 4775406178328515482958996000719481194780201067828314313954411507309766697327602402398592936844052573242705274081653994583193860 + 3528381321380368083594961454997422094241837847317957074543832643804670074418168234251527826193469648447514505161752970468032251 + 5644398364843284455563221983222109730803753471463129763873997470655511240512635865533704491564823907699160432034740568090163512 + 2019394829622861074339274739867648100223183661088275367604560854273519173101761322314118755022999112270121442893766921444175618 + 1024961245677370458394203192048216519899540056189972652416007572725591801341729111029393594712226889998156435621046992279746041 + 0271013842729391960551828591764938026380238772791709945105208575380084459912538928688891874547881085895537996185248760341022722 + 6443644163751965239785936903668129878996022934136734635016147841655906985263150160687560568016130320940069489352717984945617017 + 3980979401244807308375088961101007696165282732048547089807678715095196311609438432458589671418362252711116197050123998645160718 + 5029882228039159089170628100687054725011048437854579104323727026278151658455314659996721845525056734089399419451901797673293081 + 6285409273407838783004808714400055644398911907669583936293776767386307697838130877184976183405711337976463042849151509723365986 + 3789116449777854153143327216807443418065067164460291516731014023725079965308205893342647719238044202553135045734641879985943779 + 8298817649314977181973643591691453651364965447794449764965615478663842601481733390271221156996231579991946480360911957202482419 + 9923477919534528913583979154285960230181626227828624997322864558028580882337999440750509388244247586570466385544276236851986673 + 6266991152224272268084343794242067444247144028060688211987908624847699372423422643841707689624467016900013832905272766427426840 + 1355067343839251713050029297274635544953158759007585898844352763675665452680269506694090597773786276467200134181329183129591894 + 1203185079814519449730972616794089846681228932967991544425024262788862162483806670387321965112895932667954720701857303315356633 + 3010223406691406448732071777784917670640450961064883921707223591238303897553076936064137492313930301276184114003498965768546700 + 5055662053584872171686392213754554115803665951484341184481678793730256377197108916198950525496472627926989148952673813222574403 + 9135301836957832126464142557708338619444651703425091454666943559384577035607172295502116858050756179608799326777436914985064677 + 7849895476822416074994849352092796372963487124157171056152173017480389097568380804863683908585558640345480249639539155208814003 + 9261731284405809837137712563712141454654064296465941789875748814378776568326711784539691121352690345339673695586510989770974288 + 9504548640513288992288616894826847158596027709105403654435535528958145029279713253496007210603612311147571118952157286120765811 + 3172019293671644099810154685400878900781863310226630973663196219151877477083273521217193649999031944551410361083160211498456657 + 4584835039206895266033291139088493090671186991332152100943013968139485825629047583367832339953098893263224674847060194281239454 + 0086703131238762939716791409510475698044261061184491246815071586146930458568320808697308895974335329174951890370629879266697586 + 4531479959438670471013925537723663881523195629756820131576957595320119441034946472734403049979337927590688920672812290238838992 + 4555784600301091463114748695085394421438230893318590726172334093673394223159678897396878630225087240466235943323892469006400425 + 3181295825258212728965331361945064921751996326740368121061708410146864334211196041567878993280564094949434554682791503673171658 + 0842856419453623298809261289857239402872945556557159985688775020115214582384781860334689651493902766220136835999359515682473907 + 9925790212755349035787540271290598847673187935010889467948737594198142964082798741209190025028872359505393133888993203341623719 + 6881035084279659821037463368291359288972809796102439700962259394869871767171237148065599497261891353342041591198086826562479936 + 3071229176011336182119446125694433597177517266017496957596892485297788477134388949109492032269677674633006492819820954408939636 + 2158505696670981583492100994722239785061126885782859457540392078035784726890160616966602169759722004423370966068470851220475055 + 1608442432121043588281125489656099832629914426535320512741673998725277196703980523715247319219104260826637474643734228192860916 + 4370675331345005605018147797477139808981239675873728794694700612511771169428567641131258023552337644203474230406734637422278712 + 0072859216860622480346667080043679784914202926542586524758456470894276035984569755855670540260788837234221463158700441389231519 + 5908942320852274627106540557811105888610228644494103402263750822407154871367868699882023311506835501899157241704189414346964284 + 1936077419723541310264634055462791796583876957815065743467706393867078774982042343936087382789908364464848533080889495741496533 + 7254584486083999860932338903788745031776193198150907253247533783144266741445178920158676792459480942978555519260352341102863868 + 2324388659990555102109355727630603564463003730580206681960957998377155433799099008210231393030776738444219722412702108302468947 + 9926613338642730749665937063588945780266089547872794933113744630542358661411190558266352099886620858549171525338223571617167711 + 8986318093141580580876428982707764579287478469073583981696234648037808185140269756651566921560785874161230201920488349770275568 + 1902800771331526181562098287158829944843731017880219524960324079005886150803168559590390474829249427791824941894802034999528722 + 3088584384403360990907891602519470935005839028378253171884990772710302832296914348751708792698002306050160936562533914379396209 + 1408310312115069530150233048818331378284637723150482392301602795737916335332815872089409379843010863320155338585218615794879180 + 9677693345069319403701934383954872660888681515065440356051840106884171038792426226463129841417745680354406721408968771559961954 + 4557539513449236642758101806291205473048350296831633561735117237579593752211878576489139742035316348287283326781007355249045447 + 0883189604094854361797387824593448971971447378881204753543909216846733915206018358578418844775503490330084862478510316277108659 + 4392550432502243314906975265564518025479113098902169136391369512817565837562370156090165943691065253900876426946219189578736203 + 8435865573452195078786548417341611434423772217538030617156223901185493595765324312422048299670372764076523094427788078350076588 + 8758192779916285126332006796232045283091922027709795938540004604312898200544114013208612412744965934919541932903174519980041254 + 1905758872835083202758499042134848212716811095613617523820839042848090697442064092232729193928479222578050789364469898951584433 + 2042272602260087723772848808702134767220173723358646135775389214656797340171301999623954978758165595263461874252751080813852370 + 6274949154731112794816216220066048303875986872572001517499070940234617966182507743418989487331756345308613913050407521686762445 + 6252730979488500452149052167583298496816203113490366754560247487872848255355376484138619549701240217905711665471993273764649239 + 2281622687072260169420599936083131206454896277499378500769391609676460024680767553958496006032193910593446808391535507538458599 + 2191010913898494379461759294973512837440625801801770581499807998348601134363013493664904191350527640096566620000395093356134597 + 1660938804470213933500623938584649317535645503810385086838104030744441292813013981381095457570526776722828297499568794267530527 + 0049591878181449823254506571309609592366697654558586847111232650386057621118329999460228856081046031697258812551653592183584022 + 6258688415014551491572224840400910043380364244249549379338382107530054462860121947719561782286604468083436850199239844591653106 + 2286199429292183729722721966817924988059655688863458946473056847154314312282407066615331874808857982581754086039286737461422747 + 9602373046472185399409121350660074121130363291629972502459350277036971026440212505022927430609191673069989761094096992091670991 + 7527879946650183351260678785085159093046180958175365176059942440628342275638429735328061936632746613485734744234236065653841137 + 0853905941635849403951594887838110573652181835969202362039487221504242797299698627659839204874816529447544114385531980406666739 + 8062623009337523311886378539061039298966733017052114071143987228104904834551295397466673191503750551657795489921304516776700376 + 9007862096833941572335165844081198462047136819292917564132567522715598859947138927117299956642745110763969251319858190814717852 + 8138958664951405431541453825461330550794221363483549976099721937150607149588852431715285804748382531904426919820630714135461983 + 2082397885435139903190314072146037819079478576247984221600827812796545457214101194496220097049368103574832514769701472385466387 + 6896832416290927778053721602166743175733725992261187904101998561355457754417056692268681305083190893002118259512241765998122185 + 2636968504609327449982531058224266443456972154252698660084884189652857349507395676672582020179531698016039374573532855093674020 + 1136026577034357822803043248989730467073666295507784903395493121839773911132783532427651934810756742564183961335402101819870313 + 4917099632663820977131969667158301701831087873930909603855469814730542409624643679930249460380846245995843352815176947927777445 + 7319944731827475004706218777611396753968431393783636860295774463198452128755272715443101250558014321901313052738593050746571261 + 1707391395815003284391913583753339859531852184651610466904418403752429242924142601415582143805388089376849781779454300111958363 + 9869108151029888337540428241180238714963181644033868424652184814249832670934245802862990793758097055499023243559198701686575666 + 0187337650771748598070996214382876748717075026419386245187486192182726086987036097255846930650043060886509574171932845313409481 + 6310275245723435456702127325230222604362757109683102954203602714184216564293906952316506569915992137104170152492029578927512300 + 2305363922251604346990506838961419388192179030700159072409204210540634525740072656419492493606787180195424067534096459265589672 + 9014680664163948601215499948895470475969838465633327315676059364457476028555130517706511356929094761498786703750352514595140558 + 9277484889618105650227338993928615130344847104186489285414725102606461111639517477747291575877009412511989063198428666104065406 + 5967555124952181729420151522869271680843682059283488086279627160865021360567069797183031645357984651583784813809428355166017913 + 3607122306789653495447270140672966362274565501229973599229667563911606772081598572491953192767189192005766778789005815828610262 + 2082222249317420567583150769393704141643717042001944511315146960110297197944325284159980684280693676403148609684883994123930097 + 8731372124960991940185405379357412214932260280623846110357067671501251533776628907031655983387403452673941318358548346602760124 + 1976021347697640428375581819297827333264016242688348297392388997119461967525771833238891591593742490277240125530759579876491077 + 6072466888350935400785328899402008544459154165636826625026958037650740601926412225205263947146298128779293383020953022202454362 + 8044034560774166401511114766914479073842481064943729623980836043134237110449322364783254518711575480004977127696613076710220521 + 0564017571074921724777748862479718313010297525498781712387929033234996773668361156592993020275412793744070740135811199115493778 + 8419964042103133610587792208097044601548949029168486670192222439144702607241592021192461521821947279760550828661220709620486303 + 1088814982734131440185884327578226836944316287501836068430921447613687229952034388566585290882851495307655765844223170274340586 + 9005799435401477659962899657617685769970912656575731463413483835844226203192655446200112583102919467583122082891247399200176783 + 1851901588702515045318382295536798092875597244431065042731697266394552848998020859370638943554279437980607960337319274852691748 + 4157648096188098267490705839256314766006302678665206847589272557754575914579199683296869793220703658904894112352768597742132369 + 8723572441033421822131850984144065793127526826673880856427241209325971643349588168485181604003549286943794523645867631822180512 + 9961788999122788832400015923298335447164102572685865228181427272076170219015236471640964326542574283167180040163937092128142732 + 4937228274511747775697611764578391450794749466871545726021901964860582325608076362650424934625277209649989981489750831225970741 + 5984541310271980053712817247539372152339967892775462123252335196274653874061592183413734875908267266920758029830479031847869228 + 3871371830143074933411065987051697909188835376373962685096571028998970101211924718499411402849248202339306457377199877126871389 + 0586547099952007576979285722825771295071780721616176263387445055392095793671230602073249233658371312728279604207471382798903479 + 8923577166944872998618492077791653391106848257807366227129544881151900203904339062941439729248722161475876280041042987870134297 + 6237224656556330445619379055992474217471454724969182529987949872722998015945413515067495314489889032179791415649686011073157477 + 3003735334796840694489912665109880649358659073702150516968523096869480344821929684468744926264579118587187974938771984262183130 + 9005753590334142936036827167253181517255166676962390793299722321456204920350620126047032582007457817410580787154332130609567063 + 6768747081081207028623866855036005032042045118427663709885224327750939144410815093506371403873404919815687844934325487062884410 + 9939375834444884922802271908890569123942112471025359287053666892829043053920922878243233005965596366467035614279935114942794959 + 4228677728256796231027207112191813165638914358249269082781564785198933238543379292199026489661901488181239514397059686005148486 + 9858539705692720243176916548886314393535919032096542151105543882501065636878211469917818253828853172821658378951042353768012326 + 4422150194025015880156761058170304509425792379790006321176948407538912546088068547813798000277530779888405928477531694464231990 + 9405650213736879289008838391184069127301195712710013925801226563743554996233482554161918019454022970208565224871459380574639835 + 9130794172100568378934252595907690555743933712658951585006391044055921485334952756122241280828770097902109351842319381201019204 + 5387985013440379266230518099534711152536460959269911655397255034626367231069408969413762813968064236154692333107664286960252886 + 0837118680763800551465069959598175835527467398611671504215567143391659195926190188250898459493898805547983688580472819756799921 + 3903220661160023222988830014776994424185300024466935537043911148899196047568212527843430862631973366330579525805431481011727438 + 6908486037368642919233388174527626955887348839535505480142124695672332446751550909649591921180619995217291566458925431968029596 + 5922782959375057616516378703156580986104482212435661177276107010237081047649806919032851751263569965116169589560831643100864715 + 9530369870366296156375956282332841862206458152569867266578623568655520592049072587837930649946891321926334502571392866551701600 + 2244120737959672078726164762991283327806243441107419508409939471693616693409630730506528517088302223393878360169050233927904848 + 1173648771365582895309968552846929556758030253414605906336548466169612035971381029462786542081116525705113252983939162686385109 + 3234155840835288921699357747660762996672264982174457829675917923339715647526557875639742064383339589189545825487931401530995501 + 6887665436803180794927923177816956708553785264323074693008344374916559316617894764427215802134641031792988573701240438184249750 + 3839539179042881405914564139952865952209303008409731497507386952470654995467985010268759732897359668659271914262252626200604099 + 3901076984640950131960333781644223983532267536121313347358475229440208418673453842347657506344090138736051557656821297434982077 + 1623302641135870181311409682200177224901019997404700215147219379739297672524540935209651730504196225871915072497095486880839456 + 8525315354478812852093356397223120386907828133392270722811606375757983394361481913342296750609970915686272616757634461450159831 + 1758237483830901977324883248068822612744747099358422855339260889327800667524049577373525949059825015390160043063670312221072626 + 0817646239152869131112173902854770980862701701464607169211772950069653293230684510278012053087035337608494974396015461535406222 + 8646346589715796030816122730522353992998487085588488148264344066530587174128544229529685414458831257128748560990578804587360715 + 4892783957104711928531643465336739867007712821809759300577073458900066680389265377353301997705565938884080611069388312576416304 + 2814927389151100129042633757615682635990656949553591616128856450443418496471442467646240189440950521511107482659253501599167684 + 6135116334119022986012296077975055833220297155080260438551907096128989879928867449175546615606752828933549694825257606317586967 + 7016532424149169529714586507287588315821039767281860867212525388739062009398857291177966375322314074508942295009826535646980545 + 1130704846522761465358987904002837038112315864342341500267273512280490182439691698104185495677754466174462509539951393350430049 + 6239545452060864474289817540605900770875649791603624701849860428246844860967392240963173839859434643202570338001444647069601535 + 2892256768296868079082781775690843873409200886346998104928582896183217369070621962623861890767458984640863725872163427837396161 + 1015987233236680540127175130575507867333440719260832000405122222181144252353002520085749044160442813319007733231316952017735844 + 9207122991749764391450668652103974356514593013095625877412964336676292277200308352297929615022995501002585354045748416214004090 + 5010570807508645991981283973843421015013551379801238469792061968346208698033924105198332080219826873915414042770997813678587105 + 7079764317445013461353198084076807018884451655619023138435629015461147032511308684817994462582990789356614515379970417351047112 + 9725881506883451817378068264565401988152381111185798791532824098438029254469346518084626414715068349480830207550031462251028658 + 1504691090829009028694497048664643697386279163491642380984787314683252474807267403308118309227599112336474348292331546087385709 + 8374045238326514850352601439525770150385106432876360117179641265901618172845807500617241643296725102357385086749024223414320695 + 8751924711372854963768655608131773099674117966941670496696797649406607434691461307943445287152706412809962107879642575743136123 + 0303974873561466480968743445273196900705427451656962370162651211903195479518829395352847623644931113876694882674530035776397562 + 7062275706646629882491960277069009716984996924439240397590784333436313250958554553224460478301293892351431447612983420608299779 + 4021998564670601304459878729468539224393130081394097452696802435298562203672631426231047502881058781296871522825905804208338252 + 6603870763394362689777694406864771464497251023441752146535341971346977029094361489321326128197028616266687437237475295317363781 + 9156020188117437220553660891624641158468448699614504995148457693527457205903178159270764484168386506020072977552224361333700137 + 6800793585132251294965485406539737210356860431874461572263005112556102550605119443415354337340356018964066943951864924412299915 + 9176918467253843792621229869758475550809947953676328982327607776920014653501974832672677357939313552991103607402118582223524673 + 9686597280549256712036750220654564584483912204263497709158167656617008449221355316543489486938189978195357412962551710086697028 + 0388429487175354035020158054103632924527177834523214082900849111108930893956355794346651605160826522047668675831813135358949190 + 4345101694469873179969332042811556018423606297108948984557961826035019597070396285751114257989897953296299318364378614357933290 + 4949793892609892089229851776026934561460317731511255552266868980253783700717106802153694611663582999276204920297363252094371934 + 3674663375108601609896202396621130718019413744942494222052103933540452779973933501106619925311069127219850907767043719608829470 + 2702622493254040904859153876396184987380395898007693621320399251663876437827374821903867019473977298529862021085159803043642262 + 7628804430192406674682789691745692230306369379190920544277057351743344722619473702262372514469670378356778783948762245486971339 + 0209360041654178829792127599208780855624409037374530019447406585398770659754872987726192651460619482209256452092276066423476738 + 4709783672042319775995641852494077105915433063897114034300326610462577068371066683331006070063551265931785531029670403665686700 + 4587667003896460717120912220270889981167563292172474600789871114756272885374551741764032376074283701965139574996577462686971467 + 3848976224442081690472022609003207496720929495444016043645809920259850317579964113261377231461428538754038582648249855596427337 + 6172335672098748490848298205075949543310509985651798361629655073050078700179132155025462638010290501496311312192593367695422649 + 5726384573393389957861087954363684393648224844030047057212547523809090733733447320925926719918185564312722906061784825834541657 + 4665490918503684461998203394016725914244105391374685986007968106627529172068516391306150797382538751326421691707344779240051404 + 2641961236056444783029513171308212582932163735856854734301365261361011265730957017358847540597925397759304056715637265630175924 + 3143119314616534179607705689766936638499515116711864605104806787742064610741185862931157231900890917045797092416341390041404007 + 3447931172643093407899075956016941324761309449689246711224867235309324518097331543836073039264012951510199018054862544697302228 + 1563566785164424421738528286186718541346261171578886688118979569809183215506908080307606078120020216388497864724764057557754295 + 8570889786931244194585660557574434060147391448332058484468219132867607862446662006468299620134301595151046310252336800694251427 + 0217713452224504960721091364387786965013258053103569599886166960333008816549340813042469646283329089138949995982273574974215868 + 5241363057936964400802812697301682184281492778601196784957952838829973528993067785327299171845639921011068758599950934223980914 + 3238619506166339720940794008445086813283016112070588367871958447351766426343723002443074101469688320695818179265745434758910694 + 6296789680362763149161376071869217199662771928863547592423030630832336241218625794010606091635986342053359908043568336874619758 + 5796450483018638379674081988788071939094611782491186354599577562913830254367966241420426194905385522339051453836242132016154075 + 7739106134294761084702741107955615651072406250165155261201936784282832131480551569227393410480076418655073059966098939360374229 + 2971567365547701845803783070635993312664824380381023912535236337973918393748125160984639017693662692774791712740599492208482304 + 2270720904622266004044552929046382853488397030569658054130832432158967100326401536494483965188041727224259066348964879067583812 + 3443273270836744114169351145812281297836105568675664537098362750380900035541986757124762712416133474277811013584828903165701857 + 5742987445704693742780012691654778768416076035850059897986267208927114643299349752186944079949266040605774961616317552910045136 + 1240573283641630694358812830029096031820509750547875205950719721469746524236951030334909216603563649107173637973757255912252238 + 1182181309135378156725140117731218230316055150298076621940456444204177883491865113883523054776801063888819486505485385264913416 + 5069068146388574137237425212952037225400371744975152454660711335647864580574001943714998326035983681508282903233341771279568745 + 8467943310622656536228892538026964919357667642832630682651110048817452858559725652837991052187308635773654812551494387013316194 + 6440134083862480163392226300450457593962112666903507568451147153007397865298280740371802995538252604177619078977124651051346524 + 0537206772933648445348418297957633068071300723364120286017796847418742109018037795201017609886014503958468715621463005263787770 + 3432430202920291906940764640954727327787760258258401409130943189103009317398784374181000619017547537895364515789076658241461815 + 5914935373373404632064261928025631881068410722283620043865276873695737002786518062855969064577740316535280772509182462064465423 + 4663807875203623784262624547123565729447932492414543360035449489544264792983057557527120665531457725601958452570287012086637115 + 0847474551270439717567791117916716520890209772268515126243374020404961236068669964591032312120458856151122774707229179093256702 + 2728583785414355071386563956562688209782901746373262288816864290881579324219562028197868974414398025024344306680144426091625030 + 0910829767068265611067617086376443471268114912189289789288578161296371552096260414590275441364898692653660772972831143055685254 + 6907552020126899986435407709381912657932246467804972165765350364308400598137400904853881086873855469475626923756560878726730206 + 9692227748520363042215131444256441345425607520902904049752565589636006403442938604002826527897011684910364030121356648587505405 + 4764025506989776287250936345001157192241256998927684892678268726606209680040843191546472014984020704327316352200558172668843000 + 0564503985848436331698791790813182963520559967441699554268886929254925633860614440306175833628563304317763920599751129071094309 + 0175566287557279025857970584297243285600759435104151831150200001725607992873593941524916608511725999483859291253760003734973775 + 3039168535120967789573627753936889933310390638519872912077737282540474993630496322839461848810678646381314301370434612679202453 + 5290955424609618789728513231303753525180260090737043547498273247450093929519045624882089783253628274100484171694237532423254859 + 8186844862044986653314802892230697717326617551815053423012041608272398516591496440428962043914698069230013270892802838135287280 + 2942112717174269473287862314996229628874313075502005461595688743732840097634991389852224318945641142059923309434297254976695326 + 2444525231843962298275031069381314438305678331941237253189959661616931936428403908777740475422459580996785256969423138340880864 + 3680179310627154010609137293613898326769365871171324366981855057912989303388559760676270131578093527806064422528032847530674921 + 9355461118722504639190973677696806900807813249020915988601326357024391608006515894656601520223498473406143763133984605551760635 + 2692839783034034225135191314183486878688437669767719161941937422862653760924569831725084821460846216076710658987697058689127356 + 3364076178555288032798058397361297765867389733546080821420688209714329880465424718281983378741966307965647446727248970877582835 + 5097154920011309551648620026419749934729546113147672841385317729841476832905993191729886098778334663461209723905553676387326787 + 7544038203057755483948118938898802083672133837458011190981229303171157034238018580240354203030584798053880317332961525265980136 + 1511152526450600575245224610801100379737911240153008627074626764499468695975779959724757934622234502314480579416277867481722879 + 9208761275469748679977983637248710137550354113725122267268928582906191386758550109656015747293931779066403562806751200098816649 + 2774371960428126935364571996703554555526862912399267217503390978028481995519553561409174881144281743002477593997449474113614320 + 3283118387697337618913008345214573134792212133551845640272542182183565756097005950085429574121104212579366752791246087630740431 + 2251626647794796903046417171601708089033102353726791435541243544024082843362831636356376144988414260766152555993385246920667885 + 4120430579803988192186052185336786436260523534744839109920724061087523726726856003315563861271636470368332064799342319979701963 + 1178460847308168095740461067148790390275190816124283621727277092177096823111400887004927669450338704196432823728793780107282726 + 6147466566392578561700534815888328209861843963585876273190658740165656380640111544922854734365367040797352367883442096872576161 + 0655254149992445465845820920429897376775083347655359252308973271695549200271712623988532809944592500421544522541040542744651771 + 8895306524774577797925949127567789976094837338117657136712633080384090456221881872243825996086082147423517476054977573177854050 + 4943011385246149882784947556915542478920754812582717541224558316858308474902436139789610336015128572291595765038163819815572793 + 0059519490142292292642467486355644357871443222407272677363258010549846343690410511589487255437861629574221414317395258487976995 + 6701428890977392343133134256358135045673673123158832116303929634062094950503008501398110339118434776130231986975400156621462276 + 4809112204042804726404274446015570840535663272343219408139885535879522105193162064034829419212674983141334515042809663864776730 + 3339872236842534294842100648778519220364381792736266281427277880995347117460315427394400908444602067720779504370559025897150525 + 0666515892628240976196163023835072227181720931267205367481763695114784962335391370607825220441784558120081030826294430035145825 + 5990171621923618467399400881105334235398291318764791324436841208478784739274728174080402657482105706012062680090302017358495564 + 5800215155555227538662802534678916888507797284554941341847639680300462071370712985768701847640442454877861723356457893345549450 + 0044372835991682943791367236860846326267985956993372513320157207230356385776345982286545530591945027191940491720657627496371424 + 3896431871159669144163572836324937737933585239956934241358540063356296466656555165061326841756648545874963895216091891197215432 + 1150436121846416639357239779525130732656046114770001886098939931426129354428928259723637803567803101198938817466591948073654097 + 3680333838160206864509221215320873122528703603282455751545397796927467717336094169326962640299653768153008615924472102530867643 + 6770050643269265320774249712789524649226429216132578192388680218997460246361157967129125548877818859824163987287642561738796200 + 5254046150685030619784205850259746232647288005274167276588953501245671262327906633892459399349248665683674586756619925085832749 + 8138659441098017401153449742392984232024716079021347321627336986000612605589176674195767657558188526805373912850372987580206973 + 8191739475819996816485468724355025309335206345790673864079265551398839303546015301031614690697079405116794058344817857751170058 + 5907733664187032783992586304169841870946162957846844623230375351751398150941213221188521406317499729525031329275753209552972135 + 9176007624492506072188440485436086995355405038611315169617103420795642254487038087275622057368505174049950711687063028236514019 + 2054382102455304130470152360854926810408620809647732343016107388521668970316223874173994646760209951211428665814705542349614124 + 6010507266966547829863386841978029050310064720150129583679215294838434102788460967870976228374996605588773396271433676057289822 + 7051841412308687295953020826737760628903413518500966433370038504670238126933304749517485860557144247313921158680957030845329616 + 2360033770199629503223807832521648961131842719239878810835014788911969787608442436353630358920568228223028658040834409931217202 + 8400997693934004696590555410764211165674028575041130093079293183383749718414250933932351869983505392135593326730456694681893830 + 9601966479081797142729057700273038016579775812303462568369987589932810195102540708796028133906200420900692102185183676170434137 + 3162497370959471401670744764602103343725945241209609871641803759642428128312023652491828868062451307296471228615569464816843941 + 8764436487815154921343571706294950245330020417561336192910050884197950522678946771691143370350696790098631293864395203215663546 + 2103973531056753606278933160819590888661208989653023859755262642075600795082475977389553769715231157147229187302967554388198370 + 5511263147464601148510010944839861149087736327442223343582633059022202904665113422199247896714934045390179111585670544907398745 + 6503691628140930095878935309503466424485388886339832328600458315631288162890181616057639363435222140281269282576385033650710680 + 8454254370393439429040009560609022779619788056284224520991161927353411842168395626223590494290282053470410540843450407987926472 + 1336825679355920509182270187363852809609898538144457557442453481966013998014732868105005901821373796606751500831791325616529203 + 5075118330341336536977717509239821947081842843667207368538939749602952519028901304254002381236022047524790390418089280097834547 + 7087002693940685994858725839374363930880942852293359924965925052590869503751762743229260822706873201650092697209849276502693145 + 7306083000612674447155484200177291509744727003567573915026132438684216504412932709214471251820240604475149792423248249870477794 + 1828750345492089414352178700274996717656637631789061874232476374372589026121784200003799632748786969419729627555600483655428983 + 1419038605582900945308948756881180557106644399148478031842482768934058982366460243721966998715761966320233275607842960609086807 + 8995674775072395937621113944922442969450956475559169579744736615353848691595206952225921509080923588771792361528472949801095259 + 8071164393093218807836177998870397618178243287174730595843254576188688725044187468313573761652235487642008727514328298453902298 + 0249472421551084408818726321837167660068433212182140863918498142778473568559604363644028430498972834010437189971676814372359835 + 6326215711122626023900879284642848379045342532983675870120785391214889560676166670449442675798343547201651587376372310330260972 + 7721128349367234491190961548434288775058240627555576639847795303346657927088312538298685663289068965153779510427872075661840307 + 6404054826004851129562529146035965093659305313594131922007840749997852785915480413483418179403471734301385082608331943522033365 + 9733723661694274986939415998932370600151791965983225598026282848806043753357041009447678948117256393500635321688798336983220809 + 3023589135170563869561312040343087996767334919517638058142422305672311345678035221436322642357974773060658747505711133889241231 + 1715152441111565992971519735514891973779991073609482568950260394204089469526267416519043590653468197703445241031998318436540928 + 2571161687670398639649025206286059219618343667065497532146361041751088315806996390315937024865023472982359206847895714744923905 + 5104856285757044366877940768642231044057490201353054349716001939164041109356173546969025877651803874584635636362767779008126317 + 3656921864783698643075571406752016536758441120671704957195627803118074461526120679475816346733176098378409722349965248254591396 + 1131443502066788861338718815939549028179403039813213172777877033453234020243883715396074872970863142546452822669185069959899184 + 3828769910844736669658151259692028871696603091005326667495981150974845310134146991259645265882236097619326183020932698293809389 + 4299190605742357746915386971343055529972124390299804481008342198376182446383261925929177219506772125075974364335839610948010146 + 1147666764087177430198110110312435274731031579695008275499991697667495238558041459480531076474591001063866865437151222907417625 + 3118583599222787818632900781019308738830040805599161996484071877144944130661026998282751748208682924005109173737574254051272267 + 7248376535827628635806240316333585049198937287552863170331727642858039762809709721675292461634836370227092107000659180675306750 + 5306506627623780068062337884640840561088552876565604494700675337745509144650468822636638698294453362040534422173031206225551013 + 4252579308534696009946359817557643262143167696605231236359117810698816646524895198187607892477097108960784373761400944824549798 + 6045449932335488814802338206074710052382801251742328755176048705595171441928353779134497634248965450262069632636038949744898591 + 5048702418591439721957110373280102402968469372594873031440576890966279374555142674908990757259647232567240212811527932452059539 + 6445116473158402926922663638150560761537491240522157144544441504700466911488897981059188305240921784775901100861995605851341634 + 6426302952753103378949324692632848243080208624864503932730319385221633332864218296337728836033257029589381148577572779689079838 + 8323351033213327371073881110283228611521471023685177945561596153462821296338506612181495253533007296541471850977144060198153791 + 8612240193336900124220751825865213792796718254928148410457543169565765686381156512821242185857562689521331372459681870446271120 + 2190046770619246800670427384048126037985607253433475697587520496744179478706647309818755439429545326720329201172200607765064227 + 3736184856673482672738889087427014657874110745468152414492168023597661163943017362999706603380493625843592458433287608755926735 + 4182865681401614720438201427164757077032257161772988732629306857669039790289782177374506368443513627759379215518499475202046737 + 0697566863573366009839193988358046426820897141853585923998497091914817356341676241151406963597520055377063092845547594101697448 + 9770510287164808256026738019695567751276805483623280478598925336381177794945569958800804342768914035606587017994256909693642474 + 7259755154611086941695255874435534803016372667978524879504844920733928636400671846029963027849546724083520281554956394251995619 + 1834558695670914755649864898844629047200426021450454765139131674876570357846943407935142270035129746721137853801869970041785717 + 1163596604514706992103337640896730977362836499853948987124318776421720842943109071494096297915872890046802390417171851693498985 + 6696873506860390067654571204036998680608912603658516851469732917336706912396900863519518863153116679969409193499475151912748965 + 5772630153097284117632752487886616553301227224710840592032831301443809681968538716385350119500103381352429438906070006049324510 + 7255320449590155185339594353774382542901912346562333365165993746566717810379624006716063017965110258762932735063223456498216112 + 6248309487192090873881009634314790029246770378814629258114526635202683322798948006269443152846896870196478753064865917440440787 + 1079237303256511529274839846470858035223497145513826461412560940325017754834231423361883666751693338383865225187216612119160015 + 4861549012935871901840283860561328549067295489644918336638431557892707608901138017599623121810750153111482390969696067122547247 + 2439131148441383234199376711842415663942174805857098114579871600691759196917341291603802573327405138562282722593414751206457843 + 1973359935209045256671529911507316084304214657632392500349841226204006608244837820483129185333807659672251730206136609040933140 + 8184943256874541309753395121370721662620513066937352652876771594490437810449353276322830929392380590748672786848276069239565457 + 3348707026381104836690412750227080237859968000391150025633563394577801401905026748085615086352851413067595432050498561008571529 + 1877075667972855586652155165911443897166143801340467259805712033287524340520335275436517702758812944056177253493418193171478211 + 3774854369590560985587771159245595691913575127970445498501177157738494672527414527162836050852813684096791146417973149365483037 + 6704552131555310027219368793280881514598163193897955852905718685913917573430057096937340959824715120372466589909944315684960960 + 1012314375846207604646749185426484171598374093369935297204972798525329648052886568477644707532784462941904877487489747098535818 + 7985674284714583813663198777955800874049562438949351977791559431711873042288148908962573859023348239888106006645129281470473018 + 9254850687404139400561382825175974131012329412859199274634520950110017567085977669352012785318630525841745235957179742713982397 + 5097303689162257167085390435448404263178199429357071875772715774544733708487138600770119134943129539543347602041901144161660698 + 6953181183113203630678272715731094392489433607360104735402092320971396494926265205286840279679199637087859730680473846380532205 + 7565033230336604389926974822292700950491849340699150720775179860790531037997637976970549940150909535407513425455328335706561853 + 5335368312471755733760541805372968424193070274491865313428788002453279122401760512494622819480016105587606929438634932015824839 + 5559016338160351661853688320039654018084969722536423822579994200012801736919709694310831609907486201946501673508356764142877308 + 7309191546539260723637253628477957548575327772499530308454034050815650925443083418507106015799454347735223841084017225944595226 + 4885590707691548323545253419048477650698836445425272829459034786263150039138385336170173040262385017882023012446601786508537725 + 3159300795992899648874466508404624507417341674483549750138299511054547355595935184376005929821246479521411349307469101710751249 + 2708412392547375974662585574062716099744667256888486220537125770970468132844596575936704205294434437646542619212125911160088350 + 7671842861670510559275736664436986661209239228900436842961873275642777838933287515196746049787877411927981310119576400549956135 + 8080578380146388148902757671260230173280743467984486835312292349158474503715607238743382799824745964056080082925917323860644616 + 2120225379169780135148292573265658608927358543522142151484031366388491618786494744941370627406622031907792989518445311039563243 + 6616422310981362438162790258221845503573731451992162868203601740290116853659138924079987226446597241351646843845278977024986205 + 3662517640661488061073964114703410205367685498808240378692251201166863090113025726146269622096930731719426952075506480919216671 + 4823643457908716999726557603223790753609939423361772712423018042932577115436095139459068730410826645568806300379584835433450946 + 7837676208477360145796134097352072195957133041368812408314333472555459775670645841696822521516557015970698046160780950308863139 + 5015658403765286649459660652152764801017680991103667912937430519322186712931073677796456215078436603241360959178629806771058487 + 9139921128024002577938454673706047243620589115000240242563021016654786832806633509254081676514023612790990852595917560180876986 + 9308821204883025320496874045455981233709125160954382611635568126874562312377547977111739040746530325193651004237373402504537024 + 1600821697316131396065115975797494969376263815891380490449703227459763844691726208596151555303610430036532384862800860173068687 + 1677749011530966588655330008218462556189908006964342216676682876215290543872066380630113889263010720992320394875173725292986311 + 6989579261987669045792589013853182107944124182584456537044269091571439065320682853599165887592383283334586801282099984394392022 + 9970108676029913047954776468886108937529661369633484559390003673582932372797656385704195055160295258401674267521236080828952316 + 3273802761420937902459164150004835781371893878839475301617292925707508874975102558388990001315786419341804043737604037226331752 + 6423865093791333509337877707981916567162340796885934470115945789596479789320653277617641131277451340371426117129794514423620761 + 7417609321834214164793102707841568625675868448913528641242723253295495191476269874558175687931888576975179732585669568870748778 + 5922089337143793314961512325922930026645734559888635155138481555659443901618808201784727019382947895019140665125084159195324704 + 2832300412363246058905063308416630201890917641050411420603351067801736891124820850891397186056454796477918095532199343583413766 + 3842538349880871712437577001398701888177344881522702272474861972439339253087204797211344636084653095826769076765966355059432859 + 9877839498202302366738674681533509411775934456542381162185787945980551914209016996885507489310451917077029188324180322160260432 + 2738878897545393488539641042595991720479279596803533846602159358145022104838297930283221202267258855473584700375502341592186375 + 9062102173051107870783580788794675784912283028909776152369743147402812551267763802726764393893702046520930303504745751378996798 + 1890158543698671287785156969862722836025364759849336645190863408137034806850238192071351320453303572785270717307117565718365448 + 7734822410504169526033583218346170435610106103279145679136488844339942839493180608845290017442034674025577300763459944350044123 + 6105040904995754702216898271414142776115817083443246834852579568391309141621714380298793479424942862844759389997283360409266478 + 8207744090633188685115276563756960203356370566871533095111186389044186232441179082078908516925531610020829064403059153715127765 + 4543411669625489070844963508370766554494552051662899693726257799474616282059274838670819153036396550543481066774790569529843561 + 6679799651036598201198464287278166599830430479287605906552407498711145045497296895091710143423667516678729308766311555682391918 + 9060618446032966067396024483927774799271013972963401931215359008050857228820472502367068320857075813753280582206475097498167537 + 1091834892775689353192772704190529392359261014072163618697328287354942394830079331974933337512857161868992496906607708010073398 + 5364177554337994653512816619520240821994073186844625407311661314696382001907220045017648487411581430791143507856735567122196867 + 0716761726451434192525856251744493844256079661428358229774069510316066898590543756088198375973992063361152435222465923662351366 + 0043075513893517349925411233398957648025096112448548886678072991181902374596438596256297098774636238148028169588473828501924259 + 3228516645884143195864667466124866845099402543607000135666586926382976262509368071827459582454935921975303881150829096536404067 + 4761157693052962556888050028734514069905365690844215214316263823173976897101122538440327270223709317772895230031391498145736860 + 6385041084622772519780334652630409495229736116311103527030831268982936563366735822928512879378203876837625284271193343076105495 + 8825229991999801614347782438381474867852878074358430022437396713162807802543161593009219312576950358519990247724194904234397934 + 7703801976947027234960802861233790319790676821468496141323682139060568458559647230530529267618724263639883376817372167884440632 + 1726382143017323548108870010820096752312836426102452450577004449101845698867822824844060001600494219691513701486376765683162295 + 8567344046439933818792026021934172754782928648841755910876641284145941585066904498876784179002951113808421135227067381608911653 + 2236981696764483162752804813037353468784452076739585261632267090804876266610444767882886160729217192498345880705115733282372008 + 1313046830998564657547840785183730714291004250275503590948256987454019097344722968276149211207582987088443854985798581722550023 + 9063006406664758572850022859344148370428972822517076773683529207252067208935050546823673576957790680951020623419459032466629849 + 7938928170423206022080881849589066531884975323736816185913375521669990715327020849225286810140422793741838143465182856377816749 + 1265756842388175742586708059491362377918488379984875832030848543287918941984050070389106581268802594158962582407355351035627049 + 5900221712437059899622129468224343840497771816212975521659975058333318690798732737341876177817630804815720469182652538833483463 + 5823081639915099173836211725045578069819187508359785075471465778986260818861591546963352470179514396250583548650281488440780418 + 7451048170517299540822354367273854496577812259623792325601325690996083083112151683648900535783537568629739368276233311118065909 + 9084734714613092289461178939653038690130944168935857129538400432419569476969252314501208058863985767404598559353985694589773895 + 6277214607560240011967714168838143750302367595949536752213657372427124984199709048837186130780108450270594932950252051594320147 + 3499572321088417920853211811454866152496225537457554175697449661675274675801653044218258736968600625898775131530277707042339508 + 9914225219653958408220404955503421597988800462882509224240059485399789816322467527449242209991095322026817971575335077154317985 + 5278081500892846628897442768350495212681297210154604830667333056587120720522354514329460517681155334733974540010110756237411297 + 8210591237075811936724693019310304435150990235368637778807792760313222154371335709089813727563208995319466715986861635780866968 + 7932415587435911762210037637958044637519791039364219987373646146500303943912999127265553435145017969397164413915816752545161718 + 5633226031400350789184112011648210881013020831437183038308240362781644283374155015679893305443987813011631237184023671550613020 + 5811978080228290171238069706605813947244025818423549831774560590994763911374360626408512454006214897383037052649605527910939842 + 1578662832737601740265954708879993575835470810729170613732770615041114798158887175252200232752097837948350852301754510131346245 + 6068409444406865116594371496646576550470605636603063539678037419994055698404550683594340710909264161990867009969259182486360989 + 3207255402572128867597708386762297362519921843080894171603067736003753278183424031926979188196805787920726466251458690002582913 + 5008569364534625206093594865389861974491057988729642501378201086357626134901180260883065306275795854872408871966970358994916566 + 5260870280380960692056382943423819321600456629197713258529958092905135072192290151897612011642141070383635146934909632500071674 + 5103943101344555719687493820066438065019249811470335254469779344109290667032018362593087359223818942995619770011635033602760781 + 6090182191502983738438010896590866621707943859659299906860770756177151013807688207972939771298998138528654622092955429850905653 + 1626336772125369872523005387925612023085181385255260458074393235131647700974860337649978590067937668268507156384372177447503498 + 0983088220975640726485831380650348574527016263360984693517646111104451963030529155545125362875373684368744288268392996464031787 + 1886577864886560438915496753180364296870396016073972814584707172757602216484353054194841318491639088652070784986581587056423963 + 5791295955798452846006486957884980659241458306340044696019455166134558465794056766142717707049752847050948964499027310212291201 + 3920118159051788842792018209898781792646763214510193250573669914454162275192491103856842226701566784572791940951044194717542411 + 5568425247114245514540844570366702834465456557122445652286286614869534230920871827766118797945440453053831301603663599611151007 + 9132285049335898106348530191639824752961756612096827245060794650887002292087021431444313048295402370831165699527783501924024187 + 9094264576555332744996979181892440388769625070877328456545115444598432716233979462060670021904359658071557042696819752714761359 + 2624335032983933790947468174067700780434730280286305837296068262033116687738482347338258135450536831314508366201724139587815922 + 8450751384747855334597310320588125802084226440657572189418133991724784364158225409421748567123411489197359560319327166452150553 + 0217315146965805878176534045386582646736519057669936823885725039838691917663928104666774688631639185290691596050519297245051431 + 7940957013433199012061114563562278128253591876081307949974283942244584406336676182042124767131849195077146222822951756668914757 + 6589005956437167623060683298552386150740712051896264556502825752701728084586373026820140301271827258402697782005508526864025995 + 3287288894211530920495178421618385358928209601522908652144815977173646436635300032777312309529559530424309089857544514218168330 + 6097483328468004536631471410495796391660358670051698715076410248502303660016161800128810231929174703618080502422800241933644130 + 2956392224013095847029227680428083425620941588942686433369479814315411693725173853101111802188051631515982053459377355277916857 + 3065681935968907368748287973480293783213808382487086015879418794067438804225330554229750223350574245985145312570124344685276455 + 3489772935059313564818602631010215526615299221297140830316899208960430528821219213991899112889288129943720176337014173173174332 + 4169981630658215328566362976636435099613640630157506404256612156966851420692144492745499377619802506248375541742742014068421649 + 3723697831339666759125999969874386488250045997138226100381868783065151573396084764792101954730971063666073382268822664370648202 + 7695739092394145422409597895972497681500338948172798211529024633083754418602669479252615594701113082363308526566375385313538692 + 0362024243582700927996091721261779876357892824920462321831613846936511858949877169168914710103805138231321626700946199996026230 + 0910370398336603134902288593437904852970471827636244578441003561376156126397047213862430430449454667576391124197185148345471598 + 5028346423876572027639326365391106837855425740087158529449602646500698308039624506892347711322718143846562617911464289132024496 + 9181010776426759091535139982513243227866023899159123168014651495554175929065144279128447458894513674919834462361991122972799428 + 6472902683846165829490192503189706567753176937559527683694767361120216602239730653948099377610225798683453077405631209096231256 + 0512986051426035486790488833906991553793296020140460296126591780195814787329857676072922129878562425136025882880600984983973989 + 8577540121631192413042201337007929873227061283325668352988181356692287167551269236062168964313569524237889901244379824573640154 + 5738145734013901847027973765976787682776812683421111101939034836663608749968365412229382487929512185391212964474327857768911300 + 7562207836356806317921677823535902895646261255973726228824124734902468677105214682457780953879753523764199156291556619449942205 + 6685144408630396033374384521831023348395708816803320958823787110609396335187767019703187308157675845831700883961350733812554544 + 7576609828782901349340272529157644117188745883108516505970478068227119245704450471362770646680973620118556831550370068906691429 + 7387998131808587529731801781598911046784196725282943998624870759033897379214694560999940160160935915403688360574784745832951209 + 6248576464881189569842693329569180599977760906738941622134746107827192298531798906163755685774369390363347404463590563452485459 + 0534570888244129725519284614466994594106901806409139995601464274045789187815608635654309801136434736637205014712781222746921224 + 7852721958335248170761829133326246797700730414740667697834509581576475365734827900004460335634027879413672459976734498386195835 + 5088370360545200433735093090688791665393907039059272593032100436084501418577206986549399579720624028466951070544585214365207165 + 6435187129368614449937580538296933531792687165143536181239511296901417188887649499928950174527974591005214327286330726199831884 + 5864261175041853165789209708620714822361777843032399821785843235985913827357647540975103877312914819841724359018056154229990484 + 1936832320986190570216413377747783409617074645446275675504398782817281167330026961325947267465552277788937638823143961712338389 + 6643014994016028760819796829700070956205113377466899907953033114796754643995517690305975245695734383895488045495784881027449542 + 9277149772110266765516542199009389979979428729803481968242094114554310414335680714665255584623073310801300516821617747378223514 + 5122582985363185134103472499467534154970594419472963412571152321765481331992341844237099548533622925469977982035402603376599366 + 5702039170472823969912601643296899307773750835106819267275831078282467998094066465029472821615682366477091470622470049719032042 + 0671010358945492991105729283517652015315441687350701252921272273957729883415005085140318681745681298665587818639399209287652478 + 8504952151973256765543113775190946452315557877268395630007206112950274261280515123602637574614066439170518948486082023049534264 + 8318785147359309244073883391968368385030412213804815219561275632927036049996919071912768810313118985299449822580618372563128123 + 5447965794084022881336224721150430474622954063445132529997642171980649882452452874371660709010271333178089011623650142945593513 + 7498570392070031176556263724838104407401975655807188803601068318852915004571680712468602581133705435004279673319305506280782318 + 4235251770160613000830130983063100984485301111420207302571915861863284245935054969687285090784775829404258632032504825073887582 + 6407248272722201582954889873840796724288126199508498948167917317499903480984445960848498060154084891463403285778107348687889003 + 4953941330396268815099409977237615027521463257528034758197037642240947224961515275989640733601052280398818164960445717239008728 + 4426630124553142687273205330644281511721380282097626819427510520776002629092574526215543555846304555626987349130475830717662512 + 2679622415503744585776560549326024439456730222065789254179516934309405880579097989297964155354764447981652276792153719461894070 + 6549452078295195952851972101892868752466073329081552637836554870868329745518970415001754631788228704301414087107528862687179382 + 3095714010946058367115405111675588241660359378724218257897889232511664785827286570897205547229279697287663245465265895194075831 + 9805465298621739062011152177896594580714703932025865262409510756369094551491315344002976208292437754134178483455044310999687172 + 5635853083465443752399385809613532628000929554168679920157180193163062291041706935484519604033746044464716659982230583915172977 + 1397085494342438160066950214161726216316797535747161972858218528442291370670389809452231490128596440810108729216233152926963393 + 8718938957831579949398261083744948669476176529513240710990560722588644755296402086806852345746538236347718030640062631744819555 + 9204989031916871283227517942830744003831314993547893753197955379403077174291901637842637655437310798500528596483721526174221178 + 4510621681082500438705444746385938892179962383128718253236867948364044872547102979732643922151263657382171953178711857903512864 + 3434625913079139632847162412927858083774910063803492872036606235419074389757800463882617655159555904544646003283714069095719127 + 9422478480758793975004764634088848124200701219293815383644557399151474644429876593122326476162568364525117348282565684006439054 + 6415412788931044743766779624337137193856769272687596658353208728053926044570228051289974744446738511898266628888688489033821326 + 3857187055764486798882511807937125159502970249818799519647825055901143034107396715341111836431533491237288074873324479254847609 + 1944275217447109672414805304798039892872048551668309961639053276921203694927946551682999672834794575568139407200344761188832584 + 9228691574818073805866351085919567356330517627511140717776424135867621344167516969731782408297076690641510925488519425339786231 + 2831239904815704920016412032913992948413502229392159186483640311971384616648328934218616172408437024641339341534952850417631408 + 7800709599423404547224077175920136421077429331304204846667623312748910375272177983791546978316206296185604509872479031731294077 + 6784795879386865023891006814459422181459242147354385223330262696056730516247499993593952360113613078289229711721789291466201911 + 1558378948527819137236700414103122090944390583763494240148255786716027072401897565958932034145583789267171948650451004479200278 + 5903365269957297061267790413012843976619330012086443873201405355132327717135407147467813950090532723390786355726062359803253439 + 7629287528827946090011668159293077488731123501345393936384022425933097863996545653037874008416991412735073016080615679561676815 + 3237960418959875052085168366152912866396485668534444686608623522780325138572281373258421046475238324527598957994900036953588632 + 9883457218912143598750744649289916045155230666253998012127292069605955397882251577278616463161982956480851083203582599294132885 + 8739605725967415654345383552272209454198363876790394143551885453633595477692847087747048445889713841117432214889427740276964122 + 1808274594398149686259653460592417452536265711085053636183889817336547379067581749366999937190487929782077243956107305394452893 + 2858306534503555758138192142342374976569912519114070071304001216131565171144485590883323767986065555672710513575942087665489357 + 4757258115582473299797872077008431880804766429204591994348523186470015406253571125582684142251809933836340635261386229168816736 + 9918555292750664784762306372865895993392873092492120139178044227677315162874458415577767229742354738329991177067335396671747156 + 9915416169565774505455198608946138326580556663002878103141442158950284935423931276623631554768708518659417736110868144091121408 + 7485024844800932215930566743200643612646843426043824587026297306446562930746643938917961270550045568670866510426684185886721448 + 4920398501344484751530060228048138752162844188260697740262204586350188489261031255952257367650241279996726021255197979400713310 + 0983903945365766675649828378701431579004857069167244696371192650313930100887222144395396003002837274898192175630515559492616368 + 3277569441388072350944394279081011821982637576381780324461779633187405677617459795408379063310477462661505822241372624056397980 + 2796195339856562934096874382820282192099707799004934067504550995736513197478848274092619553245513516215920528915358178045259427 + 3947135872153511247151284668940911981933985156149720562664695031030349744372110088157223178406720212021960705751648342245477823 + 8276198303392861443910819050105767637970397653898744484200995946877348235373325786715347188697829025445506211703973576651655150 + 5882576032689008918318143363475006909501115410116941599853261283394744451901101910507633092078494500214632287815925595536310673 + 7269241743888980922214944937348603959760552838607959592411748713582006971089673926445144319837129979120595791416170081356544964 + 3311215693514569183444297282757452024106434743342415838798070572517431245405339373780763180400593713529558089381582197573125752 + 4556878108283717136754864320383151773421100605854818531410424407658443836201366417280243912680383714161438889747985913112617159 + 3825283938152818066103999819485641639048153915591788440799327104545750772861261496085802570014233362502408220258846139854490942 + 3543037705426699624325696485612282411023745859388735341967646420985563945181345313960301854453402790876180716518598169356488497 + 0055015399759018591540911328290609447855851641187622864276870240973176403939507548117764594583218172186919643238977138111158956 + 2302146157347717928300258596580246250649908644352652697865369736710811431250945078622499892640698932203651495464626034751579299 + 0465216581077322245370388400939469195489616593652097640401043603078806904801413336072374703228412879808024013691780444525050754 + 9151727760868811886689437563229171390965138504950138407176506255752456724326383897323049258585289255126700265024238726662681731 + 0098281899254404044904741984338800905867702052389334861534065540083641450439874866038625038945827791603161398328731872690722059 + 6264530562489216043969280034408943083142765136686187837798682491792210809601751533837187815038112873969767271421029102693650921 + 7670518311894906730059859298650685509520663627502700465860614043829130684092155123515969024766529965326820247830045239762876384 + 1971827918374425559499103800305418434180845901819771222995898394549615763182780848478726307902754377493105414864115497763562067 + 7293146824231836764324358936471102982745003549454252992884038807314576844595566006507289403671236553892547396334547842381936455 + 3707012658412106034610065750021436552038057251146149724375405389299956024255098042568008242870114719254029045709055991603654930 + 4543749521242879802728408392725236169206369176046813175364511678612424177154836269263324760122983569594445005273913013269664551 + 5817700093174352547416009939112502133121085536020612539401905269863944981266637678387919942591042471679114800424206674615903746 + 9928390417067700668674925186060124842260894166668581468768675095262594932684909013159566891337437296287921942274275342136808279 + 1720526807320641693668140417766107453595978158154018754776221360462162393984770342801365549647871062173743896063916005240392253 + 5161802386530577435326894842370519298812054283209695964545050386222673476579184628919106024296128426895608065795872894836272477 + 9269809290510364760281346041981538977140734635535715877861564862122154561230471413453427434440292536928348809500100637413855174 + 0657501300841813074935854851050163894991818276164751987873048063138250805404584707419292446697964047248725308217946641983844311 + 8063478785147013188508380911686106501438761736788881545360437305874844044022285005421389985126661063912349587081288388003345466 + 5080385912620164034274035663131591931589292314684519240800453976434478145811035864455399019210261903984106215732682395895799522 + 0939020059406813121907073513079575778716665344964094359764782266431575550874973231091097656538411338304404129653958312868999842 + 6732798933518323978985303323091966916070134400750942228988862433672654847071015762525448860254590537863809085645618465872667306 + 0427846766351683194895724811056690695837239230026578986973494357639196637007765612283664140977141629336513743191474504552821790 + 3228155682944358310924291228796943417467684350283874136741330013804595358442242749651649995689037646356343539795964269040555905 + 6826145487746532059740843858150338835296508366342272235981293613561407683050389559856243442342524690245207486156018191382164551 + 1327436225221742602074234993619036983345996345216008664910823535986496447271949044534929738194453356131648251656209560053354614 + 0407290886807276555505472513777566509192309345071661761386510676177956004136233159240180697853305064135526857625954524710679122 + 1431829687708285619275876929673787963838663779016128696006658789855078135858492072768308764926825429711165034052613724177837083 + 7028553048202580189681827868563421125284289066186493489485470631057243002992982744971998313406439308961352814738730662842546474 + 1661580089658576037549874036611720164076275368701553799369961428692585978010787204558502174932891500734632543309652429899761996 + 9575856899639421670892327891209797029282817824375074240277705275435359082312316792956844954585652271368228646822716619012170165 + 4690146795978834583378953218274128128954879679834962721495470431115747652300230454490265247933455376976025418712883919785265770 + 4032584676449148273007032590154174755542691092611500872882432669889260868344191769763590664159630537010368972815582431630162563 + 5692592732110530293190433213941741940871216528267789341138499704212959459631375151781937020467215223500973204249438057106028338 + 1541214818072382006149334712979978351719934230083959861254175062060206728245934867359880240685020444293227864055618527079589472 + 1439159705776204064690488345048299759772753492079024651663143703086754589449249599931908249754660757813918172727140178033198709 + 7752381183500066741893133463291861429042158260704598873907314527361438231014952758222297919601552459311683576335125432073345960 + 4158788096315630807867178963280856579732177587633674289101034755608242832707107748491269005626588055241208204418618388578035469 + 1184416032139115028602210049000593619116279959516862765906011705138739437332038056873961010636018153261556031158803924660448426 + 9834587809319862013631879808865489908412831755556199315250744409755028410760389172898604230817719091796600511778684843691064279 + 7878372956127669698977302339079670592653146391325443980293253311254734925614678750486528888944734310378404782150993544089766813 + 4482271911480681906845899905802627519765113355182171607609262740960268207890619067150293516596923655844247586174848972864721468 + 9552003526630991149245651109495761934587784128507108647124483752936558263106644305431230364441437558819641682185001628863763328 + 9406159315820904843204929487522677107941937076263988953382649335050929875295580457118791755887589396355358703932935557257606830 + 2969493527901243167542109903168828628101917337300403325039813279857934939104326409957807201457446262732489661524241158979368142 + 1833967145487476098973136162241392322964264292952490319901422154921305200229075272133864200487657774340560812039475075659326308 + 1445298822625141627089594319278576573094647719202883678449230305616300998398218250958603519589651710614887336894157702428315107 + 8911019753589361230572967964751571906635823516517521975275494263948066958905939807605210390275340148405377313480598158489558111 + 3183749609096747980513864052412964607501407465024842349303716927046134047076464086834827581454812880653390898896534483223922702 + 2047220404370553586495348686661844320582343653984119122227275984849504305399708851775077220602618170548438073982557547603633042 + 5484875538490583169391720574953649919139069950121342298729189319935008363006908499817188567294646844902804708973781249800855552 + 7421001424990409022663446235185073936721530809635245828159482916215742480785440259606637437758227633658889520747280770098045723 + 6510075506635860479703887783619213078585799368504850589990946726994909109916359460180863720392604659818835051505356439580781411 + 0959165291367850253561235537386721365762207442766902579631829064237987397582522884081947056330594794737026301952693630585102680 + 6267281924773054128920399667616892395906931391070201721710734680164804934661829697133693962106573047827000567454860592220102084 + 6351225785373403775734572811446819619019190839393144125015360556285521375890386016901082233720031340998488590003458019399286006 + 8086983669350678861956334882898616321436714400384547300867927315159417274826609618496301870293049853960758679069277021904136960 + 9865037759852510085988938641077600576537641357106366728530348981390205491195956901092388717027996104357442748303975082427786786 + 7507248774842522159480897459767378325396763974897420116495369220388118224704985677597657612836164641593242643705906198310715923 + 6020323897854469493762019753971728667497338537420217765895884555350482562903234559598367966289598307357713584270039680501758042 + 2970682482901424731104641663111768757582340710358846705532647449734646971482108058532929343635001949578504462729212526976463810 + 8406644630764947233594179128313043631264609165757699872474368034583055609364865453910940072958562666156078109884350362008700655 + 9106501316131398908994689175684333822574784889714347654697727209736986308940910431037486363365667132654371414795819563310659169 + 0137910472839714679161637852622472509459014895991142745425159229935069751019575455036034662579025492228994125955644298201357138 + 2263663590472781654218931217059804728469684174302359039764853349702219977113201315914188584584955078222068657185984247622363558 + 5695450824338155861977114741562006985207639935376048162114526556989656274727076392276059583216303897816482298413238883403403632 + 0038975862485843345228895776545691226502347548540923009663654944132545600827380276828701039586345737400863528654887451057233197 + 1285772332269416234665537910079978608222632602148452508934499816027147308767944385913555512454637610386856292966968437445496548 + 1261330191618765210009782014085845073559775965093415001665110717532374517158996315004359428915981278340620344383170562473911188 + 0755483943667647640579099438554263999127548734337936583257964438443463208543269429173892355146856191237124938489437234962714824 + 9129303544439064208938552091032859116474732583566245269345387009587018850752964356086348467165770868170114265169858965115946288 + 7279622065007376862875602615836848329672073134886504804366938182665036461895999032293214820132094992897811456738921945565996030 + 4834236494451378286976564913106384851412866607459667235230175488097172277734513000370973157558689076209485032473704000163914074 + 2906852713508769108670361019771730001144071549164484831831379004788411810506441972725735257048988599402331202363984166872400551 + 4374843284474261559922201408952633150671870157517305411040726961843624607898601648184347808307024923212656070285299487288795732 + 8117441033938778257340076295628604371272466046790715921004843853378457388333862596453687093388500288301007959254642621709441228 + 8336419205482595246714478040728678515920231077940527413442313540990859460129785367310524821300597125039005330560255760446207185 + 3407569957745240672748410048085824476146107644741791845367520753456514888607145322239479922742610070735465164422006326154369011 + 8894279996606564122245246476739025836636961740221798143384506169709797876615015522415620193119156094455114077417058486277270353 + 7131151035004395224877087554662361771017971918239145723682405673667071436258453271309611849685373102636336093172827546720740657 + 8432145665345782054212385521456100690288045272048653500410117161030682916822394178179943934653293870095835416016828701651397729 + 9807379993673315841883406823522043062628694861759093682354411179777001696451399181533177926653740164108712792568617753057780749 + 7552198060883514609633356358462724322863739238474217533806217264897669042731651388657558396154686026363774639912794923252267503 + 6291771443785740732590982981719905524567339994411151615939323485160260431350712239547320702908777027534814334898810771281406391 + 8383725943909858701756050979518960102350055348726092344362770497395426060226252186716626586574811491995835598427931237638307288 + 8507265667315900242180544608612147833573934012185340789193936346356941286917069481442515796977733286907179390046007293777378415 + 8688298391307343027481331662068268845813946664921272848764804887244314914603468930763919183778517730411504413547554154855526591 + 5310568546507610904043747230819248926074837842921381365456929822505503792963441504203788828448597610860322974517666735027993699 + 8190512204618058514563016675739391233696406975567198996502543146118326981238682542313301537034074950744994938638623004424018628 + 5962797353210542352910227068452267455627736914233254078275501019026029219977380762852165264848013890176220808626487330453830607 + 1392715231741123546207682784414187261145744424815836598165304144212321073536110482416294352751979189695534837507189501132643925 + 9547196873348778230662094351866444409683500705986806451682346762409749401895555972393170493498341109191510645940668680160665767 + 9096955810744288162025152776265225979561511052982298941267330985571152782374720461772752985049704669084322641186449467889515212 + 4360617959299125510229120098324080014685874269740158186892010379118371918256414709312045505595343772662619039003425826619680875 + 8242651081630156918805572079983037638369031262141838260427869758050055377235638965872717517504788429694521145838583513263909672 + 4433259455372438105974775408627724880736064277338137893108385178827104479149305047828800826485922049778207824411348676510055718 + 8718825984885049258859271868511156347573558547616835487996237695354831720772501296121171500663173314753159506044722718279173640 + 2709996430110563394535123371054969016136174141380219513450493806426805948941155396288218826477132071568170532718023856256400877 + 4412955918580719390710872526700485018418160226844433869987075876676044792011973789419662798626013873183203506118837233134120481 + 8772819562426148199715932002776622117594716096791960417797687467419822085071157480539482033047913473604918965910085487367720357 + 4625085282706988812822930138218466374524023159847349699030998731244290316248877616127354994943514784160430249591960166158827428 + 3012297335233487487686932791672504848939891571342804916267615897166810277253170819233520663757428230248104405100538854660927429 + 9123919446207336590235297840044149569787830675448852079217813254125078565940555357151112153929694801251132171203795549941163920 + 7476175369012980559938118310990110840174599144325883878065361105628152837782089093135806082805172562067617245231771061838879589 + 4768469919871257284902195592516344833223851928691778696654759047583702848545509080899254152913598427216007302226235522358460750 + 5223927757227044947866784478462919350895723643402842384138354740120256079056226884847266693352002580953694527348195695223607106 + 4705073558122375415417200921965563405533347843275197814453910296613637292816403322858277400213988846375567124674868467361795016 + 4745728385156852832029629080429064757351207656991841817680115495315482039644479548944488439788311653187692817074819840714497361 + 5386314847182104599263810424039609228765878994123179215715094367283327303020988006589792974721368333841513658700314945433634456 + 3685020221252259142980926069027074077129168059113331677771782227727933843623094566219277157186574916058687802285827552124321505 + 0794558617931775588320039074320252238014802597836590634824227249703483529574186006183975509386000848443692647358501225142361167 + 3942679708028160995866607265771564423203677879968679929985370044267348240320617033379072586756373490054605230219409903866795469 + 7536599276764983130315949383875187945686502994166320326189211280377933687730984141460802381512939077916932152569652666724046409 + 0292377825630966235158683241512971091944539929600065707699283877623772501033680549048220288927590692487589517712276010516389098 + 4141777627623117777410741182897322646935774432337593489702909715834793849902052358894916963594941828827118210427424755222982593 + 0263099400776234259640984881940007947968250580544744304077736076557953616095573458814306253535718606350692981623255928091096507 + 0588327094996262431505059042095661828596107333578122924612340170790916991622052806671333685104366780235136494027277232872825498 + 1523246308282008538061408160202517775966824053244715248653671495274650673682535042749033828795099010214859776685551489176975506 + 5811209762314534687747281829159103097186141033482266881873367741901377849867980657673782571505747169485443159028925476795003998 + 9634367858634565656906133482371306765239555613722480562207025106068336976469898723556668691361827599343403798798405762012284113 +

+ + \ No newline at end of file diff --git a/test/testdata/html/footer.html b/test/testdata/html/footer.html deleted file mode 100644 index 4fb22cdf..00000000 --- a/test/testdata/html/footer.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - -

- of -

- - \ No newline at end of file diff --git a/test/testdata/html/header.html b/test/testdata/html/header.html deleted file mode 100644 index abba6009..00000000 --- a/test/testdata/html/header.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/test/testdata/html/index.html b/test/testdata/html/index.html deleted file mode 100644 index f87a411c..00000000 --- a/test/testdata/html/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - Gutenberg - - -
-
-

Gutenberg

- -
- -
-

It is a press, certainly, but a press from which shall flow in inexhaustible streams...Through it, God will spread His Word. A spring of truth shall flow from it: like a new star it shall scatter the darkness of ignorance, and cause a light heretofore unknown to shine amongst men.

- -
-
- -
-

This paragraph use the default font

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

- -

This paragraph use a Google font

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

- -

This paragraph use a local font

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

-
- -
-

This image is loaded from a URL

- -
- - \ No newline at end of file diff --git a/test/testdata/office/document.docx b/test/testdata/libreoffice/sample1.docx similarity index 100% rename from test/testdata/office/document.docx rename to test/testdata/libreoffice/sample1.docx diff --git a/test/testdata/markdown/footer.html b/test/testdata/markdown/footer.html deleted file mode 100644 index 4fb22cdf..00000000 --- a/test/testdata/markdown/footer.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - -

- of -

- - \ No newline at end of file diff --git a/test/testdata/markdown/header.html b/test/testdata/markdown/header.html deleted file mode 100644 index abba6009..00000000 --- a/test/testdata/markdown/header.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/test/testdata/markdown/paragraph3.md b/test/testdata/markdown/paragraph3.md deleted file mode 100644 index 7e43a3b6..00000000 --- a/test/testdata/markdown/paragraph3.md +++ /dev/null @@ -1,3 +0,0 @@ -## This paragraph use a local font and has been generated from a markdown file - -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file diff --git a/test/testdata/office/document.rtf b/test/testdata/office/document.rtf deleted file mode 100644 index 02f93cd1..00000000 --- a/test/testdata/office/document.rtf +++ /dev/null @@ -1,2196 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1036\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} -{\f38\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} -{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} -{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} -{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} -{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} -{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} -{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f420\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\f421\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;} -{\f423\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\f424\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\f425\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\f426\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);} -{\f427\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\f428\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\f430\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f431\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} -{\f433\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f434\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f435\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f436\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);} -{\f437\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f438\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} -{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} -{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} -{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} -{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} -{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;} -{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);} -{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} -{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} -{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} -{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} -{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} -{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} -{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} -{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} -{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} -{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} -{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} -{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} -{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; -\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\caccentone\ctint255\cshade191\red47\green84\blue150;\ctextone\ctint165\cshade255\red90\green90\blue90; -\ctextone\ctint191\cshade255\red64\green64\blue64;}{\*\defchp \f31506\fs24\lang1036\langfe1033\langnp1036 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ -\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{ -\s1\ql \li0\ri0\sb240\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31503\afs32\alang1025 \ltrch\fcs0 -\fs32\cf17\lang1036\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1036\langfenp1033 \sbasedon0 \snext0 \slink15 \sqformat \spriority9 heading 1;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* -\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv -\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\* -\cs15 \additive \rtlch\fcs1 \af31503\afs32 \ltrch\fcs0 \fs32\cf17\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 Heading 1 Char;}{ -\s16\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\contextualspace \rtlch\fcs1 \af31503\afs56\alang1025 \ltrch\fcs0 -\fs56\expnd-2\expndtw-10\lang1036\langfe1033\kerning28\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1036\langfenp1033 \sbasedon0 \snext0 \slink17 \sqformat \spriority10 Title;}{\*\cs17 \additive \rtlch\fcs1 \af31503\afs56 \ltrch\fcs0 -\fs56\expnd-2\expndtw-10\kerning28\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink16 \slocked \spriority10 Title Char;}{\s18\ql \li0\ri0\sa160\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ilvl1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 -\af31507\afs22\alang1025 \ltrch\fcs0 \fs22\expnd3\expndtw15\cf18\lang1036\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1036\langfenp1033 \sbasedon0 \snext0 \slink19 \sqformat \spriority11 Subtitle;}{\*\cs19 \additive \rtlch\fcs1 -\af0\afs22 \ltrch\fcs0 \fs22\expnd3\expndtw15\cf18\dbch\af31505 \sbasedon10 \slink18 \slocked \spriority11 Subtitle Char;}{\s20\qc \li864\ri864\sb200\sa160\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin864\lin864\itap0 \rtlch\fcs1 -\ai\af31507\afs24\alang1025 \ltrch\fcs0 \i\f31506\fs24\cf19\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 \sbasedon0 \snext0 \slink21 \sqformat \spriority29 Quote;}{\*\cs21 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i\cf19 -\sbasedon10 \slink20 \slocked \spriority29 Quote Char;}}{\*\pgptbl {\pgp\ipgp8\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp11\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp13\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp11 -\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp8\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp8\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp7\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp11\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp3\itap0\li0\ri0 -\sb0\sa0}}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Utilisateur de Microsoft Office}{\operator word}{\creatim\yr2018\mo12\dy12\hr12\min36} -{\revtim\yr2018\mo12\dy12\hr12\min36}{\version2}{\edmins0}{\nofpages3}{\nofwords182}{\nofchars1038}{\nofcharsws1218}{\vern95}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} -\paperw11900\paperh16840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect -\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0 -\showxmlerrors1\makebackup\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin360\dgvorigin360\dghshow1\dgvshow1 -\jexpand\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule -\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450} -\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid5638726\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 -\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 -\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang -{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s16\qc \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168\contextualspace \rtlch\fcs1 \af31503\afs56\alang1025 \ltrch\fcs0 -\fs56\expnd-2\expndtw-10\lang1036\langfe1033\kerning28\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 \af31503 \ltrch\fcs0 \hich\af31502\dbch\af31501\loch\f31502 Gutenberg -\par }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 -\af31507 \ltrch\fcs0 \charrsid4728168 -\par }\pard \ltrpar\qc \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \lang1024\langfe1024\noproof\langnp1033 {\*\shppict -{\pict{\*\picprop\shplid1025{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLockAspectRatio}{\sv 1}}{\sp{\sn fLockPosition}{\sv 0}}{\sp{\sn fLockAgainstSelect}{\sv 0}}{\sp{\sn fLockAgainstGrouping}{\sv 0}} -{\sp{\sn pictureGray}{\sv 0}}{\sp{\sn pictureBiLevel}{\sv 0}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn wzName}{\sv Image 2}}{\sp{\sn dhgt}{\sv 251658240}}{\sp{\sn fHidden}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}} -\picscalex133\picscaley133\piccropl0\piccropr0\piccropt0\piccropb0\picw7594\pich8467\picwgoal4305\pichgoal4800\pngblip\bliptag276711534{\*\blipuid 107e486ef6f08100a0e5ef6a660d26cd} -89504e470d0a1a0a0000000d494844520000011f000001400800000000a0e427b300000002624b47440000aa8d23320000000c636d50504a436d703037313200 -f80103eacc609500007b1f49444154785eddbd0db8246575efbb7262040b621cd268219881421328f08bdaa8052a6ac6463897464be2edf104e3638026b9b1c1 -2639910673ce3df468f224d00de6de283dfa24eae921367e80e7f6283d86687a00ad013f426df1626d6a14c3c8901a25a97620e4a9fb5b6ff5deb36766cfcc9e -99de63bcefc3c7ccdefd51b56abdeb5debbffe6bad5fc8e53fc21a5be62af47fc5bf931ffcccafed17fe63c867b11c7689e63f80907eb6f25910c058eeb8f337 -dffcdc1d3b67bfb1f345082b3be6d8d3cf5d10dacf504e3f4bf998dbdef2f0830f7d55c663230ce7684945b61582b15f75c25197ca71cecf748ffd2ce523e3af -8c3e3fab62199ff2b29973b03aae91c5ece71e7f56b6e5fe8994fee081932f585398a59fc1fad9c967c77d7f886cfcf79e73fce4cec7df90a33e2772db93cf7a -127154e5e96776caa8d0abdac5ab0bd11df175e4e563cea76d777eea7e71ffcfe7bd6435773cf7c08fb73c26affac123df9bab3c38574def2a7fe9aa5bbaef94 -6d73ceabe59646b1dd7a6b8fb86ccc17e6477e656d94c1eb24f9b0ad5f9ed61a8d663fc9f863b59e57655095465415b1c4726c714a0e02e51f373cf2579ae747 -5a7fc6d6dccdbd27ac0f5ebeed810d5be5cacb1629c5ecf08c8fdde63ee77e2961ad4bcf7ae609c134cf89fd8e638d911209677e062a74a41f4acb927a968555 -c76b4579ae4a9327a346ad6c8b6b4b3074db795daa912fdd514fca6811da633bbe315176d09dbce3c85df491dc5f08635092661ed52b56bdb8c541bb55f36b75 -5f6a83ca280b9c41dbeab544aabe1a65bf24b62d96255e6d5e7110d0915d47523e79ec89d76bf96e23357ad0aeb8e55a2fa9f6f2bce70dfb65cbaddb76a7e40d -9a52cdfbc28fcbf5bc29a3b6483bc0049550a77aa172476c1d49f9f451865225e8cfdf5cab1de9cdb6a4d9eb364b7edeab64799865de20ef4a37746490456e2b -ef34f2d06ee4116fc64e5badff5fca27cbd341994d52aac7463a939bcc6cbb5c6e555555b2f230efd6c2b0d1f0a45a6153b11cc7721c57ecba235e37906ad758 -a17eeb88694f9e1f31fd51e9488d8db5b0e261cbf7da752bcb6b3ef2094a0d0c8e53b1adb61be4232967353b4b73a7195a526d067ac67bfa19ec330cfb915a47 -483e710507a6abd2319a93e5c3baefd507e62f69d812d7f51acd30cdbb18e0fa286fd4f3969b0fb0e579d349eaf843fd92d4501f3489030d711ea97564e4c3dd -cd1b0e1549d4b0edaaba7b613bf0dc52c96df707931beef5fa6c24f6148b4d6607f84096cdc664c335cb2aa33ae6bad8a447621d11f9f4448234efbb85654e5d -29238eb0e5972a6eaddd1e15f79984fd7eb5e962a29ad28e4bb5dc6b7088051c6292465627ef56c5a9aa59aadb529917e78a8be808c827f4ad5a980f1c072b6c -04513577e74973a20649afea79ae1b04cd5e9827faab7aec3a3ddbeef56ce98c3ae2653d61e355ac347524409b84b36dc54563be60e5e38b2d67bbb79e7bfb1f -cb5b6f5c141d2c462b365d6cbdfe752f78cb2a7ebde3feaf8de56e916fc9d59f4f9abdd9b23c3aebbc42eed95622a67fee334fb86fbd6dae71fae59dbfbdd7de -7c8470a1157f0ce54e9e04ee52cfbb50812c336a9474ebf55aadde1a68a01a77f2969d0fad248fa4cd2feb12c7d249224fcaf8d4b803aeb82b7ee147447fc68d -8f0ed64b6317568a96ec0575cd0ebfbaf5c4eaf37ec3a8c4d6edf2cd7f7cfce9af3e511acb73adf136a9c8ce7fbedfbbe646f9aa58a756d76d686cb3ad3991fe -2547245a5de1c730c0a1c3eec4e505af79af2f8c6db7da33ba14f7dae59255722b41ad396cc92872a5def288cd3a1d9f13ace4551d6925810426223b22367a85 -ed732442b095544bfb0c2c114cc8bf5934082ccbaf7587f32e6462d5fa8e10928957ef46a1354a4b526d10e6071c625ee872b41d011bbda2f6796c9d7af4179c -f1073e71c575bd73f60d908ebff2896fcbce371fb3d63580fdf6d1ce7fd2adf3edf4e2a37a4fd8b7ffd1bdde566056ebac9154d6ed3c23f8cc8ed64dfafbea86 -23b0c156543eb2f6ebff68cdbeefe8b623eb7e5b91d4bdd7d67beedb24a79d75d66b56c9d6d94f3cfd8c95ca8cbcf26c11834acfc9dfc9653bbeb8f6e6e6578e -77d77c60f43e293de1fceda98f5d340788268fea91b7c26b45e5b3b9fc8fcecd733577f36ee679f11ded78ed6ce5bd2ffca7ed3fdafed043271d7bfce972b946 -e98509dfba5a6e96abf46fb3e77de2820d97cdae96d9f153df6fa5fceee859fb99272a77acb070f4e357d23edb56d51fe45138dab7a14830224dbfda6a119ced -7a55590f75afa93f89db38dc9d3cf789c51656967690a37d04eccf4acaa7818dc0779940854b3c8861931b07f39938d69357647987b7e5f990302bcb5be5bca3 -be0e48505ba5c6cf09482a6de9108aad7c1cb682f2198905a4130cf7891973509bd8abe538be8615f32bb28afbf6471ae827c4f1001a819b3b957cc8a78dbc32 -015925cc1db1575c402b281f5fe2cc6fec63ff0eab713e6846003c665bb9c61dcef248a11da00db34cc6876d95795694678906ac0df3ab063a85566a988fbc56 -74ad9c7c46e2b8ce9e5e21b79c0c1b7e8bd8a1978f1c37708ba0bee316b6a453421ef3f241409e97e5e858b7c87d4db02342fa6aee257915d0c3e92fd6bce98b -6ae5e45317bba1d677f7d5c70526882a102e7647d22a616c76bd2ae16f03d18da5cb453c7d7bb1680a70b52d9e93e4a59a2243d68afad12b269fd472777bb27a -c359cd937e1e3af5b83c2f1180697b2fdfba51dc72d65620ac56d9a53b3988903f1aa9c5b2f256292b75816d8d315fa9b552f2c99a92e69ddd0fa628eaf49b36 -e186d5256a5fb8a37a2180f9b548e3ea258414eade8a1a4ed0f0f485435f6cb7d4af896f85a995541b156701ed5f0121ad947c72ab1cd6e7c5a3b73c74067d4c -4dd62cb381165bd51181a606604bdcdca8146615af14341dc08d407a650ff4312bd51c3befda23a753e984d26dc84aba412b251f20553f318fbe5880a3ba63f8 -b7bcbb418dadc2f133fb6f09196180d893558e7cbf1293e671929af49d3873b2b267f7cab5bc66831dad988856463e591e483ba9799cd6a1c99442c49837134b -de0a368524eabca51ed6b2425ea334ab770752cd72523e6dc9f038251e49ecf6e24a5e4e013946b96df365ea16acc85a19f9e0e0d6faa57a9e36f4f86e97aa49 -dcdadb8c660df659cb1c485541243d2985792725f71590a3e7a74ddb69e879479ec7f222d74afca02a21079a061c61392bd94ea922fd54f3402ba4412b249f81 -58018eaf5b4e914e9953885060f11d74d4ebe928765a96b2d11dcd1b87b5b0e99371c7cc94cb79c246ec492fd380154207d86adb4eda32ecd7f25223e8fbedbc -d4eef3bb514dbcea4a111756483e758804690d1f991dd1ce47b1b9d9454b1a88ab2e3efba2cd06c987bd06b2422cb835e4e3d543663f61df7110eb2a83bee41d -b560301c709aa45d915a3eb0d2b6905a336b8572862b211f8c07d6a64306b0532397850b53db259a913ee9ac528ae218fba1e14284fd6d0e63e81b515b6ccf72 -482d4b3365bf3929f2cd6b529630b4541cc8aee1f5116c5a6ba279ecac3aa14991989fa4d1a66c8556423ec403326a40b9f06b83a8c475a7bb5c5c9333563cda -b2bc0249ed678e115f3ba897e001f15e1c6feeb73e08710f4b7e868f6c8ff0b2eba581edf7f351d8b007b96fabd4a592b7fcbcdd40869a205b81b532f2413186 -19587bcdc384068be19fc0e486d51461a2920192a9d6084e89f2db5645e23ece10dc280bd4591c0d5ebb695aee34e2b28fb52aa1476cc541b59f27b64443afcd -dfcb44c1d6202e493d594c7e9896a856423e59eeb8588f3e3ba735acc496b5c8418e04cb6256db71aa8aec8c90448b03ba2e258e32cfcb935e18e7b12df62ebf -38e460534a998b08aa0df2af24518703f1907519eb35b00c79467f3bedb512f2c17e569bd8e62c6fbbb9dfe6fc59e42f876c1610b12cf7a3a814a8d5d05b6bb1 -ad8c140793883f4b076a50462583f0b44b7aeb2dceb89172159aae135998ec246f7449c6d7342def0c356f38f5b522f2e9908031f7d916bf120dc2c662188b3c -06acc2b48d3fe47a1a86633b70766aba77f6586cc3c93b177c83a1d7842ad354c97b6d74302221cf56f5cba5145ee7d4c5b302fc286e0513eb39ec919ecb39ae -abb83df35fb2582d7807031b01628dfd52a824bae5ad8994ba526ec8a82971bdece651a593678e54ed00cd5cdec71cccaba6ac3fdc4107b36bd55d927e10511b -3d747eb7701422582dcecb166777937d97f8bbcefe7dbbc07bfc6660893b0ac4ade60e2763c3ad28e7c5eefc1cc84775a70e4dd5375678808b53e84d48801557 -3043c4adbdaab41cdca2d89ed79b838e0d42cb52b770900f3c1fd72977876c69cda84e7d4d597f30cd6ea782c70b0f37eaa3221a46a52dce1ed7ab340bf9446a -9183c1b088410f7ee9bbf8186cb27e38106e34741a31560dc876ea6bcaf289a35a47b316357dbe544c68040f3f1e43ddcd5d9f3d87a908625c3e47cc9174c8ab -aee519b541ad6ad72b6297ca84f18726ed035cc174e553c6aaa87c081ae238e6f8c576e6a36eab4210ded72d108c9a9635c0e5f13b87753bb807ec2f0b670aab -e3e4412527ba3f6461efe78d53958ffab33870868ad96f542c409b7c54ad87bd404971564d99719d6e755412f089c35b9946bed5520fdfb064d7050eb570624e -7f4d513e65754574997c68bbdc1d6a205ecb809a9b5d88839ce4153887383f267a3fec55c5e2b8bdb21ab7ea088f54cdd1143e76f7eb9a9a7cc0411bb8c1bb2d -276aabc4bc8050b22c50525bc0a1f54876cf6c1caaa0622c90a59a1857ab399954772542f8a9c987bb4c01c122c2e8ee04ed54f7d7b8d1e8ff50aae060986b2b -ea2fe1291f928ce29ee5f6f514ecdab9d7e15bfe239f5f0843e5a13e3e3126ab65d212bef4717d280ca8934e8fe0c47bb9bbaf9cf3410b2929bb04697dbe6438 -2a654322e2a9afa9e94fccde22202563354acc7502fcd486795a116b948feab82976d40df2c6a04b626c4a2baa91e3ef544212400d71cbd298baf9995efcd505 -29c66f6be62199713dd53d50c4167fa84aa519e661103a79b59b7aa13535f5c9814efcaa3de82b38044652406fd35d53d31f922cf14801195642d83db232dc40 -2aba86a541d3b1d32e58aa17f6aa2d346c5a2b23c0cd6b8311b16e2d48f01da6f5c1bb3ee73f4d8da2f6c9a1fd9dfbaf1398941bde3ef7ea0de7daa7def31efb -9eaf743e36fec41fc6afbaec7449c75b9fbaef859fbb7a6adf28967b9ac8c57ff09d677e67ab6c7dbfc819d3fbe8854f9a8ec807a5b67e5023483bc180730433 -9d8ef09f414ac93858516a75bc52a6becae185157b5c6dcdad5a51481db871a75722853195fd850368f2077d8f2ac84ace59d593a0dccd1b9ed389bc342c95c2 -ba974330ecf970c0a6e6c4b177f1ca83c8763c9264c6159afa9acafeb2e4b55ab335f77b9ffe9fdb64a7b46e99f935ff8ba3abce97f7bfe2a28b3e31fba1edaf -bfee94ad4a4abdcf3ff38d26f29ed25a539375cf9cf107e3f3066319fbfb64c91eceb74d49e26a982b5ab0859a77b5cab6d32cb7f2460c552c4a347ef4474465 -930ab0297da77e0c8adb6a5914ae081cbc155853d95ff83c4ac3d4428b9606a2cdb03aec20ad612fafab4b92e037b74601dbc1ded74dec0283f40dfbf76316fd -b65bf65c12cf0af12fca414e514ed3928f8d5d51dba261b56535417f60a4940bc83dadc0fca9128af194fbfbbef74371ee3c1969fe1070cc9c0fd35fd3914fe6 -289e1a5000a9e788b896554dbc3499e4bdeacd663307d368c0d8dce71d0cbbdd5d1962b2f5cb935600bbc1ad4967c568acd3918fd6ab85a1f855abd410cfaefa -9c5681021bba9260c4c93b0222eb72a62d79dfb1a9feb6e83a316ab6da01f2b596d6876c341c7608d7734318c2e4959be400a674134b3dbbe97c74224d1f9ec0 -90d454ddaad404caa5268753f3585b5de2ae5a40ae67b47402062687dbeb6add92652a78ccb26c7faf84588a75d3260a65fdb0b4d38553564a4b887365b8097a -f1d3914f53ca54ac352940526681df9de0409868d4c51d06ad9e5dea7859b08f04deb052aec0f6f0dbc98830b3d2198d3ab8950082a629d0fc1ae15cfa0d1560 -a91a58b60aaa13485745ba22d0aaf9dee9c80740b93d94b0011e3cec25791f1048933a25bdeea414b5878157f2826cc9e71cd54a52098240b505023dbb72d42e -7b45471b93619f2cf5c5fbb59245983e084a41a39be4cdcec0538ccc29c0959558d3910fd69745a3957ab95e73da75dd57308094d094c7f04c9b02f399ace912 -77800303bd5017841fcf777daf52a981e7b3d99ac3f62e249642cd3a99e876ad2c15a712e5ed668bf2829474231d39564232c5674ea9fe6be67ef1ef1d3aa736 -9e79e8827ff8ac44eefa1f7dfd8eb54f7f86ab9f3ddb5ef5ecffb1e69c7b7b5bbeb767c1d6d8dafc5a71be604a0b29f9eafce045d90bdee4089ddac8f6b58e7b -43f8e1a3afbfb82808bbf616f6d539673e78279ece4d1a4c6cb73e77cd7d4fddb1cd7ec7cd87e31f1fe8bdd3117d40f05322c9a21879a08c5d90f83ca812a202 -d2d032a3cb6f5b81d1a7dd5699b4b0d91bea1f66be5b2ed92e079d5f759bd8f73ef1ece43d11fad4c96a12e024b4543dfbe51efad6b45726adb3709153d95f4a -e7f50750275b5803dbec891afe2c65c9c887723fd7aa0e65501fecc543c8827a615aa37ebf5ff71d8703d02e572caf8a55f1e9ee924cce7172f9982207f75bd9 -882671daf592301892195cd13515f9688f230e910669778d3eab463e55e463003d6c099da1e077ed6d4293ae3f54ed69d27b8c7dd3836d60c0d77ea7dfd19fd8 -6136314e8140a4ea40d9abf7db5504e92ba09292fb5a09506391c4a7241f341f32c600e30abd520154958f57e47c1be47fb1217e7b4f339a9114ae1a79c49c43 -a63154d4aaf8956aa7db1d0e6dafbe0b308dc56f82c5d74c3705d6b05a55e25d9766402baa3e533adfb946f2bc8d7e3c52ff4781e801fb0b5331548de0367b1c -70d4b8ed792f5ae034ec342a25f191536412acf3ab11a64d41bdcc0ad125f506b5f06930e854cbd5c0c7c9eeb00b57e8609f5cea94f447ed81b939abea14340a -48975d714c6d0ea03df89eb5a473d883bfd96e9660cf23d2f9553484a4cf166a55281db4867e5e6e28ef95e043bf66382cb9b41132a66805d7f4e4a33c0da756 -e9551d2e3941388088d64240aa71ebde0a343149b1b603524f86d239637f8da4bb79d5c69e157c57086388a72c2edca8a2b5263ed280a3ce1439afdc9aa67cb0 -b375077f1f93590e234913bc185c68737ab760b4ec857fa6b64ddf1fd7212e55526fa56f970dc286a7a3ff69e690e3279c27f83de5bed5a8b9ec34158f9e6115 -28ac2bdd8563baf229d72b71dc2301581de6b075cbd2a94d72bed1925b61685b9e5785ea123b2e84578c98453f12ee3df62a6185bd99da935a66cddf934eeb8b -5bd34e5b1ebded42a715cebb472ba640d3958faf54672d1fed74f34a00f859a9ccdb0714640957653eb298bfbf616f18b8cd067418a36ccaa79ad056101d02a4 -02cc97669851c05a2e3971835ea52b261af3c153940f575a56d8a6450a63e043cc016fe6d8995c3f71d672c2ec263d587112cdb63207fe0257c8337969887576 -bb6559696657d8cb8b99d52b22a829ca871bb2d59a764bda508dce85bd3c85b634ca537ce424414007a8343650351d6c945d366f75e3499332b5d066ab0ee820 -45e38161c9d1c2b0156064ee2ee6a9ca073a7814e4bd019b033e82c287d0a2ea791783dd7233ea6c96f388b35e579d9ee16ebd24f941436a436df96bd610c707 -6af8b23e70395fbacfd74c553e23695351d1cb6004566b8506d00413e7a7cfbea08ecba668697f6b580a346243acfdca8444b5eb0d51c91a806890d1a786d96a -472570e7bd29f787258c25de3c55f9e4de2868e75d4e99a4bf10abc3e26ea3407eca61bcff1a24d2b0f491f402d0536b09ae53888b3868c1d773a5e7d06f41d1 -b815b6ce53b5cf18cfd2c8cd479c3c36156eeaf872f9714dd294b8804e1c5def800500541f4cd612871dd50466b912453496e05ba6ad2d7b7fde54f2cbf3f774 -dbea2b2e97f0f9227f70d7aca3d818aeca4517fb7fb1eaacbf043e93cb6edeb671218658fa0fabdee57896ebfb96fd577bbfe0b444a7198cc171cfb8a1f982f7 -ee985e9e7a3f5735c54740590a4fb4d9c1df736b5dcb981f14aa5fcad96d233f2541b89c24274147aa3ef85eab638c81b64b1cc1d850d069c5b7d734fd1ff576 -40739a1e56666469553fabe5e5915632456909a254c7086d196b8f72dee21db1b5608f13fd53e7400ec332bee8402f99d6fe42f33bb312ac919e9cc85082735f -fbdd0aea3496c74f14973e73a77d6ed5b31ebcfa0f67c69b954075e0b57aa96e6e8eb579fecdab7594c18cac3ff0271de62ba6251f6cc1f692dc206ffff84e73 -45977f50eeda8afd79eac54620277f5c5e75f759b34fca96c361b7bce4abf326c7c8e904b96759c23e1c114d4b3e4861dd1565f7e2cfbe27b954afe79235770a -c362c68fcc2090b1ac1dcbc9f7fc0629bf5b761cf2d58e65f537e7dfac721a3b956ddb0ff9d396f9c6a9c9c792adb75ebeeeceea39a27d5199575591f79d2fd6 -b13f5a374642332fdbfaba2776fadffde81c11c7212e4b5eb3db3b2d79933c7c889fb5ecb74d4d3e229f7ae233d73b1bbe75927e37cff7969a8c66e5b14f7fdc -ec89d76fc77abfe3536bdcbb38e20f6957f0a6bd67b97d78d9377a882f9c9e7cc61f97dbe4cf648be9e8c85afd91f6f80679c49f48e3e1b17ceeb5dfd9fcb8d5 -59bff6901c17de74d21c2cbd45eb5cc87c2bbca6279f5be708402f99fbca1fcd0b88c6c4b7cd9e685aa9b27ec4bfdbd181affcf3e5df3e887bda4dd59e278a1e -2eacf1c372ca417cd421bd747af2f9943bdbde207f77ff3d3534c6dc96539359f995a3ad0d1cc3e317fc588e595d7ae5ea53df2f49a105cbda65935972c5bdbd -44ee5d7c93d62fc9638774d307f1a6a9c967c3fdb3eed5f0e7846cba25d76ed0dbbf58feedfc6376ca1c98f2ddbff63179c1d12fb19efdd8252d2318b5da075c -e399372f7ecd6aeb9f164975f6e2634a9b9627e5037ed13e5f302df9ec20ef70b9c8e6bb7c3cb7b17cfad7c4da7cfb7972fb29c15b77bc40e4ed0f9fc460c15f -3c7efcc83f6d7cb56c976bb658070ac55486afbfffa3bb09c0deb458aa775ef2c4e9cb91f2a14b87771ec8c15ee6effb0c322330aa16b8714c1d6a0e259cc3bc -d7040f4abafcd229fbcd88b62b437e694794ab1c68d1df6f0f40a4e86e629602714b42da07fad483fbfdb4f46783f58273003c5f236643fce22b568de5e6976c -b9c69239ebafad736eb9ec9dfcf4ae47d67dec9d32f335f91bd9c69c34ecf8fe4d1093c2747edaa21735e8073dbf3e7bd55a5b1e3d2cdd58ce9b0f4e9cfb7cb5 -5da61d3171a94232ed3ca9818feae425abd9ea3940f53d27e3e819256483a1b542ee89e9bcbeff723f923e64db778fd0e3453990ae30784699632bbaa6a43fb7 -6f3b65ab9eb55bd4fa6c1c1fcf1f8772ee83627dfce397cddd7ec19a77ca53f592f39de13dd68ea38617c96cdf412b6edfaffa581c4e9fdac3bcec340ac3dbae -3a472e736eba5407112f47090efd3553918f5ee3479f38992b27809cb38ed3bb7aceb61dc73f3afbc4297f39964fca1dddb9ffdc78e72bb66c11f9f257b22d9e -7c4312917b0e70821d25f79fba71d3ed5b37cc7426bbec03a59d7c1732a9dd7ba5fcd92d171599d4155dd3d2ceaac14e991098e49504ce2a0d3453bf0b8b23a1 -b230cfac3274b22a19b04127ae41131ad5ed4ae9009b23296edef13c436b011073ab06624d86603f8952a5563cbf3315fd310ff01cf3dfd3b75273342b2ffb13 -b9fdf54ffe68a3fc4456bfbdd4da945c799a7cf337ffde5e2dc7cf398f7ceb4f3a576d7affa507da1aabdbbcc2b6df7afe35c1fbd66d3cb5bbee9bd7df76b931 -d77fb2e3aafa87e4bf3b82ceaeec9a9a7c9e3e69e1a0a15aff779f1e5f70ddeaeab5ded3b2e9b82766df3c1667d399afd8f60e6ee62979fd9af02ad979d5a307 -928f5c1db7abc7bdec231f7ce767e5fa0be7ae1e7fe2faded5aa53abdff81772f3239b56bd588e3ed01978b8d29b927cccad62178e97d56f92576f913597feee -0ed97ce6cccc25b2c6a5579dfbf9b90f5fe91a80e21179f50fb9c557c84358a1fdafb173f586e84beb84314ebacfcebc442e2ee0a3dfbd6d4e2efc30d11767c2 -ca1aa029c9e7a9ebbefad4e452bf20cebf6c94b77e7b46fef27179845d77f9712f1fdf31b75e2e90da5bb8b76325b9ff4c91cfce0de5ef0f201f6e9d51b16f93 -3b9fd1cf9e6bdc7e6defddb3a8e99c53fdbfe4f207b1f66f3a5cfd38d0fba7249f2f7ff009f34d3ff9a97c47e4bd37c8eae8efd6dff6d64da780231ffbede3e5 -e58df12d625dc24cee2fbd8e50ded9f4afd6abdfdcfe7f36de7ea0eb832cf6efd66d4fd4472fb7ac2f9c7bccc7e55ab1b65e34b7eec12dd6ab7ee71f3ccdc1af -ec9acef93528b9104da1ad0e73f2e6a1893238b298134725bc4b9544ac0907ea3152da1b7bb451602c25354f93dec6fbb906bc44880de6d4a2135756b5753863 -af9df7ca39731b57a0e07d8f6b9992fe644fec4c2d18f0bffa6ff2c86372eae8f18d6c83ab371f7d01fbe2dc9d9f952f3b3363d9fae0ff217ff1fad59bee7f9f -1cff244f7d3c1e3fb4df87bff9aaf5eb4e3df583ade65fc8fa9b65d3b06355b63d01aabdf6a4d9b5c76e9c79eecac33f538a4f33525145baab9557f0765a1011 -48ba8f92217ca99e05b95b7fd9243bc8d4ee409fbae35a2ecc7af3f3a516ae51544678aee3b4b5e152e6f4922ee5abcd96f6b40de9791bc0d15fb1b2b8854b9a -52fcded34bed75f32e0d5161c9d36eb8639ad824b44aad0a13279598c2bc0f56acf4f1bcdc6c48936369df0c0c08c38cb18a6890a859d72c745d38694997de6f -70c6e89b5ccf2a5cfccf49fcf56b42bcf9d797ef38c792b7fd40e4cc1fc9bbc2d59b8927ded391e7cb43162ea35cf7325380bdf3ed7a245fc090b39d8ca94a96 -7660b674d65edd7955e5ab331ff8b3d572e2511c5f33b7ceb677bcf743a76f2d7deb965be5b4fbe4f9eb7e289a615be1351dfbacada28ce634b1d1711e92520e -463d8f1d01e023345303c8991f708f5e0dd3a4914b9029e5722915c0f45a61c0e60bd4d06be323f4843ae5b49555a85776ea56a03ce0e5f6953c8c7b9c927d7e -897c49e4986319db352bbfba41665eb8452eb969edcce96ff95399fd0954efb77c596e7feb0ce90760a19367c5394a1e94ca67e56a3966ef6984c4271750ce2a -cfc6bff97340a22b67e528d593f75b77bdfbf7adf7bee53bce934fc91737531977d60aeb0e1f3f25f9acaeddbf5534f375d28df2873f184bf04959fbcced97bd -ebc15fbd8f7aa5639f4d1f910bd7cdbed47dfbb6f1d50d57be66658fca1bc57a407eb0d70e01dcffad27c67f33be72c3ec1648d3736b3fc9e8c1f53b64c737c6 -72e765b2e6d700d78e1a9ffedbf7cb732ff8b9910f49d37bc47d3e79e5746ed587be21e73e7fa3dcf1df9237df75cabf6f10eb5f7f79eed5c8e163afbdf4b3df -bdb57ce3d6db1f94a35f8c38e71e93f9f4cffc9d2a6c7fe9ac0c67aebc542e3b7bf3dccd2fbd0d819d77f99baf9ce93079f95f65075dd99e7b8b9c880bfee4ee -d9b01511d654f487e8eb7972a71cfd150d1ffe48561d352767dd2072eb1fff44b67cec7a2cf4b146b7ee5df7918adcfd2772c56f9d22297d38c4f9cf72279b68 -f1b2765cf30b5bbde69acde76b1aedb52f35f1e8f8accafd1f9d93575c66fdb35cfb9d8fbe7d9bebbd6a0d1d57d5875a11a92cfad0c3b05dbbbdb50c598931c2 -79b570692aa69f0bb5a5740c70c37205ef6808557c401785a1ed32dbaa0d7f304cac3d119c26154b75c8515a9951eae88c231550330e11473c2859d8e78e5b67 -82731e1c083e9aca9d4d457f54dc7f2277c85164bd7ef7a7b28387faa6ca96add79c4d79e4afbc57d63c75d7a66344bef01ad9f8dd477e4f3ebced2d8edc7092 -64e51b565f5afbe26205da72fe072df9c4a3efd9ba69b51edcad9e3cf9117bdca97df0dcfa29f629a7beeb1332fba6e75c74f9536bfc7f91ad4f1c28fc9f8a6a -4d45cafa21ae052b99ff7b695d79e00cc36b0f280aa06d005372701f231a9205ed721e594c83815f9fd5f27a3aeafad57c81d58c0f35b0bb899dd795991a4b05 -2159ea5536618a51d461457e377650c476a3099373e5ba02ec12cad4f487ece0cd6be41a909dbf79c72699bbb8f2671bae963f9571322b6ffea494cf918ffdf6 -b8fd3a394d6e79cb3b2db9e37f48b25d9ebaffdc47def375f9fa2dc5939e3d8fb1dce75cd68094a158ff9cdd965af5e5df42c1d60d6ed8b14ade353efb5bc77c -6d6ee30b379d79d3adb1583f5d468af1b075686afa935214d1a57b56e8e5fd306f34fb26872325bb828f4c2ac78db220a346d22312497488538df82c6fc6ee20 -2f1b5a7c46411c55f36d42b66a8d717a9a1e0adbb165d7cbe52a762a2e97228b3e1483a8325045a31278e5e3afe9e9cfaa0f8e2fbbecf5bf2f33abcfb970fd8e -1bcf3cbb71117b4bae38e5c5f78873b1dcfe1c9744c6cbcedd74ee1ab841a48156ff57f9cea3728af3d62fca6ffd4f7dccd7de6f7dec3a474e429b1c593b94fb -82cd27bb5fdb69bdff35c7cd88f3d9534fbd60abfbf2ece36f19edd80e00b9e965f6ab343a59e1353df9c855c16737dd74db0621aa3aef5a59bbfac6d7ddfe56 -71bf2437dc28efb1e4936fe320faca6fca1780b4aeecfdae46e6f2e52df2653965fd959769e2e7f6cdfe95d6e7af904b80d48effc9ce47e4eb3795d7584fbb57 -ffe98fcefc2f00b373d6d9ebce9713ef5dfbaf47c9f32c2bf997ffedbd2b2c1bfdf8e9c9672c7f6e5dfcefcd776e5efd8edf5d7b1e86482efde3bb5b7f73de3d -bdfbe505b2e3c1b5d8daf56f92e45d72f3476f57dc6f2c67a21722973db6e5dd306010eb8debafd0cc22eb85677efeaab93fbfec35f28c1cfb86b7c91957af6a -56acb275e6bddf754e3df6d45fe6343ced3dbc2c5b71094d4f3eb449b8435efab6f2157275ba76edccc55be4dcb73e72ddcc8d3b3ea0dee3675412729ab361fb -2a19b44c206fc90f7e4a702fefb8f29bc86ed32f9ff832f9f255867829f2a2a3676f69a4b7fc127f7bfc5d0f7f4e2a971e5f3deb2d8ff7e4baf163739ff8f6f1 -d6f895979d22de7d2bee204e4f3edcca9a3becf38e7bf1ccf97fb4a9b3f655176c91173dc3bef97dfcdc4df2f1aa7abaebe4365fb67cfbb7cd631f8f1f3967c7 -f7e591a35eb351ce9bfdab3fda7ee966820623b88d9fba9b54da0df29b40923b3f72f1fdbed57c5ffd7bf73c0515d672ffefd6334f8da5bbf5a4e7cca49b4ed8 -8d40357d759aaa7c64cd16fbb67beebfebeeed1b375cf7a1b337acfbab1999fdfbfbde41fc2d6f433336138bad95e48f579bb0c0ea9d66ddf70cc8ceaa67b6be -faecb35ef2a3735ff9fb931b7cf4fe7bc5ba5c82557af7579e2eefd930eb3cebc5279ef6770ef8fc8e27e4c9b1f5c0c33f7c72e67bb26da5879c4fed7c2f3e28 -51feaed5ac81cdb4681eabc736f84d3b37bdbd8b51cca6fb8d3a94d4360fea437840bd28b6f2bec115cd8aa84528591dbab81286048c68228ddc359d37f513eb -34a21227083bfdd805775a590471bafac3a9bd216ccaf84ba7cbf5375f77f5b76ec383b3a83b3873ee59fce1ba475f87e26cddf412a325b7cf3e718f6c7ae9c6 -6b39aec61b4e976f9cb90075dcf5fc07c7cf5f73d5a6afc9777f617c921ce37f712349213e02c38d16ca8b1e93f13333f98f9de7243f27f9c1858d3f96997523 -ef876f8dcaf7c975a76378c637e30e9f33c78dec78e8331722827b76ae9e5576a2899ebe72f2af41818ab63ffe12b9a2b04aba3e35fbbe35d7bf51b6ff927ced -cddf78a9bc608d7c42bede7e19398fd5e0213704957b83273709600700c70a3358a7ad3f7afe9cbbe5a6d77cecb854acf7cbbd1b4ffdd337d3ff87739aaefc46 -41e65e2143fdd397c2ca4bce9f59a330c6dc0f9f3a53e64b52c6b29e34e21be51764cb31b2d5fdcb73e4c33f965f91ead98263943e0d74fd19e7e8df1b53c540 -bdc28fecd35716e298b67cccc174d5dc1fdc74dbe8fcf32f74efbde4c9673e098be0399c3cab5e893a89bcfa06f9f56d9bf8e38c6c7f3d4e8faeec324ef82b4d -247ff336f940a3212f78de19f24fcfddf4cb728dbbe597df72e54736ddf753d5947f79b66c94ebb6e2389f2e8ffc923ceb816ddf5f59887e25e463bde30d6927 -7bf95ddf8340291fdc7e99fb1c91a795ca749d09284f86c5f0e772f7357372c17545fae135e7ce38b2e38ee3f8e3edb73ae79f72e333f2bcefea7b3e3c2333e3 -87df7d94bfe36b6f49b4a4499cd9ff77f641d9f91df97579e879f286b528e58aae95908f9c7bee8d5725b7948ebe3c693e7ad1dc43b3e7ca67bfca5d6cdd72c3 -e6adb2c692cdee8ccc9da336bb582f274ec348fd22a7fe67ae90effdef12d67f63fb73e4ac4fe330e111acbd55663e7e41f6265ef3c8f3b7bef996331fedf55c -1cede3777cfbbbb26df3cf9f7cf48a2faabf64d6baf96deea9a7dec5c973f415f829b75e60ddf430c78fdc77da2bc74faf4e00edcdda7a5ee3ca75f2e56f5e78 -0ffaf1ae1d72f97affa5bf78e109f2827714c0c78ebbbf7be696addaac85959df0990b1f7b83fcca8c9cb27a87da9e553f7ff251efefcdf79e206bbe70f6c543 -3a4b3d38fbd02bb5fea222379cb38353e885df946fbc4eb614deb2c8e7de79c727af5ffbdeb99d6b64fcd0aafb5f617d61ed89c2cb7ef4cad532c7ef2f7be3e3 -97aebad56caf674ebc307efeb99bee7c872fb347492a9f6798f7cf9f7cb4220e868fdc7967f732ad603bfa5ba79d45c0b0cea153db2a92320f6e3be1b18a1cf5 -f2e2ceb63c547b722cb76d53ea3469d6075fb775e7cc179f9bfda27c0eeff96324ccbef93bc959f2f9ffc24be79ef5c3c1f62b767cb4f2ba17c92c44a2d3de29 -c7fdfc9d5fe6ae5f64fefbf11bbf42f8757226ce09e6efd893b1ecf8deedee85241f4ec022e90f3f724b9185e02d9b4f93bb65f638b968d5bffdbbe0106d85ff -73dfdf7df164e79ad7a99ecc3d79cba35f24b87d3b67fbbdaf947b4f7a9c1fae688a7945ecb35e33dc67a947f76cb8e9bfeaf59f22c7dc8c646e879c62b175ee -d084e8cd47c92d5fe28733f26d958e255f3d5fbe6fc9f633f102c0d076cad58e64c76c960dabfffaaaf59fb856f5e46bb0c992535779cffb862bff7436c9b350 -665736c3b342f291ab6e9397779c6b8f3f66f5abe7e4d18dcf93357f4a2cfe996bf42ec327874863ccdf3faf7d4445404054afee7ab7c81b36defbe3afbc4b55 -e55b7ae3dfda0894da39ceb9f6edabf5953f101a09ae1abfff39b27aee85ab65eb45b47a5951f599223e56189362dd7ec67ab19e6e5d7de7f34f96bf0af8c177 -e5820f5bb2e3e1b70878fd77dfd9e2a612b28967bedabcfc02c8064e5d825fda7aef5123d920cfd543ee477ae35b1e3845b67ef81af9da470cd2f30ff24be11b -e5d693bf7fa6fc1df6fa979ff3348ef68aae69eb0f7c4ad972c6862b480adfff5ccb7af1e34ffcd667ad67ce02f0bb9073fd25ab044cfaabafa19c598e263c38 -799202fdef2d69bd46d672fa1fffcf72d36f9f0020f2fb2719aaea874e16f9b319932ab564d3acfce686df90874ebdfde5f29d578f375d20bf6d9ff2f3659f75 -22d78db7362063965c4ea5ef5dd11b34c73be1f2eaf6c888bed76e1e8fea73fc45fb1b85905ef517ab1c67ed5fd77e53e465abbf8df6a4d425affaee5f70e7c7 -3d72fba6d51444179b6823a4a17b5eb3f1b1a3c4ddfa8c637decd8ef7c8d236e4537d894f5672cd71d2f1bbeffda39193f6b56ca5ff99b9d1ffec0dd72d70f8a -24e9bf690471d460fcacc2d5231c073833ebfa96dc557fecec0767e4616bd54996dcb9435efdaf626d79fcc1218ec1fcfabcacffb2b5ea2317dd7396dcc3477c -fb44da04bd6245b7d794f8870b205b5a2a4529bc417da6e5515bc752b035e0879b5740c0cb233add143d6941cc26cddbb25a0bd42b6bf51a4942c332e64f2bd2 -469bd2b0cdd0be8529a96dbad5557bd4d6f15bda8d0fbd51bd3fdfde6eca30dfc2c74d597f76acf9cab74eba4b1c5bdcfebbaffaf0fd76f3d13fb6dc93c70906 -77c7063688b8b30fd757637ef4744a4c791bbd045e74dd787dc5fadc5bb4fcf649c5c0f8edea6c8724d929553c8562595d3973cbdfaf5dff2a3ca1d9a767e4c1 -d5e1293f1c3fb0b2fa3365f9381b3ef04e54666e5cfdc2a37f7de2d18d3ff8d7d7debd3d7ca775fa6b3bf2eedb5e4280257715408f6ad8d12602b364ed75f2bb -e30facbff4a837aece08efff2933bf3d7d87dc3b9eb1ecbf575484b561d67aefe637c8c7490ecaff7c1d87d9b577bf60a0667f45d73415530706b9a14b57d061 -d21b042486b97408ddd50eedc706d40e2a5bd56e53a83499130669b1af745d7adeb1ad14970ea1fc4e7a4a56a3be1376db3af1c86c467ad2a741129a1242268f -0cedb01ced9b203ca5fb9aaafe58ebdfec8d4e7df1cbeeeafc387cfc23c7bfe116769a3c317cfbd7df75a33c75c79fd3285b60305cfdd4ecf15857b690c666ff -a61ef4ec173ef4b2f1dfbfd030637e28bfaab1acc8c363774e7e946d93afabd3306e5ce3afb9ef99d557dab7e15f1d3d235f78c7c3a71c2d2b32936891424e55 -3eeb2e0fb6dc77927ccfcd7fd86d9df099db4af5e13f3a72cb43afb87f7576ed4fce956b92f196cf7f4156292fee7642b1edb48758abf3192eba72235bed98f1 -2aeb29b6d629f3acfa932deb81074067bfc14b7a5bd6defbded1a5b3f7df00a0f1dfae1479e8d2fb2efb9a28e2bf926b9af2b9f9fae033d75d38be73db152f68 -3ef0ac8f8efd8d37cbdb0028aebfe463175828cebac4b566e299ce8e075418dcf30f8948d773f45f593defb3af9b3d71b5b5557e0a187b32dea4ae53679b2ecc -ce57bdf5b304aa97dfb071b57cfc92f769c9cecd2fbe40367def3899f9b09cb5b2eecf34cff7405bf2735b55ac9087e5e952855274e2adb959ccc4191ddcc8a2 -846592011b608f6a837c58c91a9231d031eff41906978ccc149ac4cd879dbcdab483116e00d50a76b7598b28d884c70733caef0cea39ddc335fdb58229b029d5 -1768f24f1a0c7e17b74753d14eeed356963eaa156662e0fe403a0cf22ed6b86bda0798aee0dc14732df37a9456b2a851ef269a048c7ad546129be66cfcb737cc -839ece0ed317b72a4989668190cf8d77e4a6e51163497651c479c90ac8695afbcb7afbffca664e3dafd6885ef2ebb775de75c6cbe29d276caac5efbde27d96c3 -082179f006f9ce3ad9fca18ba8ea1eff040f47f7c599a78a3ceb84dfbfd2baeb82874efcf767eb892f67fa8fca236a5376fa261ef935b6e6cb28e39efde02d9f -7abd3dac3a1468b23ebfe6b1ef9dfb69091eb878defaf0792b11694ce91c0c3c864fe3f752a135cafb70c2eafe805214299bc172c3bc95b7d9252e1308a801ab -4f9e34acb2aca3838c927a491b4630c7badb82b868f4a0db40b7c2d2a84b87403666d04e4ab4289df4f867ac41adcb64844e66dbad2a4dd72b954aa07defa7bd -a6a33f5bcff8e2b3cfbe27ba40e65efaf5f8dc6b7e2f92639e7fcf05eb4e7d38f9d26337dfbceeebcf9b3d463e7595ac3fed2af956205fd4478e8acc81706c3b -c63a6a7cf33dffebb9e31348213e24cf3bb6423b135d5f58234fb9c9f8fbdf49e479c0ae7f7ef52deffcc62dae36ef62dd91caf6cb6e7f813f633db3edfadb1e -78cb156f92efddf3ced59d892b39c5136d1a02ef435a36d33513cbcf989586b9a5c74413e6a94efd62c5ed3edd21732f1ea8fd69b512478d88f6edeff18376b9 -cc48e28cceb3cd5eaf96166d2752274d9a79b5e156248db5cc9d816b656c7e5110e50e3bb4276f7a235a4e77aab6197f809d3f600be583bedba9e80f64942702 -6287dbddcbee995d53fdd2eb3f125ebdf6e47fbee7a71713c82b90916e3ffbcb27cbed33ce0740fce4c1b75d08730cb84363837365cbbad19f00a089f17d90e5 -9d46a45f7ec5aad9d7cad36b1fbf537610e28ee5c26be4aef2651bb1c9841aa977ebdb2845d87aae1c3bfed78f3d3694e3ce9f857e147a97e89ccc29aacf54e4 -73e395e3ea2701df7f6bfdcdebcffe1feb4e78f6f653cfb8adff91b7af7d15fcf8383e93e29ed5b463fd467dd379f4ddd8f2f56b779a41455b70a7e7e8ffb7ba -722e0c69c5a5255b608b3f7a997cf778f9264977eb01328ad675b2f63fcbbb65fd6bf59dad9bbef862f7d60b8e3d4b36511a7ffc55ce3dadbbceb87287cc7c5a -2e9c6e4dd861cb8787b5e3aa9b844e366fff78b4f6ba6b872f3ce18fefb12edb9992e0db7eecc97ee31767b697af076e5e0bf5ebc100316c963b3fba91c7bcf9 -27ab64fc069dd4748dfc1bfb50b762e6937cd6357bf70592cdcccdfd7846c6ff20cffea9dc7aebe67be59c2dcf56c5bbf939e7fcf587e4eedf199c296b0694dd -af3f75266d581f756fdeeafccdec24a53f251d3a6cf9802abff996d27066f6d4c762f79cbbb73fe78c4f5ebdf5e2d7c5ff7dede64f9ef1b7d7ffe8b527ffea2d -c78a333e7966dd6f8c8f0db7c8f898b9d1f67711c3fffddb1103d5e0ebdf3633be91dbf96794e8fbcfdb0e5783f5b1370a363d95e7ccc8e8a9adaf969b9f7fee -1f59b5d537fe01bb67b6f9890ffd8bbbd15af5c08b647c81a7ddceeebfe923b6b5ed6af7fcdf6cdc32ddaa9e83b6588bdfa007ea8801cb0955035696ba8d5c8b -6923af95d84136f4cb669aa51a9530eee541d6ee60686ba572ac1057a2e058c8d0e15a0a331ce4ac56cb5b8d41058a383f57671a075c06b412aa85a16d471dab -1c25a6a13a65e2d600273cc50f0dea5603ca1adfc100091621df61ddd19e6f3e0cffb9f03648b8b849d672a41de2f5d4f0817a3e74395871e29bc3abd6e6eaf3 -41381a6501e592cc658a9a5a5e01439ea32b63c8575ef699b99bf77a54277354a90c5a21e06294371ac3a10ca32807e37000365a6dfdca411e50c651a13c887a -668a13071ae2d62019996e37ccdd98e23a0cf9e469cfa6658d36c90f2448436a4c7d8f4929e52c843ba83c4496376c73427367c9281f3418b31357fd68611470 -c2fd56a241294d389f89b6ba2db4ca9cd52c5edc4811b396a83afdb647832a9e80aec88972a6179709362861305eb3e58c7afa7fd5587b8a6d030e553eda16a1 -900030719dc71b597ec25886d4ade4b8251dfd25a55fbd9cf8cbe9a479236967f5baa97c1fd6267363f90b901953e7f0693a3133abf2513d6b6bfb205dfd761e -75f27e1df9641464b814bc8fdcc44ce3a1df7fe8e671c946cb2657c1f662f8a5a66cf5c1e8274ec7993e54f9e88405f3dce888cd105b44540e1c8a90bc206ff8 -94aceb1c38db4f6811c6d556bacc73ed67710bd76f407189294799dc000dca50c02e383bf219fa513d0f8ae1b955a6b00cb4e7b6f6b0eb48ab4fbcc13073f665 -979f3057ae5e6d36f9b6c94155adda291dfb795c66bbedbfb7d9f237e0a1ca0765360121971a704d81f447882aa677380a9477fc7a3d74cbdc76cdcc63aa8c7a -bdb0376ab1732a03463fe82ac8be79a55b49f1bb89ab681cd0f5220a030df88a5dd6440693d5daf07cabae0e92735494281c7b1143ef779aa91f31d4c87c03a3 -63edb086452f473acd5b3b4e4d43830e513e64c51dddea6c9898d2234a2533c7cf87d8079a8f646e30f4db58014ccd40e563598499511d863301473aa9834715 -58834a95fbd551448c476300c2d0cf2b463e1df62ac18a6e60a452aa87dd7c58d6c1b35a1fa57dbc8641dc60a46c051805e0d6e9125ca8658fe7736b064939ec -7568f28900cd13e4a39ae05ac3bac421e538256b94b9f57c60d7396c4a21c193a6c2a412f61923540f3b1d9e69add6a78e50f5a6509f9ece851b9a21949c483d -1bbb52c8a71de678038cb5b2cbe53a83796bf41bebb1e790629ee9408d60103210ac5fd723ccd199692cd38e0c4baed3b2a6333ce490e493a0d23a5a476f3108 -b03fed761d3db1d31193bc1a328c5d0cf6d0a11d3fd75c8a7a4c0a8eeabd50e1302ff1cde912cff7d62ff32186678fbdcdfa36559835552c7483b4073319ed66 -d9ae63e4bbd836dd5eac2ca74709f059b39757fa5469228cf9b9cd4cc5d06accee8841cdba670f7b1d927cca52d658d9245a5c4ea8206a301739e05cef31f32d -1ed1976554b1ccd6b27b1883723ef0d862a800531e4a3ab1b2a2b33d8c7d2813e4330ca590cfc8c99b45fd419b211118b4b654239d62a9632adbb52a471a3a68 -4c57ab9937e2bc3eaae57d2f634ee33c3ac6b8beb68f345573a7e0091dbc7c386ce9578452eb5d95298af0188ad328e91046dc920a6385c5aa31fe344189d85c -445cd561a5e2e264b333ba214386e321dbc6b4d4e014d76acac25fa1bab7eb00a4356890139599364ccf5657ba9176d104c860780d23d45a8826a6c79282d9f4 -0e6c84752e27e8f4cd318f94da981f7fd4e1c8d073fef06dd0c1cb473de6505165760b76993a74b3f9553c718a516e5856b9251c2d1e43e17d0ae0013806f900 -e78602944a8ef3d36836b52394914f65904793b131bd12139be35adee66c8e14996e226a61acfc20ad71996155c7c837228a573150ccd540b4712b6e672609d9 -adb2a11a7c9d4e16b54b5ddfa1bb2deed0e19e62072f1fb85f88c70c101a50201b581682e019d36cb7cb036b94d288e9ec241a18b68759885b6cba219aa57058 -188093e6f6a859d6b1affc8c333d0f26dba08c685c7ea0f2512ba367158c847ed01daa91aab66b54f454f00ed50a79037d5dd44e2a0067fab4344fe23011b49f -57caa9eb3678026de8a0567be28d1fa2253a68f930662aea231eec40841637bc94b1e6ec747618ddb1f30ee9e40a93ba4acd5a13e8a16b3b569cb825bd65bcc3 -3a98f1b057ef76b01e396195b6c4e1c4d249614c4721de72d8349da2648970835693f45baa33c6bb9bc7ee8809c3d4cf1390b12d895fd965dd6622355cca89b3 -caf5b4796e81cbe151f6bdbc6305249c0ecb4c1fac7c181137e883a67292a69ce51db52336c2aa489d189b0d17a51e939aa4536fc604aef05d9852aa03759105 -8f364d3d7afaf8dd8ac2a488a18e45994ce8d4b93adc9993736cebefda66d632534fdbec2466ca3734418685ced45a79c855cd5937f7347ba4d369d54dc4a960 -0a74ee71b649a769a56d0999eb58b8eb87b60e563e1d69ebac5f4adb72f643acb3960317068274ebf8c15d2bd4d1424c4a6ed552c7a795b18be293b4d0de76ad -61c454423f756b5e3c994ca5392fe3ef990d8575a9a04dbc4ad507e707583bcdcae94007bc075de69fe61ef7aa3bd34bf326726af673afea5b34dc6a581d8e0c -8ba65e8154b45b5357ba1d37ad588c08d5371dea3a48f90cc48f992da97df95a98552deca3312d53eadb2d53e3c7e326296375c06ebc3ad6629860bb9bccd265 -75235a02b46a1dcfaf6346cc7d76082916f7116f78003f6a631015c3d04a52ce7849b3c49fedd81e42892aeeb3d1ce32bc054dbefa5a641f6409dd04b17b7a6a -b02b75d665575a6d5a44abaf78187d040e4e3ef4bd2285d9f2b8bd21de491535e8817d3108b055c932dab534915462553b08c2ce42869773ac98288435e87501 -8806b5b235a035825935ca27178311c8c757f9b079f9bc7603bb536b923925ea1f68cf854633d7085e63b1b4cdab48acf90a8fd976a5829a8e6c220d8a368182 -744ea4349b8ece4df594217388c1d841c847dd1dc6b34a8f995e79c2d1d9e7ff21beaa25ad0188579f69a7e836cadd648a9c9364c30cbb890d99f41149922ef2 -4acb352b6d4e1c139c437add2cacc853fde148c2001337543dc932c000bb84254afa08b2dccf876c476d74466c8fbbc061d0c2df28dc43b651c52aa98a75c48c -299456a51291a3277a3e12fb6b48bfcb162aef708965ce55dc9ad86ae1c3959b60597ab8837c829a35cbd01188281220c41efc6d2c4cf1f4aa491a640c30cfc9 -7dea4ff85765bcb06a1cca75669cf38320cc5d58d27de28736a0292e38a4068c133d5fccff324e2ffe82887ac8a79010e7436605b4d954ad5601b5a4a3958abd -dc3df030807d08f020f427717842aea43584d0e019bb5c08ff123beac4dc1e875895cb00eae1d8b2e3a1ce96ae73738d8a491deac280d41312c2b9c285c5e244 -9f2cee27095c4d44a35cdd20efd770231a018880944b6093c4250cc7d4538b03321fa9106355a928afe1331b1f958362501ad272314383d4c30a6cda9830d8d9 -066d00a43b84b57cf910745a1d4fe21e0a1cb3cbeb3cc5063d9c5c370116d6d0abcbe08688432a2ba815c254464c529f63a83a1f09751ac9ee73bcfdf6e28b66 -63d2d99f1d57860413f9e201b70dd8bdb55a37e5c8ac5034decc9bdaa99c9b05c254f970c219936c162e77051a1e2f186978481c038024f58ef1b1db8bb6f272 -45b55cf968d4a54adc31e7b1d3e5b0887365d716aa3b447b22143905b4011beee21355fd611cf08e6e1d8aeffca4c92abd92d4ce16102a8bbdbacb72464d9793 -3f19353ab8858c6fb6dad53e93bddba55639528f10e4a81aabcb95a71ce0fcd3d34e3999785dc6cbebd5d55c4fc30d638e471360bc8d06954726937208f1d872 -e503f6a55f407cadb81eb74893a8d8c0f031d732c05f1cb18d50f8a0af4d1d5b3268e2f9146501bd2a2e88da54e2f6505fba6b25da5b7561b5ea6e1665693062 -dabb1fe6b0a2ab6186fd929603aac3c60580cd3dda4f1968035f10ccbfc2b9601044e2d28645ae8970d5d531d05c106a4d4fa17814d2c7aca3dd4ccda63ba8b5 -4cf930b3c2ec703ba3a7d1807da44427df9f0c451e41230d817ec0acead88fc6d04e122691076d5058b7c9a8461af217446e27ed6bc78385ce58a141c6cc526f -ba6e8591facff5a08e7b882bd4e67910ccd2cd184ca3c1f7158e410a778abd8511efd8a32a57562e5b1821a28900b6827af31af0e13d63bf4d200de44a0f07bd -818304a697231f7c7d2c65a241a9f6094d48cec5eac002a89ac102c065a8057a45d750428e7666bb088edf68c6256e72ea232da902d7d03caca9f9887a3a519b -9021dfbb160cde96605432b7e58c70257322527b1448956123e5aee2200088fa06fc83ae862374a9ad5734f0f3b58c936c523c08fa031d00eaa86276c02653e0 -05ed4fd52f95c250f740a5d5e82c391e7349bd5a8e7cd85a3a845d5d61e51bd7889f9d069ecf282d06449725e91480858e357713b79c60b4310d64bebcdcee07 -e5ccea60a57bea73d715d21f0d270e62b81805cd5cafdc6423e4dd363b3873d1b5b85d0aad5a823661f2bc514a37df8470c5336e10d80f7ea3d2f87872cd02ac -241f64c3c242b9d56906c82bb3b7cb8257801754a890ae40039ee5ac65c807764f537701471253b3e30692d01e615e93fbd1af082422e6d02d13fb319191ef8c -485d3054a681474085445e6957304dc02075c4d5005825eb35d961e1e2fa89c4f56dcf216ee88558e25a2d152f2bd51a56b7ea86435e88548a10b582a7c5dd13 -e14725db757190d5b480a9f2fc7a118813ee1838509fa45c29ea97ca117e2a1e227847669288e04f3801cb5a07900fdfc3b6d2cf8a794c0508de579434e7282e -fa532b46e673b06669e247991737edae450455654448604baf518f4b1d3de7da5871231f4de5ccdb1c9dccbcb0fa8e26b35af9a0df031a2cb33dd3c48bec6a99 -6f704afa13f25db19de247250a5e02c476aba8446940680a4c89a13284d96ee66b8e84330205aaf6fbaa386cd284ed6d41a8e2b55d120ccb4bb21e507fe8fdad -e16fcfb26098aa883496e6df32daaf84bf91823e7a26c56daf9f97da9d52834c4fa2f8b26f53b00ce255c7b656304ff532fb4f11ac489317b11112625b586da7 -4704ae0d9221f092df413d2bf55050078045bc670f975a3b70b33aea55201f02d4018e68d3a805ecb1888ec9018fad57621777649871054ed0e58a38e5463939 -9791c9285611d8b2b0c503c967a8b79e61fe517bb60b1b0c308bdd561d6496da9008ec81d63c2a4214bfd608691febc58d124f078b69b7a4d4b4c056bb880bef -37b1b1542dcc3a7f2db806903616565d47ee02ec3420d669ab70e9a4963162514eec9e873e498fac6061023d617279047412f451f1a69a5ecd56c62587035fa1 -356d464dcb4a89b2badd2187491e11f00820869d8f958603586498f6bf0e241fd7ee776963a9dba0572a8f069d623f743c4817fa07bbca25997d06b457f5c352 -955c97a74a16711588ab2201ac0c8e3b42325e0ef08a2363b6a3f9a05d73e2b9e92e8f166dd404f288b47c296f94b36ab7c54e537589fc0174703e8907a6fb47 -99b044af04e8b0cac9fab37bf9dcd82e6543344e99e4ca2aafe36d0fec4aaf44ea1a89d0295f214bcd2e34f4991f681d403e5cb039b5b8b55ae17d1257f15fc8 -25782e38d55c78d9a409ab4ed6710909d00097e403e22933c2bb4b46bce525c07d1a7be7a35288d145113be4f87811300590df64a57697a33a61f61ca6a2de8f -750084eb565b3cf606ba966583aee47df354ba1a62b0034df66b30701b74a7c7f47a21ef490056230b0facd4c425219ee17b33dfe3d26213b52a029b62d17d5c -23f78031d9fee56342e3222d593537c243a2b4286f36f46055958a3083dc0edb390d3d02765d5a0210817ac20bc75ed69b4d70aabc865893924621045275e463 -149154df4292aae3b0bd026ddc8a5b0780241c3b0dc51fb1ce854147e035b329ca7a45182970004ff34c1045d0d996f412f5ae3c1ccb929dc420afe49ecce5e4 -5d972c6f3fb6716d41ac8c80cad0fd7992fb3fe7f7231f4e61bd5ba24b55189dd4065bb79ea5dd721912819ac918820993cc557af42ac611f3d457c332f29078 -e28c1ae0af6d675452a682469ddc5c533de9fa280f27904c673e34cb1dc00828c17ec8e13f6c2bcf817f484de0351779d33c23aa203996672555e506630c46a9 -d5f238a7ea52e5f655405c4eeac10d86efa2e9953ad76012d6a1d5a8a9bd76ba01790eb5a5a4c8b99f79edddc7fff7291fae02fc453797f90875cb311b5094c5 -f6ec7edf66c245dee7a78efeba41ee61c20b708613df6350f239e2c08682bc44388fbca08d11e3c3f6cd2ba3bc3bb9b204c19b4738705509d91e7973404b5f8a -2d3407cda7f29f05782be38968588ef2e15383a48154c2aa0ff4f61909d6933a3688cf77d4a98f6ad2455e5d5b394a7817a4a995304314a2f9693e1904e54023 -e4f7ad3f43d4c1f85d0b92d5848c5afda466197750d3bc6afecc99dd906a80ef8147af14438e159033756dc372d2f147ba4543763b09e436a0204f3402fc4066 -e800baa002825ca56a810b8012912f42774a8a8f38dc4ac466c66f66ee01308aeab1fe6748709adb5acb43226994db9d2e0946e875aa1e1e5d90c1cb2a6c2fae -1f10c81c1890040064352ce2821513a96182f6bfc1f6291fae0cf9149b4b6fa078ca230eb20e5c3fedc51791b018e9c9aeb03c594bf5bccc69cdc906a132e6f1 -a23e84147e1bd033cb6c361e7dc4fb6c7fe4d3a526c3b868e66c324099693dde80a59743442090246151053d468e701473f5192b0c0d451eea14a42dcc587d00 -cb06901673320ced98dc2cd63710a017609701ceb44574a61ad7c6e9202165ab806cc0130b8162eda4c9f1b1df1db62ff9f4e1ec20e5de623042034e8d8d7906 -4825e31032ee5d58680fc029481617c3038234a8802be2ed549c3a79843e7d8dd54344d1eb5c30140d4c6bdb5c5a4664a5d9c1416ab00eac4a356f8424bb12f0 -527832f43cee697b768ac3354516f222fde680ff0743af9362e3780fa75c53da586f222c8acfd847a5b4239e559b8c64c5e740f3f434c42c056c3e04846df3b8 -c8451efcdea2da4b3eaa25313ae2279e1ee80bd6bd208bb635f7a6a535a802d6a46d10fa16bf70f0bc9c760bf350f181a83842cb7e8707647826e05c75dd8858 -2dcdded7d5ed453e43158caa9f0a155ea69f8d906a9e0db28642856001dac7a4937991ba5f1a914e16ce74c257240de2b17ecac98d3bd493e6a8d4c485d79898 -204ff3708a9a457cbe62d1e6c8c8bc768d8cb57443a702ecd177c427d9bb3f055a427fba4e77c8479281d43752cc57dc04a9161eb0a7dfa5a068877b0d09a773 -7cf71c48b366db3ece2207705a227857987042616dd6fc91af1b33c6c30f5dc2dd1c94886cb3215bea0e0bd5b1c684532818e31e37c268a8bc1025a9f8d2687b -046245db4dbe9bff463c72427b6a5b2852010ec3af21441c967026896879bf7ef5302e796a233491ed9a282f729d8c932fa0524f3ad5c4c734a07c9869dc897d -8a684ff9645d074994945c3c7ff0ea9b3bfcb082a3e1e8b16e4228334609b5afeb1ca252b727d5b60615cdea500fbc4ec1f0ad6192dcd889fdb6a27ed034d56d -7225044c24f565d4b058a99f3ab4186da9c79779cd34ade8a8593011523365c80668183e812e2fc4b0a4ca80869ad50cdb51ad546a7415354910905f4a1010e0 -6347e2ace42928443612eb6894c467f098a5cf9db027618414eea90ed33666701f22da433ee091d0237d49223d05cc2a74930d51ca52c7a45e000b6dc22ef389 -ca74cbabd58194940184375422d9a9ee50669748b4621c1cbb31749473a1a008f41d765d133cb049a8397902ea2940ec0874db29b1c5f140f873bfac69acc0cf -4be50a8aa788864a08f974d103f552494b429e8a61f05b75a2760d80738fbeadc374688f2a08886faf965b1dbf8d6f6df26c358d8fd50153ea74a87915329efb -ada15f2c9f2c210185fe52cc175af32c6d1542a49bcb8eb322b4f0d486e8dee31b35b3c37d268ee393b651930cb0997a1e2c6490fcc2fb16b8395c499f474654 -35729d5259f1523243cc809b44173aed0010a2d870e08d208cb8049e8cdc0e1d395a3ac300bf510f0bd00452ce0a00f4ca0e7b54c10b953935845c0d8d2d82c0 -f2864327d134074f1bc49aa36f085b4b63688ca6e795ec28d52b22035da05a7584aafedc126bb17cc837a97eb4d41786bb35ff862c2d0130d80c7d55f130bca3 -ec0c2ccc509d1a388573a173057647236cf6bbd6285702735af4c85b618ccb657e1ce27d74705a478997f51ce49b928b275701a9d9e868839a010e74048ea2c5 -44e5b888d5546a7882bcbba5e57441a6fcd798eb4009e198414e28ebce18a8f98d1ca7030d4b7d54af53891ac3d81af9b05d5cafd5e5bd59bd3a34351eb9dbe8 -78e4e987916abb1ea50a77589801d26b07900f968e6a11ce8c0eac944591ad3277fbe809b128c78b332cf990a2387dd8d2ec012e1c97d857d70e948e40297207 -994d943db01cc4847fd857d2b6c9265221008c1ce33d067d1d8155d52106e631681a30d661735e974a1693bfa1b2b0cb6e886a651bb9220e2a17740313cab183 -311d1565d1728391ebb529371480ea72d9d1c02acaba03a8f83ab797fbc8583c74dc66ae31b1db645ecb42308fdb64324120f82d5805fa80f75e13fdc1fb83c1 -a35f4b6909a0d2e2d7e2cf24f876ba3fb8b71ee96106752047bc433dcc1a95b2d878298a7330be81c393b0db307252b65b6de090ca248d8c31ecf0411ad5b213 -471530e4dc89e0cc1b01795154d2d873e0a10f7c4fe2a8a3a8a3bf38bd99f338cc53f0796587b36b7aba53f0a5faec26810391696a7b40ec5bab8569a8f45e3e -2e4dea759e96820459366cc649a5a10f99ecb53a51a592622ce882ea3f5a47bde6d244aa85fde59ab63ae6a836d05ab1f8f81ea68c835bbd402ebb5df287ae02 -aeed061fcc9de8fe1e182fdbb778323d158fce19b4a4a6fe4f586b04a03690cec08a93d0f8cad85c148668a33c8c8a8414a91c0dbf489db54df251f5278a7808 -76b95fb3495ef0bcf013b9aca1c6336695635c41988e8c63a33c831f1080982999ba619c6814b72a3a618dcf4fb3ac4530ca43d27be85bb01aa0d9eb118bcb82 -61551f4d5a903ff8f23dd7bc7cda9a30d26b47a20081bb56c6d3c6e934fb23f78256c92b78c503dc7bac55ace702564ffb03f0b601a27379307d1f37a78ad394 -3870e20b1f96f981059831c2b8a150f8d09d5ca1229631ba88578f875ab54f9a90978166d9b59a06737c2af5bd24536190eb1d53b8d203cf4c422618190dd44c -33e5e04514a44794d576eb95c2e4e431bc9aa4cc654356e84357543e5057da9a4389ad7a8a3361e24cf0fdbd5dc5897cba4a9831b2df13b606c860628e82a35c -79059c97f29162c121e06173c775d58a50add788b9894a0e8aeab86ab8f6d00d4850f1b434ae20ec991ce86c058e163e145c3a0ed5de60a121c3e38ef0e17d27 -2da1a011fc4be5ca70e6f5712fa09a69039c96d19f4e89b34c7320d900f059454c665a3f452f921638a80443579b604324f3952a85b7d62f917b81ab50a90c7c -828b56a547e086670481132f819d4a98087da7f0421756219fc1442c38a28b0cb3fea68d235bae67f8f8ba6b394b16b65ea20c13f5dcbae63dbe8e9651f62882 -0481caa433d420c7ede1bbf81c3a7d8b6444ac5fdd4a0c67ac1a28b3b7d10576d79f0643f2136aa135cd0e2682f3c947730ce3346a6e36ad912ad41a6e7d4564 -d217c40b244d8a065c1c057a16a977a2c94993696186a8e338954e92d6bd124fa851a2d241ea15ababdbbde20163711e6ad239a8a4cac247e114becacc062996 -910fd3d98dcc08db768f47511d38ec3c32bc1560f9b467ea860af9b6f419f3ad7d53ed56259cd10a9e16664573a975afcae9eeb4021e781bd72381c2aa45826a -99705df993b2acdc0c2554f056073bc28f564e218771cb107df44c87ec41215c500a18f099957a2a0905ef2953e0d1298f1c10af4a2da70ad818422e8a9899fb -54e62af75e69ab231b927b02aa6eb26f9b154ae6bb841a1c277a0c35a4c5e9ce35851eb11e6f92ea003ee36ef2a9958c948a32d0450be0b296a7f83803bb7096 -f5f76cf1267764ae955b1b1a73a49e04e155acc7d4002d0a1cb7068703361707bf0a9db30780823544b78bf40c66b23e885d635694ea44854ed3f0a6866eca6e -c19a30c34a060e54a2811712ba963484c77a7105789249a7db889c6198874dfa98b07ab4a15072c750f324641400e1c99e2edc510bc7be5d1ea430a77d1fae9b -7ab9285084ae0f5c45eed96b25ea440105f5909d2cd59f502f994534b89b78f84a7e406e77c2316d4eea2203b44619a47ada24187dbc22ddfdde20b1b0bc1df6 -6ab3ecf899e7b6f832db44b2d0c412274d071c247a2f99062138ccb0e0bdb0aff2c157c4a1ea1517e2a6d42fa13f144f7a243880573d35fa76cb3c5875547ca2 -2b6205987cb61d3258d7b4bc6bf2459a8a84484c2a92d8832b81435483d6a78bd0cb50b6b537c300283647faa8be7e328a4ad92a7e82d63cb2d4c6163aa4f2f1 -8a3393ccf51e916cc68e1f128701e4b100cccd69c981660651e7ccca2b7ceabea286f50135cc7a728283549c2acaa865166c358d0795ccd924bef28b6793018c -642991936464f3757f52173724f1aed7458a7308facab03e8a9f3aa4b738dd7b35aecdae78590c90d4e6cb38dcb1e5d588b34ab3a445c0a31174cd4af0161406 -8a0013a9b8cb47b576ababc164c2831d1980134f083b8902a15d2482d1799e25a133026a202a0a66e7131bc867a07ea62944de1329c2ea288857c0e13d45e8d5 -05521334e02f092e454b0d65aac94a5230554d3d0325d4ec4a803febf17556292117430e8c77289f000e07c10047b27117d2612fa56eb7cac5c04aa3df91e680 -6090373b70581b005825bf4339940ccb6489791e3abd58b586eddad3dd830de310d0920b6d2fd0c1cd51a5b634f64523888121a05950186beda65bc721d03341 -fd762d3bca5018b06876b3ce1d49e0fc412ec54c59010006c29a602fc82755a74ae15873d02e5a00dee82bbeb99e197ac6aaed31213cf099292de9c3df36755a -ec815108a41393f76ff9658e039f27ca436ce5fe8008a9e88934f175b4be38d20c1f46497fa4fe163b8dd39e79e8dc590c55b59a4234aa96ddb6db2283adf944 -bd30ea27015fd922d5beb27e20ea2b8491f66ba62b8781c134b58d32f6502c4a9ff0ec496e56ec6e14d57d7cd1c052aa00ba5bea9174a2304df77a45fbe7b0ba -16870c1b123bdde406cda7cdfb879074f7144f8adaa45a4daea74dbf207a650aa8128af0341b049866b7288cdcb11a2dfe1fa25ca3001435e82bb18c21efad8e -4db8822a4c0209f5238dc9c483d5b9c1bad4cab5aab8b945e960a78931aa8e00a8914f577ad0e727ee071e40484caba1778ccfaec749b3841301999518901632 -66570ca4db18b62cd053220efe9354350f838730cc3a4d8f77a9bdab5a29658e969e130989082f50d6104a0750612087e604789fc887506f8f93bd00064d7a42 -676d0220ab4015214c8dcd497593a8ae825500487546304b238c751280c8d75a194f8f5e0aa5910d898c429be2d3f904bfe842361c0ea920299e1b001ab89afe -c9d4a4f6bd1a086997760158a501b30ca46f60392e04f938a61eaa03cd7a8004146d43d1fc619d976918457e8c928c006709d71a97cb4c0837ec43b511e93068 -83e5f39ad46af70592893edf529276a0b8aafba1c0a99ef12552531a144cf427728c5ddf6dc1e4222f6bb4666111807304e8d1a5dd0d6afae91a849130afe7dd -542bd9e2a0ef86f873101afa8ed368e00a3a50e1012f8cba86505f544c85433a7ff6a275e06c83660e7ccc6a3781959b6a71b272dd4135463c2a7d7b211f85c8 -1ad452395cb5f2d140943b01eeb7d6e9f20f181b3a95724e286616992f64d74c3c5b48fd75a5dae388a7d2a36da52199eaeaf8361b46f38acaf957d283be13fd -d1ab5d005317441119976097a3a4bfd032e308ec556d6cc304ae248209ad03003135296d765dbd410ed3f0d9f53f43a7cb19d5d4b4b84a283621a07a1a2a9ef9 -c2380d3d4035c03a0af944d4e0a64d463765387a5658a9b48350e9740672e59910c776ba5dea1c38719bf037e1d9681d7382e130dfc9a901eee1c082e2ecd5f3 -54497d18744e1a3d4d62e3e70162d7838c3f40579c5f616075424a39f53cd49a752e52f7570f2f45157bd7e24e14a3d87d6176a018912b2e5662b29ab0e1321a -0154c09e474e4b7b3cc0db2960c31299dd88726e007b18c93825bc595d033628b1294b9b909835302c444207dfa8191c4b7e96e231a71e104fb9c201a0c1763e -e4ed4479d546de0260a70c577ac3764f4fb0b29640a996e0b4f3fc860877e4e12572ef4d1ea361dc91da348f9ba23a979f556ba1cdc9412100f95ab3d1f9edc0 -a69b5c3586122c032688a62a1ff08049f0be4840f3b673e147243a95ab6c6c8f59a66a74846b8f17a88b323988089ab6004f178764770f7f1deb43b11af895ee -5f103dae21510dd43f4c3283fc05171d4089848cd9711535e62934b104d88aa848c14ce3c2c61431f385808ead26ec0ce974ecc8522a7ad4a9537869e2235242 -b07ed557a9d1c1413d5acf33541c656e90d134fc49cd21d4ec5409793809369b7121ec0c2c30271d4c2a1c0103e4c367ed19b36377f66ed000b6ad59eee2d670 -9971691ac0ffb50c5202e2190632d221c91dcf8617e174b5d29b3167a9474f478d0d798238ccba0cf942d7bc7c38d3d41b429d34e4447ff4af0821c8b488dcea -7a6462acbee625b4da0c41f2d5837e33a969b52639268c67e468d309b67c29c15141361c376929880d895ee51ba9642a4ae46293ea23d55e65a54a0d0192e0f6 -f89939fb143e5512891e620eb811f289607aef6e66948646fe73f755c58d4ad4d819e928b0c4ce267ddd67d77baed65c9a9a0217624900fbd101ac2835836a26 -fd1a0f27213ac47599178f29a81c72d04ddcd4a2ae8b78cce043ad009080563f001764faad26c92c8e438e29e302c0b4f2e1fe0ce33a9e3629b4a6032c4121b5 -f974306f9c33da98e8dee809a5f7e81d4cbe08b603f11c063dd4c4ab0733b2e581225350d305d5248e8c14ecd3150ffabc42f33ebaabe6fd9fc5c2407b76038a -f4669a98ba8c24a759d51ac1c3504691a1a9e178b844f671a8a52844c23cf38116cdd9d2b521c9415334859091522fb8e3f90deafb6d9a6a4cbed7d0324c629d -2f2321036803deaca6c69741dd8a879c5461a671e8443eecc47a346ac42915792411e3b680a1f0e61e274f8d7f3b7a4681dbf19c741167bb8324230da57e0cc6 -bc0c9c2bed1e4d9d141ae2ad38f4f3f94afd1c8010c326584a3edad569b7454a1215355aa823ca1525e9c460833c373ec7f76dfe47e513a5ea9c2538aecc3f4b -7834da8887f235d50d2e00778c5580451c24b834c33aa525c5aa140e32d5f3fc3fa80e88021a318a5daff785fad526c07bcf195195a8f2c9fd4cfb30815ddb2e -074024be5721d42b8e181295e8b156c593ac959ee65a3191d4d5bb090f817d03f5453847e8db51d1c009f844716dadb62173a589fe62370d515d6e7a49fdd95d -3afc4d111ced3ca28fd89c4d104b489897d210a7b55322375cd7898cda6e1eefaadbb013608f0e866024b4d4d0a6079163ac8e8667ba6287cd33ac9bc686ba28 -48d1eb3244a838a0b6524f1510fa76991257e1a81a1063e55dde0c173e2be33168462c4200906c7a25883ec0f85c23b7d617a7ea10e69440a2e06a6bd56a1e8c -721904e45fb097f5a4e9424e246598c0d7021e0809fb079a36e21c9c2469cd35f1e8db4bebcf9ef2211daa1c28d0bfae39bb4b760c0349b1169f5a5d4d9d9b2a -34c016e58f55213e56fd18ba3d83ca695f83ead8a11619b348ef988763fca06199960a859d0b0bfd5144407359f0c434cc0075a694ac014422600fc55ea43712 -232db54a41f3219e9f91fbe9da366529f3c70cfd2e14d30b0de65da5bd808abe1a28559f1490a64d06e5aa02333d8b87de53364882fb4011c9eedb261bb9fd65 -c9c7845b9a8e24c706ac2bb55a7560c54c6ad7ae4809794df5ca707b4af021f1e71b64310749c3ae716e490f87bfc746d618851b2b4e4a75b459dd326976f54c -f0438b3c86769b00ea76b53ac704da14a8546c9b3770f9452514f016407e576f26b3f1517a06fd5697d7d52ca2bea446eb5787f0460f2b2bc1f9d45469420d1a -f70028dfaf0c4855357dde0e12634afd2a984b6801e652765f4bda9f452fe1f515b53db0b15a585f87d38a8342b73fc645019f6060dc08ba819532f88a7427c1 -a7c5e3f30109a281ade06cf1cd2a1ea302593221f783e67b9aa8503914a7072088ba01347aa9f4a9d4653fd6341b813f92245a86a337cfb32a530ea34e03413f -6d50544f0841c9f51407a4160ff6949be701c2e003e8721a1d95b2019f820e4f362ec5f0676232fda447baec84cad22da70e241f05de137c3575b9313b88889d -4a5a2175f1851d89ebd0fe405f9c36c4779ad1d4d20ea74ed6c4e88027457e8d2279255599cb9ea42f324d5f68e892f8008a4a48e0af5ad38ad7bee07d56fa91 -91559f8842da91e03f14a613324c5e4b0716cd86f034fb2449951d6ba834033248c5a2cc11e74129d031fc2155c98c3042c16275a1a9e284df3e0233269ea4bb -450a4061ca1e965807924f8ca212e02a525a8847d1091bf014e35b95a8a51c1b757b88780b0e66331bd64b18ee80e6879d92463ff363ec15c6d035ef25f0d8b2 -6e3a69b355d46541ce344bcb23b4dd8b56306127dbd4b83aa46855f9ebbcb0960ead96e1677964bdb5c8aaa6d7d719004d1b2192e1a10d81093d5160d28c23d2 -0454a5e520036054a4bfc8c98e74bff5384fabca48d47d7ef0f2892995697a6d7563798c23e4a0c7015fc7414e97842ec1b33a5274af4953359910943816a1f6 -68493fc72ce17bdbf047f49a0b8009735bac9105ab6a40f70cfd6d91392cd8e230ec70dfe83451f44884f7ed3b96139be0c0c8a7920d2a0dad7ecb4b8394ca26 -68e302f0055d711e85c09a87182c87af867cd7ae652429b1fa2d2d4d0570c6191cc0bee7e171508c90a2ad5f76d0f219964ba3c4f6076a605cf52bdac04a44d2 -a88ae90569ca27a11383c365a94db511658215c590e1f268c650e20a3ce6827a931b4ea752ca277e2a008edbc36f348251ba944a864dc3ceeb0664f1d95fb4da -300736a3acd9136024bc02081f0476447ca19e1ece2fb598568f8922b0ec3887e6413ee807383d3da889600df4a4e2c8f30b03d45304a0911191ab7146095134 -cee025b5671ffea1792d1f8c06d45cba60fab80d16ad43aa1c1738ed459b67c4435d11de8433f4fc34a3628e1b3145d43dcf282b6e6c6cc31b708de268328e85 -c928ae44f1da4a7b08a1d29c4ba635224234ee91a7ee38edc8cc718f6fe241aa8413eba80c5ba690a7dbe9b76c5536002a69a1a535821c857e0a73cfea96bb28 -8c627c0a675b49c2aec2171a8df82920249a16d98976aa6c5b2681a3766d8965f01f829d250a5731a87edba220cfa1fece86b856cd7a36c55cda2f0cb62ef0c6 -88ef24fdab9939be9a165b462e5df02bfd484c15c835b2d5fda5d6c2dcfa24c0ede9a36cc06037c8abb124ba183fc4d7d23b81ca1b3266939c31cfbdc7853ac6 -626bfb76e2af7ebfa9612c85322d108236d38c2d4536b452a358aeedd89374b4c6bd1e1eb99ea556b9d20b7a117fc473065048b5ed671b03b43ffbacf7b287f0 -4630d57c202f94973a0a9aaef17b85e731177c5caa144d0628f1b306239b50722d0335c7a7d94549c3a118878a9bd023eed0f0adf8398584c52e33af85e74d1c -a59e8c125b26f231c3631413ac45f39b85e834c0dae0cf61c638b3c9c847eda802a767a0c087db0a6df2fd2c8a7b8b640cff6a3921febb2ad40835862f4c2633 -a8a6f50a193da89043ad37e28980aaa8cfa8b25f6215e717e1c81e1bb0a8e4739a398846c50db58646ed077b5aa16203db8fcca6ed282b93383b28158eaa5e1d -0d68a970d7226db695adad78d163bd6aedf962be6fd293c789804934a9335999a63246fcebc246c08cceffbcd430a0b1967e11c2e3028528731dfcd0d466a043 -4e5d2be4145e681567188bed5ec9b5185c3505848c66339000b2d2a8930055e636156cf04c25541cd430d49632d093f37d4ff3a49e5e5f69355c28847780d581 -a1af601f426c0f757c38b46a2b9a9aa721adacbd2ee63fbf6b5022a28a7623042783713fc1dfd222d59ef5f1f5783160453575271581c53d69af2d5048053d27 -6d36f90a28efbd2aa9e77c38ca32be8e22e63604a130a042870e4c21a4b3ae900863718d1343c787e18d1873a65ddf30e9201084375ed0a6ec1089d0054499c9 -54b9125b4c32c80b0f6ae10ffbf07f4cdb46529700fc4ab4aae27070617a5fa67308763351ac3841c194b3045db7488fb1466d68a8fcaa26e5eaa8d9a43e279d -24db329c057d1159f3c9f7b3635a60a793bc246fa7ee7f346a54538edc0ef7aa1f38c43fa54924db41598774efd77680c30cca268c295038ce4ac2673bd01a54 -a5eda64a79360b0682c10c386b49042372700d5870f4f1a086048c483b534aa4cd0e88c7f6b196960ff012dd09f0f9514f834b446a7a4da847a2408d49aaad86 -87d0f779dee8a68960cdeac1b1e3d2aa7605af7a44b790ce02ce3cdfb757d96093e568b39c6ad1706cb28251a5479dfc7c3c6128aec85a89e10a916929178aac -e50ad5368455e4072d9bd6094509aa22d70b3d19941e034588bd4a2eb5628e29423bb63b917d4719fce4aad587d472bb25bd9f7d9def09ad3cb47a4a1d7f73c6 -92e9ca34bba515d62335a8848013a7b389180d815b17a43fbd07da3a526484596ff4b4c55df174fa93238c86622ac106ae80e6e19dd1421e437f4e1acd49e166 -2a6f4f17595af52d914fa662a4300c8f9bb30db46568d1bfb4a331080197e3682712435931592db3a04ec20c8aa0466076f40c351d38013170d415dd05a143db -4c3c185717acddfcbbf5fffb8c2f4c491271a3c93c55f4cf965e1f2c6ddd5814234197328d6434169e6053184763a33dc364d2d2b83e391fc5a5588651cb2a92 -ca80c2e689593d5c3c7732f9447f52eb11c473bcb0ef7481f0a9d02807f1e919892b5c5715d09ee3d01360cf686f4e1bdf3d800f6a6a4109a613cb5865be468b -40f116289e46a8ca1950ff4ab354204c04a9893daa2b1f56ef4eab809758fb948f8a1ecb61aad74c1655592d5a71458edfb4c1884de26880c9a52b5b71a4662d -fd8e96a50f49c3d686a31e1e86567fedfb4ac2a22bbd5e453a9fc3c0a439b109db8b9561f3da393b7672a0d2c58ca5bd4ff848fee59b110c26b645af2d32a454 -d86bfebbae3c573dc154603cb979a605ec06686a768ab3a971858a46ad03b52e58ec3ca81950483d7a2da03828f99817374c67d49e66494c232360081a671917 -9d126b7ed757f1cc6f2eda7faac936c92d3a8448bbdee0585533c8a2ab927e56aaed71089c0b66a94ad36f35b35d5d43683b62c7e449f5865845b5bb99ba57ac -4ea425578d51d662a703c101fb70868e28cce581b02072a0a610728a4fef5bf8b31c8aece90e237e94dc8fec0938329d2960c75c9ff97202a6a50dd0fee3f758 -c305e35a9207e78f009234331c2a8b92e4326003510c6d7f0a6d3648e6c898ec0e0108b5c3355a101a74979f4c4e08137a640c3a308b3e5299c2d73dc4a0a101 -716a082a48d251dbe1b094cf6ae4e3532e58ac3a57432c03eb6e026b502c6085d0218a2e37888c2b35c475fd3c12df203fe49932fc64650f4f383b9abd0b5a55 -76177199a6ec97dc5dfb8bbfe61f70a60ee0840284336fa3215caab2120ab3acbe902e2ab6f01fd586871ed53a3466248502f9896f8643aa1689df9bf2632d30 -36ab6fc2513d16954aa49f93387ec97824b0cf59f3cdff904f8783dd3c076879744884de477d7747c54164c3e8317a2c1bf140eae3d395c435bfd87e3c3acc50 -c4d30cc99fb19d952f31f40891d11cee01f769e1e5bbffe140f80fd904b55e1c417045e9274fc405d85d34f96ca8bba71c6c5de469d92c356ecb54bb0318b51d -78f6ea84812628959605574b3f8cffaa59d36a755dc464d81cedccabcd3e84b67e6131e84229d366a97cf0138c95e372420014a2bf5a0bba20715746f22276ec -e2806f4aa8958ad1423d055c47b6a29a04453f08f0948fa6c7afd7d5be8c7ab164a6f6219e03e3cfcad73575825afaa6809b66424d22d8e8426fc27e50966246 -96c6a4724c15b71fd6d883319bb3da02fbd57b8bcdd826e5239a9bc6c3377f600380a31a53a38dbfa16b6b6918bf6364c1bc7c2c7c9f5e0c8b41bb6bb6465ab0 -41c5555d15483bae6a2f48431db4aa1c512a771072f35e45267158716971344d4c04084e910de080f66e802aa219687de192223a80fe8425fd9ab0a48f8e47c0 -41663007adfac24e68c6bb504c6dda6698e10843e30d18b416659174a4b57894457f70b44e37397945f317fd6d116528ed87e3976738f0397fc83ad26b535fa2 -746673e524482020e15c231f3e0bcb1394cbf472f7c340e747103f42a4b2b5db9949a4349459d254d8dcd48469e356945e93030418081864434b8fd88386896e -ca78f6b1f62f1fb22a1a45e003abc712910548345688a1b364c564b8629bd314a9c861856aac1008e6506c6d3ec1e6d78250b3086cb5a144a1cbda4b61b2a075 -010b6abea24f2370700aba681871aad69ac78a7cd894036deba3575247b388eb80150790794a58205a94e9e823e3417349e423946ac3cbf569e04d81ad51258e -7f86a450376eaacde459a505f271fb6b127000f998c75736ee89d7d6285eabd50d88a3a4c38c9e2466c135c51352560c374dc653f3a45221c3c1a1ca30cb623f -0dcdff3576d355e8145d3838d171a087018a910c344f43e3a58244c91933517ac2656c85ea81ae41977cf50874c92d53cda9877ade80208578b420b703312fa1 -a6c5d045f4c4258281a26172fb78ab58664511d220d47eaeeafa9037dcf73a907dd6cb34c69d199db0d80db15bf72ded5527cd57c86ca95ba88ea2692061889c -0da5ed83abe2ed94272c3a63138d77a9cb8ce0294a37d00aa41e2013f83e266f635a44164504c5423e1e06d7cb3a6adda8c3c041763da2af402d56db6f87e46f -8df1d1b9137c824152e1ec2bf1812a1830433dbcb45d23ce9032ff6b756da8ab7c3843a0dae7da9f7ce2b6b1b58c2a514750ab5bb5b501d02161b436a9ec82e2 -104a9b3adb5019640a49284095daf40b73b1ec04dda3796a0d9de9e82ea33576aa020500d4514a35d033b62c50fb0cbdd6c0d326c6ed1551826e35e4d3856ad1 -0915e5a00c55c98f90d24a258b66d4526e4b1c98d38b24025aa4f6bfabd687322f669650fca84c4a1a2b521ea9ec16f37c42e4659e36ed020e553eaa0ef30f90 -943eb7a46950ed5e406b420e8d022f4c2153a78aa9d6d8d0da81de948395cac449b8f4249dcc31053b5e31bdc212c605ce3c325e110808f1bad65d2b3f5b5fa6 -58c6fc82e0adb37e9c9eb60e370342d4aaf0059474d198b7aa64bea8dce8743d8a06a461d1bbd7e0dd5515b4691785012226e3abda8843bd4b168e285b4d4b23 -eaa6dbe63ed7fef797d11f3e0d0c48fb0a9967afc7f340ed1fee9a994e0529cee416fa86e301eeadf68ed26ceec7427d52ed7c59485619c3452c66241b16647a -ed9340925ad1e309ce6bbca589c3acbd12603353e7846d2d4fea0d5ba6fc98eeedf58a36b1680e028a306864017d0566a8091d133d07a2a68f6b4e0f13c5b272 -f0fd74526f66c848aaeed121f697582c505215b49e9b7cb2018168200acca58ae0257a6c693f6773b76a5ed436c255d4943355da86f46d3051cccc441f8b329d -02ab576951ea0d4b9ebf613ef854e3f14ff85c4552b1590d1b199fdf6a5575830d3cc50f5cc0b55ab7d9b761d394bb54e245d07b7c0f3ab061a9a4b00b0a9453 -f34b84459485ef82efb178a141fb0a52f93ed732ec33e6d21a29626b961606f4557d5a541564d85f4e515378ad71866e6875b6b0b34c1148ad7008495d378b81 -da4dd727bddb029f2928cfa828dedac857c234997c45aa227e66706c52d013f7aa919532dcabd0876d40f8ee2b0a00f08fca964736b13729f59810cfb13aea1e -68ead8786dc807a20c4f658827af6df0b5ab81d9a03c54cde3929059e835b8a48c96259fe29dfab1f5b2b60d28f7f163d433047d80ae9669e0ae0f3dc1db3274 -0a9ae673bbcd92720db5797caa6885bec358a2822c6bea7d8de9e43c8c7d8ab9b59e6942eb9fbf56d3bb845bad02b077387d6a2d3fa9d06a30c41327e64e9d51 -791404f846802d890d8bcce79b99b36bb67483ff72b868b888bfdfd5ecc6245e510c69a4d08d3e63e5bcef732d533e132584fd836930708dfa2f90a0a90b3068 -100a80dc88123410aed640ce41d5b529b171e0351a98783c289aead27ca2502d5186e7e6a53a92409b454d96f9c6790627ace76e90f191dd6a0b922c938c3920 -74080b9d03a893a44ba9ca197ba20dde4b4a45d2cbd1d011a00d3551004bb3746413f5e7995e94ba015a1da9ccb1c396cfe403baa64042270cb58b204a272daa -c76fe23e6ca069ab0781362488ee4b5a2f9b0690da91b400d9f4a24dfb7dd310115d32ee103638485044e433718f0a2662a619532328d2fb564a8c97b97d4e2d -802dca9d719a19ec34f2e01df914e391aa24006af468594369b5c1dfb4da3853e60cd8de9020822e16c50236d14c5582faccd3e7f721a265eacfe277773911e1 -cd991f29ad405b7dd6918016196a1d7cb304540d1ce7972100e8d961742b2c510ba91229fa7a987a5f2ebcad3fa40f423024a882bf387fb29b49838455c51767 -9c911eed4aa19953146d6bf5317fd619294e0bc787216c664b05d4b244bd8156862525731630434acf02a80d900be70f77a3f0ca6e07f3a390671f92297e7cb0 -f2c1646afec41ca105944bd9840996631e8672b1e8ec807358c28da41764ac295693ce010ad21b9d205e060fe20c2c126274d3a8d53948d831068b0578339f5f -3498d2853a3585de074ac5857514311e45932634fbd591b2acba7e2d4c17af57e9d2966e123482c9d08d4c41322d1d06962c16ce9aee470d4e4d9fb9fdac8395 -8ff2a5d48f3326b6adc13da5a0b1d2260082280763a70147d5496c719cb80cbbe01706d89968c224d364d0a2099f0e3a0b315109700fa7692291b2261bb5007e -72e95d88b8b4dc668b8e7a34abc9a4828f00c9a6056382ff61938ddbead2a1a9425f02cdec26045bb493538bac212917a25dba74a92fa4302ff6bb7fa0d11807 -291fe5aec14c9f44bc1a32689f6abac49b7dacee1f82c036706497e0ff0ec97518f750612096093cb9e7e2ec626315ca8def4f071d22490a6a8b5b3091cd84b3 -a0aff7215032d3c844bed4e9e01da70d4067fa753b1ec17ddb963e1c33ba07a594049379d7dd99f2e9a9928668cb051bd9601cba6228249ae789900d4da6f6bf -0e523e3c167a1d670bb300d8218431e668d7d1681ac113f1d00084aa8224280ff9091b01a52a42ef589d612ed8e4ec770118a422aa0e9021c562857c68ceb0db -4a334e1fe86650354c5e9de8bdddb4a026c17f9436f4129d91805f0afac2a6a38f84514f3cc496d601105328b0a105e5fa70c04213cd21601c487b4c5b3e7b7c -1ede336900f365ea83cdc7e79083287ee8726e34f4cc8827294d9dc5c8ea4d10c4f9d929fe40db31d174d5e99b22579371d943423c7b6d388a02e145961329d7 -246a34ab242069bfa52d74861af43400a28586c645af1508917c9c560ea84f5f508cd8cde433b928f44dfb1aad8c7ce6ed420c3d41392b7d9e8ffa5923930768 -907c579e2fbea271238b039e55b07c4d2daafecdc0adbaf9466db041edd96858980bf8fd1ed78ef9a116b545a5206589d89c51ec947987d0e630a1d1b3a21824 -937ceda339195550537dc3106a7d4eb2a8d9aad629421d5ba8d5dab7900e7a7fedfe5140e1ea346be8a7cde9b44e40493ee45a1c4aa1b486078de1b82f043159 -f418314be369452b62ec66442929b750365c857d0caad0a400aad121d3459350987d7a74d528422615aea5b6e0d86c6c92ee8a7968ce38292b45a3513cc2229c -314b5325b14f0fb1bd2a73f612d4e1c947cf32d50d9d6632e4ce8c0306664974ca100322fdd4745730dd9a772d3a0899a5bc24b4bff0946de40396cc07b2e6d5 -738fcb6570448dfa371a3f6a895989e278e030a76e8784568ed3521f11ff1d5bcd0ed4674283c5668571089a3082c531ffa9a1a90aa35a71de5ddc4b2abb7e70 -58f249399ea2c51de41550e729aa7e27d5b2dfcaa03cd3d07657f5995118ca95540689810ab58855dd478876a6734f71c6ec63410aedd57c3a2e822748a5af3d -3678121ed572f81a25e683ab7b41076a726f0951903a57656d06883dd3413f130169a8483ba6defe919fe2120e463e4b3e554d66edb682841b2f5732baa198a4 -659bfe7bbbbfc06c2b345c1bc0e82bcc5f28515256fcbe78c8c55bdcc1b006784661198a43aac9a44ccb10c0303d508f75030ee92b516107f694148e07ca9805 -03a44c08a07c48a2a73f5c8ec5adddf7f9440e463e4b7d88a14c2d5e74ce600075b94f1215e69b6915b228778b8893824e3fbf50752377a7d71f2452359386f7 -b946310ded68f904af409a764665bcd6a5d04581442bad5a699ca7c6bf5c22bee1c032fd03c34a0fcfd2f0f2ccc265e4c791c4bb0d665b29f9249accddb5cc04 -8cbcd32717d468c37d27fd6f1ee5e2d5593adb542b830670084d10d87d5c706308e6ac8e23cd4f71b89b51465548b7ee405143f9fa7d7672abdc10e628e909af -d91bcd5ce3e528f03811909ea890020e10784d5e7d98faa3dd079581687ab0e8a229288df719c0674366c323437df6d008a6892cb551e960558ec9984d5ca4a5 -e4c3db6a3e5db84723a217a105076cbb8c9a878066ac38c410d113d811a0f0a6104241ca76472b8214089bf01df858d52ababc9983757fba5afcee30e54336d5 -d4fe6a364c17a185ce79a3715313e70f0ca3522a92200b2bde07e01b0983000072e6a7c32f7de943348c67ef5219676ba68402374e300294cc8a3915685ba3ed -ae60aee968352e845e8e661ece2251285f0f5c6fff07c1c2b71fa67cf4738afb9f787e104495f262d1e05323ca78af96679d7da59b0859cb7da0a5c27734a9e8 -bd16a077bf5f1c4cf4d624b1c79b1c8fbe78f420a05a92ca756446e9b4d06f14601501e112285f71f715627d0e10b7cfbf610af2997c94a6c99848aed80ade73 -056091d132b5bd8c8d56822cb9869237061aef9b652afa975894d58fe8acaaa9337a60122144646aa12c528e12c26085174a6a49b9ea6a18957a84cbb157b042 -99ab265d96b30e5f3ef39b189c3945933593c190e82e34e0328661cfdb5cd45b71cfcb7387e5b2c6d6baa8ca595a7f7ae46874c7a29cf884dc27f477126074b4 -711948ab738d6997e49b642aafe2140fa16feeb1b40c6a2f99ed4358872f9ff90fe61b21f07668ec0ef7d181059768bde59ed741f7ec7d3f36d81050e24d52ac -28715972a505b3a14c7a47a8b2d59e740d18df3a0889789448b452707df573f0c38a41128b17c41cb2cccb30cebc697af2d1240ad43ebd90aedba3b089cc5c51 -b4bf6b996bdad785f15029e5285a97ec6f4d6c9a0e12d67ee674e485160e3ae675408286b8474dd8beea57eb874c80cec59f37a4647992fa3db090a6271fa053 -aace4d87c3ac3dd216f93d43f559de732ae4c6b8957432187e9f12820e615cd218a00eb65f281443d179c4827da3edc03907fb1268b54ae1f1ec418de74b005d -e6dbea1ff8daa6251fbe891093e37d48bd5eaf06679dde3a15eb00aab0d7af6938b5ecb7806ae8f0187c669da152637a51af55765b752f66e215f647bd67f274 -8655bb58858766f2c232d7b4e483cb4ea84e290ed4649e6c87ea3c4f4de841ae8592a6fdbeaf78ec74e4d7109c004b7ba7c5326cd2a4bde2f6b5773118bdf616 -dbc76ad01669996b6af28981720d2f5a9d5c450e82be69a074b06bd957ce394e0c4ee800764b0d1ff93f7aa1d05c958211ca2ab5dbd61e91e1ae2b59446e3dd0 -e54d4d3e7dd8ff139a37c8858eac37d99f155bc8b1c5ee3225dc3a86a64636a0453307b2dd4e427a439964c6a6ed2df049f66559973635f9f06dca623357a495 -de6de85d0ca85ed6451ce28b183684034ace501b50583a9cb8ac696d227847142ad9d7eea61fe6b2b5749af2518244b100487d0893545b1ce2ad2fef6da45141 -4b28c16a115bd0d19fce671a0dd77caafd81c8e6d3817b7c98f69558f69aa27c76e5da12729525ba332dfb2a0ef585783d0c6e447b52a05930e898740f734384 -293cdaca606903d43c987b3e98d71ee02eaa0b959f40acf4bd9c341439d47b5fcefbd8263aac2487efc88cd604deb8962393be74b50dd1d21d35c8bd2e7b774d -d57f2e32ecac98cbf55bfe413b3fcb91c85eafd1264d5a4203a268f693696eef1299360d86b8f7322db796bda6a83fc5d05e3a0ffa410cff60ff737f967d8107 -7c21bd91283297b86f78b6861e41a3122175b257bb66f359e4150ff899bb5e3045f9980f05a0d2e6e8547599c6564760458604c35166221b837d51d7c2e1ded4 -6addbd563acf9959dea5fd27c3c99fd21a8b3cde3bea836bd9f9f239ebdc09e17f4a1fbeaf8f717bb31b45be30b7bea8be9073d78b9cf49ddadfca1be58987f7 -7cd35866e5fa83baa0e589f1205e45b99b3688327572476699de860b23b9fbc4396d062dc08258120a5876e8652e7eaafaa30f66ddbdefe1a8754f1a5f76508f -e9705eecaee2ddab574f3ee212fb3352bee79764b3f57cf9d2121fab2f5efe9aba7cfed2be42e496d7fd8337b3fc8b98c62bd9db93f5d687c57dd68f9d4fcbeb -e4feb9c3fde869cb67fcc92faf96ebe6d66c3a4f765df1e15ee472de5f1437e9bafed3d8a17f24483d4fe4bb877b15d3968fb5060ef03f3b27cfce1c19ebbcd4 -06023cac3eff8c27b6be5ae413877d152b6142338a97f7092eacc4172ef19909c699477530bece5257366dfd299ea7f5a9d211363f7be9d16aff6e0c10c7f9e1 -ade9cb07b3638d7f387f9a1cded51dcebb57df2b6ba479c9e17c04ef9dbe7cd4507e65dbcf5a7dc672a66c71e5c1c314cf0ac847afe88b72b8cfed70efcb92b7 -c9374f30f239ac7374fafaa377b649fb60fc8c975b3df9317972ab89390e7dfd427ee8efdde73b771c4707e1ff006bee54e91fa622af88feac62f6c67f84e5b4e53387b5bb4456447f5436e3c352eb294977c7afbffd2387f7512b269fc3bbac69bd7bc75187f998fe3f57fe5bce88c4adb00000000049454e44ae426082} -}{\nonshppict{\pict\picscalex133\picscaley133\piccropl0\piccropr0\piccropt0\piccropb0\picw7594\pich8467\picwgoal4305\pichgoal4800\wmetafile8\bliptag276711534{\*\blipuid 107e486ef6f08100a0e5ef6a660d26cd} -0100090000034ab60000000021b6000000000400000003010800050000000b0200000000050000000c0241012001030000001e00040000000701040004000000 -0701040021b60000410b2000cc0040011f010000000040011f0100000000280000001f0100004001000001000800000000000000000000000000000000000000 -00000000000000000000ffffff00f5f5f500a6a6a600585858009b9b9b00e0e0e000eeeeee00dddddd00d5d5d500ababab007a7a7a00727272008f8f8f008484 -8400c4c4c400cbcbcb0052525200141414000a0a0a00222222002a2a2a00181818004e4e4e00676767006e6e6e00b6b6b6003939390033333300bbbbbb004646 -46009090900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010107020101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010107121801010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010d090101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010d00040201010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101070015010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010800000a01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010115000801010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101041d090012060101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010119001d0101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010109 -00050700140101010201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101011a001801010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010102010e0010090017010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201010102161c0101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010104 -00010a000b0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010102011c1201010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101011b1b011800000a0101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102020d001001 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010600 -0b011500000901010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101011814100003010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010b0e1d000608000004010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101021d0901010b000a150c01 -02010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010708010114191f12 -010300001a0102010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010116160601011418191c010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101020101010101010101010c1c0101160514190118000008010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010e000b01011f150a0010 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010114040109120a000f -0115001c010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101011b16010109000d13180101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010109070101010606010101010101010a130a010d170300010212000b01010101010101010101010101010101010101070101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101020101190302000a0101151b1c13 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010103001a010109000501010101010101191301011e0c181b01 -1d00001d0101010101010101010101010101010102010f0003010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010e00070b1101010e1b0e000f01020101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101090015010101141401020101010201011c1901011505001f010b00120601010101010101010101010101010101010107001501010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010606010101011710011b110808160f00 -18010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010118000501020c00080a0f0f0101010108130f011a1505000707 -13001b01010101010101010101010101010101010101011800090101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101011c0401010101010101081611011b0e1b1301010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010106001501011d000a1000001e01010101111b010111150404010b130018010101010101010101010101010101010101010103000f010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101041202010101010101011f16010d150e -001d0102010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010201010b000a0101161101150014060e0f010713050107001915030b00 -00000301010101010101010101010101010101010101010200170201010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010a001d01010101010101060a0106121a1217010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101181801141201011f00070d00001d030008091100080103000d000317000000100101010101010101010101010101010101010101010b00010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101160c01010101010101010d08011b0e -110001021d0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010105000d06000d0201160e02120019070003061300170101181b0c000a1e00 -001e0101010101010101010101010101010101010101010102161a01010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010f16070101020101020f000d010d1c1a001d021d010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0102141401180007010e16011f0013061115011e13131d01011b1d14001a0000000c01010101010101010101010101010101010101010101011c160102010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010a1e02021603010101010102060019011d13 -01171701010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010201010e000a0100180108001a0114001806001d0e1b0b16010204140600170b0013 -001f0101020101020101010101010101010101010101010101050009010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010108131b0103150101010101181b1c110101110a03000801010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101020101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0112120103000901041c0119001401111b02000a17171a01161903000c1900000010010101010101010101010101010101010101010101010101160e01010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010109130a011e0a010d1d010800111f09010b -1c07000c010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101090301010101010101010101 -010101010101010101010101010101010101010101010101010102010101010103000b011c110110000f1d00000308001d0b1b071417150a00091900051c0000 -14010101010101010101010101010101010101010101010101010c00020101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010201010316011a15011d0c020103181a1101030002171301010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010115000e0101010101010101010101010101010101010101010101010101010101010101010101010101010101 -17000606000a011c1c011c001502181b0800030e1e150e191c0800121a0000131e01010102010704080101010101010101010101010102011d01091707010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201151901040802010101020d0f150801 -15031d000f0101020101010101010101010101010101010101010101010101010101010101010101010101010101010102010105001e070f0102010101010101 -010101010101010101010101010101010101010101010102010e1001010101080011010e1601100007030000190213090500071b001409000a0a001104000000 -0401010101011e0401010101010101010101010101020101110c0103110101010101010201010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101011d1310010901010101051503170d01031701121b010101010101010101010101010102010101010201010101010101 -0101010101010101010101010101010102010612120918000b01010101010101010101010101010101010101010101010101010101010101080018010101010d -001d01000d011c1e011c0012061818011c1f0f00001d1f13010b0003140000000c010101011b1b01010101010101010101010101010101011d140110001a0101 -01010101020101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010601011817011f0a011d0a011614031101 -0612060d0006010101010101010101010101010101171b02010101010101010101010101010101010101010101010101010105000a19001b1a010101011c1f01 -01010101010101010101010101010101010101010101010107120d010101011e13010e00020300100a00000c0118080a13011700160216180117130300000000 -1a0101011e1702020f01010101010101010101010101010101181901110e01020101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010201010101010101160a0107131a010c0101100d1400051110011e1106001f0101010101010101010101010101011100190101010101010101 -01010101010101010101010101010101151d1e1e08120a010101010107000b01010101010101010101010101010101010101010201030d01070d060101020700 -0c011404011b1b011b130009091e01150b0800000c09001a011e1b1800000013060101171e01100d0a010101010101010101010101010101011a120201060101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010f0f01011f11010c0c0101180000170e04 -010a1301180010010101010101010101010101010101161401010101010101010101010101010101010101010101011d00010c1a1f1c01010101010101151f01 -01010101010101010101010101010101010101010118001d0f00080201011f001d090009090009051300180114041000100b000008041601011217120000131c -0101040401010c1d0106010101010101010101010101010101011704011b03010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010601010101010201010101011b05011c0901090013160f170207001a0800180101010101010101010101010101011f000a01010101010101 -0101010101010101010101010101011e17011e0a1b0b011d01010101011d0901010101010101010101010101010101010101010201090a0a1a14010801011c00 -0f1114011e1701141c12061000020b1702120004080003010513190019120017010b0b0101111f01051501010101010101010101010101010101100008051701 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010d11011a00060101041f0101010101011a15010a0b01011513140b11 -0b0117180117120d060101010101010101010101010108000e01010101010101010101010101010101010101010109000a05171013021a000901010101010101 -01010101010101010101010101010101010101011d00040104040115091000161000030119010a00141401191e0213080e00001a0e0007011e1917000c13000a -0a0b01010e00100106131a010102010101010101010101101001011c1901130f0101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010111000d01151001010a0a010101010101011c05010e0d011f130b160d17010f15010616001701010101010101010101010101011e0006020101010101 -01010101010101010101010101010500081e08041401041701010101010101010101010101010101010101010101010101020101181b1213130f0f13011f0004 -031501070302171700110600030304011500150613180106130e00171700000b0b01010d1f0a1701011b1901010e0e0101010101010101051e01011016010c17 -01010201010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010106131c01010101010101010101010102011a1b01011f0a0812090c0d -110701151f011f000003010101010101010101010101011f00100101010101010101010101010101010101010101181e090c0100040116100101010101010101 -01010101010101010101010101010101010101010c1d121213010d1c011c001f110d010b09020e17000519140714081a00000a0a0006010e1e0c001f1c000019 -01010c0401011706010e0009011d04010101010101010102161d0101040401120301010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010a131001010101010101010101010101011105011a00091e0a101c1c04011f1501061600130901010101010101010102010106000d010101010101 -010101010101090101020101010114030a1a0600041717010101010101010101010101010101010101010101010101010101010f080f151f130118181000000b -16021a160a1c0400000f151d051401040012071c1c01011b1d1e12091300180101051e01010110170307001a0101070201010101010102010b1e010109000805 -14010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010201010101010101010101010101010101010101011115010101010101010101010101010101110606000c1e170213 -171c07021305010d12120c010101010101010101010101011114010101010101081e06010102130501010101010800080d101a0000001f010101010101010101 -01010101010101010101010101010101010101151a1d181d1e01120b110000140b010c16000000001e03000814030115000c1d001d011d040900171f00000301 -1f150202020110000f011c0c0101190b010101010101010106001a0101171e01150d010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101071c0a01091308010101010101010101010c1d01011f16010e00000006041e1b0e020e1e0102070500060101010101010101010101010f001d0201010102 -06000c010101181501010201011014010d010c0000130f010101010101010101010101010101010101010101010101010101011a011803181b10000e15190000 -170a1111000000000c1c0e0b12010d1312021111010104050400191e0000061a1401080101011e000f010a1206010a150101020101010101010b1b0101091201 -03130701010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101011b120101180401010f0e01011d0f01010a110101010c04011700000c1d -161f160707130a0101011519010101010101010101010101011b170101010101011b1c010101091402010101010316010b010d00001201010101010201010101 -010101010101010101010101010101010101111f01181200171a001c150c000012161f0c00001414191610160c0114140e02161d0105130916000a16001e0913 -10010d0e010b17100c0107001f0101151a020101010101010110130901011c18011c110101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101011c180106121a0101140d010a16070101170b010101171b0816001402151e1319010c1701010209131001010101010101010101010103160101010101 -010d14010101010f01080e01010905010b0106151e130f0101010d080101010101010101010101010101010101010101011d001d011100001f1f000005110000 -1311021b0000181500111a001d030014011f1601011e1805001b0a00001e161a0101061e181b01010c1001171b01010b040101010101010101010e0e0101081b -0609001a010201010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101020101010101010108151001171b01010a120101160401010f13090101010c0618000010 -0c0019140107161d0101011804010101010101060201010101011b1d0101010101061410010101010108000f0d0b0301090108140a000a0101021c1c01010101 -01010101010101010101010101010101010b16010f000a0e101900120f160013000f08141e140a0000091700061e0004011403010816081b000a0e0000001f01 -01010118000701011f04011a000601061507010101010101010101110901010c1e01121e01010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101011f170109160801011717011d130901010411010101010118001611080005110c010c1101010108131d010101010104170101010101031607010101 -0101110b0101010101011b1a0900140705010f140a14020101010f120601010101010101010101010101010101070f0101000b01120c01010716001e06001e18 -00090c0b040c03001c03001e0a00001d1a1601010c0c0800000a11000019010102010f00160201010914060116180101190b0101010102010406010c11010109 -00090900050101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101060b0601021f070101010101010102011c09011f1b0101061203010416020108121d010806011e180900 -06111e1d1602011b10010101041c0101010101081f010101010102120b01010101011d150101010201010c0b0104140604010f160d1e01010101011a06010101 -01010101010101010101010702111b010500020e000701010a0000050f000d0b1306161b130911000d1e001917001b011618010614080400000a150017010101 -0107150a0e0e020101190a010e1201010f1501010102010111040106150901011717011900090101010101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102011f001101070019010101 -010110090101030b01011c1101010a130801121f01010d15011a1501191b01120506001d1c0a010a1c01010108000a0101010102100401010201010a12060101 -0101011e030101010101191e010d001a19010f001e1e0101010101010d060101010d1c01010101010201010a1b131f011e0402000c010105170013010412070c -0f1000001602141c0f00000d16000a090009010a180713121c0f16001a010101071e030107170701010208010800050101110f010101010108120a0103040101 -09001d01131b01010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101011b120101050009010101010d130801011108010813030101111c010a120701010405011e190313011f -040115181f1c010111190101010d150101010101011e0401010101011e1701010101010a1701010102010411010e12110d010813000b0101010101011e1f0201 -010f1901020101010101010105130207001a0b1601010f031800180200170b0b010e00000e0800030e00001300120118180101150d0e1617181f001606010106 -150d0102010b05010101110301111c01010a0e0101010101010c1b01011c1d01010c1c010a001d01010101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101020106130b01011b1b0101 -010101171701011a0b01011a130801081205010c17010108130f01141512020216061f00081c0f0101141d0101011c04010101010201151d0101010108160f01 -010202011c0801010101171901181917020108000018010201010201031b010101010e0b01010101010101011818010b0006160d01061c0814000809001e1b10 -010400000f0b00021b000000001908130f011d000d1c0317051c001e010106161f01010202070b07010105190110000a01061e010101010101011c10011f1b01 -0107121a011117010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101051307010f000301010101011b0e0101171d0101190401011a160201120401010b12020913000501 -1b1e07000a1f1801010f1b02010110120902010101011d1407010101011f150101010101110d020101011e0b01111d1106010900001e01010101010101151a01 -0101030015010101010101021b03011c0c061407010e040500160105000d1407010c001501140e03000018190002191c010111031a1609031a00150601061219 -01010101141a1f0b010101170701171c0101190a0101010101010c0c0101140a01010c1401071203010101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010517080101011b0b01010d1607 -01010101081609010904010101040301010c1b011d000e010118040110131c010a0007191e07120f010118040101011916010101010101111701020101011718 -010101011d1101010101141f011106111d011000001101010101010101181801020102140d010102010101011c0707130719110102150a171c000111181a1501 -011c00190f000f1c1512061b1802161d010f1501190c031c05000c01081217010101011100030214060101110c011d0010010a1101010101010101151d010e14 -0101061205010a130801010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101020101010101011500000f01011a140101011b040101090c010e0401010c0c01010f1b0201011e1801051309010104180813131d -0116050712060b1c010101111a0101011b0401010101010115030101010106120a010101011b1a0101021409011c071c0e011000001b01010101010101010201 -0101010314010101010101081501051102131d0105040e0b0d0017001a180e010800000f0e1b0f17031e1013021f1b0101041801000b1100120003011e1b0201 -010111110105010e19010119160101111b01011b1d0102010101020b1c01011b0c01010d12070119150101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010101010101010101010201011d191e140701011e0a02010716 -1d01011c1901111d0102040801010b1b010106121a0119140101011c13130018010b12011e1101160a0101071706010107161d01020101011d1609010101010a -12060101011f1b01010a1401081b070018010712001b010201010101010101010101010114050101010101100401151f1f120201180e1b061708170010141001 -0f001507140f1e0f1111111501160d010616080d001b1313001202191c010101010c1c01010f0f01141d01011b0501050009011005010101010101011503010f -14020102120501021604010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010d130f1a1801010101010101151801010a160101010e120501021c1d011902011011010101150e01011f1401011c1c0101071c00171e -070713101d0006031e010101090301010105160101010101010b1501010101010b0401010101060101191b010f1b020018010716001601010209060101020102 -01010201061d0101010101030c0212021c1701101b19170106010d1b1d1b01010e00050a12081e0f161f00051f1605081f040114131f1313000b0f1602010101 -10121001010f17010b1901011d130901160c01011b090101010201011d1701011b19010103160801100f01010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010218001519001e02010101010110001a01011e05020201 -09010101081c061f1701011f0c010110131a01010411010116180101021700000e011e1e011b19011e1a010201180a0102011e190101010101010b0b01010102 -011c0c0101010101011b0e01050b01000c01011400000901010b1b01010101070101010102031b010101010b04100c02131a010e0e04050101011a1c1b1f0101 -1513010e18050b0a160c00061e05050614091a00121b1c19000a170a01010107150a0101010f000f0115080101160c01051402010c0d010101010101011e1f01 -10131001011117020101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010106010101010101020f000b1f000e0101020101011f1607011a160101010f020102010a0e011b030101110301010a120801011c0c010900190101081300 -1e011d13010f00070a1c010101010602010107121f0101020101011b1a0101010110131a01010101061609011b101000170101040000050101011e0f0101010f -1d0101010101141f010101030b0b0b0f1201011e1d0401010201010e00080110001305161917061700000b1a11100b0315011b001200191c001b1b0101010612 -0c0101090b1b0317011f1801010c1b0101140d01071e020101010101011a1b01010418010109000e010101010101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101081e19010101010101010110000f03000901010602010118180101180e0101 -11001a0101010101071e0701071c1001011816010107160b011a00040101121e150301150b011b18011a020101011d180102010f1610010101010108140f0101 -01010f160f0101011f1e010814011f11110101050000180102011d1e01010101010101010101051c0102010f1514030d1e011d1e050e01010201011d0401010e -00171c00170406131300091e0c1f051c1b0a00000c13141300000301010104120601011b000f010c0f0117080106160f010d140101190a010101010102011b0d -0109130a010119130701010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01080d06010101010f0f0101010a1c011b1501011b0f01020216030107161a01020512090102011d01050c0101101c0901010418010110000301071611011415 -1715011d1e010f000601010101010110090101021f140102010101011a1209010101011f00090102180d011f1b011105170101061b131206010101150f010101 -030502010101010801010110000005170c011f100b050101010f01070401010b000b1212131a0a00001e0d000811030000000013150013000016070101051208 -01011012121d010818011f1b0101191e0106130e010f1e0101010101010b101609011f1401010116170101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010104001d0101011815021211011f140101010a1401010e1602 -01010a140101010602010e0901011a1c0801011e1901010a001a01010c160000041508011c1d011e1c060101010101011b1a01010104110101010101010b1e01 -02010101191401011802011e1f011110040102071c00000c0101010d1f01010109150201010101010101011000001c121d011c021f06010101041d0105020115 -1c1a001411011b00000d1b0d1019180000001304140000141b0c010109001a01010612031d1c0101181f01140301091609010c120201110e010e1a010118190e -1101011c0b01011a000a010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010201010101021e14010101011c0d10000d011e1f0101011c0c0101041f0101020d1e010101010101181001011a1c020108120d01010a000c0101051300 -17160b011f12011d001c0701010101011d1c0701010115110101010101011b0401010101020d02030b010915011d11090401061a040013001c0b021004010101 -01040b01020101010101011000001515010f1c0101010101011a050105050f00050e151e041d0000000014010c110c0c1300001b0013001f051d010616180101 -011b0c01011e19010f15010f160701190e0101150d010911010e150101071110161d011d12060101111401010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010205000a010106161f0101010812090500060614080101081c0901021e -08010101170e01010101011a150601011f17010110120b010109121b07021300160414010114050117001c0101010101010b0401020107120c01010101010612 -0d0101010101010101021f0b011903100401010a0513001313000b0108010101011d1501010102010101010f00001115011a180201010101010819010f111800 -0f1c1b141a19170012130c011c000e1100130000000000040e010117160101010c190201011d000f01170501110301081409010e120101110301110a01010d05 -0d1601010c0401010800190101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101011012130801011012100201010315011916010d110101010d1b01011f1b01010106161d0101010101031c0101011c17010101040e0101081513051513 -1c0912030119130109121b040101010101011d090101011d000f0101010101091203010102010102010111090119011a0c01011a1b12001e0900170105090101 -01010c1d010101010102010f00000a0f010b0301030109040101110601111e1e0215191b10110d000014010300150500161113000000130003010c000801010b -120801010101191e010f1c0101110f01110b01011e0501091b0109160601061603160e0107121a01011900100101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010117150101010d15010101011819011c0b010c1f0101011b050101 -181901010103130801010101011911010102170b01010106010101010b00131b101818150108000a01040e040e01020101010814100101011f16070101010101 -10161a0201010101011f16010f180105170101011b00001307170001050c010201010f11010101010101011000130f06010308080301091b01010e0f01111a01 -011812191f00130000030111000e0d00041b0000001304140f01000b01011a1308010101010102141d01181a011511011d1206010f160601110b01191b01010d -110a1401010b1c0101011c1c01010102010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101020111110101011104010202071b0606161d01110f01011d001d01010c1c080101111c0101010101011e170101010e18070101061c0e01010e0013 -0d1404130901181b010914061e0f01010101010b1501010101111501010201020110000b01010101011c0c01040d010e190101010d0013000d0c001006040101 -010101150501010101010110001b1f1f01100201010102110101100d01050a010f180e0e1400001313020800000814160300000000000b00101c18010109121d -010101010101011f14011d1c0103150101040c0101040301011e1d011b1a01011c05151501011c0e010110000c01010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010102010101010102120b010102121f010101031c010e160106141d0101031e01 -01010c00100101150e010101010101170e0102010e130d0101101c1c0502101e00000e1c040109130901080108160f01010102011819010101021c1c01010101 -01010a130f01020110001a011706010e0e01010106141b121807001f011d0701010101051401010101010110001b1f03010f0201010101170901091b01030e01 -1f1f011f001300130c010c000c08000d0d00000000131600131c010107160e0101010101010101011405011e0c010e190109160901101102011a140109110101 -1d1c1d001a010f0010010105001d0101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010108070101011d000a01011a00100101011e1901160c011d150601011815010201031609010900030201010101021e0c0101010f13180101011f131b020d -000c180b1307010404010101011f040101010101011c1f01010102150c010101010101060701021b1b1601031701010909010102011b101f1b011f0b010e0e01 -01010101151d010101010110001b0f1d01010101010101190a01010c010a0e01110601040000000009070013100400081600000000001300131001011b1e0101 -01010102010519011f16011d120702130501110d0101191801011e0c01040b0101110e041306010b1b0101011c13090101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010c150201010103130901010c140101010814060f140601031501010115 -190201010a1c0801050010010101010101040801010106141509010101170014000d190c151f0108160801010101180c0102010101071c1d010102011c1c0101 -0201010101010e1b0e0b0216030101010101010101030b011608061e01091701010101010517010101010110001c010101010101011f09031101010c0f020e1d -1c01061300130015010b150f10000b1f00000000001400000b01010d12010201010101010a13121f01110e011e0d011f12010914090107141001091c01021c06 -01091608151f0102160301010f001502010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101011b1b -010101071414020102011916010101110c0101011a1701041101010c0c010108160d0101011a1c0801051310020101010201020e090101010e13040101011f00 -00140c140d110101041801020101011b1b1e020101021d1b010101010712170101010201010a131014081a14010101010101010101021b01040d011410011706 -01010101011c19010101010f001b0101011f0101010c0c011506010d1d010e0c0b01190013160003011405011900091b000000001312001e010110120f010101 -010101011b0b01110109160709170101150b01171701010b1401011d1d010e1c01011118100010010f120601011f000501010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010f001101010108141b010201011711010101130b020101171d011c0a01011b1f0101 -10121a0102011f1206010b00090101010101010e121a010101021c160f01011d00000d140a150d010616100101010109000b0101010101040401020101081212 -02010101011303051b0115030201010101010201010118030a17011705010e1f010101010103130201010110001b061b091e0202010d19011503010a0e011e15 -0601121c12001e011a16070700111f00160000130000120801061305020101010102010a1306010e19011718011919011a140201140f0101171701010c0a0116 -050106160f191306011811010101170009010101010101010101010101010101010101010100010101010101010101010101010101010101010101060d08011a -001d010101021411010101011504010209130d01011d1c010f1c0701021b1a01011d001f0101010b1406010c0010010101010101061919060101010d00040701 -17000c0c0c03001d01110401010101010a1e0101010101011e0d01010101080c070101020d1501140f091501010101010101010101011018011407031f011d1b -010101010101171a01020110001e011d020b0201011d0d011919011d04011c15011d13071e001f010d0a011f000314141213000000001d010104150101010101 -0101011b1b0101021c0906140702120f01171e010304010101190f01061b01031401010d1502130b0106161a0101080409010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010108001310010d140601050201161901010109001f010110001a01010c0c010b14010107151a -01011d13180101010e1410010400100101010101010103150f010101080416171400140f121d161f01101c01010101010118170101010101011e1d0101010101 -0101010114030f1501040b020101010101010101010101110f17030814010613100101010101011010010118001e011d01010f0601010101051501011a011c18 -01040d1a0014011d120201141b0c130300000000000401011a131d0101010101010105001b0101021a1101041e010b170110130f0115030101011f07010c1f01 -180501011c0d0a130801051601010201010101010101010101010101010101010101010101000101010101010101010101010101010101010101010103001608 -010c1b010415010f000b0104071d131001010a1310010111100115110101061c0a010106140b0101011d160e0118001a010102010101010f0d181a0101010618 -001e040f0b0b1f1e01071408010101010102171f010101020109141d010101010101010313010e1f01130f0101010101010201010b03010f0f0c04071308011f -0d0101020101011d12060700161e1d1e01010c03010703010f1502011d021b0f010401041319011111010d000916110b0000000012060107130b010101010101 -010812001901010101151a01160f01160d010d17010a12061d011f1901061506081608011d0009041e01011e0401010101010101010101010101010101010101 -01010101010001010101010106010101010101010101010101010101100000160a010418011511010a00101717011a000d01011a140f01101b0202150e01010f -000f0101010b15100101081515010e001f020101010101010105130c0101010116160d0c101418000f011f14090101010101071c0801010101020a1310010201 -0102011704071501051701010101010101010101110e01010e0f0301160d010418010101010101010b1d011603040b0501011d0f0202100101040f010d070b01 -101108131306071210011c0505001d16000000000d01011e1e01010101010101011700000f010101010514010e1c010f1407011e05011c110d1d011808010e17 -01181b01011b1807001f010f130f01010101010101010101010101010101010101010101010001010101010300170601010101010101010101010101010c0000 -000e01140b01130c01171510000d010c040102010e1401010b040107120e01010f16060101011f120b01010118131112001a0101010201020101090b1e0c0601 -0c000f1b011e1e161c01011f130901020101010e15010101010101031209010101010114090511011e0a01010101010101010102040d01010f0d010115110104 -0b01090101010101010101120c1c0003010103020101070201180a0110020402190e19001b010c04011f1c01141903000000131701010e120201010101010101 -0a0000170105020101011e0e01151f011b11010a130702120f1f061a180101161a02130a01090010030008010e14100101020101010101010101010101010101 -0101010101000101010101040000050101010101010101010101010101010f1c12131b09150d0f13030b000c0c001d010101020102141901011b0d01071b0d01 -011d1c0f0101020c121209010c00171200001a010101010102010101060c14050c00091b1a101c0e000501010b14010102010101171b01010201010103001a01 -01010f14011b05011c070102011a1c010101010104030101011e10011814011f180903010101010101010200181100100103130102011002011817010a090d09 -170e00111a01130f01150e10160204000000000901100003010201010102010f1600000f0f00090101010f16011a1c0106130a0111040719171911011705011d -1e01041b0101041b011b1c0101141401010101010101010101010101010101010101010101000101020101060404020101010101010101010101010101010101 -02010e1b0d130a1900141e0019161206020402031608121f01011b04020216140a010f161d010f1701111b01011e0c010c13001f01010101051c100101010604 -0000050e17011b15001c010101171e0101010101011c0c01010102010103001a01010c170614010d04010101010d1c010101010104030102010e19010b13011d -0401030801010102010109001a0300010114140101010d0f010a15011f1f0a0a0b191801011f1c010e0007040d07001313001701010c0d010101010101010115 -161416010e160101010101190d011c04010c16010115131e17031103091601011e0e011b0c01071305011b0d011d000a01010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010202011a000018151b14001b15001813150714040800030300090106131b020218 -00161a0b0019060b141d1c1b0702140c010a00001f07010101031c1f0101010118001b0816011a121500030101011e1e010101010106120a0101010101010a00 -1a01170d1d1901191d01020101190b0101010101140f010101011c070300080917010d11010101011a161c00061a1b0110140d0101010e1d01101c01051f0a0e -16121001011b1d01000e05140118001c15001a0109090101010101010101051e05140301141b0101010b1f08130606161d011e0c010f0f140301101e01040c01 -091606091309010d130110130f010310010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01011d1e120f06161b1a160000001500040f000d041307050801070f00151a01180016000000131100140300140207161f01091e001317050601011111010101 -10000008170d011500150801010101140401020101010312060101010101011d001a15030505010e0101010101180d0101010102130f0102010205110a000509 -1401020b010201010a00001303111501110301010102030f01071c010f1a0a0b00110101051b010c000f13030200131b0015010613030101010101010119000f -0e140103000c020201091c011811010b1b0109001a010103150101110c021609010b17010c1e01011518010b1606010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010108171f010b1c0d0400001315000d0f0015000c010101160f0e000003 -0f001f050018140013001415001c0707000e010104001c1300120d0105120a011a0000190514010d001c010101020110000301010101010c1601010101010101 -0f131307181a091901010102011b0e0101010107121001010102010416000e07140101020601010103001c1b141314081707010101011903010117021a170c0d -00100101121a07000b1f00010a00131b000c01040c0101010101010105000410001d01141c01010c02010d1802121d011403010e13070101150b010914061a0c -0107000a01130d010f13080116140101020101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101081418010e12060e00130000001717000000050101161b021c00000f0400090e1c0a0000000000150012070f000d01010b0b021d1912120710111e -1b001f121a000a0116001d0101010101031b0101010101011b1901010101010101050002050719190101010101160301010101061b0101010101010916000b06 -18010101110701010a000d0f001714120401020101011903010118071d130e171e01010d1c0104141d000d0118001300001f1a12020101010102011000160715 -18010a1308010d16010201160f0e16011d160601181c010108161d01051e011e0f010b160103130601041b011d001f0101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101011b12060707011e0000000000171700001606011d000b071512 -0e01140008190c1f00001400140d1315020f001618071f0e0701020b1610010e0000091b181e180103000d0101010102010e1e010101010102120d0101020102 -01061b071a0209100101010102141d01010201081e0101010101010101170a09140101010d0a010815000d0900090a000a01010102010310010118071a131213 -0f0106120a0200030d00060104000000001a1505010101010101011c00080e15010900180108001f0201011f1502160d011b1801071902010111150101041a0f -1602011c0b01110e01071405010c000a010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010102010117120801011d00160e170000141c13001b010118001a01160b0109131309111a07160000000e011e120210000016080f160b02011a131b05 -0e00091a160d1601011500100101010101011104010101010206161a01010101010f1e071c02090101010101081406010101011a140101010d0d0b1001170a10 -1b0101010f18010b0000090900060613100101010101180a01011e101a00000c01010e1c0117131a001f0101041300001e0e1b010101010102011f000308001a -011c14020118110101010101140c1f160109001a01010101111f1605010812080c1901081c020712100105000f01170003010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010101010117000a01010b1601011d1c00151100001818041a13081a -16050119001e061b1010130000001f011512060d000000100c0014161a060c1618000c01000317030103001801060201010101110b010101010109000d010101 -01051e0717011f0101010201020402010101010a170101011f1515030117101004010101080d01171616010900010f001d01020101011c1a01011e0605001c07 -0102161a080003191401010104001300151410010102010101181b1a011418010d1209010f13061917010101050006040e010b16011d0c010a171a1206010b1b -02161a010b17010c1701011716010715001001010102010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010104001001010c130802010515000000001216081714011f000f011b001b0b16060f0000130003011e000512000000040c0018041b0806 -13001601191705170101161610131101010101011e0501010101011d130d0101011d1e061801020101010101100b01020101010d11010101091414030117011f -0b081a01070607160c16011f000205000401010101011b0a010111010b000e01011f1b011c1b02140f010516161c0400000b0101010101010d0011010d160110 -001f0101150410001a010101020411100010010f11001c0101141a1e040106130d031301011c0301141f0106131f010f001c0701010101010101010101010101 -020f150a0100010101010101010101010101010101010101010201010101010101010101010101010101010d000901011c150101010118000000000017011619 -011b12071012001b1f12060f001918000e011c000013110000050c16061d130a1f00000f0f0003161001090d01091411010101010f120f010101010108140b02 -011d190811010101010101011f1701010102010c0401010108110c0a0117010b1a0c05010d1e08000400060b001a18001401050f01011e0901021e020b000f01 -011b0910000319190103121800051b001e0901010201010a00140414161a01121507010c15011e0c010101110f01001a1114010215001819060b150900180203 -00061e19010a1401101607011a1606010e000401190f010101010101010101010a00000d01000101010101010101010101010101010101010101100701010101 -0101010101010101010102010c120801011c1e010101011a0d1c0000001f080005060015010a00001b1b16010a000b0e000509000000030b00001d0c00060617 -0c00160b011b0c041c0101010601011619010101010513060101010102021417011d19021e01010101010101170b010201010117040101020111041a1004010c -08191a0119190a000c160c0b1e1e1403140f1f050101170701011b0218001a011d0401161509140709001b1c170800000901010101010300040f000019010400 -0f0110000309000f0102010e14010e1506161001180000140106000f03001701171702121f011e0e010404010119150101171c01170a01010102010101011d18 -13001208010001010101010101010101010101010101010101021b0018010101010101010101010101020101010b140701021b1901010101010104181c001d1d -000f090017020c00001200150703000810000c17000013060400001a04160107160005160605000a0003010105050109161001010201181e010101010101011b -1b0d15020401010101010101161001010101011818010201011f1b0d0108010b010e0701040c1b001a1913081d0014011002031d0101170701081b011f1b0501 -19090f0c08070a011e001b00080d0016060101020103001b0118001b011f001f0101171e01141e01010101011b1801151a06021a0012001101010d17011e1201 -18000d031302071b09010a0601011518010608010101010101010102010a00000000180101000109191a01020101010101010101010101010101061b000e0201 -01010101010101010101010101010412070106131701010201010201011813011a000a1700150a1c13001c1513090a000f0f000000151216061100161a141e01 -07120b110402000a18000601061b06011a1b01010101011e11010102020101011d0e1501070101010101011d1c010101010901190e010101010e111901010604 -010b0201181300130b04001d0200180f060101070201170701081b011f1f1d0819020f010608010b14120015011e121b0101010103001e011f00150608001307 -0103000903000f01010808010912080809010714001410111d01011c1116000e1c121206170c01051b01061c0801091406010101010101081a0a1d0101150013 -001409010100011a00000b01010101010101010101010101010101021b000301010101010101010101010101010101181b010110130c01010102010102010511 -011a0c07150018021c12001313131d11000f101600161f1c16081c0014051319010c121d12071c1809000c01010c1f01010d0d01010101011e11010101010101 -01031401010101010102011918010101101c01190d0102010111191801010a0c0111020704000013051c120901130a0202010f0401021102011d11011a1a0a0b -06181101110d10140614000c09140505010101030012061d00000f011800110107121108001e01010812120801090701010117001209010f1e01010e00131700 -001a1217181309011e1f011c1e0101070101010102011d00000011011800000014070202010001010c000014090101010101010101010101010101010215000f -010101010101010101010101010102011e141d0102151e0101010101010101040b0101010f1102010e001313131313100c000b0d00001e0104150c0000141800 -1d03001f110d03000704000d01070c0101011b0c010201010612170101010201010314010101010101010116030102011d1b011b0501010101170d0401010707 -011d0608180000131712120801130f010101080501071102010a0c010e0b120b06001f1f1609130f0f0000091f190c090101061600111d00130f011a00000f01 -18161e16130901011c1c1e1b01010102010d0017070101011804011d001901181607160000001e010f16071a0006010101010101010111131500090900000000 -081a001a0100010101031300160901010101010101010101010101020108121501010101010101010101010101010101021700060108121e0101010101010106 -140a0101011f0b01021e161b17120b010f140e0f0300001f0115000000000000121b0017091407151907121307010e0a010108120e0102010107151509010101 -01101c010101010101011a13020101011d17011b0301020101111f0401011a07021002071c1600171e17041f01131f0101011d0e0102110701040c010e1f0406 -0b000500031d0d03160004011e0a170601011b00001e12001701011d1a0d010f1c0616000d01010b000801151f0101010c00190201010101090d061500080104 -1810161a00171e17010b1a0106010101010201011a16140b000408161300001a080013070100010102011a00001e010101010101010101010101010101010900 -1901020102010101010101010101010101011717010109121701010201090c01030008010102181d0107111c1c09010109150d01010c190c0306131300000013 -130000001d14050f00020b000b01060301020108130d010101020118000b0101010915010101010101011917010803011a18011c0a0101010109091801070b1a -0d0102011c00131017170d111005080101010f1e0108150101110a011f050518000e1900160b0213000003021b0d1701061c1300130000001d010e1517100114 -0b0b001407011a000a01010b000e0315000c01020201010708021c00050109000f191102000501160d0101010101010101011011131f10161b011e0000000c01 -11000b01010001010101010914000c010101010101010101010101010101010e000f01021b1d010101010101010101010101011c0b010109001c070101021909 -011815010101081406010605051901050709000d0108110a15101013191c00180a14140c0c05140114170202110301020101010110131701010102011a000b01 -010105010101010101011403010d1b011a0b011c0a010101010d0b1c010a0b0a0a0101021e19140614140f141b0102010101061e01101401011c10010c050500 -1409140014010b001814011f110c0c01170013000013001a0109120013071a000a12000501091317010101011b00000019010101010210191917001f01010e16 -070003030002010a130801010101011f1b16121f0106161606040013001b010d0017010101000101010101010916001101010101010101010101010101010101 -141b01011916010101060201010a0f01010201011604010107151e010101070401011504010101031e01010f1b1f0f10180109130d0106110e1501180e020018 -010d131d120f160d03000301091101010101010201011b1c06010101011d1d1d1e1b1c060101010101081408010b040101010111090101010a1c181c010c0503 -030101091e1a001019000a14170101010101061e01101401091501011f1d1d001a0d00001a0115000f06011b1d191019000000151d170301011c13111801161f -190013070600001001010f1b0000001f010101071d110d071c0003010107130d0a000204150101010e1206071f1716001b0501011d0017021100000012070a00 -1e0102010100010101010101010f13000301010101010101010101010101010107121f0107120e0101140501010a131d0101010102150d01010217000a01010c -180108131a0101010e0b01011f130c0e0e0b01101403010f11190c01110a040008011415000e1f160214000f010d040101020101010201190005010101011a00 -1e15000f0101010101031b01010e040107020117080101011f0b081e01040f051d01041e150500031a160a000b0101010101061e01101e010a1b010105081a00 -041c0005010b1200130f021e0614140012001b07010101011a00050c1d0e130d00000d011800000d0604130013001901071d021f0b1c041c000a010101041307 -16190113140101010613131c1c111a08010101110005011800000000050b000401010101010001010710010101011d0000030101010101010101010101010101 -011f0006011f1302010e170101010a001a0101020102140e0101011f001b0101171a010a1207020101041f01010c040f100e030108161a010e1b1e1707191b00 -1f011900000e011b1a1a001701011b1d010102010101010109160b0101091510010104040102010101040d01010e1c011f19011e1a01010111080a0b0104070f -0601041e150d150e0f000a000b01020101010118011a1b01030c0101040a041313000c01051c180000070a180f0000000017020101010106161e091e01030b00 -0018010a0016121300121716050909191b04020111131b000b0101020712030d000603001401010212170a06010101010105131310011b001c13001f0b001b01 -02010101010001011a0003010201010e00000f010101010101010101010101010101191801011e0c0102121f010101031402010101010614030101011a140201 -061706010e1502010107120501010c0d0104000a010f120f01181617110714001c010500131206051601170011011a14011019010c0801020109040101151801 -0101071d0307060f0104070101031c011a19011e0a0101071c010b1f0817010c0f010d121b1f1b0b01001d1e040a0a01010d0517010e1b010b0b010104031500 -001e010f151d160004011800140000141f02020e0701011113010b0e010111001e010b001c1c130a0a18180d0b1519030601010411011004010101011e150212 -0e0115001101011d12070101060e010617001707061b13111400050e001408010101010101000101011c16010101010119001610010201010101010101010101 -010102160f011d1407010d12010101010e00090102010107160e010201181d01010d110101151e0101010a16080101191a09131309011a000a010b171404021c -001d080000001801001f010e131d01040b01181a1b131a01010101020d1501020708010f000218040109010101091e011d0b0105060101020f011e1d05190118 -10010300161f0c1b011e1d01031816100116171c02080f011c0d01011908190015060104090b00001a011e0000001f01010117150201181306081c0101190000 -091f001201051c010f180d0e050701010106110c010f16080101010a000f1715010e00000501010b150102011a150e00141a010500000c11001217001e070101 -01010101010001010110130f01010101011e001b010101010101010101010101010101031b0101191101011c1d010101010b13090101010101110c0101091c07 -0101110d0106130d01020105150801011c1a06131208011f000b010b1e141b021c150e00130016011f1607010a1501061407071a020e001d01010102120a0101 -0d0d010e1c011c100a0a010101081e011d1801030f010101010115071105011910010900001c0a14010c04011c150b0101160e1902010101161d01011b080212 -1b010b0b0b15161610060515041a0101010b1607011f1308010e0a011a0000040900000b011b001c18050601010101011a130b0109000c01010107141a0e0003 -01120000090101150b0101011100120e0102050000041b0000000011060101020101010101000101010118120101010102021c00050101010101010101010101 -010102011b1801071603011a1602010101010d000501010201020b080101030e0101011c08011d130a0101011900100108160f08151502011a000a0111141518 -02160013121c121f01001101010404010318010101011d130f01011f14010101170901191a081501040a0101010119011005010b05010201011d150715080119 -0901071200001a14081d161a1c100f02011203050102010f12020102110801061f050c09141d1001100b031d01010101030a06011f000f011d1501061600120f -1500001e1e000501010101010101010e120a010d1e1a071c1a011b1b0a0017010e00001e0101090010021a1500190102011800120e14001300131a0101010101 -0101010101000101010102131e020101010106160011010101010101010101010101010109131d010d160101191801020106070300030101010201010101010e -1a0101090c01010a1309010101041310010f131d010e1507011a001801191c041e1200140e110e16010d000901061203011b05010101011f130601140501010f -15010115020511011c08010101010b020f04010b0b01010102190e1015010119100101110000091e0e011112110102100212030e010101060b0101011c060101 -0d0301020902011004161102010101111b01011a001a0101150d011c000011110000160000170d0a0102011007061b1b06010b1502090b17011e130515140208 -1200001d01010c000e1e0000130601101c13001f11000000041a19020101010101010101010001010101011a000b010101010103001306010101010101010101 -01010101010d1207011e1902021c09010110120a0000190101010101010101061e0601010c0010010513060101011b12070110000a011715010103001002001f -1d1600130f1503160f011b1606010a1307061c08020101010e0605140101010411010915010c05101c0102010101111d061e011d170101010115100b11010110 -0a100105001b010a0e0110131901071801160f01011d17010101010915020101190d010202070614000e010101021c001001010c1d01011915010c0013000000 -00141513141414171f0607191c120c01010c12100a00001917130512130901171c1e1e010108160000040211170719000013171c0000000501020a0101010101 -01010101010001010101010105000801010101010c000b010101010101010101010101010101111701091305011f150101011817030000110601010101010101 -0511010101140e0101191401010110001107010f1e07011c170101091902040018010415010e191917011a000c01011917010e1e010101010101120d01011c00 -05011f19011708100301010101020c0c011e0107150601010a1407121a0101090d03011d000b0b0f17010a001a01061101041d01010e16010101011f12101101 -100f0101021a1e000b020101010b150801010102010101180610001616001511000b1c00151d0801080105001b09010a121b080c00131717171a1b130f010e17 -031e0f010118000d07010900161600001b0d120015181d010102010101010101010101010100010101010101010d1409010101010111000301040d0101010101 -01010101010102160e010e00060115180101011c110e121c130a010101011a0601190e01010815080101171e01020119000d01011a131a01150b01010a1b0a13 -0004050005061403121d0104001f01011505011b0e010101010f1208010a15150901181f011e02010101010109011f04011e0601151d010118040a1502090101 -0f19010216181818121001131a01071101040a0101031601020101091f010306010606101f190004010102010f0b01010119090102010201010b000013130d15 -19171c00050101010108051a01061e130a010c00130a01061c00001d0105000d1d0c01010813190707071700000000040f160018010101010101010101010101 -010101010100010101010101010115160901010101011b130711001901010101010101010201010300080116040110000a010106140d121b1d15131a01010d0c -0108140601011d1b01011a00040101011b131e060103000501121801011f1300181f00000010180c1112010212130901091206101401010101111b0101111a15 -07011e1d09040201010101081c011a1501110a01110d010114050101070b010909090201161e0a181618011e1d01010401041901011d1601010101010101011e -081900001e0e00180801010418010101061f0108100101010c00001314090f080e17111c01010201010702020e001706010a15000a01010a131709011a001e1f -131f0101181301181616001313000e0f16130d01010101010101010101010101010101010100010101010101020102170019010102010813110214001d010101 -01010101010101011b1b01061605010a120601010812031b170104130902011d07010f170201010c171e001612040101081200150f010a000501121501011f00 -1607050000181a141f0004010a151502011f1b01061a010101160e010f17091c010114091d040101020101011c090912011819011a1c011a000601010614010c -050101011500091b001e011e1d010705010404010110160101030901010101190c0a141600001906010205001f011a120d0118181007100d1c1c1b1c09090706 -19191408010201010202021d0b0806170c0a000f0101090e0801011012120f000b01011d0003010108140000151d1f00000a0101010101010101010101010101 -01010101010001010101010101010101040011070102011d001f071212060101010101010101010102141b010a000f01041401020105141d121b01111305011d -1801011b1e010101111414001b121f01011d130014080109151a02161c07011a1314021c0000101e0a1e000c0101151801011c0b011e050108121001110a1004 -010104011a18010201010101111a011c081d1701011c050803010101070b01031f0105010b0009181e1606140f01010b010e1e01010f130601180a0101020107 -170916001710010109151c0d010714000f11001e1e141c00001e0902051a0f19020003010206010102020202010e001111001f010106160d1e06011e00091900 -0f010700170101021700130e081800161d01010101010101010101010101010101010101010001010101010101010101010a00130e0101010e00100612120801 -020101010101010102071218011f160601151e010101191b011e141a13170201190d010616030101081e0611161f161d01010a00001c0601011711021c000301 -03001e120000191e1e0a0000100109131f0106140f061c0203140e0000071a1801081e010a0c0101010101020c1a011103011e01011a040101081b10011a010e -0407001808000f0a00000e1410010111020a040101081606010e19010c0301010b0a1e0b0101011a001702010914141f14141a140000001c1f17090c1d08130f -1b0c010d151c0e051001010219041d1c0005010101150c1f1c0915001d09000b010119001001010c0000131e0000121d01010101010101010101010101010101 -010101010100010101010101010101010102061800151d010119120110131b07010101010101010101010900050118160802161e010101171c010e00001f0101 -010801011a000f0101051e0614141b160e0101050000140901071c1c0904001f011c000000000000000504001b01010a1206010f17010f1514121e031e011918 -010f1e0110100101010101010d0d010d0d01110801010101011700060219070011011c000f151f0600160e1b0f01011b1010110101011c09011f040117190101 -031e1403010611000d01011f00001e1315011a001416001111131c1d1d14060b1601011c00111d1b010103181d06150009010101171e011c1c12160907001b01 -0105000e01010f0000131912131f0702010101010101010101010101010101010101010101000101010101010101010101010101101c001108011b0006090014 -07010101010101020101010d001a0118120207140e010101111c011016160a0102010101010d1b01010104041a001212000b01010f1312120a01010400100216 -1216001f1b000014160c1d141b0401010d1701010e19011f00000b031e010b0e01051e0101010101010201010a1101111101181a0109100101141c02071e011b -1e011f0017111b01121e17160f0101171d010f0101011c1001051402021e10010114000409001608010f1c13191200050101191e011c12131f1d071d160f1700 -08021b0000041e0e1f1b0d0203001508010101181b010b00001308011e00080110001b0101101300001c01010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010205140005011217010a001e01010101010101020101011f0005011715020114170101010b000a01091b09 -0101100a0101191506010112050300040d120b01010b041d001901011f131f01040000181e0000150814081b0d1c05020117050101141a011500100e0e01180d -01050c010101010101010101071b071413010a0e010a1801021c0b070717010f1e0108130011000a1e150c00100101190f01010101011c10011a000701111e01 -0111110b100d091812120c051900050106121e021b12060202010f1b101f000802121c180000001b190801180018010101011b15011a130b001f010e00120601 -1415020107150013000b010101010201010101010101010101010101010101010101010101000101010101010101010101010101010101010514051d0017020b -001f010101010f0501010101010500050118131d011c170201011b0d01011f1607011014060101141b01011b13071816161b160401011819071215060110001e -01040000000000000b181b0f1b0f120f0108160f0110150a130001190e010e030106080101010101010310010616060f000d0f1901080302010c10091d120701 -1c05011e001b000c0d1c0300070101191d01010201011d010109000f010a000801031f1f0e01040011080300131a011d121e0204001c0202010c1e0104001d08 -121c0a0000130b01010915120f0101010915140202121f11110105001f04061b120901071b001400001001020101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010201010108011f001b061c001f01010201010101010101010a000a010b000d011c1b0101050c01010117 -1e01010d15010110000e010b0014020400140d0e161001171b021e000301071e1b1f000000160013130a130d0419191601010a1607010e00001901181a011805 -011d05010101010105001001011b19011b1b020f02010501021a020c01170e010c19011d0013001f021c09120f01011d1d010101010101010101141d01060003 -01060c1d1c010a07091b0015100103000b0f120b1c0a0117001c010c001a07131b011b0013000901050017020101010d000d01021c0d1814010a000510141713 -10010a14001b170018010101010101010101010101010101010101010101010101010101010001010101010101010101010101010101010101010101010a1313 -1200000a03110101010101010101010101010103000d0117001d011b09010102141f0101150d010110000a010c000402171b000e1a1001011b1b010e000e0201 -05000013001f1714190e0d000a0f011c180101190c0101190010011809011805010d0e0101010102140501010108131a07131d0101010c020104010c100f1c01 -0616090114001204010403170a010103050102080101101d0101141f0101111d0101111d1c1f071b00000c02010e000d0b000d1819011900001c1e001a011512 -071f001c13180104001f010101021c0003010115040e00061a0011061600130f010d00001c0500000f0101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010a0000131c00130004010101010102010201020101010f120f011f00181404010201 -091707010f1209010105000a01180004011e000018010101011e1b011016160801061700001e0e15011b0d121c01020216050101170a010a001001170801051d -010e0b01010101031401010101010c1401041c0101010c05011b010304011603011e0c010400121c010a0d0a0e0101031801061701191c0f010118180101070e -060119191a141b001e0f01071c001d1016081817010d000311001508011514011a001c0313171200100101010d131c080107151619001d011617010e13130f01 -050000000b1e000e010101010101010101010101010101010101010101010101010101010100010101010101010101010101010101010101010101010101011d -13131c0000000004010101010101010101090901010c001901061813000f0101011919010119160101010b000a010c0004110012001608010101181210010c13 -0e0101170000101e061f1b0f00110101101507010f14010d000202170801090f010a0d010102011e1f0101020101011b1f01121f01011a1b011b0f010e010c17 -010d12010a000014010814091a0101061f01011d0713030101010f140101010f1d011a170116180f01011a00130f01161f0512011f00120e001407011c14011d -001609170016000401011a16130a010109131919001d011b1b011d00000a011d0000001817001501020101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010201020e1300130000001901010101030101010f000b02010b00161c160a0a160702 -01010a03010114190101010c13090114000000000000141d02010118000a011a121b070a00001e0b1101120f0f000d01010b1e0101051414000701170f010519 -0101010101010614020102010101011a150111000701061b010b1a010e0906120808001a011400001a01140a010101010101010102161001010108000f01011d -18010617011f1801021900110110130c1f00060300191c000b07011714010616000918000506130a0516000c0101011a00190d001a0115001111001b09010814 -0000180a00001a010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0201100000000013000401010117140201010f1400190207051e1e1e011117010101081610010f130a010101040010061213131c12000000050101010d000d01 -011c001b0000000d140f121e0105130801011e1901010b00130801190f01100a0101010101011f1e0101010101010101141f0c001b0f011b10100f011d0d0115 -17011517010d00001b010c04010101010101020301170301020102121f0101010c02011e0f07130e1c001a0119000419000a0e000306130a01071c1407061616 -061a001d0119001b00170801010110130c18001d0214140511001407010614000017061400190101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010e000000000000110101010412100101010b00001e1001010b0c01141a -010101031209010e0004060101110007101c060e000000000018010201091311010b000c140000190b0b0d000601181e010106120d010900120601191f01020f -0101010102011b0e01010101010101011f1405000011010d0d0110010218010e00091d130c151312001001140801010101010513011819010101011e11010101 -180f011805011c001502011b00031c000a0e000306000e01021c1c0108121606081313111c001600180102010105151d19000a081614070103001001071c0000 -1e081c001e0201020101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010c0000130000001c08010118001f010101011d161e01010117010a1306010201041401011e00180101010414021f15091b0000000e151e0201010913 -1e05130105001e000e1c061c0e01011e0a01010f121007001c0106141f01020d0201010201071210010101010101010107160512000006081407040601190a08 -000b01121515040e000d010c0d010102021a0500010a1b0101010105160101011f1f010a180119001a1a150c1015150203001c10000b01061b1c010913160606 -120b060d000c06000a0101021b1c091b000803001702010d000301071c00001b0217001507010101010101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010115160a05171300120f010103121e0f1a1f0f01010101011f1c011e -1b010101011604010812001d0101010d1e01041b1012040019021c000a0101091300000c10001700110b0e081c0701081c080101160c09001c010f000b010207 -01010101010a140101010101010101010115050c00000a011f060505010f17011512010c1e0204050e1e010314010101091b1a1201021c070101010215100101 -090c01071b06011e00120a100017010b00001c000b01081612021d00180109001801010d1b01191601011a161703121b0919001901021f000e01101500001502 -0c001806010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101011d0011010102091c0018060106140013001b020201060101041a02130c01010109160a0105001209010101040d01180c100016131c080c120b0101 -180000160e00120b131a0401051e01011f15010616061f000e011d001e01010e0d0101010118180101010101010101010119170500000e01100c060b01011706 -05001f0713061e1517000901161d0101101b08001a0211030201010115190101010a01011b10010c1b010d000b1015000013000501081214020a001f011d000e -01010b13011d00090219161f11000c0a16000d0102040005011a13000017020c0019010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010e001c09010101031313050611000013000a0101110a01011e07 -0a00030201010f000a011f00110101080d1c0a01120d1f120c141b0106161e01011b161400151508041919190117180101191e1a1b010b000a01091719010108 -0801010101150d010101010101010101010d140300131502011808180f011f1f01151c0117191000040018011f141d01101c01150e010517010101011f140101 -01191d01181a011a161e000b030000000000001a0912000e11001d0103120501011f001d02140015141105141b010a00160f01061b000f010c00000004011100 -19010102010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010201010d00131a010101081700001300000000000a010f1b07010b150117001d0101010c0010011b000b010207061b09021c080b1605131701020415 -1d01111600030c1908121f130801150d011a00001c010c000a010108010101010101010207120f010101010101010101010a140c0000000e011a0a031801061e -01030007061c0916041e001001141201061e010b1101081607011d010615020101191d010504011900121a0b00000013040b0015140000120005021b15100101 -0e001a011e00040a0a11000d0111000406010814130f011e000000050916000b0101010101010101010101010101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010101010a13000b060101010f000013001b080c1501010d1701011c -0b02151c010101011100090816000f010101081b08091c071b140f151e01011a130c061400190a1301170d171b0108131c1519001c010c001a010201100f0101 -010101011013080101010101010101010106151b161c141806010310151001181807001c0212180c13050415101d1308011c011d1c0101040d01171f01171d01 -011d1f010912161515121c00000000040f160000001c03090404001802010118000a01091312090a121e091d13000a01010d00150203000000000b0b00161a01 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101011d15001408010106130000001c010118040101140c0110000f070004010101011e00061f0015010102011a1b011a1506151e0615150601 -061e1517001c01160a111e02131f08130003010e150119000501010f1d0c0101010101011000100101010101010101010102151c1e0b161f0b01050d041e0102 -15070a00080d12101318061911011405011c0f07140601061f01091c011d1d010110190101141a011700000013000b1f13000000120a190016151f0101011b00 -1d01011e001e1e001c091e001907010111000d011900000000000000110201020101010101010101010101010101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010101010102010d00130c060d0013001305010106131a01081c0701 -0b1b011d000d010101061600101a0018010107060c19011f0d021615010c000d010103000000080b171700060a0000040c08010814010b000e010219071d0101 -0101010110130201010101010101010101011c1b130e000f0b0102150e140f010e1801181f01160f1100041d18011e0501040b01040f01020101010b1f010508 -0101110701191917120000001b1d18000000001c081a110a1a0801010f14131d01011f160801071213131e0901010a1212101015000000170e0c1f0606010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101061700131300000016020f06011a140701051f01011b1b010c00030101010f001c011013190101111a190e010d0c1d1606060a00 -15110d030000150b130a001b1e0013080101010114070a000b02010f01010101010101011013060101010101010101020101191913100901100c011911191101 -081c01080d010b180b0015031e011919010c1b010c0c0101010101071b01030b01011110011f160f041313001e1e13140000111100111f04160d011700140901 -010d00100102170013100101091c000d011900000016030101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010101010101010101011d150000000014010b180101041e0101191a -0108131f010400080102011a0011010f001b01080b01110a01111f010e001a0b1312001600000013000304001c090e0e0101020117101a001101010101010101 -0101010106131d01010101010101010101010e191502090207110f0c000f1b1001180e0104100213001c000e14010d1c010f15011d1b011c050201010b030117 -10010d0f011a17020a00160000000000001b0c131c001c04001115130d0101010f000d01101c0004080f101900161f0b16000000040201010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010102010400001300001f011c1d0101140501091508010a1308011514010101011d000d01090003010701071b09011e0502160004 -1b1d081113000005191316001e01010101010101041f10001e01010c060101010101010101141d0102010101010101010101090b15081e01060f0c1f17010e11 -010b130d040a011b000d120e1e090a1c010115100104081f000f0101070b01050b01050301061e0102001c051b00130013000018151c021e000017010102010f -000401011100110d1613001e0f1b00000000001f0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010101010101010101081500131f1c0008031c01010815060119 -1501010c1202011515060e0d011013030105140701091d091b02071e0f0f000000120f010a00000a081300040e010101010101011f0c06000009010201010101 -01010101011b0d0101010101010101010101010b150118011d0801011e1d0118091b001c1c11011a000e1a18180507120601170e010e0b010b16010101070101 -02010f0b01011e07021e011d00000000000000000b011f171b13070101010f001e010108000012130000191f1e000000120d0801010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010614000901150007180c01010c170101151801011518010f00171a000f0103000d010414010105010f15060716081d16 -1e000019010d000c17001b010101010101011d011d190616160e01060701010101010101010c140101010101010101020101061115010e010d1f01010511010a -180a00130c111a011c001e12130501121d011f1501101801011c0c01010f0e010101080b01011e09011814000013130000001509011a121d161a0102011f0004 -02010111161a16130013171600141b1f070101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010101010101010101010101011d12130b0e001e02141d01011e1701 -06141a0108130e0115001e0b18020105001f01170c010107030b1e02081c080919060e001b031b13001c1d010201010101010406071102171b17011805010201 -01010201010a150101010101010101010101180015011901090e010101111001150e13000a0a18010d001219001e01181d011015010119070110150101021e06 -01010119010217030e00000000130000001609010213111b180101010300170201010e001f0c0013000301151401010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010201011e00151800030f150101060019010a1501011000050f13000e1a1e01020a00171700171d1d000b0b15010f1406 -021d021d13001900000f010101010101060605060104071e1813070b1f0101010101011e0f01150801010101010101010101091c1c101c0106170101010a1901 -0b041c0002021b06011612011900060a0b01011e0a011d1d01010e0e01011f1a010102170901170e0e00001300000013000901011713121c0101011f00170201 -011d000e17170900120111000a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011013000818000e1c1701011d13 -1d01041e0101030010081400040e1702020a00000b11000d0613041f18010e16021019060104001300000b01010101011a03051a01181a181e131a1f0c010101 -010101180d01110b01010101010101010101010c1c101b010817010101071702020d0c000501180b010e170101141a061e01010c0b010608010102040201070d -010101171d011b0c04000016161717001f010f1613001506011a14130008010105000b0b14011e00121c00170101020101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101011a001b0816001f130b01010e1501011b1101010416010711000d0e11010105000a011e190910131f1f05011c -190108171d061300000b15150101010105091a18010e181f1c1b1908170101010201011f0401051401010101010101010101010c1c101c010817010201010c0a -011a12001e021f04010b120a011a1608161d011d1c0101010101010c0d020218060101181a011b15150000110206131e01091500001310011d00000013080105 -000e0d0006191c1b0000001d01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011f000d08001b0b12060101 -1e18010800040102111509010400051917070105131007131b010f001f0e1807141b070617151312001f0109020102010e1d091b011a1b0715181c081e010101 -010101061101011c1d010101010101010201010c17101501091b010101011d11010813001207021e071a160a010111051e0c01011c090101020101091c07010b -0b01010b0a011c041b131902010c131f0b0000131506011100171d000b010500051f150717130a12001c09010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010216001a0a001200110101071519011f000f010216000d01170019161609010c0009071c0c0105001f190b -08001506071212150c160c01010101010e0a011707071c01111f1b0517100101010201011908010e0b010201010101020801011115071401100c01010102010d -09011900000a011e0d010a1706010a0c0f1c0101040d01020b0101011c0e01101801010505011c13131101011f0016160000001210010d001d011c1b010b001f -0b13070d00101e001209010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101091213090a0013000d01 -0109000c010c1c07100c00000e010c120000000a011f1209011700181d120b180b1a00130516141308061512030101010e0301190501141d0319051f0e0b0101 -090901010e0e011015010202010101081309010c140118011f0b02010101011d1f011d000017010e191d0d00050108150f1c08010d1e011d001d01010a1c0101 -1e0601050b0600180919011d130000000000000c010d00030111150704001e1b1c011f13111100000a0101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101011d0013100d0013000301011a001d011113131c1500000d010d000505001f010c12070915000c090018 -1e1917151300080e1303011d14090101030b01101101110d01160f0b1e0402010109010108040101110e0101010101011e18010d150804010d03010101010102 -0e01011c0014010a11051d1e190101040d181f01081701021b040101011c1a010d0301090d061701061c0d0000131200000014070b000a01171e0715150c0015 -010d001513130d070101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010e0000100d000013 -1001010c001001111213130000000b0103140807160b010c13131e0e000b071b1c1500151b0004040014141a011a04010f04010217011817010c0b0b00150101 -0201010101171a0109150101010101010312011f140818010d03010109100101190b011f00001010001a071800010110040f1b01010c0901061e0801010e1c01 -0a1701080e080d021e0000001205040013130c1b0004011800041612051b14020d00130019010102010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010201040015010b0000150201011e1207011c0016170c12000b01031409011704011f00131818001806 -150017000017110013041d171715001c061801010510031601081d0800000f0102010101010a170101040b01010101011d13010514010e010c030102091e0201 -0312080115000509000d01021c0f01011c0f0408010e190101081e0601071c06011801060c1019010400111f0a15000000001300000d1400001b0f1f000c0104 -0000001f010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010100010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011e001e1d1700 -001e0101011e15010d0011090c0c13001102101303010416080f13001c0f17131a1900000016031c00001e011a1c13120f1806010f1b07121d01020117161e01 -0102010101011e0f010f1502010101010812020f14010b01191d0101010d1f0201131d010d00040900161002161b01010d18040d01090d010101191901010e0b -010c0801190f18010a1c02051300000013000000000014110d0d1b0005011e0000000e0101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010106160000070400001901010111110211000d0d1919000016070f1319010c001d08150017011d -141a1f13000000120903001408091903100b1001011c061b0b0101010108001a0101010101011e1901011b04010101010812020a16091c011809010101080c01 -01041f010f00160b1e16190d00000501071c0304010101010102011b0901081b010b0301170a1801190000131513000000000000140a0101010b00050f160013 -130a0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010916001706 -1b00001801010115131d1900081015140012130f021519011a1619011400121001040c071e00000017100a00190219101f1f0d010118180a1c01020101011719 -010101010103001608011d130601010109170103161015011708010101010d10011f1101080000161e1e190f00171806011903040f0109180101020d1b010111 -1a100c011e0a19010b0000141313000000000011010101010d1c1c1b000013001001010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101011a0000141b0000000b0101080011010c001002141b011d151a011c15010215111d1b0d16 -0b01041b091a190000001313120f0509190a0401010f1407151001010101011109010101011a1704170101171701010109180103121d1b011708010101011f1f -01071b02020000000c03040112191005011d1e050e01011c1d0101011105011d11080c011b0d170117001300151405170000040101010814000000000000001f -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101030000 -130000130005010111000c0111000a0f131d01081c0501151701011f1b191910151e010513181900000000170f030310030f0e070101171a0418010101010119 -190101010101170517070106130a0101080401051c091e0111080101010106180101041a011213000d010801041502040201140304010110170101011d110101 -1b1f0b071b09170a1600000000170e1600161018011a001e09091c0000000d010102010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101011d130000000000131d010211001e0119001e11141a01071c11010c1b06011c000016 -1e161b060619000000151705010f0f0a02080e0301011a171a000901010101010201010101010b0e03040101051308011d04011d1b0919011106010201010104 -0f011f1a01150000050101011f000e0a0c0119131109010206050501010f0f0119040b0b11010c00000000000000040416070c001e000c011a15130000030101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102010f -150000000000000c01011900170109131b061b1f01071517010b1c0f1f15000000041b0003010d0000141f07010c060d0219190b010101141d18170101010101 -010101010201101701151001011f08011d04010f19020d01170601010101010a0d01091f010a19000e0102010418150f11010f150608010101021b0a01101501 -08121610010215000000000000001616060f00130019090400000015100101020101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010703160404000004010111001107101305011b1c02010e1e0210131f010400 -00000000001c1d0d1517001e010e060f011a0c18020108041b09130901010101010101060d010117091a1207060701011d1f01050e0619011b07010101010101 -1802010c07010e000e010102140a0d1c1c0b01151a0101010101091409011e0e011e000801090000130000000013140f03000000001b000000160b0101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0201010101010e00001506020e14000d10151a0118001a01031b09081311010e001b1400000000180d001300011a100f0f0211111f011f1600090b1e01020102 -060101010d02010a0e011e1b1b0501010303010b0e081101040101010e1001021909010c0c1d1d001d09090100170114001e010e0d010101011a01111e010917 -010a000a010b00001c1a15130000181413001300130000120e010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101020101010f1c001c06010913130207150c010d131d01091c0e06161102 -1d1b1e1b00000000130000001008030111020d1f11010118121e08160901010619010101100701021807021c000501011818010e0c1a170104010101101c0101 -1f05011a001a0618011810101616091f131e09060401010101170c01131a01181d07001f011119130c04000013000016160000000012191d0101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101071c00121d0109141b01011b1b010f001d0106170d0119170802151b031400001e101100030219010b0a02050d10010205000f0312010101 -0e0a010110050101050e01021c030101180a010e0c1d110618010101010c0d01090d0110000f05000f18060d1d1f15011b131801040f010201091309181b011a -0401120d0102011c0000000000001314130000131e070c0006010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010102010107190000100101111409010b121d09160d010111140702 -1611011f151b0f061c1b1e000e011710020e010d0f0101011f14001d1a0601010f040101020f0101011c1001030301010b06010e1f0a18060401010101091701 -010e0108001d1800001901041d01120f0f0000061004010101011f1c061e090117071e0c01011a00130013001c0c0c1300161f06010a00190101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010c00040201010e00030105001d01161b020715000a0111120e130011080117000e0b01040c010b091d0c0102011014171401010101 -01180701010e0101091c04010a0e01010406010e050c18100401010101010d1a010d100114101c00130a01110f010b15011b0003011110010101011503031701 -0d0d1f1e011d000000131908010e0000180701010813150601010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010c131300110101010a131901101b0b011c1310010400 -18011d1700000000141400100b060a0c010a18011c080101010409151701010101050f01010310011012130f060e01020407010e030318100401010101010a11 -011a1a011110120000080211010201150307001e011a0d010101010316071509021e0e12010111000e02011d1b001e09010101101c1306010102010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010a130012001b01010106131b0202141e020c000d01060b1b0f010f140000000000080d0a071101011c081a1f0101010e0e0614100101 -01030b0101031f01010d1e1e060a01021702010b03031807030101010101071407060b01040c151700070811010101061c071e000501100101010101151d1f0e -011e0b1c0f011e131f0416001b070101011d1700001a010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010615131b131209010108141402010c12011a130e01 -010e001c06010f1f1f0e1610090d011c080105110101030f0103190102010201010818010108050102021f031414020717010111050a1f080301020101010117 -1a0118010a13030c13011d1a010108010c190f001501010101010101031e0211010a1b1b0f011200000012111f1f17151600120d1d0101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101111c0917001a01010204160f010a151a01191b1a010804001e08010101171d010e010d190101151f01090c0107190102010101 -0101030101021f0207010106191201091101010b05050e0d0d010201010101050c01190910120f0515010a060101110d06120219000a01010101010102040218 -050114001f0216160e041e1315171717110302010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010111140203000c180c011012001f0715180109 -161318081d150013140e130f010d09010c01010f1408010a02021509010101010101030701010c07041a010d1d1e1a080401010508030e0a0f08160201010109 -0c01050901110f050401180201020913060e1102140401010f010101011f19091401190011111701010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101020119000c081c000015030704001f011b140801170000170f0d0000131311011d1101050b0101051f010101011b1d01010102 -01010b1001011909071702090c190506110101050903040c06081b01010101081b01031d0111031117011b010201010e17061208180008011001010101061507 -1e0f0f00000e01010101010101010102010102010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010111000b011100000004011d001c1e0000 -05011a14000012000000181502081c01071c0601010101011d01181d0101010101011a100101181a011d17020c00020f1c01011f0a100013060f050102010106 -15011d1f01040b16110f1901010d1b0116050b18090018010201180f01011b1f1a19010012010201010102010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101011f0011010b000000131f0313121600131b10011d1e00001403030405011810010e1101010101010d070e0d01011a0e -0101050d010105100101180b02000a101c010106011d0015011d0c01010101011c07100e01040b00040c0c010106001a1a041d16011e000801011f1701011d14 -0819011b000801010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010e0011011a131714150d1f1e1218 -120012191d0214001415111d1102180401010c090210141001011a1801010a0b01011a0c01010101010101141a11190216060201010f00140105180101010101 -1c1002130911110014140f010101051c011b1d0b0a090005010101151a01011e10191003000a0102010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010105001c0707171e001f0a0a1f1718040000001400001f1114071c0007180f01010201010c160107091801010102 -0101100b010103090201010917051e021609010702100016010b0d01010101011c100900100e0e000016020201010218030c171a17011c160701010a17010119 -19031808001901010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102011d00151015161e001d06031a -1116191e000000120901041f0300021a1b020110010101160d020111080101010101060b01010a090101100105121601041d01010110001c0118030101010101 -04090a1410050d1600170101010101021c1b1307110610001e0101011e10011d16101e09001c0101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101011100131316001604080d1e17150c0e19151702020e131c000d01171710160101010d1c01010201010101 -0101080b010101010101010101040010051f020b0109001501040a01010101011f08010c0b050e16161d0101010101010300131d1f04011b1c0101010b0d0101 -111017031e0002010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010108040903130000141400150a -031c1400160b070d13151500130f01010703031101010109120601020101020101010911010101010201030e01021317011c071b06060013010c1a0102010101 -1807010a0e180b000401010101010101011500171016010517010101091101010d110d0d1f000a01010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010107121209071e0000130000001e0f0d1c00001316000013131501010101010305010109011b0c060101010101 -0101021901010101010102180e011900020e030c0606001601041a01010101060c0101100d1e14000e01010101010101020d0014010403011609010101041001 -1d1c0f190a1308010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102010b120d01030000000016 -00121e10100c1b1c1b0000181c0101010101030e010104100a00160101010101010101040201010101010101140301000909190d05011213010a09010407011d -190101101917140b010101010101010101011400070a140117051d0e01031f0101151a1e03001001010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010d040f0f1400131215120013150b031a0b001e0e1801010101010a0c0101040f0213120801010101 -0101011b07010101010101010314011e18071b1d18011b00070d10010301010e0b0102010e0b181d010101010101010101010c00110716071a17021101061901 -01040505040005010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101020201011015111f000000 -00141313171200000013170e0d01010201011a0401010101011e0301020101080801011902010101020101070e000303000a1b1d1b061800060d08011001070a -070101010c051d01060a01010201010101011d000007111a0118071109010c08021d0d0f0d160501020101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010a151300131c1200001515120a110011110e01010a0101071c07010909010e190301010109 -1a01011708010101010101190000141900110a061b100b00111c0f010f010e0d010101010c120501061410010801010102010115000a0a0d010d100303010503 -01011e0f1c000b010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101190000 -1b1f1f1712131212000011110a011a160201010403010201010a121402010102020101140301010101011a0000000000000003010c0f1a000a1c1a0101010e03 -02010101031e0b01010d040112180101010101180003061701020a0f0b01080c01011b1d1b001b01010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101040013001909010102081400190505010c1f0102010a1c0101010106141802020101 -0102010c0e01020101011b0000000013001e1e010c0e011b1d0c04010101030901010101090d0f0101011e08051206010201010e0014061707011c1d0b060104 -060104191b0000020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102010e00 -000000001b041818160019050b011801010101010e0101020107141a0702020119070106100101011001180000000000000e01011f0b01170d1a04011d010308 -010d0801060e010104060319010c18010101011d13140d191007000a0a1a010c0a010c1919001501010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101020118000000000005100318000017030b081701010101010101010101011e130f0a0801 -19090101010101011018091300000000001801011011010d0d061e0119070a06011c0801010b02011f1407170801150901010108161f0a1a1f0700040a0d010a -0b010a110e0015010201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101020101011800 -1100171700181d1800001e09110a0d01010b08010902071a01010c140a0f0d011803010101010101010d191613000416001401010211011d110117101a061a08 -010e02010108010101110d190a010b0b01010101120a021015011813190c01091901101515001601010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101141b1b0013051016000000000c010b0b0301010b0d01111d010f010104110a021101 -050b01010101010101061218180e010a14151d01010b07071402050c05060f0801050f06010101010107170e1707061e01010101161f0a07120f0a04161b0101 -180108150b0000090101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010910 -121500130b0708081e0019010c12010101061e020f06010101011f150b0104061d1101010101010101010902010101071106020101041f01141f011b19080b0f -010e19170101010101010d0a1414011f08010101161f1a09180b0f16161510011e0607150e00000f010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010f0f0c1f021b0014051500131f0119151c010f11010101010b0c0101011d020110001e010b03 -0817010101010101010103100101010716080101010a15011e1b0119001a0d1d01110f170b0101020303020a070e1a05050101011b0b091f0917060c0c001a01 -1e1001040a0016010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102190e0e000013 -1e1e021500131312130015010f0401020102011d0101011d09011a001d011d1c01171a0e020101010101191f100801011810010101011f0801160c0c00031a1d -01040f1d1e011001101e070c011d191d180101011b04011a010b060b05001f01191d011611000301010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010103160c041e01010a001b1a1616180014011d170101070f01010101010e11011f160101011c -1017101e1801010101011905180e0101010101010101010201050000000d031f010c1a011b010409011b03131801030f1e0101011e1101010101010b1d001801 -0d1a01120e160f010201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101020101010f1c1606091e04 -01021c000c01021f140000021d1101010711010201010103140109030102010b000003011c1d1f0101011f1a19040106060101010101010101011c000017030d -01030a0104090f0501031a130401170d1e060101040401011a11080c111313010d0d011205000501010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101100b00001c1f00001f010b13001a0101010d00001d080c0101010b110a01020106150601010101010a -000003010c050c0501011d100e1c010b0e0101010101010101010d150d131517011d03010d1f0219010d0c131a010e00160701011b0c01011c000d0a00161701 -0d05011c05000b010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010604000000130b18000e01 -0e131b04010101020115000d011901010201191901010101191d010101010101151206011a191d14010103090813010a0401020101010101010109121d121213 -1f0108011a0d0111010e1b1101010500120701011b04010119000c0f001411101f0a08151d000b02010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010714001200000b011e0301050003120a0101091606190019011b100101010f03010410010a0d010102010101 -010519011a19010e0101170608130e0614010207010101010101011500000013001711010804010c1a1c0005010614161e1c0d06140005010800121a0013121d -1f1a05141d000e010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011d141304171c1e1d120d010e12 -10010d121001010416160018011b0b020101010101170c01101606010101010102021e02070c010b100711010309111d1b0f0f0e010101010101011e1c1b0000 -051700070204010c1713001b0413001214161814000014010712120f13001e060a0f181e1d160801010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101011d1313101e1501011e040103171001010c16010101071600000a010514010101010b01031b01011e0e0101010101 -0101181d011f01050f1a050118011d1e17180104010101010102010d0d0b00000c10000a0117010b1a1d1c00171f0d031e11191600131609041f161012000a01 -0d1d1c04010102010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201081313080b000f010d0401030c0101 -010f141b0e100c0105000005010714080101011108011707011f000f0101010102010e0f010b0105191710031801011b1c1b01051f0201010101010d0c0c1519 -000819030117011f04060e00001c0b1712130e0c000d14070b071e1a13130b05191d001f01010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010111001d06000301061b02031801010101180a0b00151c1b021c000e0101170e0101021a0501191f0101181608010101 -0101041f010401051318011e1001010a1c1b0c01150601010101010d041e0b01141113190111010e160d0e091f140000130f0b1e1b1a001019101b0a1313111b -191d0005010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011f00110111040101111b021807010306 -0c15011500000b1b0c03001402010a1c0102020204011d190101010c0b0101090801050f0105010b1901050b01010101190013020b0b010a0601010b18170501 -040f0f15020409121f03040b04140014000d02011b051b0c0b0f1b0500000c1e1417000501010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010713130705120701101c010a10010c0b0a0008090000001216170600000301011509021102150f011c1d0101061e01011a -18010f06010b08151a011e0901010101021c00040104010d17010104180206011f0c0113100d081316191e1e04001101081e1209130305151a09171a00001a16 -1316001d010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010d131f01130c0101110d0f0c0108170816 -03011a1600001300000919001e02010c0d020e0d0d19011811020101181d01091101181d010b05140117180101010101010912001a0a1101110a011918010201 -1d16081318041b131f0101011a1b0701011a0013130303001a09151d00121012131d1a0101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101011513011d130101011c07191a0101010d0d010d1a1f00131515001f1000001d01091c0102110d1e0109130502011a1b0102 -180119070f051b04010e09010101010101010900001a1605061601191e010201080017130000131b0f01010b001a0107010413091b050814011d190d0c0b0712 -000f0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010f000301190c01021d1501070201011f171f -060c061b000b180300190f00131a01011903011a0d191d0117000c01011b0a01181e1701181813100101010101010101010101101e0012001a1105061d010101 -0112121200131316001f1800161b1b161b00121a13101f1c080d18191b1b011c000f010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101011e00020118100101041c010101010117000f01010a000004041b0015101e170a01011d1901011a0d11011d161508011a0d01 -0c00100613001101010101010101010101010101010b130012191b010106020101121f1900160c001300000b0810160016081a12130217151f151915001e0111 -12020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101020101100004010818010101111101011008011a1b01 -010f1404001c0b1413130e11040a0101011b1001171a170f011e000501100d010a00010e001310010101010101010101010101010101070c001c1c0b010f0b01 -011b0000130013130000001e17000000131119131c0118181d1800151c0e01160014060101020101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101011d00030109030101011e0801070f01010e1a0101150a18001808030b13191e040d0101010c1e18001a0d1e01060a0b01081701 -0a00081b0004010101010101010101010101010101020101011100001d011c1f011b000f081f130000001312001c1814131413001e01071f1412160000171d00 -00130601010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101180006010a1f01010a0401071802010f190101 -170a10141e1e06010b000b1b0b04010201091313110802000c010103010915010d000111000c010101010101010101010101010101010102010215000010101c -010910010101080413001209050701070b0000001101011f13131319001c0d000016010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010106001c01010d1f01010d10010b0e01010c1001031101180f0c1c16090400191c1104010a0b0108060102011f0009010802061e01 -1700020e000d0102010101010101010101010101010101010101091213150910040101010801010118000010010101010a13001707011d0c1314121813131c1c -00131a01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101011d000b01010e0e01010b02011808011004010111 -0f031c05150a1601180019001305010115100101010101010601011d07060c0100110212000e0101020101010101010101010101010101010101011013001310 -111c0101111f01010115000f010201011c001e070e0217151c0014191311190000000e0101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010f001f01011e0007090401091801010e0e010702010f1010060b1e0119001813000a01010b180101010101090a010101010d0b0f -000c0300000a01010201010101010101010101010101010101010101100d04001f17170201110a01011719010101010f0015071d180f121213000d01191a010e -0b1c0006010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010103001d01010305010517010e0e01010405011f15 -0601010106161a0104000d0000090101011b0f010101010804010201011e0b0c000b16000010010101010101010101010101010101010101010101010101011f -0016001c10091406011c1801010210151505011706051c001b1902011e0701190217000101020101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101021f001a0a010101010e0e01170301020e0702010d1b010f061d17010103130e001c010101010b1801011f0601110b010101141513 -150813001c010101010101010101010101010101010101010101010101020101091e0000001514140d131d01010214030605150a010b0e1b090101100d010f11 -0117001d010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010a00141e010201010b1a011e0901070f0b1a0102 -131a0f1701010101011400000401010201061408010b0e011d000501101215000b02130011010101010101010101010101010101010101010101010101010101 -01010f19050b1400000e0b1a01051f0102140d010300000e0101010a0901111a0116000501010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101011a12150402010201181d0118070110001f010101131e011e1a0102010f151100050810010101170c01071e06011c15011a141500 -0b0112130b01010101010101010101010101010101010101010101010101010101010101010201080b000015010101011b180102041612090101030d01031e01 -1013000b010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010a00001801010101041d01180101031b01010106 -0500061d1801010105151700090c000601011d1d01010e0d010e00081d1e1312180d1b1a0a010101010101010101010101010101010101010101010101010101 -010101010101010108130000190f1b13131001031b17170101061508011e10010415151c01010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101070b121801010101180f011f01011b1a0106151401041f011e0601010d041b000300131701021807010110110105001d01110008 -14000e01010101010101010101010101010101010101010101010101010101010101010101020201060004120000130000160f0505170901020108010b0c0102 -14101800080101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201111901010201180f010801081e01011f0407 -010f030118030101151e1313021419171a0200030101101e011d1c0d0111110118000f0101010101010101010101010101010101010101010101010101010101 -01010201010101010d000316000000001403161402070101010101081408011f1701180005010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101111901020101110f060501030b011d1c020101010b101c11011d00000000100c1f1d1710001901011018010e170d011c1401 -0d00020101010101010101010101010101010101010101010101010101010101010101080d04151e1300000000000000000b0f14030101010101010b0b01011e -1d011e000b0101020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101041101010101110f060501171a01041b011a -0e061411000401010712151d090c19011405161601011019011e130f1f1c151f0a13020101010101010101010101010101010101010101010101010101010101 -01010d00000016160c0b0311000e1a141f0e1403000d01020101061b07011918010714000c010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010416010101011105010601170601151d01131e071b05001801060500030102131e011104040006011a1f08181b1e000f1916 -17120201010101010101010101010101010101010101010101010101010101010106001300000000141c1c000d01010102011115041501010101061d011f0006 -01190000110101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010102010a0000001d010102110e01080104020118010f13 -07061509001b1a000017010105001b0a1911181801010a1a1f181c000b010a000016010101010101010101010101010101010101010101010101010101010101 -01100000141a1d0a06031c0d01010201010101111214020101010201090018010a00160014010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010a001812050101011f0b0101021e020218011d1401101e0112161413000a01170014071b1214050501010702050500000a011000 -0011020101010101010101010101010101010101010101010101010101010101010f001c010101010101010101010101010101090015010101020101191b0101 -14191000160102010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101161e1c0b0101010f1e0101010d010618011d18 -011f0c01130b0e0314011a130314021000000f061b02010706170015000809000003010101010101010101010101010101010101010101010101010101010102 -0108000d01020101010101010101010101010108001e010101010101010101050006190014020101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010111131b170101011f00090101010106110102010104101013000e0e1e01110c01190801140016010c0c01050e140d0100100900 -190101020101010101010101010101010101010101010101010101010101010101010d190101010102010101010101010101010f000501010101010101010900 -19011600150101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010a00141208010104001f010101010814070101 -191c01040000030b0302160605120801141e1b0b091601181d140701160910140101010101010101010101010101010101010101010101010101010101010101 -01020d0005010101010101010101010101010111000801010101010101010911010300001e010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101071200000d01010f001b0101010201160f01010f0a020011050f0c07051e011112061e0003061702161d1a1d0010010c10011a -01010101010101010101010101010101010101010101010101010101010101010101021c001d0102010101010101010101010114120101010101010101010101 -090013001c0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101030000150101011e00100101010119030102 -01011a00030b0c14010e1e01011b0f040003081b011b09010e000601010102010101010101010101010101010101010101010101010101010101010101010101 -010101021c14010101010101010101010101011304010201010101010101010109171a1213010201010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101011c15000d01010500160901020102010101010118000a1c181501030501010b031d000d0912021c070a0013060101010101 -020101010101010101010101010101010101010101010101010101010101010101010101010801010101010101010101010106000c0101010101010101010101 -01010a00170101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010d0015000401081c111901010101010101 -01080000091c041402010101010e0d10000e1a000f12101c00150101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101020101010101010101010101011d000a01010101010101010101010102030018010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010102140000000a010c080101010101010101010d000401160c1402010101010e0310000e10130f12131e0504010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010a00060101010101010101010101 -010110001e0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010e000400140103190101010101010106 -18001309011b1b1401010101010e100900090d1c0115001a01010201010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010201010d1401010101010101010101010101011f0017010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010106120a0e00040911010101010201011700001e0101110d0e02010101011e060a00091b0d1d001e010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011f14010101010101010101010101 -01011f001d0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201010b1e01170005110a01010101011700 -000d0101021e030101010201101601191208001a1414070101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101020104140101010101010101010101010201170006010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010b12000901111b0c17010101010a13170006010101180c01020101010c140117171a001a001f01010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011b11010101010101010102010101 -01080016020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201010d0000110101050b17010101011e0e17 -1e0101020119170101010101110e01160d0e150f000f010201010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101121f020101010101010101010101010f001101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101011500001d01020b1c0501010f130a000a010101010e1c0109040101150907121d121a1f130101010101010101010101 -01010101010101010101010101010101010101010101010101010101060601010101010101010101010101010101010101081310010101010101010106100101 -011f001a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010500001e01010b1f1f020115180513 -01010101020f15010a12010a14010f1b0711011c18010101010101010101010101010101010101010101010101010101010101010101010106020107131b0101 -01010101010101010101010101010101011f0001010101020801010f131401020111000201010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101171c150d010d0301010e00101404010101010101151a1b0b011e04010c1b01010f001a0101010101010101010101 -0101010101010101010101010101010101010101010c141c13151b1b1316080101010101010101010101010101010101011913020101010201020c00040b1b16 -07141e01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010103120f15010f1f0101161e02000a -0101010201010818000707120f011b0c01051c160101010101010101010101010101010101010101010101010101010101010101071200000000000000001e01 -01010101010101010101010101010101011e150101010101011500090900140a01161e0101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101011c0f110d0105010a00060a1401010101010101011504010d1b01011b071a000005010101010101010101010101 -010101010101010101010101010101010102010b1200131c11111500130003010101010101010101010101010101010110000a011a0e18020215000314150201 -0c001e01020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010f000d1f15010302161401041801 -020101010102181601011b0a01030002190016070201010101010101010101010101010101010101010101010101010101011d1211030601010101070a170015 -0601010101020101010101010101010912131a150016170201011d1b130d09121518001001010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010d001b091101031a001f01140a01020201010714001901051b01010e150215000401010101010101010101010101 -01010101010101010101010101010101010101010101010203051d0101011d180701010101010101010101010101010c00181d0e09010101010101011d13001b -09140004010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010216000801010512000709130701 -140301070400000f010706010106060b00001a01010101010101010101010101010101010101010101010101010101010102010101060c160000001b1f010201 -0101010101080b08010101010102010c0003010101011a1e120000131d1d12141400000011010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010201011e130d01010e0017011a1b011a13020115000016010101010101010b0000000601010101010101010101010101 -0101010101010101010101010101010101010101010b00111d1700000011010101020101010912001f0101010101011c0007010101030000160d0e1313070216 -17140515001d01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011b131701011a000f011f050117 -11010b00171719010101010101011b00001e010101010101010101010101010101010101020101010101020101010101010101011d031d11150b0c1116001f01 -01010102010214140801010101011f001308010108001c1b000b1002121b011e1214080c00190201010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101011e1917080803000701041d01120e011e001f180301010101010109161600190101010101010101010101010101 -0101011d16131c1c041f0201081415040801011f00130e1c00000019081c171017170101071613080101010101011e0012000e010a0015181300000b1c001414 -10140e10001401010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010b19140515131b01011e100900 -070600001512060102010102010e0014001f010101010101010101010101010101010716161c151515141319011b000013170a161e010a000000000012000000 -000b010a1200110101010101010800001e0a130c18151000000013001300001901171d1a00001a01010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101060f14181703041419010106010500010300131415010101010101011b000000090102010101010101010101010101 -01010106020101010101081a0101101100000000001e19000000000000000013050104161e00000801010102010c000f1e0c011e00151a130000001300131417 -14001a1400000b010201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010516000000001304141303010101011515 -010500141917010101030b01011b0013040101010101010101010101010101010101010101031614110d0b12180201011a000000000000000000130000130000 -1c00041a1c000a01010101010214000a011e0c01081e13151313000013041d1d12150c1616001901010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101011f00160c0a080f0c000000030201011a0018010c00141d1a010107000b010312000009010201010101010101010101010101 -010101080101061d1f0c1712001b07010109181600000000000000000000000c10070b001b1d0101010101011000001608011b120f0102011a1a1f041e04111b -1313131f13001b020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101021800001d011a1b1c171314000c010101180004 -011c1616020101010c0016121300001b0d0a01010101010101010101010101010102011616040701010101081a1c000e02010101090e171b17041f05051d1d16 -1c19000b010101010101010108001b0b150f0118000d0101010101011d040407071e1f0513001201010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010e000000060c001b1e00001300040102011800040115040b01010101140013131519001906020101010101010101010101010101 -01010106051b1d010201010b151600000018031a010107010101010a1f0a1f16000000161002040201010101011100010f001f01091b190a0d041b14141b120d -0101071312161b010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101020111001b1a0d001d0e00131316000c010201180018 -011504030601010713001513041d001a191a0e01010101010101010101010101010101021119060101010101090a0a0a191b1414170000161e17131c04131300 -1b1b1c0d060f0f0101010101010e001c080114160901190000000019010101051c0610111d121e01010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010111001f01121701150019010111130b010117000b0111040f0601010813001413050112170e111401010101010101010101010101 -010101011e00161f010102010102010201021b151e1216151400001b04150b0701010a0e1b0014010101010101091300131f021800110c00140e1d0101010a1e -0301031c0b1613060101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101011c00001b001d08000c191e0d1100000901050e17 -010411010101010913141c1b1d011b00030c170101010101010101010101010101010102010f0000140901010101010201010d0c0d0e05080101020f0f0f0707 -0c0e0f0d141503020101010101021900000012170b1700000018020201010d0b0e1c031918160016190101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010112000000000f0d00191e1918140d191d01010104011f140101010108141f170b00181c0003031601010101010101010101010101 -0101010101010b0000040201010101010201031c1b151b1c1717181714001300130b1d0d000c01020101010101011a0000191800000d181e0017141709010d0b -0e1500160711000000160a0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010f00000d1d00100c001e011d0306010a0501010201 -011012060101010612090d1d111c121c1102130f010101010101010101010101010101010101010918120017111111100101010201090202020f0d1e1c1b1300 -000000001c080101010101010101010c0013190a1812131e000c1a1112110c0506010b1f1a1c0013130014020101020101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010b001e1c18000b0f00170c0000001b050e010101010101170c01020101151d110e0316121f1c021104010101010101010101010101 -010101010101010101011d171e170410011b0d060f00151e171f0f0f1f191c00001408060201010101010101010101010f1b00121b0c13000000120411131613 -0000131f110005151300000601010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010106000b1b1515001d17000019131718001605010207 -0101071d010101010e05051101181115000c0f160101010101010101010101010101010101010101010201191503051511130013151300000000000000001316 -1b1001010101010101010101010101010101070e1600130000131e1115000c071f0508011b1207121115130f0101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101011500151010001b0413120c001c16041b1c010711020202010101010106110f1b01010f140000051e050102010101010101010101 -0101010101010101010101081e00000000131319010f0b0e0d11151313130d010101010101010101010101010101010101010101020f1d1d1f040401010f0f01 -01010101171e0b000c03000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010102141e010101110014041b0000000015131304061c -070617010101010101190b0b0b0112001f0c001415010101010101010101010101010101010101010101010101011d05050f0101010101010101010606010201 -01010101010101010101010101010101010101010101010101010101010101010101010111001e0f1518001f1d01010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010f1617010114170101010c000013130b1200001308011e10010101010107170a0a01040d11011c00000a01020101010101010101 -01010101010101010101010101010101020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101011c000f021600000000160d01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010f111d0101160301010e160000130b10041d1f17 -0c011d03011902010101061c09010e0f11011d001609010101010101010101010101010101010101010101010102010201010101010101020101010201010101 -010101010101010101010101010101010101010101010101010201010101010101010101051e1c151c001e1e0000001801010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010108010101170c010a0000001b05011002021f0b1e0e010c081b0e010906011117011b0f0e0201150a0101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010b00000e0e13091c000013090101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101011a000407010812080b00001e010e001c0f1b1313 -131e0c0a110814090f1101111e0d1201070201190c170d0101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010102010118000d17000e160c0a0000001b100101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010102010b00000f01010a1c09160017010019010300111e05010c1c141f091c0710121210191c01070102031b1417010102010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0102011d000013110916141c02130013001f01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101011a120d010101010c11071f111a00030100040107 -0f06010c0013191c001c130907131f1c12021e0e1b00120701010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101181504130910001314011b0000001b0101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101021d0205000401020101031c0812030114161d0b16121a0d041304070117110f001602120f190c1c0e0101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101150d01011a1405121306181c0400001d010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100080f1c080101010101060108010f13 -020216001702011d121a0b141607050015011c1003040e1201010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010200180101181a0f160a0118110600001f01010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101050003020101030b01101c06010102010f1c0102000e0102010400170b100110111014010405071c10130c01010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010813131b04161a0a1b011f00140e00000b010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101080e010102010d1201010f060a0101010112 -0f01181d01071700130f010f19140a0116090511010c1a0500070101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010109181b00081f1710110b140c00151e000c02010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010102010102010108000401011c1c010101010e1a010201011b000a0f0f011c000019011b0f0915011a1c01150c010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101061e150f01010a011b001d0f12021d000a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101071908010905010105090101010101 -01020101080a0101010119000e1d00041e0f011c090113090a001001010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101080313150a020102010516011c1f0119000301010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010102010a0c000e010101010101010101010101010114090d110101011c111818011e001218010e180118190900150601010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0813001313001f01010804040116080115000f010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011e140011010101010110030101010d1e -051d000b010c18020202010b0507140012100917000b08161600000c010201010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010400161315031e0e1b0000040f00040b00190101020101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010d001001010104130e0201010a0c1713151101010f0419100311111600001318160000001f05040f12001f010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102010c -0000041203011a13121619000e040000140801010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011e1407011f131d010101090808 -0806010c1f0102010f050e171400000a1f000015110f0b13131a0f00001b1f020101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010102011b00000013001e011f00161401111701151306010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010809181f131d010518131200001510011c09010101060f010d000501151b1002010214001108021600140012 -07010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101190013 -0013181a18041619170016121e011616020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010600151f17190000190102 -090a07010b19010101070e1b0000151c170b1d010103000009011e0000111a1d0201020101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010201010103000013000019010101140a01091d140c08000016130301010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101050019081c001b1e010101011a080718010101020101100f0f0108171d01010300000304000e14000d01 -08160e01010101010101020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011013131200 -00001a011a1c1b0b1d0801151d1f0000150011010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201011f13061a1319151002 -010e00000c030301011a1d01010101010101010101011100001808011e131407010b001d01061b18010101010101010101020101010101010101010101010101 -01010101010101010101010201010101010101010101010101011a1300150f1100150401141a01010c151700191600161f001601010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010201010500001c140801080315000c010101010102010101010102010101010712000e0303161a160a -01010018011b121009150e0101010101010101010101010101010101010101010101010101010101010101010101010101010201010101010105001e0c000f0b -0008191e150109171f01021400041611100016010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011f00001c0a01 -0101010d001b17091a100c080101010101010101010101150000161600070d040101151c1c140601180000190101180010010101010101010101010101010101 -0101020101080101010101010201010101010101011d1c0b1700000b010d15011c0d010d1409140011011a001b1e120719000401010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010600040b04080102010d15011b0d1300001d010101010101010101011000160f01100302011b -09091211000f01011e0000000e01050017010101011a0a01010101010102071a0f0101010f1208010101010d12070101010e0e02010f160000120b151409130f -0a0006010c051600171804130000141d160003010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010102011415010d00 -0a0109000e1d17081313170101010101010101010109001e010101010101010d1414041f1501010f0000140e0009011900120e01011c1c010603100801081600 -1601020101010101010201101210011b00000015070101040c041a011116001d1a001c0801011e1601011a131a1e000000150701010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101011800151d020d1e12181c121614110f0201010101010101010101110008010101020101011a -0013061a1801010418151501111d010d131700080a001a011b0000131916000014020701010507071e1f0c081e1b011f00121e001001011d1a040a0106160009 -1d1c0d0010011e000802131a08120019060701010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010105000f0c0c -01091b181a09120f0101071a0101010101010101011a000b01010101081e13131c0701010101010a021418010101010d1119121b001801050000160c00000019 -1a10000801121b02160000160f12040119121a161b0a010f100c161a011b16011818010017010e1b010d0c011800000501010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010201020004011f0410011f180b000d01011818010101010101010101010f050101010217120908 -080718001501010109000a010b1d081e1315090d00161c1314001e02000b070201031407010c000118001e00101013011a1307010e000c1c0a01190007180b01 -1e000a0700190115150004050000000f010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010119001901 -07180408010c00000d010f0801060601010101010101010101010101000c01020119001b0901010d161601011d030c0d010101011e1406010e000b010c1e0101 -0d000301011c1c02190000000f0a00011f140101011c001c010106000d170018011a13070d000a120000000000001b0101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101011a00131106011a151e07010d121e0801011908010201010101010101010101011f0a0101 -011f000d01011e001e0f010101030e0201011018100b1b010b001c01011e1e01060601010300030213000000091b001c001e0d16060d001d0a1801120c110a1b -0d01120d0a0000000f18001c04050101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010117180a -121901070c150a01010d120406080e040101010101010101010101010101010101020c1d01010e0e01010101040018020103001210011f07010f001101091901 -01010b16140c04140000000b01131c091513061b110400100a1601151f0101101e021216141217000a07000b0101020101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101020111000d06181c09010110010201010d1416000401010101010101020101010101010101 -0101010101010101010101010f0f0101010304010102010101011d18020102010101020f070219051a000402011511010d00020c000000080f00081503081701 -1e071800000f01161601110009010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101030000 -1b061010010101010101010101040014010101020101011e060101010101010101010101010108130b0101010101020101010201010101010101010101010101 -01010101010102010a000a01041308011b1708001c05140618000a14080214021e1c16031e180118160106050201010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101131e10190301010101010101020101011d141a0a0a0101020b1e01011a1d01010101 -010101010101010f001a0102010102010101010101010101010101010101010101010f121002171c12110b14001f061100031e1c01010702121814160105160f -141f171f1000050c0002010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101020b00 -07011f030101010101010101010101010109091f0a0b160701061305010202010101010101010101191701010101010101010101010101020101010101010101 -010119120101021010010101090c14110c1c170101011d1b001615120a18001b1310071306040c17140102010101010101020101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101071315060101010101010101010101010201010102181c000a01101419081e020101 -01010101010201071605010101010101010101010101010101010c1a0101010101020d0008010118170101010101020101010101010a001b0f0f010e14141301 -0e120212051e00000401010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010119 -00160c0601020101010101010101010101010101010a041400001e121b0101010101080101060e1204010102010101010101010101060401011a000f01020101 -010101151c02010a160101010102010101010201010a0e010101010d001c140601121813160000131a0101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010f001415140a010101010101010101010101010101020101061d0c1b0e011d1303 -010f14151115150a010101011f150201010101011f120b01010e150101010101010102011c1c02010f0101051001010101010201010101020101011e04011c06 -0104121300140a060101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -1b0008021b0c01010101010101010101010101010101010101010101011d0408011a0b090207010102010101151501010101020109090101010e150101010101 -0102010101040b0101021c1309010206011c0c010c15010101010c1e011f190101041500161d0101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010f00131d0105111d010102010101010101010101010101010101010101010101 -011100110f010101010e14141b06010101010101010101010109130801010101011b0f0102011d06011a000901011115011417011d1d01010f1c1e0709131710 -01140016080101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010c00000401011919010101010101010101010101010101010101010101010101011d0b1f0101020110030101010101010101010101010102011f0401010101 -1d00080102010e1e011f15010101150e010d0d01010101011d0f0101170d001f0500190801010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101011613041b1a0109100f020101010101010101010101010101010101010101 -0101010101060102010b1b040e0e050701020101010101010101011e0d0101011c0b01020101080d0107151f01011b0b010101010101010101010102071f0013 -00160201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010f1308011f1909010f01010101010101010101010101010101010101010101010101071500171d091d030d0b11151e11181f1f0202010101010102010101 -0601011f1f010101010109121a01031306010109100f031516141414150016120017010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010104140201091e170801010e060101010101010101010101010101010101 -01010101010603191515110e1a070101061a041117041e1e0b0b0a060606020101010108080505010703011f1310061317100d00001200141007091400001213 -13070101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101020114150801020c120b0205090101010101010101010101010101010101010101010101010101021a04151514180c100201010101101a0b0c0404040404 -151618191200160f1b001c12131313121e1313040809001101070c00000000000401010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010900000c070106041205010101010101010101010101010101010101 -0101010101010201011002010102091a1113131b18051d07010101010101010613180a1400151916001c19050910130f071200040c160015111300001c101500 -11010201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101011a000016030101081e0a010101010101010101010101010101010101010101010101010816150403020101010108030d1e121312151711180b1d0e -000f091500190e1c00181a1f1f1b001213121c0414000e06110011001c1800001a01010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010218001a11110f0101010101010101010101010102010101010101 -01010101010101010101091f111c17031a080101010101061010051904111200121313161416000017171e1c001c031c1c020201140b0103160016140000000a -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101011e1f010611151a0201010101010101010101010101010101010102010101010102020801010101060519191818190e1a06020101081f010e16 -011d13060109000d01010119000808001f06091c001e120016000301150015010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101011000150f010a14140c01010101010101010101010102010101 -01010101010101011d1312110d030701010101071d0e0b0b1b1b1b13130b15130e15001e1e1500141111160012161313161200150b14000c05001f1b00160801 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101101b131810011a14140301010101010106041a010101011c000b080101010101010603041c1c151511110b031001060101011c1908151403 -1616030316001f0f1f001c0203000501011713070714001116000000001a02010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010300001107010a150a01010101010715001e1a010110 -0e1b121715180d0d0f01010101010106100a0a040b150012190b000d081218011c0c010a001101011e000709131f01050400140413000000191600171a010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010a1200130e02010101010102010101090c16160410010101100d111c151212150d0a1a0101010101010103030a1100041500161616 -16131300161114000013160000121300000b1e00180500190d000008010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010108170000150507010101020101010102011d191b -1c191a020101010107100e0015151c0c0b10070105050101190f010c19010e15011a000b01010b140619000c090a1200180500001914001413001b0101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101011e0000000018070101010101010101010101081d0e1b1c0d19130201181b01010211120c1b1200141716130d1511010f001e -021816020701140b101300040b11000013001c000000001300120901010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201071a1e000000121908010101010102010101 -0101010216161e1e0e0400030101021e1d01051810100c0c1c00041713130000000014141314141500161914001c051100040500000000160a0e010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010a1600131217110a01010101010101010e0d09020101010e000b03050b121b01031702011002021c1a010500051014 -001a0209150e011f0c0110160c0109160013000013130e0201010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101081c001c030e1b150c0701010201 -010d17151e18030604030101031c1d0a1e13151916161f121c1a0b0004010a000301011e19010b000f0d00000d11001300120400001901020101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010201011a12000b0109191713190101010101011a0d0e181b18191b00181a170f0211141a0d13030e0000041b000000 -181b12001616001313001c1800000000000000000501010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010e13001902021004141c -0e0901010201010101060f0c181e1600151600111d150d01190004091b00050f03001e04000014130016141b1300000000161105010102010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101020108191200131f02080a111c1c05010101010101010101010101091f1d0400151c000012130000121612 -0000141414000016190b150000000000001001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101020d1500001c1f -06011d0d0101010107180c0c0b0a060201010104190104001a04000c090400001300131416001412141300001300001510010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010201010102080d1c0000150a1d0601010101080a051817170e181e1400171400041e001e0119000502 -02081d08121203160000000000000301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010107 -1a150000001b03060201010101010101020f0f100b0b0b14121613131300040411171e1e13000000000000181a09010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101021a0b150000000014161b180509091009010101010101090e190c181c00 -000000000000160e110c1d0101010201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01020101010110030b11121213000000000000141515161616000000000000001617181910100801010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010201010101010101010202030405060708090a0b0c0d0d0d0d0e0d050f -01010101010101010101020101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010102010101010101010101020101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101000101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010201010101010102010101020101010201020101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100040000002701ffff030000000000}}}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \charrsid4728168 -\par }\pard\plain \ltrpar\s20\qc \li864\ri864\sb200\sa160\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin864\lin864\itap0\pararsid4728168 \rtlch\fcs1 \ai\af31507\afs24\alang1025 \ltrch\fcs0 -\i\f31506\fs24\cf19\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \charrsid4728168 -It is a press, certainly, but a press from which shall flow in inexhaustible streams...Through it, God will spread His Word. A spring of truth shall flow from it: like a new star it shall scatter the darkness of ignorance, and cause a light heretofore u}{ -\rtlch\fcs1 \af31507 \ltrch\fcs0 nknown to shine amongst men.}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \charrsid4728168 -\par }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 \af31507 \ltrch\fcs0 -\page -\par }\pard\plain \ltrpar\s16\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168\contextualspace \rtlch\fcs1 \af31503\afs56\alang1025 \ltrch\fcs0 -\fs56\expnd-2\expndtw-10\lang1036\langfe1033\kerning28\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 \af31503 \ltrch\fcs0 \hich\af31502\dbch\af31501\loch\f31502 A paragraph -\par }\pard\plain \ltrpar\qj \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 -\af31507 \ltrch\fcs0 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut al -iquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168 {\rtlch\fcs1 \af31507 \ltrch\fcs0 -\par }\pard\plain \ltrpar\s16\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168\contextualspace \rtlch\fcs1 \af31503\afs56\alang1025 \ltrch\fcs0 -\fs56\expnd-2\expndtw-10\lang1036\langfe1033\kerning28\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 \af31503 \ltrch\fcs0 \hich\af31502\dbch\af31501\loch\f31502 Another pa\hich\af31502\dbch\af31501\loch\f31502 ragrah - -\par }\pard\plain \ltrpar\qj \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1036\langfe1033\cgrid\langnp1036\langfenp1033 {\rtlch\fcs1 \af0 -\ltrch\fcs0 \f0\charrsid4728168 -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure d -olor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4728168 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \charrsid1669608 -\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a -9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad -5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 -b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 -0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 -a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f -c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 -0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 -a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 -6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b -4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b -4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100f9627f54c60600008e1a0000160000007468656d652f7468656d652f -7468656d65312e786d6cec59dd8adb4614be2ff41d84ee1dff49fe59e20db66c6fdaec262176d2e672561e4b931d698c66bc1b13027d8242212dbd29f4ae85de -04da37e8bba4b4e943f4cc489667ec71f6872d84d2352cf2f83b67be39e7e83b23cddd7b2f13ea9ce38c1396f6dcfa9d9aebe034643392463df7e9745ce9b80e -17289d21ca52dc735798bbf70e3ffde42e3a10314eb003f6293f403d3716627150adf2108611bfc3163885dfe62c4b9080af59549d65e802fc26b4daa8d55ad5 -0491d475529480db69fcfbcfe0ecd17c4e42ec1eaebd8f284c910a2e07429a4da46f5c980c9619464b859d9dd52582af784033e71cd19e0b13cdd8c514bf14ae -431117f043cfada93fb77a78b78a0e0a232af6d86a7663f557d81506b3b3869a338b4ecb493dcff75afdd2bf0250b18b1bb547ad51abf4a700280c61a53917d3 -67bb1178055603e59716dfc3f6b05937f09affe60ee7be2f3f065e8172ffde0e7e3c0e208a065e8172bcbf83f707ddc1d0f4af4039beb5836fd7fa43af6df857 -a09892f46c075df35bcd60bdda123267f4be15def5bd71bb5138dfa0a01acaea9253cc592af6d55a825eb06c0c0009a44890d411ab059ea310ca3840949c66c4 -3926510c85b74029e3305c6bd4c6b526fc971f4f5da98ca2038c346bc90b98f09d21c9c7e1614616a2e77e0e5e5d0df27ce91c311193b0985539312ceea334d2 -2ddefff4cddf3f7ce5fcf5eb8fefdf7c9b4fba8de73a7e88d3e84b82d20f4d00abdd84e1dd776ffff8ededbbefbffef3973716fffd0c9deaf0294930771ee20b -e7094b60719615e0d3ec7a16d31811dda29f461ca548ce62f13f82f8e9e8872b449105378048e8b86719c88c0d78b47c61109ec4d952108bc7077162004f18a3 -039659a3f040cea58579ba4c23fbe4d952c73d41e8dc3677805223cfa3e502f495d85c063136683ea6281528c229168efc8d9d616c59dd73428cb89e9030639c -cd85f39c380344ac21999253a39a3646f749027959d90842be8dd89c3c73068cda563dc4e72612ee0e442de4a7981a613c424b81129bcb294aa81ef06324621b -c9c92a0b75dc880bc8748429734633ccb9cde65106ebd592fe0024c69ef613ba4a4c6426c899cde731624c470ed95910a36461c34e481aebd8cff8199428721e -3361839f30f30e91df210f201efbd2fd8c6023dd97abc15350579dd2a640e42fcbcc92cb23cc8cfa9dace81c61253520fe86a62724bd54e0b7a4ddfff7a4fd84 -a461cc2c2bba2d51b7bb3632724d39ef67c47a3fdddf12f17db86de90e5836231fbf720fd1327d8ce166d96d5fff0bf7ffc2edfee7857bdffd7cfb72bd516810 -6fb975cd37eb6aeb9eecddb9cf09a513b1a2f898abcd3b87be341bc3a0b4538fadb87c925bc47029ef6498c0c0451952364ec6c41744c493182d60875f77a593 -8817ae23ee2c18878dbf1ab6fa9678ba4c4ed82c7f60add7e5c3692e1e1c89cd78cd2fc7e16143e4e8567bf31056ba576c23f5b0bc26206daf43429bcc24d1b4 -9068af076590d4a33904cd4242adec5658742d2c3ad2fd3a553b2c805a9915d83839b0ddeab9be07266004cf5488e299cc539eea757655326f33d3fb82695400 -ec22d615b0c9745772ddbb3cb9babcd4ae90698384566e26091519d5c3788c66b8a84e397a151ad7cd75779352839e0c859a0f4a6b43a3ddf9108b9be61aecb6 -b581a6ba52d0d4b9e8b9ada60f2513a245cf9dc3833f5c260ba81d2e37bc8846f0fa2c14597ec3df445916191743c4e33ce04a7472354888c0994349d273e5f2 -cb34d0546988e2566f80207cb4e4ba202b1f1b3948ba99643c9fe350e869d74664a4f3afa0f0b956587f55e637074b4bb684744fe2d985734a97d9130425e6b7 -eb328033c2e1fd4f3d8fe68cc00bcd52c836f5b7d5980ad9d5df28aa1acac7115dc4a8e828ba98e77025e5251df5ad8c81f6ad583304540b49d1084f23d960f5 -a01addb4ec1a3987bd5df7722319394d34373dd35015d935ed2a66ccb06e035bb1bc5993d758ad430c9aa677f85cbab725b7bbd6baad7d42d92520e065fc2c5d -f70a0d41a3b699cca02619efcab0d4ec62d4ec1deb055e42ed2a4d4253fdd6daed56dcca1e619d0e066fd4f9c16ebb6a6168bede57aa48aba30ffd70829dbe00 -f118c26be025155ca5128e1e32041ba289da93e4b201b7c84b51dc1a70e52c33d2735fd5fcbe1734fca052ebf8a38ad7f46a958edf6f56fabedfac8ffc7a6d38 -68bc86c622e2a4eee7c72e6378114557c5e18b1adf398049d6efdaee842ca93275b25255c4d5014cbd611cc0e4272fce541eb0b80e01d179d56a8cbbcdeea055 -e936fbe38a371c742adda035a80c5b417b381e067ea73b7eed3ae70aecf59b81d71a752aad7a1054bc564dd2ef742b6dafd1e87bed7e67e4f55f17db1858792e -1f452c20bc8ad7e13f000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f -7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be -9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980 -ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5b -babac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000000000000000000000000000005b436f6e74656e -745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f -2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000190200007468656d652f7468656d652f74 -68656d654d616e616765722e786d6c504b01022d0014000600080000002100f9627f54c60600008e1a00001600000000000000000000000000d6020000746865 -6d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000d00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000cb0a00000000} -{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d -617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 -6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 -656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} -{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; -\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; -\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; -\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; -\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; -\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; -\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; -\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2; -\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme;\lsdsemihidden1 \lsdlocked0 Placeholder Text; -\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2; -\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List; -\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1; -\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision; -\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1; -\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1; -\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; -\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2; -\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2; -\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; -\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3; -\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4; -\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; -\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4; -\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5; -\lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; -\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; -\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; -\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; -\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; -\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; -\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; -\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; -\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; -\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; -\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; -\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; -\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; -\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; -\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; -\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; -\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; -\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; -\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; -\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; -\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; -\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; -\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; -\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; -\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; -\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; -\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; -\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; -\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; -\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; -\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; -\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000 -4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 -d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000006014 -a5e70e92d401feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/test/testdata/office/document.txt b/test/testdata/office/document.txt deleted file mode 100644 index 16eab9d7..00000000 --- a/test/testdata/office/document.txt +++ /dev/null @@ -1,3 +0,0 @@ -Gutenberg - -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file diff --git a/test/testdata/pdf/gotenberg_bis.pdf b/test/testdata/pdfengines/sample1.pdf similarity index 100% rename from test/testdata/pdf/gotenberg_bis.pdf rename to test/testdata/pdfengines/sample1.pdf diff --git a/test/testdata/pdfengines/sample2.pdf b/test/testdata/pdfengines/sample2.pdf new file mode 100644 index 00000000..0a0b284f Binary files /dev/null and b/test/testdata/pdfengines/sample2.pdf differ diff --git a/test/testdata/url/footer.html b/test/testdata/url/footer.html deleted file mode 100644 index 4fb22cdf..00000000 --- a/test/testdata/url/footer.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - -

- of -

- - \ No newline at end of file diff --git a/test/testdata/url/header.html b/test/testdata/url/header.html deleted file mode 100644 index abba6009..00000000 --- a/test/testdata/url/header.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/test/xerror.go b/test/xerror.go deleted file mode 100644 index 6bc04278..00000000 --- a/test/xerror.go +++ /dev/null @@ -1,18 +0,0 @@ -package test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/thecodingmachine/gotenberg/internal/pkg/xerror" -) - -// AssertError validates that given error -// is of an instance of xerror.Error. -// If so, returns the instance of xerror.Error. -func AssertError(t *testing.T, err error) *xerror.Error { - assert.NotNil(t, err) - standardized, ok := err.(*xerror.Error) - assert.Equal(t, true, ok) - return standardized -} diff --git a/test/xlog.go b/test/xlog.go deleted file mode 100644 index b8c93611..00000000 --- a/test/xlog.go +++ /dev/null @@ -1,23 +0,0 @@ -package test - -import ( - "github.com/thecodingmachine/gotenberg/internal/pkg/xlog" -) - -// DebugLogger creates a xlog.Logger -// with xlog.DebugLevel for our tests. -func DebugLogger() xlog.Logger { - return xlog.New(xlog.DebugLevel, "tests") -} - -// InfoLogger creates a xlog.Logger -// with xlog.InfoLevel for our tests. -func InfoLogger() xlog.Logger { - return xlog.New(xlog.DebugLevel, "tests") -} - -// ErrorLogger creates a xlog.Logger -// with xlog.ErrorLevel for our tests. -func ErrorLogger() xlog.Logger { - return xlog.New(xlog.ErrorLevel, "tests") -}