diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index b981efd24d..0000000000 --- a/.dockerignore +++ /dev/null @@ -1,32 +0,0 @@ -# Version control scaffolding -.git -.gitignore - -# Docker scaffolding -Dockerfile -.dockerignore - -# Translations -*.mo - -# Mac -.DS_Store - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# JetBrains -.idea - -# Built documentation -docs/_build -docs/_build_doc2dash - -# Virtual environment -env/ -coverage.xml - -# Jekyll metadata -.jekyll-metadata diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 617ed56d3b..0000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,16 +0,0 @@ -# The API governance team is the default owner for everything in the repo. -# (Note: CODEOWNERS follows a "last match wins" system.) -* @aip-dev/google - -# These AIP editors own the generally-applicable AIP guidance. -# PA-specific directories are owned by their respective teams. -aip/general/*.md @aip-dev/google - -# Team-specific components are owned by those teams. -# @aip-dev/google is added only for structural changes (typos, markdown, refactorings) -aip/apps/27*.md @aip-dev/apps @aip-dev/google -aip/aog/30*.md @aip-dev/aog @aip-dev/google -aip/auth/41*.md @aip-dev/auth @aip-dev/google -aip/client-libraries/42*.md @aip-dev/client-libraries @aip-dev/google -aip/cloud/26*.md @aip-dev/cloud-cli @aip-dev/google -aip/firebase/32*.md @aip-dev/firebase @aip-dev/google diff --git a/.github/renovate.json5 b/.github/renovate.json5 deleted file mode 100644 index 044857ca6b..0000000000 --- a/.github/renovate.json5 +++ /dev/null @@ -1,5 +0,0 @@ -{ - extends: ['config:base', 'docker:disable'], - commitMessagePrefix: 'chore: ', - groupName: 'multiple dependencies', -} diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml deleted file mode 100644 index 40b9ea9883..0000000000 --- a/.github/workflows/publish.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: publish -on: - push: - branches: - - master - -permissions: - contents: write - -jobs: - github-pages: - runs-on: ubuntu-latest - container: python:3.8 - steps: - - uses: actions/checkout@v3 - - name: Install system dependencies. - run: apt-get update && apt-get install -y rsync - - name: Install the site generator. - run: pip install -r requirements.txt - - name: Build the static site. - run: aip-site-gen . out - - name: Publish the static site to GitHub Pages. - uses: jamesives/github-pages-deploy-action@v4 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: gh-pages - FOLDER: out diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 5dfdbceb85..0000000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: test -on: - pull_request: - branches: - - master -jobs: - build: - runs-on: ubuntu-latest - container: python:3.8 - steps: - - uses: actions/checkout@v3 - - name: Install the site-generator - run: pip install -r requirements.txt - - name: Build the site. - run: aip-site-gen . /out diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 4f56b7ee9c..0000000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# pytest -site/.coverage -site/.pytest_cache -site/htmlcov - -# mypy -.mypy_cache diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 186ae1563c..0000000000 --- a/.prettierignore +++ /dev/null @@ -1,3 +0,0 @@ -_includes/aip-nav.html -_includes/svgs.html -_sass/colors.scss diff --git a/.prettierrc.yaml b/.prettierrc.yaml deleted file mode 100644 index fdb892b056..0000000000 --- a/.prettierrc.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -printWidth: 79 -proseWrap: always -singleQuote: true -trailingComma: es5 diff --git a/0001.html b/0001.html new file mode 100644 index 0000000000..860f773593 --- /dev/null +++ b/0001.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0002.html b/0002.html new file mode 100644 index 0000000000..4ecb7d6806 --- /dev/null +++ b/0002.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0003.html b/0003.html new file mode 100644 index 0000000000..49c0ea691f --- /dev/null +++ b/0003.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0008.html b/0008.html new file mode 100644 index 0000000000..97ac08b7da --- /dev/null +++ b/0008.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0009.html b/0009.html new file mode 100644 index 0000000000..9fdc3a665b --- /dev/null +++ b/0009.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/001.html b/001.html new file mode 100644 index 0000000000..860f773593 --- /dev/null +++ b/001.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/002.html b/002.html new file mode 100644 index 0000000000..4ecb7d6806 --- /dev/null +++ b/002.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/003.html b/003.html new file mode 100644 index 0000000000..49c0ea691f --- /dev/null +++ b/003.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/008.html b/008.html new file mode 100644 index 0000000000..97ac08b7da --- /dev/null +++ b/008.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/009.html b/009.html new file mode 100644 index 0000000000..9fdc3a665b --- /dev/null +++ b/009.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/01.html b/01.html new file mode 100644 index 0000000000..860f773593 --- /dev/null +++ b/01.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0100.html b/0100.html new file mode 100644 index 0000000000..34fd75beac --- /dev/null +++ b/0100.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0111.html b/0111.html new file mode 100644 index 0000000000..b2631de81a --- /dev/null +++ b/0111.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0121.html b/0121.html new file mode 100644 index 0000000000..49d58978a8 --- /dev/null +++ b/0121.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0122.html b/0122.html new file mode 100644 index 0000000000..688f434e5f --- /dev/null +++ b/0122.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0123.html b/0123.html new file mode 100644 index 0000000000..a423b4dcef --- /dev/null +++ b/0123.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0124.html b/0124.html new file mode 100644 index 0000000000..334912eb64 --- /dev/null +++ b/0124.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0126.html b/0126.html new file mode 100644 index 0000000000..3a58b89f8f --- /dev/null +++ b/0126.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0127.html b/0127.html new file mode 100644 index 0000000000..a1aa76caa3 --- /dev/null +++ b/0127.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0128.html b/0128.html new file mode 100644 index 0000000000..85c7f92d55 --- /dev/null +++ b/0128.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0129.html b/0129.html new file mode 100644 index 0000000000..f72cfd5129 --- /dev/null +++ b/0129.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0130.html b/0130.html new file mode 100644 index 0000000000..657745985b --- /dev/null +++ b/0130.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0131.html b/0131.html new file mode 100644 index 0000000000..c12f5792d8 --- /dev/null +++ b/0131.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0132.html b/0132.html new file mode 100644 index 0000000000..83241da9f2 --- /dev/null +++ b/0132.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0133.html b/0133.html new file mode 100644 index 0000000000..dd6c713f42 --- /dev/null +++ b/0133.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0134.html b/0134.html new file mode 100644 index 0000000000..8ccd22e5f4 --- /dev/null +++ b/0134.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0135.html b/0135.html new file mode 100644 index 0000000000..329047d663 --- /dev/null +++ b/0135.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0136.html b/0136.html new file mode 100644 index 0000000000..e57dadad6f --- /dev/null +++ b/0136.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0140.html b/0140.html new file mode 100644 index 0000000000..2f6e1310fa --- /dev/null +++ b/0140.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0141.html b/0141.html new file mode 100644 index 0000000000..7132ef2984 --- /dev/null +++ b/0141.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0142.html b/0142.html new file mode 100644 index 0000000000..baef3e6693 --- /dev/null +++ b/0142.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0143.html b/0143.html new file mode 100644 index 0000000000..8664fa0903 --- /dev/null +++ b/0143.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0144.html b/0144.html new file mode 100644 index 0000000000..2b2b6c08fd --- /dev/null +++ b/0144.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0145.html b/0145.html new file mode 100644 index 0000000000..60357a804e --- /dev/null +++ b/0145.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0146.html b/0146.html new file mode 100644 index 0000000000..081a8820bb --- /dev/null +++ b/0146.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0147.html b/0147.html new file mode 100644 index 0000000000..a07c94d26b --- /dev/null +++ b/0147.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0148.html b/0148.html new file mode 100644 index 0000000000..ce66bc5dcc --- /dev/null +++ b/0148.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0149.html b/0149.html new file mode 100644 index 0000000000..612bfee80c --- /dev/null +++ b/0149.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0151.html b/0151.html new file mode 100644 index 0000000000..91176be3a6 --- /dev/null +++ b/0151.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0152.html b/0152.html new file mode 100644 index 0000000000..41c6aacb39 --- /dev/null +++ b/0152.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0153.html b/0153.html new file mode 100644 index 0000000000..175b32c4a2 --- /dev/null +++ b/0153.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0154.html b/0154.html new file mode 100644 index 0000000000..39d974dbb8 --- /dev/null +++ b/0154.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0155.html b/0155.html new file mode 100644 index 0000000000..e21e2c4607 --- /dev/null +++ b/0155.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0156.html b/0156.html new file mode 100644 index 0000000000..30ab611c08 --- /dev/null +++ b/0156.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0157.html b/0157.html new file mode 100644 index 0000000000..a4d5be2781 --- /dev/null +++ b/0157.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0158.html b/0158.html new file mode 100644 index 0000000000..783d414b97 --- /dev/null +++ b/0158.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0159.html b/0159.html new file mode 100644 index 0000000000..7e1db56e62 --- /dev/null +++ b/0159.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0160.html b/0160.html new file mode 100644 index 0000000000..a2214573f0 --- /dev/null +++ b/0160.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0161.html b/0161.html new file mode 100644 index 0000000000..9673baab27 --- /dev/null +++ b/0161.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0162.html b/0162.html new file mode 100644 index 0000000000..5be52e666f --- /dev/null +++ b/0162.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0163.html b/0163.html new file mode 100644 index 0000000000..538c59ff17 --- /dev/null +++ b/0163.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0164.html b/0164.html new file mode 100644 index 0000000000..d372f8d758 --- /dev/null +++ b/0164.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0165.html b/0165.html new file mode 100644 index 0000000000..a6523cf721 --- /dev/null +++ b/0165.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0180.html b/0180.html new file mode 100644 index 0000000000..bcdac329ef --- /dev/null +++ b/0180.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0181.html b/0181.html new file mode 100644 index 0000000000..fdfe73b665 --- /dev/null +++ b/0181.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0182.html b/0182.html new file mode 100644 index 0000000000..1b3b369633 --- /dev/null +++ b/0182.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0185.html b/0185.html new file mode 100644 index 0000000000..9852bca2f3 --- /dev/null +++ b/0185.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0190.html b/0190.html new file mode 100644 index 0000000000..5baa1547a5 --- /dev/null +++ b/0190.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0191.html b/0191.html new file mode 100644 index 0000000000..aee76a49a2 --- /dev/null +++ b/0191.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0192.html b/0192.html new file mode 100644 index 0000000000..7655769baf --- /dev/null +++ b/0192.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0193.html b/0193.html new file mode 100644 index 0000000000..0c0fde0447 --- /dev/null +++ b/0193.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0194.html b/0194.html new file mode 100644 index 0000000000..87afd16121 --- /dev/null +++ b/0194.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/02.html b/02.html new file mode 100644 index 0000000000..4ecb7d6806 --- /dev/null +++ b/02.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0200.html b/0200.html new file mode 100644 index 0000000000..32ed0d049b --- /dev/null +++ b/0200.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0202.html b/0202.html new file mode 100644 index 0000000000..ee084be88d --- /dev/null +++ b/0202.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0203.html b/0203.html new file mode 100644 index 0000000000..5d9ad34f38 --- /dev/null +++ b/0203.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0205.html b/0205.html new file mode 100644 index 0000000000..abd9238b45 --- /dev/null +++ b/0205.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0210.html b/0210.html new file mode 100644 index 0000000000..5ed5a2135a --- /dev/null +++ b/0210.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0211.html b/0211.html new file mode 100644 index 0000000000..459db2d2c9 --- /dev/null +++ b/0211.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0213.html b/0213.html new file mode 100644 index 0000000000..9302fc1cf6 --- /dev/null +++ b/0213.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0214.html b/0214.html new file mode 100644 index 0000000000..3a0c3453c2 --- /dev/null +++ b/0214.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0215.html b/0215.html new file mode 100644 index 0000000000..a99a8aea0c --- /dev/null +++ b/0215.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0216.html b/0216.html new file mode 100644 index 0000000000..9cdb67387e --- /dev/null +++ b/0216.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0217.html b/0217.html new file mode 100644 index 0000000000..855f8ecddb --- /dev/null +++ b/0217.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0231.html b/0231.html new file mode 100644 index 0000000000..4f0b882088 --- /dev/null +++ b/0231.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0233.html b/0233.html new file mode 100644 index 0000000000..db741087ae --- /dev/null +++ b/0233.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0234.html b/0234.html new file mode 100644 index 0000000000..3039387ed8 --- /dev/null +++ b/0234.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0235.html b/0235.html new file mode 100644 index 0000000000..434c8e020c --- /dev/null +++ b/0235.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/0236.html b/0236.html new file mode 100644 index 0000000000..c9b30befde --- /dev/null +++ b/0236.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/03.html b/03.html new file mode 100644 index 0000000000..49c0ea691f --- /dev/null +++ b/03.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/08.html b/08.html new file mode 100644 index 0000000000..97ac08b7da --- /dev/null +++ b/08.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/09.html b/09.html new file mode 100644 index 0000000000..9fdc3a665b --- /dev/null +++ b/09.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/1.html b/1.html new file mode 100644 index 0000000000..82f6710a9f --- /dev/null +++ b/1.html @@ -0,0 +1,948 @@ + + + + AIP-1: AIP Purpose and Guidelines + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-1

+

AIP Purpose and Guidelines

+

As the corpus of Google APIs has grown and the API Governance team has grown to +meet the demand of supporting them, it is increasingly necessary to have a +corpus of documentation for API producers, reviewers, and other interested +parties to reference. The API style guide and introductory One Platform +documentation are intentionally terse and high-level. The AIP collection +offers a method to provide consistent documentation for API design guidance.

+

What is an AIP?

+

AIP stands for API Improvement Proposal, which is a design document +providing high-level, concise documentation for API development. They are to +serve as the source of truth for API-related documentation at Google and the +means by which API teams discuss and come to consensus on API guidance. AIPs +are maintained as Markdown files in the AIP GitHub repository.

+

Types of AIPs

+

There are several different types of AIPs, described below. The list of AIP +types may evolve over time as necessary.

+

Guidance

+

These AIPs describe guidance on API design. These are provided as instruction +for API producers to help write simple, intuitive, and consistent APIs, and are +used by API reviewers as a basis for review comments.

+

Process

+

These AIPs describe a process surrounding API design. They often affect the AIP +process itself and are used to enhance the way in which AIPs are handled.

+

Stakeholders

+

As with any process there are many different stakeholders when it comes to +reviewing and working with AIPs. Below is a summary of the escalation path +starting with the API producer.

+
digraph d_front_back {
+  rankdir=BT;
+  ranksep=0.3;
+  node [ style="filled,solid" shape=box fontname="Roboto" ];
+
+  producer [ label="API Producer" ];
+  editors [ label="AIP Editors" ];
+  tl_infra [ label="Infrastructure TL" ];
+  tl_design [ label="Design TL" ];
+  tl [ label="TL" ];
+
+  producer -> editors;
+  editors -> tl_infra -> tl;
+  editors -> tl_design -> tl;
+}
+
+

As noted in the diagram above, the TL is the final decision-maker on the AIP +process and the final point of escalation if necessary.

+

Editors

+

The editors are the set of people who make decisions on AIPs. The general goal +is that the AIP process is collaborative and that we largely work on the basis +of consensus. However, a limited number of designated approvers is necessary, +and these Googlers will be approvers for each AIP in the general scope.

+

The list of AIP editors is currently:

+ +

The editors are also responsible for the administrative and editorial aspects +of shepherding AIPs and managing the AIP pipeline and workflow. They approve +PRs to AIPs, assign proposal numbers, manage the agenda, set AIP states, and so +forth. They also ensure that AIPs are readable (proper spelling, grammar, +sentence structure, markup, etc.).

+

AIP editorship is by invitation of the current editors.

+

Domain-specific AIPs

+

Some AIPs may be specific to a particular domain (for example, only to APIs +within a certain PA, or even a certain team). In this situation, the group will +be given a particular block of AIPs to use in accordance with AIP-2, and the +applicable AIPs will clearly indicate their scope.

+

States

+

At any given time, AIPs may exist in a variety of states as they work their way +through the process. The following is a summary of each state.

+

Draft

+

The initial state for an AIP is the "Draft" state. This means that the AIP is +being discussed and iterated upon, primarily by the original authors. While the +editors may get involved at this stage, it is not necessary.

+

Note: If significant, high-level iteration is required, it is recommended +to draft AIPs in a Google doc instead of a PR. AIPs that are migrated into the +AIP system from Google Docs may skip the draft state and go directly to +reviewing provided there is sufficient approval.

+

Reviewing

+

Once discussion on an AIP has generally concluded, but before it is formally +accepted it moves to the "Reviewing" state. This means that the authors have +reached a general consensus on the proposal and the editors are now involved. +At this stage the editors may request changes or suggest alternatives to the +proposal before moving forward.

+

Note: As a formal matter, one AIP approver (other than the author) must +provide formal signoff to advance an AIP to the reviewing state. Additionally, +there must not be formal objections ("changes requested" on the GitHub PR) +from other approvers.

+

Approved

+

Once an approved AIP has been agreed upon, it enters "approved" state and is +considered "best current practice".

+

Note: As a formal matter, two AIP approvers (other than the author) +must provide formal signoff to advance an AIP to the approved state. +Additionally, there must not be formal objections ("changes requested" on +the GitHub PR) from other approvers.

+

Withdrawn

+

If an AIP is withdrawn by the author or champion, it enters "withdrawn" state. +AIPs that are withdrawn may be taken up by another champion.

+

Rejected

+

If an AIP is rejected by the AIP editors, it enters "rejected" state. AIPs that +are rejected remain, and provide documentation and reference to inform future +discussions.

+

Deferred

+

If an AIP has not been acted upon for a significant period of time, the editors +may mark it as "deferred".

+

Replaced

+

If an AIP has been replaced by another AIP, it enters "replaced" state. AIP +editors are responsible to provide a notice explaining the replacement and +rationale (the replacement AIP should also clearly explain the rationale).

+

In general, API producers should rely primarily on AIPs in the "approved" +state.

+

Workflow

+

The following workflow describes the process for proposing an AIP, and moving +an AIP from proposal to implementation to final acceptance.

+

Overview

+
digraph d_front_back {
+  rankdir=LR;
+  node [ style="filled,solid" shape=box fontname="Roboto" ];
+  draft [ label="Draft" fillcolor="orange" ];
+  reviewing [ label="Reviewing" fillcolor="lightskyblue" ];
+  approved [ label="Approved" fillcolor="palegreen" ];
+  withdrawn [ label="Withdrawn" fillcolor="mistyrose" ];
+  rejected [ label="Rejected" fillcolor="mistyrose" ];
+  deferred [ label="Deferred" fillcolor="lightsteelblue" ];
+  replaced [ label="Replaced" fillcolor="lightsteelblue" ];
+
+  draft -> reviewing;
+  draft -> withdrawn [ style=dashed, color=mistyrose3 ];
+  draft -> rejected [ style=dashed, color=mistyrose3 ];
+  reviewing -> approved;
+  reviewing -> withdrawn [ style=dashed, color=mistyrose3 ];
+  reviewing -> rejected [ style=dashed, color=mistyrose3 ];
+  draft -> deferred [ style=dashed, color=lightsteelblue3 ];
+  reviewing -> deferred [ style=dashed, color=lightsteelblue3 ];
+  approved -> replaced [ style=dashed, color=lightsteelblue3 ];
+  reviewing -> replaced [ style=dashed, color=lightsteelblue3 ];
+}
+
+

Proposing an AIP

+

In order to propose an AIP, first open an issue to circulate the +fundamental idea for initial feedback. It should generally be possible to +describe the idea in a couple of pages.

+

When proposing a new AIP or changes to an existing one, it is best to reference +prior art and/or example use cases that the proposal will impact, so as to +ensure that the proposal is grounded in a realistic problem space. So, proposals +should provide concrete references and/or well-defined examples. Appropriate +material includes, but is not limited to, the following:

+
    +
  • Existing external RFCs or standards
  • +
  • A corpus of APIs that have aligned on a similar pattern e.g. Search methods
  • +
  • A concrete use case that has yet to be solved that exists or could exist in + one or more APIs e.g. adding an AIP-202 Format for AIP-143 Unicode CLDR + region codes
  • +
+

Once ready, create a PR with a new file in the AIP directory using a file +titled aip/new.md. Ensure that the PR is editable by maintainers.

+

In most circumstances, the editors will assign the proposal an AIP number and +submit the PR with the AIP in the "Reviewing" state. The editors may reject an +AIP outright if they have an obvious reason to do so (e.g. the proposal was +already discussed and rejected in another AIP or is fundamentally unsound), in +which case the PR is not merged.

+

Discussing an AIP

+

Once the PR is merged, the AIP author is responsible for championing the AIP on +a follow-up approval pull request. This means that the author is responsible +for pushing towards consensus around the proposal. This may involve a +discussion at the regularly scheduled meetings for the API Governance team.

+

The AIP author may modify the AIP over the course of discussion by submitting +follow-up commits to the PR.

+

Accepting an AIP

+

The editors will work together to ensure that qualified proposals do not linger +in review.

+

To gain final approval, an AIP must be approved by, at minimum, the TL with +responsibility over the domain covered by the AIP (either design or +infrastructure) and at least one other editor, with no editors actively +requesting changes.

+

Note: If an AIP editor is the primary author of an AIP, then at least two +other editors must approve it.

+

Once the AIP is approved, the editors will update the state of the AIP to +reflect this and submit the PR.

+

Withdrawing or Rejecting an AIP

+

The author of an AIP may decide, after further consideration, that an AIP +should not advance. If so, the author may withdraw the AIP by updating the PR +adding a notice of withdrawal with an explanation of the rationale. +Additionally, the author may be unable to get consensus among the group and the +AIP editors may elect to reject the AIP. In this situation, the AIP editors +shall amend the PR adding a notice of rejection with an explanation of the +rationale. In both cases, the AIP editors update the state accordingly and +submit the PR.

+

Replacing an AIP

+

In rare cases, it may be necessary to replace an AIP with another one. This is +not general practice: minor edits to approved AIPs are acceptable, and will be +the common way to tweak guidance. However, if new guidance fundamentally alters +the old guidance in some way, then the AIP editors shall create a new AIP that, +once approved, will replace the old one. The old one then enters "Replaced" +state, and will link to the new, current AIP.

+

Changelog

+
    +
  • 2025-01-09: Add requirement to include references/examples in proposals.
  • +
  • 2024-09-04: Updated names of current editors and remove TLs.
  • +
  • 2023-05-10: Updated names of current and editors and TLs.
  • +
  • 2019-07-30: Further clarified AIP quorum requirements.
  • +
  • 2019-05-12: Collapsed AIP approvers and editors into a single position, + relaxed approval rules from full quorum.
  • +
  • 2019-05-04: Updated the AIP to refer to GitHub processes, rather than + internal processes.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/100.html b/100.html new file mode 100644 index 0000000000..4116330e9a --- /dev/null +++ b/100.html @@ -0,0 +1,1005 @@ + + + + AIP-100: API Design Review FAQ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-100

+

API Design Review FAQ

+

API design review exists to ensure a simple, intuitive, and consistent API +experience throughout our API corpus.

+

Do I need API design approval?

+

TL;DR: You usually need API design approval if you are launching an API +that users can code against (either now or in the future) at the beta or GA +quality level.

+

API design review is fundamentally about ensuring we provide a simple and +consistent experience for our users, and therefore is only expected for APIs +that users code directly against.

+

The following flowchart illustrates whether or not your API needs to go through +the design review process:

+
digraph {
+  node [ style="filled,solid" shape=box fontname="Roboto" ];
+  graph [ splines=ortho, nodesep=0.2 ];
+
+  audience [ label="Who should code directly\nagainst this API?"
+             shape=diamond fillcolor=bisque ];
+
+  subgraph audience_responses {
+    rank = "same";
+    node [ shape=oval fillcolor=orange ];
+
+    googlers [ label="Googlers\nOnly" fillcolor=lightcoral ];
+    public [ label="Anyone" fillcolor=limegreen ];
+    partners [ label="Partners\nOnly" fillcolor=deepskyblue ];
+
+    partners -> public -> googlers [ style=invisible arrowhead=none ];
+  }
+
+
+  subgraph and_ever {
+    rank = "same";
+    node [ shape=diamond fillcolor=bisque ];
+
+    forever_partners [ label="Forever?" shape=diamond fillcolor=bisque ];
+    forever_googlers [ label="Forever?" shape=diamond fillcolor=bisque ];
+  }
+
+  subgraph forever_responses {
+    rank = "same";
+    node [ shape=oval fillcolor=orange ];
+
+    forever_partners_yes [ label="Yes" fillcolor=deepskyblue ];
+    forever_no [ label="No, anyone\neventually" fillcolor=limegreen ];
+    forever_googlers_yes [ label="Yes" fillcolor=lightcoral ];
+  }
+
+  release_level [ label="What release\nlevel?" shape=diamond fillcolor=bisque ];
+
+  # Not required is not in the subgraph with the other outcomes because
+  # it makes the graph much smaller if it can be higher in the image.
+
+  subgraph release_levels {
+    rank = "same";
+    node [ shape=oval ];
+
+    alpha [ label="Alpha" fillcolor=darkorange ];
+    beta [ label="Beta" fillcolor=goldenrod1 ];
+    ga [ label="GA" fillcolor=limegreen ];
+
+    alpha -> beta -> ga [ style=invisible arrowhead=none ];
+  }
+
+  changes [ label="Any changes\nfrom beta?" shape=diamond fillcolor=bisque ];
+
+  subgraph changes_bool {
+    rank = "same";
+    node [ shape=oval ];
+
+    changes_yes [ label="Yes" fillcolor=goldenrod1 ];
+    changes_no [ label="No" fillcolor=limegreen ];
+  }
+
+  subgraph outcome {
+    rank = "same";
+    node [ style="rounded,filled" ];
+    fyi [ label="FYI" fillcolor=lightblue ];
+    recommended [ label="Recommended" fillcolor=limegreen ];
+    required [ label="⚠ Required" fillcolor=goldenrod1 ];
+    not_required
+      [ label="Not Required" fillcolor=lightgrey style="rounded,filled" ];
+    recommended -> required -> fyi -> not_required
+      [style=invisible arrowhead=none];
+  }
+
+  audience -> googlers [ arrowhead=none style=dashed color=grey ];
+  audience -> partners [ arrowhead=none ];
+  audience -> public [ arrowhead=none ];
+  partners -> forever_partners;
+  googlers -> forever_googlers [ style=dashed color=grey ];
+  public -> release_level;
+  forever_partners -> forever_partners_yes [ arrowhead=none ];
+  forever_googlers -> forever_googlers_yes
+    [ arrowhead=none style=dashed color=grey ];
+  forever_partners -> forever_no [ arrowhead=none ];
+  forever_googlers -> forever_no [ arrowhead=none ];
+  forever_partners_yes -> recommended;
+  forever_googlers_yes -> not_required [ style=dashed color=grey ];
+  forever_no -> release_level;
+  release_level -> alpha [ arrowhead=none ];
+  release_level -> beta [ arrowhead=none ];
+  release_level -> ga [ arrowhead=none ];
+  alpha -> recommended;
+  beta -> required;
+  ga -> changes;
+  changes -> changes_yes [ arrowhead=none ];
+  changes -> changes_no [ arrowhead=none ];
+  changes_yes -> required;
+  changes_no -> fyi;
+}
+
+

Who should code directly against it?

+

One of the more complex questions is, "Who should code directly against this +API?" API design review is primarily concerned about the API's audience. This +means we care about who is permitted to write their own HTTP/gRPC calls against +the service, and who is able to see the documentation. (We do not care about +questions such as whether the service is exposed on the public network.)

+

Design review is expected if the general public is intended to read +documentation and write code that interacts with the service.

+

The following situations do not require design review:

+
    +
  • An API which will only ever be used by Googlers, or internal tools (for + example, Pantheon).
  • +
  • An API which will only ever be called by an executable program released by + Google (even if the API could be reverse-engineered from the executable).
  • +
  • An API which will only ever be called by a single customer or small set of + customers under contract, and which will never be made more widely + available. (Design review is still recommended in this case, but not + required.)
  • +
+

Alpha

+

For alpha, API design review is optional but recommended. It may often make +sense to endeavor to get initial feedback from customers quickly, and launching +an alpha can be a way of gaining data to determine the best answer to some +usability questions; therefore, bypassing review may be expedient. On the other +hand, launching an alpha requires building an implementation which then takes +engineering effort to update if the API design review at the beta stage raises +concerns. Because API design review can precede implementation work, we +recommend a design review for alpha.

+

Why is design review important?

+

TL;DR: Product excellence.

+

Our design review process exists to ensure that the APIs that we present to +customers are simple, intuitive, and consistent. Your reviewer +approaches your API from the standpoint of a naïve user, thinks through the +resources and actions that your API provides, and attempts to make the surface +as accessible and extensible as possible.

+

Your design reviewer is not only evaluating your API, but also checking to +ensure that your API is consistent with Google's existing corpus of APIs. Many +customers use multiple APIs, and therefore it is important that our conventions +and naming choices line up with customer expectations.

+

What should I expect?

+

How long does the review process take?

+

Reviewers make an effort to keep up with their assigned reviews and offer +feedback frequently, so as not to cause unnecessary delay, but it's generally +best to begin the review process early in case there are delays.

+

The design review process varies based on the size and complexity of the +underlying API surface:

+
    +
  • Incremental changes to existing APIs generally take a few days.
  • +
  • Small APIs usually take around a week.
  • +
  • Entirely new APIs with large surfaces tend to take no less than a week. In + cases with extraordinarily large surfaces (e.g., Cloud AutoML), reviews may + take a month or more to go through design review.
  • +
+

How do reviewers approach my API?

+

API reviewers seek to approach your API the same way that your users will, by +focusing primarily on the API surface and its user-facing documentation. In an +ideal world, your API reviewer will ask the types of design questions that +users will ask (and nudge the API toward raising fewer of those questions in +the first place).

+

What is precedent?

+

In general, we want Google APIs to be as consistent as possible. Once customers +learn their first Google API, it should be easier to learn the second (and then +the third, and so on) because we are using the same patterns consistently.

+

We refer to precedent to mean decisions that have already been made by +previous APIs, which generally should be binding upon newer APIs in similar +situations. The most common example of this is naming: we have a list of +standard fields that dictate how we use common terms like name, +create_time, and so forth, and which also dictates that we always attach the +same name to the same concept.

+

Precedent also applies to patterns. All APIs should implement pagination the +same way. Ditto for long-running operations, import and export, and so on. Once +a pattern has been established, we seek to implement that pattern the same way +wherever it is germane.

+

What should I do?

+

...if I have a launch on a tight deadline?

+

The best thing that you can do is to engage design review as early as possible. +Additionally, make your reviewers aware of your timeline so that they are +aware, and can endeavor to provide you the best possible service. We want you +to make your deadline if at all possible.

+

For time-sensitive alpha launches, an API may launch without receiving +design review approval. Such launches must be limited to a known set of +users. In this case, the reviewers will provide notes for the API team to take +under consideration for subsequent stages.

+

Warning: Launching an API in alpha with an incomplete design review does +not enshrine that API's decisions. Design review will be required to promote +the API to beta, and API reviewers will block your beta launch if there are +issues.

+

For launch stages after alpha, the API design review is mandatory due to its +impact on user experience across the board. Your team's inconsistencies affect +more than just your team.

+

In some cases, there is a difficult choice to be made between product +excellence and either engineering effort or deadlines. These are difficult +business decisions and we understand that they are sometimes necessary; +however, a director or VP must make an explicit choice to put these other +concerns ahead of product excellence when choosing to bypass design review or +disregard reviewers' feedback.

+

...to make my review go faster?

+

A few tips:

+
    +
  • Begin API review as early as possible, and follow up frequently.
  • +
  • Run the API linter beforehand. (If you are disabling the linter at any + point, explain why. Reviewers often find that the linter is disabled because + it did its job.)
  • +
  • Ensure that every message, RPC, and field is usefully commented. Comments + should be in valid American English and say something meaningful.
  • +
  • If your API reviewer asks you to explain something, add the explanation in + the proto comments, rather than the code review conversation. This will very + often save you a round trip.
  • +
+

...if one of my API reviewers is unresponsive?

+

Reach out to the reviewer on Chat. If that fails, reach out to the other +reviewer, who will coordinate accordingly. If that fails also, escalate +according to AIP-1.

+

...if I have a design question?

+

The first places to look at the API style guide, the AIP index, and +other public APIs within Google. Other public APIs are particularly valuable; +it is common that someone has encountered a situation that is germane to your +question.

+

...if I have a question not covered there?

+

Reach out to api-design@google.com with your question.

+

This generally works best when you are seeking guidance on a specific question +related to API design, and when you clearly explain your use case and provide +examples.

+

Note: The membership of this list comprises almost exclusively volunteers, +who spend the majority of their time doing something else. We do our best to be +responsive, but please be patient with us.

+

...if a question is complex and languishing in a CL?

+

While the code review interface is the best way to resolve questions when +practical, sometimes there are issues that are sufficiently complicated that +working them out in the code review tool is not feasible. In this situation, +reach out to your reviewers and ask to schedule a meeting. In general, most +issues can be discussed in 30 minutes.

+

When this happens, make sure that someone documents what is discussed in the +CL, so that the history is preserved.

+

...if my API needs to violate a standard?

+

Clearly document (using an internal comment in the proto) that you are +violating an API design guideline and your rationale for doing so. This comment +must be prefixed with aip.dev/not-precedent.

+

In general, your rationale for the design guideline violation should be in +accordance with one of the enumerated reasons listed in AIP-200. If it is +not, work together with your API reviewer to determine the right thing to do.

+

...if a reviewer is bringing up a previously-settled issue?

+

If you have a different reviewer from your API's previous stages, this might +happen. In general, the best approach is simply to reference the code review +where the issue was decided. Reviewers want to avoid causing you churn, and +therefore usually give deference to previous reviews. This is usually +sufficient to resolve the question promptly.

+

Occasionally, the reviewer may believe that the previous reviewer made a +significant mistake, and that correcting it is important. In this case, you and +your reviewer should work together to determine the best course of action.

+

...if the team and the reviewers strongly disagree?

+

Escalate according to AIP-1.

+

Does my PA or team have any particular guidelines?

+

The Cloud PA has specific guidelines to ensure additional uniformity across +Cloud, and Cloud APIs have their own reviewer pool. Other teams may adopt +similar (but not necessarily identical) rules and systems. Some teams that +produce multiple APIs (for example, machine learning) may also have guidelines +that apply to that group of APIs.

+

In all cases, we endeavor to make these guidelines available as AIPs; the +higher AIP numbers are reserved for specific PA and team use (see AIP-2), +and these AIPs are listed in the AIP index.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/111.html b/111.html new file mode 100644 index 0000000000..0ad34f450c --- /dev/null +++ b/111.html @@ -0,0 +1,772 @@ + + + + AIP-111: Planes + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-111

+

Planes

+

Resources and methods on an API can be divided into the plane that they reside +or perform operations upon. For the context of APIs, the following planes are +defined:

+
    +
  • Management plane: a uniform, resource-oriented API that primarily + configures and allows retrieval of resources.
  • +
  • Data plane: a heterogenous API (ideally resource-oriented) that reads and + write user data. Often connects to entities provisioned by the management + plane, such as virtual machines.
  • +
+

The term "plane" was originally used in networking architecture. Although system +and network architecture often defines additional planes (e.g. control plane or +power planes), as the AIPs are focused on the interface, they are not defined in +this AIP.

+

Guidance

+

Management Plane

+

Management resources and methods exist primarily to provision, configure, and +audit the resources that the data plane interfaces with.

+

As an example, the following are considered management resources for a cloud +provider:

+
    +
  • virtual machines
  • +
  • virtual private networks
  • +
  • virtual disks
  • +
  • a blob store instance
  • +
  • a project or account
  • +
+

Data Plane

+

Methods on the data plane operate on user data in a variety of data formats, and +generally interface with a resource provisioned via a management plane API. +Examples of data plane methods include:

+
    +
  • writing and reading rows in a table
  • +
  • pushing to or pulling from a message queue
  • +
  • uploading blobs to or downloading blobs from a blob store instance
  • +
+

Data plane APIs may be heterogenous across a larger API surface, due to +requirements including high throughput, low latency, or the need to adhere to an +existing interface specification (e.g. ANSI SQL).

+
    +
  • For convenience, resources and methods that operate on the data plane may +expose themselves via resource-oriented management APIs. If so, those resources +and methods must adhere to the requirements of the management plane as +specified in the other AIPs (AIP-131 through AIP-135).
  • +
+

Major distinctions between management and data plane

+
    +
  • Declarative clients operate on the management plane exclusively.
  • +
  • Data planes are often on the critical path of user-facing functionality, and + therefore:
      +
    • Have higher availability requirements than management planes.
    • +
    • Are more performance-sensitive than management planes.
    • +
    • Require higher-throughput than management planes.
    • +
    +
  • +
+

Changelog

+
    +
  • 2023-06-10: Introduction of this AIP.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/121.html b/121.html new file mode 100644 index 0000000000..90ba9c0d9a --- /dev/null +++ b/121.html @@ -0,0 +1,880 @@ + + + + AIP-121: Resource-oriented design + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-121

+

Resource-oriented design

+

Resource-oriented design is a pattern for specifying RPC APIs, based on +several high-level design principles (most of which are common to recent public +HTTP APIs):

+
    +
  • The fundamental building blocks of an API are individually-named resources + (nouns) and the relationships and hierarchy that exist between them.
  • +
  • A small number of standard methods (verbs) provide the semantics for most + common operations. However, custom methods are available in situations where + the standard methods do not fit.
  • +
  • Stateless protocol: Each interaction between the client and the server is + independent, and both the client and server have clear roles.
  • +
+

Readers might notice similarities between these principles and some principles +of REST; resource-oriented design borrows many principles from REST, while +also defining its own patterns where appropriate.

+

Guidance

+

When designing an API, consider the following (roughly in logical order):

+
    +
  • The resources (nouns) the API will provide
  • +
  • The relationships and hierarchies between those resources
  • +
  • The schema of each resource
  • +
  • The methods (verbs) each resource provides, relying as much as possible on + the standard verbs.
  • +
+

Resources

+

A resource-oriented API should generally be modeled as a resource +hierarchy, where each node is either a simple resource or a collection of +resources.

+

A collection contains resources of the same type. For example, a publisher +has the collection of books that it publishes. A resource usually has fields, +and resources may have any number of sub-resources (usually collections).

+

Note: While there is some conceptual alignment between storage systems and +APIs, a service with a resource-oriented API is not necessarily a database, and +has enormous flexibility in how it interprets resources and methods. API +designers should not expect that their API will be reflective of their +database schema. In fact, having an API that is identical to the underlying +database schema is actually an anti-pattern, as it tightly couples the surface +to the underlying system.

+

Methods

+

Resource-oriented APIs emphasize resources (data model) over the methods +performed on those resources (functionality). A typical resource-oriented API +exposes a large number of resources with a small number of methods on each +resource. The methods can be either the standard methods (Get, List, +Create, Update, Delete), or custom methods.

+

If the request to or the response from a standard method (or a custom method in +the same service) is the resource or contains the resource, the +resource schema for that resource across all methods must be the same.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Standard methodRequestResponse
CreateContains the resourceIs the resource
GetNoneIs the resource
UpdateContains the resourceIs the resource
DeleteNoneNone
ListNoneContains the resources
+

The table above describes each standard method's relationship to the resource, +where "None" indicates that the resource neither is nor is contained in +the request or the response

+

A resource must support at minimum Get: clients must be +able to validate the state of resources after performing a mutation such +as Create, Update, or Delete.

+

A resource must also support List, except for singleton resources +where more than one resource is not possible.

+

Note: A custom method in resource-oriented design does not entail +defining a new or custom HTTP verb. Custom methods use traditional HTTP verbs +(usually POST) and define the custom verb in the URI.

+

APIs should prefer standard methods over custom methods; the purpose of +custom methods is to define functionality that does not cleanly map to any of +the standard methods. Custom methods offer the same design freedom as +traditional RPC APIs, which can be used to implement common programming +patterns, such as database transactions, import and export, or data analysis.

+

Strong Consistency

+

For methods that operate on the management plane, the completion of those +operations (either successful or with an error, long-running operation, or +synchronous) must mean that the state of the resource's existence and all +user-settable values have reached a steady-state.

+

Output only values unrelated to the resource state should also have +reached a steady-state for values that are related to the resource state.

+

Examples include:

+
    +
  • Following a successful create that is the latest mutation on a resource, a get + request for a resource must return the resource.
  • +
  • Following a successful update that is the latest mutation on a resource, a get + request for a resource must return the final values from the update + request.
  • +
  • Following a successful delete that is the latest mutation on a resource, a get + request for a resource must return NOT_FOUND (or the resource with the + DELETED state value in the case of soft delete)
  • +
+

Clients of resource-oriented APIs often need to orchestrate multiple operations +in sequence (e.g. create resource A, create resource B which depends on A), and +ensuring that resources immediately reflect steady user state after an operation +is complete ensures clients can rely on method completion as a signal to begin +the next operation.

+

Output only fields ideally would follow the same guidelines, but as +these fields can often represent a resource's live state, it's sometimes +necessary for these values to change after a successful mutation operation to +reflect a state change.

+

Stateless protocol

+

As with most public APIs available today, resource-oriented APIs must +operate over a stateless protocol: The fundamental behavior of any +individual request is independent of other requests made by the caller. +This is to say, each request happens in isolation of other requests made by that +client or another, and resources exposed by an API are directly addressable +without needing to apply a series of specific requests to "reach" the desired +resource.

+

In an API with a stateless protocol, the server has the responsibility for +persisting data, which may be shared between multiple clients, while clients +have sole responsibility and authority for maintaining the application state.

+

Cyclic References

+

The relationship between resources, such as with resource references, +must be representable via a directed acyclic graph. The parent-child +relationship also must be acyclic, and as per AIP-124 a given resource +instance will only have one canonical parent resource.

+

A cyclic relationship between resources increases the complexity of managing +resources. Consider resources A and B that refer to +each other. The process to create said resources are:

+
    +
  1. create resource A without a reference to B. Retrieve id for resource A.
  2. +
  3. create resource B with a reference to A. Retrieve id for resource B.
  4. +
  5. update resource A with the reference to B.
  6. +
+

The delete operation may also become more complex, due to reasoning about which +resource must be dereferenced first for a successful deletion.

+

This requirement does not apply to relationships that are expressed via +output only fields, as they do not require the user to specify the values +and in turn do not increase resource management complexity.

+

Changelog

+
    +
  • 2024-07-08: Clarify acyclic nature of parent-child relationship.
  • +
  • 2023-08-24: Added guidance on consistency guarantees of methods.
  • +
  • 2023-07-23: Clarify stateless protocol definition.
  • +
  • 2023-01-21: Explicitly require matching schema across standard methods.
  • +
  • 2022-12-19: Added a section requiring Get and List.
  • +
  • 2022-11-02: Added a section restricting resource references.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/122.html b/122.html new file mode 100644 index 0000000000..6fc51ca563 --- /dev/null +++ b/122.html @@ -0,0 +1,1096 @@ + + + + AIP-122: Resource names + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-122

+

Resource names

+

Most APIs expose resources (their primary nouns) which users are able to +create, retrieve, and manipulate. Additionally, resources are named: each +resource has a unique identifier that users use to reference that resource, and +these names are what users should store as the canonical names for the +resources.

+

Guidance

+

All resource names defined by an API must be unique within that API. (See +the section on full resource names below for more +information on referring to resources across APIs.)

+

Resource names are formatted according to the URI path schema, but without +the leading slash:

+
  publishers/123/books/les-miserables
+  users/vhugo1802
+
+
    +
  • Resource name components should usually alternate between collection + identifiers (example: publishers, books, users) and resource IDs + (example: 123, les-miserables, vhugo1802).
  • +
  • Resource names must use the / character to separate individual segments + of the resource name.
      +
    • Non-terminal segments of a resource name must not contain a / + character.
    • +
    • The terminal segment of a resource name should not contain a / + character.
    • +
    +
  • +
  • Resource names should only use characters available in DNS names, as + defined by RFC-1123.
      +
    • Additionally, resource IDs should not use upper-case letters.
    • +
    • If additional characters are necessary, resource names should not use + characters that require URL-escaping, or characters outside of ASCII.
    • +
    • If Unicode characters can not be avoided, resource names must be stored + in Normalization Form C (see AIP-210).
    • +
    +
  • +
  • Resources must expose a name field that contains its resource name.
      +
    • Resources may provide the resource ID as a separate field (e.g. + book_id). This field must apply the + OUTPUT_ONLY field behavior classification.
    • +
    • Resources may expose a separate, system-generated unique ID field + (uid). This field must apply the + OUTPUT_ONLY field behavior classification.
    • +
    • Resources must not expose tuples, self-links, or other forms of + resource identification.
    • +
    • All ID fields should be strings.
    • +
    +
  • +
+

Note: Resource names as described here are used within the scope of a +single API (or else in situations where the owning API is clear from the +context), and are only required to be unique within that scope. For this +reason, they are sometimes called relative resource names to distinguish them +from full resource names (discussed below).

+

Collection identifiers

+

The collection identifier segments in a resource name must be the plural +form of the noun used for the resource. (For example, a collection of +Publisher resources is called publishers in the resource name.)

+
    +
  • Collection identifiers must be concise American English terms.
  • +
  • Collection identifiers must be in camelCase.
  • +
  • Collection identifiers must begin with a lower-cased letter and contain + only ASCII letters and numbers (/[a-z][a-zA-Z0-9]*/).
  • +
  • Collection identifiers must be plural.
      +
    • In situations where there is no plural word ("info"), or where the singular + and plural terms are the same ("moose"), the non-pluralized (singular) form + is correct. Collection segments must not "coin" words by adding "s" in + such cases (e.g, avoid "infos").
    • +
    +
  • +
  • Within any given single resource name, collection identifiers must be + unique. (e.g. people/xyz/people/abc is invalid)
  • +
+

Nested collections

+

If a resource name contains multiple levels of a hierarchy, and a parent +collection's name is used as a prefix for the child resource's name, the child +collection's name may omit the prefix. For example, given a collection of +UserEvent resources that would normally be nested underneath users:

+
users/vhugo1802/userEvents/birthday-dinner-226
+
+

An API should use the less-redundant form:

+
users/vhugo1802/events/birthday-dinner-226
+
+

In this situation, the message and resource type are still called +UserEvent; only the collection and resource identifiers in the pattern(s) are +shortened. Since the resource type is not shortened, the singular and +plural are similarly not shortened.

+
message UserEvent {
+  option (google.api.resource) = {
+    type: "example.googleapis.com/UserEvent"
+    // Only the collection & resource identfiers in the `pattern` are shortened.    
+    pattern: "projects/{project}/users/{user}/events/{event}"
+    singular: "userEvent"
+    plural: "userEvents"
+  };
+
+  string name = 1;
+}
+
+

Note: APIs wishing to do this must follow this format consistently +throughout all of its pattern entries defined and anywhere else the +resource is referenced in the API, or else not at all.

+

Resource ID segments

+

A resource ID segment identifies the resource within its parent collection. In +the resource name publishers/123/books/les-miserables, 123 is the resource +ID for the publisher, and les-miserables is the resource ID for the book.

+
    +
  • If resource IDs are user-specified, the API must document allowed + formats. User-specified resource IDs should conform to RFC-1034; + which restricts to letters, numbers, and hyphen, with the first character + a letter, the last a letter or a number, and a 63 character maximum.
      +
    • Additionally, user-specified resource IDs should restrict letters to + lower-case (^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$).
    • +
    • Characters outside of ASCII should not be permitted; however, if + Unicode characters are necessary, APIs must follow guidance in + AIP-210.
    • +
    +
  • +
  • If resource IDs are not user-settable, the API should document the + basic format, and any upper boundaries (for example, "at most 63 + characters").
  • +
  • For more information, see the create standard method.
  • +
+

Resource ID aliases

+

It is sometimes valuable to provide an alias for common lookup patterns for +resource IDs. For example, an API with users at the top of its resource +hierarchy may wish to provide users/me as a shortcut for retrieving +information for the authenticated user.

+

APIs may provide programmatic aliases for common lookup patterns. However, +all data returned from the API must use the canonical resource name.

+

Full resource names

+

In most cases, resource names are used within a single API only, or else they +are used in contexts where the owning API is clear (for example, +string pubsub_topic).

+

However, sometimes it is necessary for services to refer to resources in an +arbitrary API. In this situation, the service should use the full resource +name, a schemeless URI with the owning API's service name, +followed by the relative resource name:

+
//library.googleapis.com/publishers/123/books/les-miserables
+//calendar.googleapis.com/users/vhugo1802
+
+

Note: The full resource name should not be used for cross-API +references where the owning API is clear; it is only used if a field refers to +resources in multiple APIs where ambiguity is possible.

+

Resource URIs

+

The full resource name is a schemeless URI, but slightly distinct from the full +URIs we use to access a resource. The latter includes the protocol +(HTTPS), the API version, and the specific service endpoint +to target:

+
https://library.googleapis.com/v1/publishers/123/books/les-miserables
+https://calendar.googleapis.com/v3/users/vhugo1802
+
+

The version is not included in the full resource name because the full resource +name is expected to persist from version to version. Even though the API +surface may change between major versions, multiple major versions of the same +API are expected to use the same underlying data.

+

Note: The correlation between the full resource name and the service's +endpoint is by convention. In particular, one service is able to have multiple +endpoints (example use cases include regionalization, MTLS, and private access), +and the full resource name does not change between these.

+

Fields representing resource names

+

When defining a resource, the first field should be the resource name, +which must be of type string and must be called name for the +resource name. The message should include a google.api.resource +annotation declaring the type (see AIP-123 for more on this).

+
// A representation of a book in the library.
+message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  // The resource name of the book.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // Other fields...
+}
+
+

When defining a method that retrieves or acts on an already-existing resource +(such as GetBook or ArchiveBook), the first field of the request message +should be the resource name, which must be of type string and +must be called name for the resource name. The field should also be +annotated with the google.api.resource_reference annotation, referencing the +resource type (AIP-123).

+
// Request message for ArchiveBook
+message ArchiveBookRequest {
+  // The book to archive.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+
+  // Other fields...
+}
+
+

Note: Fields must not be called name except for this purpose. For +other use cases, either use a different term or prepend an adjective (for +example: display_name).

+

Fields representing a resource's parent

+

When defining a method that retrieves resources from a collection or adds a new +resource to a collection (such as ListBooks or CreateBook), the first field +of the request message should be of type string and should be called +parent for the resource name of the collection. The parent field should +also be annotated with the google.api.resource_reference annotation, +referencing the parent's resource type (AIP-123).

+
// Request message for ListBooks.
+message ListBooksRequest {
+  // The publisher to list books from.
+  // Format: publishers/{publisher_id}
+  string parent = 1 [(google.api.resource_reference) = {
+    type: "library.googleapis.com/Publisher"
+  }];
+
+  // Other fields (e.g. page_size, page_token, filter, etc.)...
+}
+
+

If there is more than one possible parent type, the parent field should +be annotated with the child_type key on google.api.resource_reference +instead:

+
// Request message for ListBooks.
+message ListBooksRequest {
+  // The parent to list books from.
+  // Format:
+  //   - publishers/{publisher_id}
+  //   - authors/{author_id}
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // Other fields (e.g. page_size, page_token, filter, etc.)...
+}
+
+

Note: Fields should not be called parent except for this purpose. For +other use cases, use a synonymous term if possible.

+

Fields representing another resource

+

When a field represents another resource, the field should be of type +string and accept the resource name of the other resource. The field name +should be equivalent to the corresponding message's name in snake case.

+
    +
  • Field names may include a leading adjective if appropriate (such as + string dusty_book).
  • +
  • Field names should not use the _name suffix unless the field would be + ambiguous without it (e.g., crypto_key_name)
  • +
  • Fields representing another resource should provide the + google.api.resource_reference annotation with the resource type being + referenced.
  • +
  • If using the resource name is not possible and using the ID component alone is +strictly necessary, the field should use an _id suffix (e.g. shelf_id).
  • +
+

The field should not be of type message using the message that +implements the resource, except for one of following conditions:

+
    +
  • The API is internal-only, has tight lifecycle relationships, and has a + permission model that enables inherited access to embedded resources.
  • +
  • The embedding of the resource is done as part of the AIP-162 revisions + pattern.
  • +
+

Example of a resource reference:

+
// A representation of a book in a library.
+message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  // Name of the book.
+  // Format is `publishers/{publisher}/books/{book}`
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The shelf where the book currently sits.
+  // Format is `shelves/{shelf}`.
+  string shelf = 2 [(google.api.resource_reference) = {
+    type: "library.googleapis.com/Shelf"
+  }];
+
+  // Other fields...
+}
+
+

Further reading

+
    +
  • For evolving resource names over time, see + AIP-180.
  • +
  • For resource types, see AIP-123.
  • +
+

Rationale

+

Using names instead of IDs

+

For any large system, there are many kinds of resources. To use simple resource +IDs to identify a resource, we'd actually need use a resource-specific tuple to +reliably identify it, such as (bucket, object) or (user, album, photo). This +creates several issues:

+
    +
  • Developers have to understand and remember such anonymous tuples.
  • +
  • Passing tuples is generally harder than passing strings.
  • +
  • Centralized infrastructures, such as logging and access control systems, + don't understand specialized tuples.
  • +
  • Specialized tuples limit API design flexibility, such as providing + reusable API interfaces. For example, + Long Running Operations can work with many other API interfaces + because they use flexible resource names.
  • +
+

Standardizing on name

+

The concept of resource names is not a new one, and is formalized in Uniform +Resource Names (URN) in conjunction with Uniform Resource Identifiers (URI) and +Uniform Resource Locators (URL). Considering that the term "name" is so heavily +overloaded in general, usage outside of a very well-defined meaning would be +confusing for developers. So, the field name name is reserved in the context +of AIP-compliant APIs so as to eliminate any confusion with resource names, and +force other would be "name" fields to use a more specific field name.

+

Disallow embedding of resources

+

Using a resource message directly as the type of a field within another resource +is problematic for a number of reasons, which are as follows:

+
    +
  • Complicates the resource lifecycle: If the dependency resource is + deleted, what happens to the embedded reference in the dependent resource? + Data retention and clean up operations will be significantly complicated.
  • +
  • Bypasses permissions: If every resource has its own set of permissions, a user + with read permission on the dependent resource that doesn't have the same + permission on the dependency resource suddenly cannot see the full resource.
  • +
  • Tightly couples resources in all aspects: Changing the requirements in the + schema, permissions, or otherwise for either resource impacts the other, + significantly increasing complexity of roll outs.
  • +
+

Referencing by name, as is recommended, eliminates all of this complexity by +preventing resource data duplication, and forcing the owning service to be +involved in the resolution of the reference (via Standard Methods), guaranteeing +isolation of logical concerns per-resource.

+

History

+

Disallowing UUIDs in user-specified IDs

+

As part of an effort to make APIs more declarative-friendly, APIs were required +to allow user-specified resource ID on creation. As part of this, a supporting +field string uid containing a UUID was also encouraged. Guidance was then +added to discourage the user-specified resource ID from being a UUID or +even resembling one.

+

Ostensibly, the fact that uid contained a service-generated UUID motivated +this restriction on the user-specified resource ID, forcing the user-specified +resource ID to be a more "meaningful" value. However, we no longer saw value in +this requirement, hence its removal.

+

Changelog

+
    +
  • 2025-03-10: Drop guidance disallowing UUID in user-specified ID.
  • +
  • 2024-10-15: Add some rationale we found for use of name as a field and + instead of IDs as an identifier.
  • +
  • 2024-06-14: Clarify resource annotation shortening rules for nested + collections.
  • +
  • 2023-09-19: Prohibit duplicate collection identifiers.
  • +
  • 2023-09-01: Add a clause that allows embedding for revision resource + messages.
  • +
  • 2023-08-10: Explicitly disallow embedding resource messages in a resource.
  • +
  • 2023-03-24: Correction: full resource name contains the service name rather + than the service endpoint
  • +
  • 2023-03-17: Add OUTPUT_ONLY guidance for resource ID fields.
  • +
  • 2020-10-06: Added declarative-friendly guidance, and tightened character + set restrictions.
  • +
  • 2020-10-05: Clarified when full resource names are used.
  • +
  • 2020-05-19: Clarified that resource IDs avoid capital characters, not + the entire resource name.
  • +
  • 2020-04-27: Tighten the restriction on valid characters.
  • +
  • 2019-12-05: Added guidance for resource annotations.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership. Also changed the final + example from a Pub/Sub example to the usual Book example.
  • +
  • 2019-07-30: Changed the nested collection brevity suggestion from "may" + to "should"
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/123.html b/123.html new file mode 100644 index 0000000000..a35bff1b18 --- /dev/null +++ b/123.html @@ -0,0 +1,832 @@ + + + + AIP-123: Resource types + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-123

+

Resource types

+

Most APIs expose resources (their primary nouns) which users are able to +create, retrieve, and manipulate. APIs are allowed to name their resource types +reasonably freely (within the requirements of this AIP), and are only required +to ensure uniqueness within that API. This means that it is possible (and often +desirable) for different APIs to use the same type name. For example, a Memcache +and Redis API would both want to use Instance as a type name.

+

When mapping the relationships between APIs and their resources, however, it +becomes important to have a single, globally-unique type name. Additionally, +tools such as Kubernetes or GraphQL interact with APIs from multiple providers.

+

Terminology

+

In the guidance below, we use the following terms:

+
    +
  • Service Name: This is the name defined in the service configuration. + This usually (but not necessarily) matches the hostname that users use to + call the service. Example: pubsub.googleapis.com. This is equivalent to an + API Group in Kubernetes.
  • +
  • Type: This is the name used for the type within the API e.g. the name of + the Protobuf message. This is equivalent to an Object in Kubernetes.
  • +
+

Guidance

+

APIs must define a resource type for each resource in the API, according to +the following pattern: {Service Name}/{Type}. The type name must:

+
    +
  • Match the containing API type's name.
  • +
  • Start with an uppercase letter.
  • +
  • Only contain alphanumeric characters.
  • +
  • Be of the singular form of the noun.
  • +
  • Use PascalCase (UpperCamelCase).
  • +
+

Examples

+

Examples of resource types include:

+
    +
  • pubsub.googleapis.com/Topic
  • +
  • pubsub.googleapis.com/Subscription
  • +
  • spanner.googleapis.com/Database
  • +
  • spanner.googleapis.com/Instance
  • +
  • networking.istio.io/Instance
  • +
+

Annotating resource types

+

APIs should annotate the resource types for each resource in the API using +the google.api.resource annotation:

+
// A representation of a Pub/Sub topic.
+message Topic {
+  option (google.api.resource) = {
+    type: "pubsub.googleapis.com/Topic"
+    pattern: "projects/{project}/topics/{topic}"
+    singular: "topic"
+    plural: "topics"
+  };
+
+  // Name and other fields...
+}
+
+
    +
  • Patterns must correspond to the resource name.
  • +
  • Pattern variables (the segments within braces) must use snake_case, and + must not use an _id suffix.
  • +
  • Pattern variables must conform to the format [a-z][_a-z0-9]*[a-z0-9].
  • +
  • Pattern variables must be unique within any given pattern. (e.g. + projects/{abc}/topics/{abc} is invalid; this is usually a natural + corollary of collection identifiers being unique within a pattern.)
  • +
  • Resources with multiple patterns must + preserve ordering: new patterns must be added at the end of the list, and + existing patterns must not be removed or re-ordered, as this breaks client + library backward compatibility.
  • +
  • Singular must be the lower camel case of the type.
      +
    • Pattern variables must be the singular form of the resource type e.g. + a pattern variable representing a Topic resource ID is named {topic}.
    • +
    +
  • +
  • Plural must be the lower camel case plural of the singular.
      +
    • Pattern collection identifier segments must match the plural of the + resources, except in the case of nested collections.
    • +
    +
  • +
+

Pattern uniqueness

+

When multiple patterns are defined within a resource, these patterns must +be mutually unique, where uniqueness is defined as being by-character identical +once all resource ID path segments have been removed, leaving all / +separators.

+

Therefore the following two patterns must not be defined within the same +resource:

+
    +
  • user/{user}
  • +
  • user/{user_part_1}~{user_part_2}
  • +
+

Rationale

+

Type and message name alignment

+

In addition to simple schema-resource coherence and alignment, a number of +consumers benefit from the {Type} and message names matching. Consumers have +simpler lookups, client libraries get the same in addition to aligned user +experience where resource-oriented code has naming aligned with the generated +message code, generated reference documentation aligns resources with +message docs, etc.

+

Singular and Plural

+

Well-defined singular and plurals of a resource enable clients to determine the +proper name to use in code and documentation.

+

lowerCamelCase can be translated into other common forms of a resource name +such as UpperCamelCase and snake_case.

+ + + +

Changelog

+
    +
  • 2025-01-09: Strongly align resource type and message naming.
  • +
  • 2024-08-07: Added multi-pattern ordering compatibility requirements.
  • +
  • 2023-09-19: Prohibited duplicate pattern variables.
  • +
  • 2023-05-06: Added requirement of singular and plural.
  • +
  • 2023-01-28: Clarified guidance for the resource type name.
  • +
  • 2022-10-28: Added pattern variable format guidance.
  • +
  • 2020-05-14: Added pattern uniqueness.
  • +
  • 2019-12-05: Added guidance on patterns.
  • +
  • 2019-07-17: Fleshed out the annotation example somewhat.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/124.html b/124.html new file mode 100644 index 0000000000..15c4b6cd11 --- /dev/null +++ b/124.html @@ -0,0 +1,801 @@ + + + + AIP-124: Resource association + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-124

+

Resource association

+

APIs sometimes have resource hierarchies that can not be cleanly expressed in +the usual tree structure. For example, a resource may have a many-to-one +relationship with two other resource types instead of just one. Alternatively, +a resource may have a many-to-many relationship with another resource type.

+

Guidance

+

A resource must have at most one canonical parent, and List requests +must not require two distinct "parents" to work.

+

Multiple many-to-one associations

+

If a resource has a many-to-one relationship with multiple resource types, it +must choose at most one of them to be the canonical parent. The resource +may be associated with other resources through other fields on the +resource.

+
message Book {
+  // The resource name pattern for Book indicates that Publisher is the
+  // canonical parent.
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  // The resource name for the book.
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The resource name for the book's author.
+  string author = 2 [(google.api.resource_reference) = {
+    type: "library.googleapis.com/Author"
+  }];
+}
+
+

When listing resources with multiple associations in this way, the RPC must +treat the string parent field as required as discussed in AIP-132, and +must not add additional required arguments. The RPC should include a +string filter field that allows users to filter by other resource +associations as discussed in AIP-160.

+

Note: Resource reference fields must accept the same resource name +format that is used in the name field of the referenced resource.

+

Many-to-many associations

+

Many-to-many associations are less common in APIs than they are in relational +databases, in part because they are more difficult to model and present over +network interfaces.

+

An API may contain many-to-many relationships, and should use a +repeated field containing a list of resource names, following the principles +described for repeated fields in AIP-144.

+
message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The resource names for the book's authors.
+  repeated string authors = 2 [(google.api.resource_reference) = {
+    type: "library.googleapis.com/Author"
+  }];
+}
+
+

Note: See AIP-144 for more information on repeated fields, including +how to handle common issues such as atomic changes.

+

If the use of a repeated field is too restrictive, or if more metadata is +required along with the association, an API may model a many-to-many +relationship using a sub-resource with two one-to-many associations.

+
message BookAuthor {
+  // The resource pattern for BookAuthor indicates that Book is the
+  // canonical parent.
+  option (google.api.resource) = {
+    type: "library.googleapis.com/BookAuthor"
+    pattern: "publishers/{publisher}/books/{book}/authors/{book_author}"
+  };
+
+  // The resource name for the book-author association.
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The resource name for the author.
+  string author = 2 [(google.api.resource_reference) = {
+    type: "library.googleapis.com/Author"
+  }];
+
+  // Other fields...
+}
+
+

Note: Using subresources to model an association between resources is only +recommended if additional metadata is required in the relationship, or if the +restrictions around the use of a repeated field preclude the use of that +approach.

+

Changelog

+
    +
  • 2021-04-07: Clarified that resource reference fields accept resource + names with the same format as the name field of the resource.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/126.html b/126.html new file mode 100644 index 0000000000..3b45a28bb1 --- /dev/null +++ b/126.html @@ -0,0 +1,811 @@ + + + + AIP-126: Enumerations + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-126

+

Enumerations

+

It is common for a field to only accept or provide a discrete and limited set +of values. In these cases, it can be useful to use enumerations (generally +abbreviated "enums") in order to clearly communicate what the set of allowed +values are.

+

Guidance

+

APIs may expose enum objects for sets of values that are expected to change +infrequently:

+
// A representation of a book.
+message Book {
+  // Other fields...
+
+  // Possible formats in which the book may be published.
+  enum Format {
+    // Default value. This value is unused.
+    FORMAT_UNSPECIFIED = 0;
+
+    // The printed format, in hardback.
+    HARDBACK = 1;
+
+    // The printed format, in paperback.
+    PAPERBACK = 2;
+
+    // An electronic book format.
+    EBOOK = 3;
+
+    // An audio recording.
+    AUDIOBOOK = 4;
+  }
+
+  // The format of the book.
+  Format format = 99;
+
+  // Other fields...
+}
+
+
    +
  • All enum values must use UPPER_SNAKE_CASE.
  • +
  • The first value of the enum should be the name of the enum itself + followed by the suffix _UNSPECIFIED.
      +
    • An exception to this rule is if there is a clearly useful zero value. In + particular, if an enum needs to present an UNKNOWN, it is usually clearer + and more useful for it to be a zero value rather than having both. The + UNKNOWN value may be prefixed by the enum name as is typical for + avoiding enum value name collisions.
    • +
    +
  • +
  • Enums which will only be used in a single message should be nested within that message. + In this case, the enum should be declared immediately before it is used.
      +
    • The non-zero values of such a nested enum definition should not be prefixed by the name + of the enum itself. This generally requires users to write MyState.MYSTATE_ACTIVE in their + code, which is unnecessarily verbose.
    • +
    +
  • +
  • Enums which will be used by multiple messages should be defined at the package level and + should be defined at the bottom of the proto file (see AIP-191).
      +
    • Some languages (including C++) hoist enum values into the parent namespace, which can result + in conflicts for enums with the same values in the same proto package. To avoid sharing values, + APIs should prefix package-level enum values with the name of the enum.
    • +
    +
  • +
  • Enums should document whether the enum is frozen or they expect to add + values in the future.
  • +
+

When to use enums

+

Enums can be more accessible and readable than strings or booleans in many +cases, but they do add overhead when they change. Therefore, enums should +receive new values infrequently. While the definition of "infrequently" may +change based on individual use cases, a good rule of thumb is no more than once +a year. For enums that change frequently, the API should use a string and +document the format.

+

Additionally, enums should not be used when there is a competing, +widely-adopted standard representation (such as with language codes +or media types).

+

Note: If an enumerated value needs to be shared across APIs, an enum +may be used, but the assignment between enum values and their corresponding +integers must match.

+

Alternatives

+

For enumerated values where the set of allowed values changes frequently, APIs +should use a string field instead, and must document the allowed +values. String fields with enumerated values should use kebab-case for +their values.

+

For enumerated values where there is a competing, widely-adopted standard +representation (generally, but not necessarily, a string), that standard +representation should be used. This is true even if only a small subset of +values are permitted, because using enums in this situation often leads to +frustrating lookup tables when trying to use multiple APIs together.

+

Boolean fields may be used in situations where it is clear that no further +flexibility will be needed. The default value must be false.

+

Note: When using protocol buffers, it is impossible to distinguish between +false and unset. If this is a requirement, an enum may be a better design +choice (although google.protobuf.BoolValue is also available).

+

Further reading

+
    +
  • For states, a special type of enum, see AIP-216.
  • +
+

Changelog

+
    +
  • 2025-10-03: Added prefixing guidance for UNKNOWN value exception.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/127.html b/127.html new file mode 100644 index 0000000000..6cfac13f09 --- /dev/null +++ b/127.html @@ -0,0 +1,835 @@ + + + + AIP-127: HTTP and gRPC Transcoding + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-127

+

HTTP and gRPC Transcoding

+

APIs that follow resource-oriented design are defined using +RPCs, but the resource-oriented design framework allows them to also be +presented as APIs that largely follow REST/JSON conventions. This is important +in order to help developers use their existing knowledge: over 80% of the +public APIs available follow most REST conventions, and developers are +accustomed to that pattern.

+

Guidance

+

APIs must provide HTTP definitions for each RPC that they define, except +for bi-directional streaming RPCs, which can not be natively supported using +HTTP/1.1. When providing a bi-directional streaming method, an API should +also offer an alternative method that does not rely on bi-directional +streaming.

+

HTTP method and path

+

When using protocol buffers, each RPC must define the HTTP method and path +using the google.api.http annotation:

+
rpc CreateBook(CreateBookRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books"
+    body: "book"
+  };
+}
+
+message CreateBookRequest {
+  // The publisher who will publish this book.
+  // When using HTTP/JSON, this field is automatically populated based
+  // on the URI, because of the `{parent=publishers/*}` syntax.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The book to create.
+  // When using HTTP/JSON, this field is populated based on the HTTP body,
+  // because of the `body: "book"` syntax.
+  Book book = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // The user-specified ID for the book.
+  // When using HTTP/JSON, this field is populated based on a query string
+  // argument, such as `?bookId=foo`. This is the fallback for fields that
+  // are not included in either the URI or the body.
+  // Note that clients use camelCase format to communicate the field names
+  // to the service.
+  string book_id = 3;
+}
+
+
    +
  • The first key (post in this example) corresponds to the HTTP method. RPCs + may use get, post, patch, or delete.
      +
    • RPCs must use the prescribed HTTP verb for each standard method, as + discussed in AIP-131, AIP-132, AIP-133, AIP-134, and + AIP-135
    • +
    • RPCs should use the prescribed HTTP verb for custom methods, as + discussed in AIP-136.
    • +
    • RPCs should not use put or custom.
    • +
    +
  • +
  • The corresponding value represents the URI.
      +
    • URIs must use the {foo=bar/*} syntax to represent a variable that + should be populated in the request proto. When extracting a resource + name, the variable must include the entire resource name, not + just the ID component.
    • +
    • URIs may use nested fields for their variable names. (Additionally, + AIP-134 mandates this for Update requests.)
    • +
    • URIs must use the * character to represent ID components, which + matches all URI-safe characters except for /. URIs may use ** as + the final segment of a URI if matching / is required.
    • +
    +
  • +
  • The body key defines which single top-level field in the request will be + sent as the HTTP body. If the body is *, then this indicates that the + request object itself is the HTTP body. The request body is encoded as JSON + as defined by protocol buffers' canonical JSON encoding.
      +
    • RPCs must not define a body at all for RPCs that use the GET or + DELETE HTTP verbs.
    • +
    • RPCs must use the prescribed body for Create (AIP-133) and Update + (AIP-134) requests.
    • +
    • RPCs should use the prescribed body for custom methods (AIP-136).
    • +
    • The body must not contain a nested field (or use the . character),
    • +
    • The body must not be the same as a URI parameter.
    • +
    • The body must not be a repeated field.
    • +
    • Fields should not use the json_name annotation to alter the field + name in JSON, unless doing so for backwards-compatibility reasons.
    • +
    +
  • +
+

Note: Bi-directional streaming RPCs should not include a google.api.http +annotation at all. If feasible, the service should provide non-streaming +equivalent RPCs.

+

Multiple URI bindings

+

Occasionally, an RPC needs to correspond to more than one URI:

+
rpc CreateBook(CreateBookRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books"
+    body: "book"
+    additional_bindings: {
+      post: "/v1/{parent=authors/*}/books"
+      body: "book"
+    }
+    additional_bindings: {
+      post: "/v1/books"
+      body: "book"
+    }
+  };
+}
+
+
    +
  • RPCs may define any number of additional bindings. The structure is + identical to the google.api.http annotation (in fact, it is a recursive + reference).
  • +
  • RPCs must not define an additional binding within an additional binding.
  • +
  • The body clause must be identical in the top-level annotation and each + additional binding.
  • +
+

Changelog

+
    +
  • 2022-08-18: Added the comment that query string parameter names are + in camelCase.
  • +
  • 2021-01-06: Added clarification around body and nested fields.
  • +
  • 2019-09-23: Added a statement about request body encoding, and guidance + discouraging json_name.
  • +
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/128.html b/128.html new file mode 100644 index 0000000000..33257392c0 --- /dev/null +++ b/128.html @@ -0,0 +1,777 @@ + + + + AIP-128: Declarative-friendly interfaces + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-128

+

Declarative-friendly interfaces

+

Many services need to interact with common DevOps tools, particularly those +that create and manage network-addressable resources (such as virtual machines, +load balancers, database instances, and so on). These tools revolve around the +principle of "configuration as code": the user specifies the complete intended +landscape, and tooling is responsible for making whatever changes are necessary +to achieve the user's specification.

+

These tools are declarative: rather than specifying specific actions to +take, they specify the desired outcome, with the actions being derived based +on the differences between the current landscape and the intended one.

+

Furthermore, there are numerous popular DevOps tools, with more being +introduced each year. Integrating hundreds of resource types with multiple +tools requires uniformity, so that integration can be automated.

+

Guidance

+

Resources

+

Resources that are declarative-friendly must use only strongly-consistent +standard methods for managing resource lifecycle, which allows tools to support +these resources generically, as well as conforming to other +declarative-friendly guidance (see further reading).

+

Declarative-friendly resources should designate that they follow the +declarative-friendly style:

+
message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+    style: DECLARATIVE_FRIENDLY
+  };
+
+  // Name and other fields...
+}
+
+

Reconciliation

+

If a resource takes time (more than a few seconds) for updates to be realized, +the resource should include a bool reconciling field to disclose that +changes are in flight. This field must be output only.

+

A resource must set the reconciling field to true if the current state +of the resource does not match the user's intended state, and the system is +working to reconcile them. This is regardless of whether the root cause of +going into reconciliation was user or system action.

+

Note: Services responding to a GET request must return the resource's +current state (not the intended state).

+

Further reading

+

A significant amount of guidance is more strict for declarative-friendly +interfaces, due to the focus on automation on top of these resources. This list +is a comprehensive reference to declarative-friendly guidance in other AIPs:

+
    +
  • Resources should not employ custom methods: see AIP-136.
  • +
  • Resources must use the Update method for repeated fields: see AIP-144.
  • +
  • Resources must include certain standard fields: see AIP-148.
  • +
  • Resources must have an etag field: see AIP-154.
  • +
  • Resources should provide change validation: see AIP-163.
  • +
  • Resources should not implement soft-delete. If the id cannot be re-used, + the resource must implement soft-delete and the undelete RPC: see AIP-164
  • +
+

Annotations

+

See AIP-148 annotations.

+

Changelog

+
    +
  • 2023-07-13: Move annotations from AIP-148.
  • +
  • 2023-06-17: Definition of plane was removed and incorporated into AIP-111.
  • +
  • 2023-05-11: Removed must on resource_id, which was upstreamed to a general + must.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/129.html b/129.html new file mode 100644 index 0000000000..423ac3838c --- /dev/null +++ b/129.html @@ -0,0 +1,828 @@ + + + + AIP-129: Server-Modified Values and Defaults + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-129

+

Server-Modified Values and Defaults

+

Services often provide default values for resource fields, and occasionally +normalize the user input before returning it in the response. The guidance +herein describes how services document such behavior for the benefit of +consumers.

+

Guidance

+

Single Owner Fields

+

Fields must have a single owner, whether that is the client or the server. +Server owned fields must be indicated with the OUTPUT_ONLY field_behavior. +All other types of fields must be considered to be owned by the client. The +server must respect the value (or lack thereof) for all client owned fields +and not modify them.

+

Effective Values

+

There are instances where a service will allocate, generate, or calculate a +value if the client chooses not to specify one. For example: a client creates a +virtual machine without specifying a static IP address for the virtual machine +to be available on. Such a scenario is opting into dynamic IP address +allocation.

+

Some examples of these types of fields are ones that are:

+
    +
  • generated (UUID)
  • +
  • allocated (dynamic IP address)
  • +
  • assigned (most recent software package version)
  • +
+

An attribute with an effective value must be expressed as two fields in +the API:

+
    +
  • a mutable field that can be optionally set by the user and must not be +modified by the service
  • +
  • an OUTPUT_ONLY field that records the effective value decided on by the +service
  • +
+

Example: +

message VirtualMachine {
+  
+  string ip_address = 4;
+  string effective_ip_address = 5 [
+    (google.api.field_behavior) = OUTPUT_ONLY
+  ];
+}
+

+

Naming

+

Effective values must be named by prefixing effective_ to the mutable +field's name.

+

User-Specified Fields

+

For user-specified fields, the value in response from the service must be +the same as provided by the create or update request. For string fields this +means returning the value unchanged, with one exception:

+
    +
  • When a string field has a data type annotation, a normalized string that + represents the given value may be returned.
  • +
+

Normalizations

+

A field that is normalized by the service must be annotated with the +google.api.field_info extension. See (AIP-202) for guidance on using +this extension The allowed set of normalizations includes the following formats:

+
    +
  • uuid
  • +
  • ipv4
  • +
  • ipv6
  • +
  • email
  • +
+

Normalizations on fields must be described using the google.api.field_info +annotation.

+

Rationale

+

Server-modified and default values often make it harder to implement +declarative clients. These clients are often unable to +tell when their desired state matches the current state for these fields, as the +rules by which a server may modify and return values are complex, not public, +and not repeatable.

+

Rationale for Single Owner Fields

+

When fields do not have a single owner they can cause issues for +declarative clients. These clients may attempt to set +values for fields that are overwritten by server set values, leading to the +client entering an infinite loop to correct the change.

+

Rationale for Naming

+

Consistent naming is important for identifying standard behavior across APIs +and fields. Programmatic association between user-specified and effective values +depends on consistent naming.

+

Rationale for Normalizations

+

Normalizations are important to allow services to store and return values in a +standard way while communicating to clients what changes are semantically +identical. Normalizing a value on the service side allows the service to accept +a wider range of semantically identical inputs without needing to maintain every +value as a raw string. Surfacing the normalization that is being applied to +clients allows for client side comparison of sent and retrieved values to check +for differences.

+

For example, in a resource that accepts an email address on a particular field +a client may specify a given email address in a variety of ways. For the email +ada@example.com a client may choose to specify ADA@example.com, +aDa@example.com, or AdA@example.com. These are semantically identical and +should all be accepted by the service. The service then may choose to +normalize the email address for storage and retrieval through downcasing or +canonicalization. Importantly, the information surfaced to clients on the +normalization of a field will not describe the normalization algorithm itself, +but instead the comparison method used to accurately compute if two values +should be considered equal.

+

Rationale for Field Value Handling

+

For fields not using an allowed normalization, +Declarative clients will not be able to identify which changes are +semantically meaningful. When a Declarative client +sends a particular value it will ensure that the value is being returned by the +service to validate it was set correctly.

+

Changelog

+
    +
  • 2023-10-31: Update to approved.
  • +
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/130.html b/130.html new file mode 100644 index 0000000000..9eb2e328e1 --- /dev/null +++ b/130.html @@ -0,0 +1,889 @@ + + + + AIP-130: Methods + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-130

+

Methods

+

An API is composed of one or more methods, which represent a specific operation +that a service can perform on behalf of the consumer.

+

Guidance

+

Categories of Methods

+

The following enumerates multiple categories of methods that exist, often +grouped up under some object (e.g. collection or resource) that the method +operates upon.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Category NameRelated AIPsDeclarative client integrationCLI / UI integrationSDK integration
Standard Methods
Standard collection methods: operate on a collection of resources (List or Create).AIP-121, AIP-132, AIP-133automatableautomatableautomatable
Standard resource methods: fetch or mutate a single resource (Get, Update, Delete).AIP-121, AIP-131, AIP-134, AIP-135automatableautomatableautomatable
Batch resource methods: fetch or mutate multiple resources in a collection by name.AIP-231, AIP-233, AIP-234, AIP-235may be used to optimize queriesautomatableautomatable
Aggregated list methods: fetch or mutate multiple resources of the same type across multiple collections.AIP-159not useful nor automatableautomatableautomatable
Custom Fetch Methods
Custom collection fetch methods: fetch information across a collection that cannot be expressed via a standard method.AIP-136handwrittenautomatableautomatable
Custom resource fetch methods: fetch information for a single resource that cannot be expressed via a standard method.AIP-136handwrittenautomatableautomatable
Custom Mutation Methods
Backing up a resource: storing a copy of a resource at a particular point in time.AIP-162unused or handwrittenautomatableautomatable
Restoring a resource: setting a resource to a version from a particular point in time.AIP-162unused or handwrittenautomatableautomatable
Renaming a resource: modify the resource's name or id while preserving configuration and data.AIP-136unused or handwrittenautomatableautomatable
Custom collection mutation methods: perform an imperative operation referencing a collection that may mutate one or more resources within that collection in fashion that cannot be easily achieved by standard methods (e.g. state transitions).AIP-136unused or handwrittenautomatableautomatable
Custom resource mutation methods: perform an imperative operation on a resource that may mutate it in a way a standard method cannot (e.g. state transitions).AIP-136unused or handwrittenautomatableautomatable
Misc Custom Methods
Stateless Methods: a method that has no permanent effect on any data within the API (e.g. translating text)AIP-136unused or handwrittenautomatableautomatable
None of the above
Streaming methods: methods that communicate via client, server, or bi-directional streams.handwrittenhandwrittenautomatable
+

Choosing a method category

+

While designing a method, API authors should choose from the defined categories +in the following order:

+
    +
  1. Standard methods (on collections and resources)
  2. +
  3. Standard batch or aggregate methods
  4. +
  5. Custom methods (on collections, resources, or stateless)
  6. +
  7. Streaming methods
  8. +
+

Rationale

+

Resource-oriented standard and custom methods are recommended first, as they can +be expressed in the widest variety of clients (Declarative clients, CLIs, UIs, and so on), and +offer the most uniform experience that allows users to apply their knowledge of +one API to another.

+

If a standard method is unsuitable, then custom methods (that are mounted to a +resource or collection) offer a lesser, but still valuable level of consistency, +helping the user reason about the scope of the action and the object whose +configuration is read to inform that action. Although mutative custom methods +are not uniform enough to have a automated integration with exclusively +resource-oriented clients such as Declarative clients, they are still a pattern that +can easily recognized by CLIs, UIs, and SDKs.

+

If one cannot express their APIs in a resource-oriented fashion at all, then the +operation falls in a category where the lack of uniformity makes it difficult +for any client aside from SDKs to model the operation. This category is +preferred last due to the fact that a user cannot rely on their knowledge of +similar APIs, as well as the issue that integration with many clients will +likely have to be hand-written.

+

Changelog

+
    +
  • 2023-09-05: Update to approved.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/131.html b/131.html new file mode 100644 index 0000000000..40385ba783 --- /dev/null +++ b/131.html @@ -0,0 +1,795 @@ + + + + AIP-131: Standard methods: Get + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-131

+

Standard methods: Get

+

In REST APIs, it is customary to make a GET request to a resource's URI (for +example, /v1/publishers/{publisher}/books/{book}) in order to retrieve that +resource.

+

Resource-oriented design (AIP-121) honors this pattern through the Get +method. These RPCs accept the URI representing that resource and return the +resource.

+

Guidance

+

APIs must provide a get method for resources. The purpose of the get method +is to return data from a single resource.

+

Get methods are specified using the following pattern:

+
rpc GetBook(GetBookRequest) returns (Book) {
+  option (google.api.http) = {
+    get: "/v1/{name=publishers/*/books/*}"
+  };
+  option (google.api.method_signature) = "name";
+}
+
+
    +
  • The RPC's name must begin with the word Get. The remainder of the RPC + name should be the singular form of the resource's message name.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response message must be the resource itself. (There is no + GetBookResponse.)
      +
    • The response should usually include the fully-populated resource unless + there is a reason to return a partial response (see AIP-157).
    • +
    +
  • +
  • The HTTP verb must be GET.
  • +
  • The URI should contain a single variable field corresponding to the + resource name.
      +
    • This field should be called name.
    • +
    • The URI should have a variable corresponding to this field.
    • +
    • The name field should be the only variable in the URI path. All + remaining parameters should map to URI query parameters.
    • +
    +
  • +
  • There must not be a body key in the google.api.http annotation.
  • +
  • There should be exactly one google.api.method_signature annotation, + with a value of "name".
  • +
+

Request message

+

Get methods implement a common request message pattern:

+
message GetBookRequest {
+  // The name of the book to retrieve.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+}
+
+
    +
  • A resource name field must be included. It should be called name. +
  • +
  • The comment for the name field should document the resource pattern.
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in + another AIP.
  • +
+

Note: The name field in the request object corresponds to the name +variable in the google.api.http annotation on the RPC. This causes the name +field in the request to be populated based on the value in the URL when the +REST/JSON interface is used.

+

Errors

+

See errors, in particular when to use PERMISSION_DENIED and +NOT_FOUND errors.

+

Changelog

+
    +
  • 2023-03-17: Align with AIP-122 and make Get a must.
  • +
  • 2022-11-04: Aggregated error guidance to AIP-193.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-06-08: Added guidance on returning the full resource.
  • +
  • 2019-10-18: Added guidance on annotations.
  • +
  • 2019-08-12: Added guidance for error cases.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
  • 2019-05-29: Added an explicit prohibition on arbitrary fields in standard + methods.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/132.html b/132.html new file mode 100644 index 0000000000..9ad5f203fc --- /dev/null +++ b/132.html @@ -0,0 +1,914 @@ + + + + AIP-132: Standard methods: List + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-132

+

Standard methods: List

+

In many APIs, it is customary to make a GET request to a collection's URI +(for example, /v1/publishers/1/books) in order to retrieve a list of +resources, each of which lives within that collection.

+

Resource-oriented design (AIP-121) honors this pattern through the List +method. These RPCs accept the parent collection (and potentially some other +parameters), and return a list of responses matching that input.

+

Guidance

+

APIs must provide a List method for resources unless the resource is a +singleton. The purpose of the List method is to return data from a finite +collection (generally singular unless the operation supports reading across +collections).

+

List methods are specified using the following pattern:

+
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
+  option (google.api.http) = {
+    get: "/v1/{parent=publishers/*}/books"
+  };
+  option (google.api.method_signature) = "parent";
+}
+
+
    +
  • The RPC's name must begin with the word List. The remainder of the RPC + name should be the plural form of the resource being listed.
  • +
  • The request and response messages must match the RPC name, with + Request and Response suffixes.
  • +
  • The HTTP verb must be GET.
  • +
  • The collection whose resources are being listed should map to the URI + path.
      +
    • The collection's parent resource should be called parent, and + should be the only variable in the URI path. All remaining parameters + should map to URI query parameters.
    • +
    • The collection identifier (books in the above example) must be a + literal string.
    • +
    +
  • +
  • The body key in the google.api.http annotation must be omitted.
  • +
  • If the resource being listed is not a top-level resource, there should + be exactly one google.api.method_signature annotation, with a value of + "parent". If the resource being listed is a top-level resource, there + should be either no google.api.method_signature annotation, or exactly + one google.api.method_signature annotation, with a value of "".
  • +
+

Request message

+

List methods implement a common request message pattern:

+
message ListBooksRequest {
+  // The parent, which owns this collection of books.
+  // Format: publishers/{publisher}
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The maximum number of books to return. The service may return fewer than
+  // this value.
+  // If unspecified, at most 50 books will be returned.
+  // The maximum value is 1000; values above 1000 will be coerced to 1000.
+  int32 page_size = 2;
+
+  // A page token, received from a previous `ListBooks` call.
+  // Provide this to retrieve the subsequent page.
+  //
+  // When paginating, all other parameters provided to `ListBooks` must match
+  // the call that provided the page token.
+  string page_token = 3;
+}
+
+
    +
  • A parent field must be included unless the resource being listed is a + top-level resource. It should be called parent. +
  • +
  • The page_size and page_token fields, which support pagination, must + be specified on all list request messages. For more information, see + AIP-158.
      +
    • The comment above the page_size field should document the maximum + allowed value, as well as the default value if the field is omitted (or set + to 0). If preferred, the API may state that the server will use a + sensible default. This default may change over time.
    • +
    • If a user provides a value greater than the maximum allowed value, the API + should coerce the value to the maximum allowed.
    • +
    • If a user provides a negative or other invalid value, the API must send + an INVALID_ARGUMENT error.
    • +
    +
  • +
  • The page_token field must be included on all list request messages.
  • +
  • The request message may include fields for common design patterns + relevant to list methods, such as string filter and string order_by.
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
+

Note: List methods should return the same results for any user that has +permission to make a successful List request on the collection. Search methods +are more relaxed on this.

+

Response message

+

List methods implement a common response message pattern:

+
message ListBooksResponse {
+  // The books from the specified publisher.
+  repeated Book books = 1;
+
+  // A token, which can be sent as `page_token` to retrieve the next page.
+  // If this field is omitted, there are no subsequent pages.
+  string next_page_token = 2;
+}
+
+
    +
  • The response message must include one repeated field corresponding to the + resources being returned, and should not include any other repeated + fields unless described in another AIP (for example, AIP-217).
      +
    • The response should usually include fully-populated resources unless + there is a reason to return a partial response (see AIP-157).
    • +
    +
  • +
  • The next_page_token field, which supports pagination, must be included + on all list response messages. It must be set if there are subsequent + pages, and must not be set if the response represents the final page. For + more information, see AIP-158.
  • +
  • The message may include a int32 total_size (or int64 total_size) + field with the number of items in the collection.
      +
    • The value may be an estimate (the field should clearly document + this if so).
    • +
    • If filtering is used, the total_size field should reflect the size of + the collection after the filter is applied.
    • +
    +
  • +
+

Ordering

+

List methods may allow clients to specify sorting order; if they do, the +request message should contain a string order_by field.

+
    +
  • Values should be a comma separated list of fields. For example: + "foo,bar".
  • +
  • The default sorting order is ascending. To specify descending order for a + field, users append a " desc" suffix; for example: "foo desc, bar".
  • +
  • Redundant space characters in the syntax are insignificant. + "foo, bar desc", " foo , bar desc ", and "foo,bar desc" are all + equivalent.
  • +
  • Subfields are specified with a . character, such as foo.bar or + address.street.
  • +
  • The resulting list order should be based on the field type's natural + comparator e.g. numerics ordered numerically, strings ordered + lexicographically, etc. However, APIs may choose to use a different + ordering; if so, it must be documented in the order_by definition.
      +
    • Furthermore, well-known types, like Timestamp and Duration are + compared as their representative type; Timestamp is compared as time e.g. + before or after, Duration is compared as a quantity e.g. more or less.
    • +
    +
  • +
+ + +

Note: Only include ordering if there is an established need to do so. It is +always possible to add ordering later, but removing it is a breaking change.

+

Filtering

+

List methods may allow clients to specify filters; if they do, the request +message should contain a string filter field. Filtering is described in +more detail in AIP-160.

+

Note: Only include filtering if there is an established need to do so. It +is always possible to add filtering later, but removing it is a breaking +change.

+

Soft-deleted resources

+

Some APIs need to "soft delete" resources, marking them as deleted or +pending deletion (and optionally purging them later).

+

APIs that do this should not include deleted resources by default in list +requests. APIs with soft deletion of a resource should include a +bool show_deleted field in the list request that, if set, will cause +soft-deleted resources to be included.

+

Errors

+

See errors, in particular when to use PERMISSION_DENIED and +NOT_FOUND errors.

+

Further reading

+
    +
  • For details on pagination, see AIP-158.
  • +
  • For listing across multiple parent collections, see AIP-159.
  • +
+

Changelog

+
    +
  • 2025-02-25: Require documentation for ordering not matching field type + with clarification on ordering of well-known types.
  • +
  • 2023-03-22: Fix guidance wording to mention AIP-159.
  • +
  • 2023-03-17: Align with AIP-122 and make Get a must.
  • +
  • 2022-11-04: Aggregated error guidance to AIP-193.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-09-02: Add link to the filtering AIP.
  • +
  • 2020-08-14: Added error guidance for permission denied cases.
  • +
  • 2020-06-08: Added guidance on returning the full resource.
  • +
  • 2020-05-19: Removed requirement to document ordering behavior.
  • +
  • 2020-04-15: Added guidance on List permissions.
  • +
  • 2019-10-18: Added guidance on annotations.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
  • 2019-07-30: Added guidance about documenting the ordering behavior.
  • +
  • 2019-05-29: Added an explicit prohibition on arbitrary fields in standard + methods.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/133.html b/133.html new file mode 100644 index 0000000000..42183ca373 --- /dev/null +++ b/133.html @@ -0,0 +1,921 @@ + + + + AIP-133: Standard methods: Create + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-133

+

Standard methods: Create

+

In REST APIs, it is customary to make a POST request to a collection's URI +(for example, /v1/publishers/{publisher}/books) in order to create a new +resource within that collection.

+

Resource-oriented design (AIP-121) honors this pattern through the Create +method. These RPCs accept the parent collection and the resource to create (and +potentially some other parameters), and return the created resource.

+

Guidance

+

APIs should generally provide a create method for resources unless it is +not valuable for users to do so. The purpose of the create method is to create +a new resource in an already-existing collection.

+

Create methods are specified using the following pattern:

+
rpc CreateBook(CreateBookRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books"
+    body: "book"
+  };
+  option (google.api.method_signature) = "parent,book";
+}
+
+
    +
  • The RPC's name must begin with the word Create. The remainder of the + RPC name should be the singular form of the resource being created.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response message must be the resource itself. There is no + CreateBookResponse.
      +
    • The response should include the fully-populated resource, and must + include any fields that were provided unless they are input only (see + AIP-203) or there is a reason to return a partial response (see + AIP-157).
    • +
    • If the create RPC is long-running, the response + message must be a google.longrunning.Operation which resolves to the + resource itself.
    • +
    +
  • +
  • The HTTP verb must be POST.
  • +
  • The collection where the resource is being added should map to the URI + path.
      +
    • The collection's parent resource should be called parent, and + should be the only variable in the URI path.
    • +
    • The collection identifier (books in the above example) must be + a literal string.
    • +
    +
  • +
  • There must be a body key in the google.api.http annotation, and it + must map to the resource field in the request message.
      +
    • All remaining fields should map to URI query parameters.
    • +
    +
  • +
  • There should be exactly one google.api.method_signature annotation, + with a value of "parent,{resource},{resource}_id", or ""parent,{resource}" + if the resource ID is not required.
  • +
  • If the API is operating on the management plane, the operation should have + strong consistency: the completion of a create operation must mean + that all user-settable values and the existence of the resource have reached a + steady-state and reading resource state returns a consistent response.
  • +
+

Request message

+

Create methods implement a common request message pattern:

+
message CreateBookRequest {
+  // The parent resource where this book will be created.
+  // Format: publishers/{publisher}
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The ID to use for the book, which will become the final component of
+  // the book's resource name.
+  //
+  // This value should be 4-63 characters, and valid characters
+  // are /[a-z][0-9]-/.
+  string book_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // The book to create.
+  Book book = 3 [(google.api.field_behavior) = REQUIRED];
+}
+
+
    +
  • A parent field must be included unless the resource being created is a + top-level resource. It should be called parent. +
  • +
  • A {resource}_id field must be included for management plane resources, + and should be included for data plane resources.
  • +
  • The resource field must be included and must map to the POST body.
  • +
  • The request message must not contain any other required fields and + should not contain other optional fields except those described in this + or another AIP.
  • +
+

Long-running create

+

Some resources take longer to create a resource than is reasonable for a +regular API request. In this situation, the API should use a long-running +operation (AIP-151) instead:

+
rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books"
+    body: "book"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "Book"
+    metadata_type: "OperationMetadata"
+  };
+}
+
+
    +
  • The response type must be set to the resource (what the return type would + be if the RPC was not long-running).
  • +
  • Both the response_type and metadata_type fields must be specified.
  • +
+

Important: Declarative-friendly resources (AIP-128) should use +long-running operations. The service may return an LRO that is already set +to done if the request is effectively immediate.

+

User-specified IDs

+

An API must allow a user to specify the ID component of a resource (the last +segment of the resource name) on creation if the API is operating on the +management plane.

+

On the data plane, an API should allow a user to specify the ID. +Exceptional cases should have the following behavior:

+
    +
  • The data plane resource allows identical records without a need to + disambiguate between the two (e.g. rows in a table with no primary key).
  • +
  • The data plane resource will not be exposed in Declarative clients.
  • +
+

An API +may allow the {resource}_id field have the field_behavior OPTIONAL, +and generate a system-generated ID if one is not specified.

+

For example:

+
// Using user-specified IDs.
+publishers/lacroix/books/les-miserables
+
+// Using system-generated IDs.
+publishers/012345678-abcd-cdef/books/12341234-5678-abcd
+
+
    +
  • The {resource}_id field must exist on the request message, not the + resource itself.
      +
    • The field may be required or optional. If it is required, it should + include the corresponding annotation.
    • +
    +
  • +
  • The name field on the resource must be ignored.
  • +
  • There should be exactly one google.api.method_signature annotation on + the RPC, with a value of "parent,{resource},{resource}_id" if the resource + being created is not a top-level resource, or with a value of + "{resource},{resource}_id" if the resource being created is a top-level + resource.
  • +
  • The documentation should explain what the acceptable format is, and the + format should follow the guidance for resource name formatting in + AIP-122.
  • +
  • If a user tries to create a resource with an ID that would result in a + duplicate resource name, the service must error with ALREADY_EXISTS.
      +
    • However, if the user making the call does not have permission to see the + duplicate resource, the service must error with PERMISSION_DENIED + instead.
    • +
    +
  • +
+

Note: For REST APIs, the user-specified ID field, {resource}_id, +is provided as a query parameters on the request URI.

+

Errors

+

See errors, in particular when to use PERMISSION_DENIED and +NOT_FOUND errors.

+

Further reading

+
    +
  • For ensuring idempotency in Create methods, see AIP-155.
  • +
  • For naming resources involving Unicode, see AIP-210.
  • +
+

Rationale

+

Requiring user-specified ids

+

Declarative clients use the resource ID as a way to identify a resource for +applying updates and for conflict resolution. The lack of a user-specified ID +means a client is unable to find the resource unless they store the identifier +locally, and can result in re-creating the resource. This in turn has a +downstream effect on all resources that reference it, forcing them to update to +the ID of the newly-created resource.

+

Having a user-specified ID also means the client can precalculate the resource +name and use it in references from other resources.

+

Changelog

+
    +
  • 2025-10-03: Allow use of partial responses via AIP-157.
  • +
  • 2023-10-20: Clarify that {resource}_id is only required for management plane resources.
  • +
  • 2023-08-24: Adding consistency requirement.
  • +
  • 2023-05-11: Changing guidance around resource_id to a must.
  • +
  • 2022-11-04: Referencing aggregated error guidance in AIP-193, similar to + other CRUDL AIPs.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-10-06: Added declarative-friendly guidance.
  • +
  • 2020-08-14: Updated error guidance to use permission denied over + forbidden.
  • +
  • 2020-06-08: Added guidance on returning the full resource.
  • +
  • 2019-11-22: Added clarification on what error to use if a duplicate name + is sent.
  • +
  • 2019-10-18: Added guidance on annotations.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
  • 2019-06-10: Added guidance for long-running create.
  • +
  • 2019-05-29: Added an explicit prohibition on arbitrary fields in standard + methods.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/134.html b/134.html new file mode 100644 index 0000000000..01ac030aec --- /dev/null +++ b/134.html @@ -0,0 +1,994 @@ + + + + AIP-134: Standard methods: Update + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-134

+

Standard methods: Update

+

In REST APIs, it is customary to make a PATCH or PUT request to a +resource's URI (for example, /v1/publishers/{publisher}/books/{book}) in +order to update that resource.

+

Resource-oriented design (AIP-121) honors this pattern through the Update +method (which mirrors the REST PATCH behavior). These RPCs accept the URI +representing that resource and return the resource.

+

Guidance

+

APIs should generally provide an update method for resources unless it is +not valuable for users to do so. The purpose of the update method is to make +changes to the resources without causing side effects.

+

Update methods are specified using the following pattern:

+
rpc UpdateBook(UpdateBookRequest) returns (Book) {
+  option (google.api.http) = {
+    patch: "/v1/{book.name=publishers/*/books/*}"
+    body: "book"
+  };
+  option (google.api.method_signature) = "book,update_mask";
+}
+
+
    +
  • The RPC's name must begin with the word Update. The remainder of the + RPC name should be the singular form of the resource's message name.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response message must be the resource itself. (There is no + UpdateBookResponse.)
      +
    • The response should include the fully-populated resource, and must + include any fields that were sent and included in the update mask unless + they are input only (see AIP-203) or there is a reason to return a partial + response (see AIP-157).
    • +
    • If the update RPC is long-running, the response + message must be a google.longrunning.Operation which resolves to the + resource itself.
    • +
    +
  • +
  • The method should support partial resource update, and the HTTP verb + should be PATCH.
      +
    • If the method will only ever support full resource replacement, then the + HTTP verb may be PUT. However, this is strongly discouraged because + it becomes a backwards-incompatible change to add fields to the resource.
    • +
    +
  • +
  • The resource's name field should map to the URI path.
      +
    • The {resource}.name field should be the only variable in the URI + path.
    • +
    +
  • +
  • There must be a body key in the google.api.http annotation, and it + must map to the resource field in the request message.
      +
    • All remaining fields should map to URI query parameters.
    • +
    +
  • +
  • There should be exactly one google.api.method_signature annotation, with + a value of "{resource},update_mask".
  • +
  • If the API is operating on the management plane, the operation should have + strong consistency: the completion of an update operation must mean + that all user-settable values and the existence of the resource have reached a + steady-state and reading resource state returns a consistent response.
  • +
+

Note: Unlike the other four standard methods, the URI path here references +a nested field (book.name) in the example. If the resource field has a word +separator, snake_case is used.

+

Request message

+

Update methods implement a common request message pattern:

+
message UpdateBookRequest {
+  // The book to update.
+  //
+  // The book's `name` field is used to identify the book to update.
+  // Format: publishers/{publisher}/books/{book}
+  Book book = 1 [(google.api.field_behavior) = REQUIRED];
+
+  // The list of fields to update.
+  google.protobuf.FieldMask update_mask = 2;
+}
+
+
    +
  • The request message must contain a field for the resource.
      +
    • The field must map to the PATCH body.
    • +
    • The field should be annotated as required.
    • +
    • A name field must be included in the resource message. It should + be called name.
    • +
    • The field must identify the resource type of the resource + being updated.
    • +
    +
  • +
  • If partial resource update is supported, a field mask must be included. + It must be of type google.protobuf.FieldMask, and it must be + called update_mask.
      +
    • The fields used in the field mask correspond to the resource being updated + (not the request message).
    • +
    • The field must be optional, and the service must treat an omitted + field mask as an implied field mask equivalent to all fields that are + populated (have a non-empty value).
    • +
    • Update masks must support a special value *, meaning full replacement + (the equivalent of PUT).
        +
      • API producers need to be conscious of how adding new, mutable fields to a + resource will be handled when consumers use * without knowledge of said + new, mutable fields. Likewise consumers need to use * only when the + risks of doing so are acceptable. In general, it is safest to explicitly + specify the fields to update rather than use *.
      • +
      +
    • +
    +
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
+

Side effects

+

In general, update methods are intended to update the data within the resource. +Update methods should not trigger other side effects. Instead, side effects +should be triggered by custom methods.

+

In particular, this entails that state fields must not be directly +writable in update methods.

+

PATCH and PUT

+

TL;DR: Google APIs generally use the PATCH HTTP verb only, and do not +support PUT requests.

+

We standardize on PATCH because Google updates stable APIs in place with +backwards-compatible improvements. It is often necessary to add a new field to +an existing resource, but this becomes a breaking change when using PUT.

+

To illustrate this, consider a PUT request to a Book resource:

+
  PUT /v1/publishers/123/books/456
+
+  {"title": "Mary Poppins", "author": "P.L. Travers"}
+
+

Next consider that the resource is later augmented with a new field (here we +add rating):

+
message Book {
+  string title = 1;
+  string author = 2;
+
+  // Subsequently added to v1 in place...
+  int32 rating = 3;
+}
+
+

If a rating is set on a book and the existing PUT request was executed, it +would wipe out the book's rating. In essence, a PUT request unintentionally +wiped out data because the previous version did not know about it.

+

Long-running update

+

Some resources take longer to update a resource than is reasonable for a +regular API request. In this situation, the API should use a long-running +operation (AIP-151) instead:

+
rpc UpdateBook(UpdateBookRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    patch: "/v1/{book.name=publishers/*/books/*}"
+    body: "book"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "Book"
+    metadata_type: "OperationMetadata"
+  };
+}
+
+
    +
  • The response type must be set to the resource (what the return type would + be if the RPC was not long-running).
  • +
  • Both the response_type and metadata_type fields must be specified.
  • +
+

Note: Declarative-friendly resources (AIP-128) should use long-running +update.

+

Create or update

+

If the service uses client-assigned resource names, Update methods may +expose a bool allow_missing field, which will cause the method to succeed in +the event that the user attempts to update a resource that is not present (and +will create the resource in the process):

+
message UpdateBookRequest {
+  // The book to update.
+  //
+  // The book's `name` field is used to identify the book to be updated.
+  // Format: publishers/{publisher}/books/{book}
+  Book book = 1 [(google.api.field_behavior) = REQUIRED];
+
+  // The list of fields to be updated.
+  google.protobuf.FieldMask update_mask = 2;
+
+  // If set to true, and the book is not found, a new book will be created.
+  // In this situation, `update_mask` is ignored.
+  bool allow_missing = 3;
+}
+
+

More specifically, the allow_missing flag triggers the following behavior:

+
    +
  • If the method call is on a resource that does not exist, the resource is + created. All fields are applied regardless of any provided field mask.
      +
    • However, if any required fields are missing or fields have invalid values, + an INVALID_ARGUMENT error is returned.
    • +
    +
  • +
  • If the method call is on a resource that already exists, and all fields + match, the existing resource is returned unchanged.
  • +
  • If the method call is on a resource that already exists, only fields declared + in the field mask are updated.
  • +
+

The user must have the update permissions to call Update even with +allow_missing set to true. For customers that want to prevent users from +creating resources using the update method, IAM conditions should be used.

+

Etags

+

An API may sometimes need to allow users to send update requests which are +guaranteed to be made against the most current data (a common use case for this +is to detect and avoid race conditions). Resources which need to enable this do +so by including a string etag field, which contains an opaque, +server-computed value representing the content of the resource.

+

In this situation, the resource should contain a string etag field:

+
message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  // The resource name of the book.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The title of the book.
+  // Example: "Mary Poppins"
+  string title = 2;
+
+  // The author of the book.
+  // Example: "P.L. Travers"
+  string author = 3;
+
+  // The etag for this book.
+  // If this is provided on update, it must match the server's etag.
+  string etag = 4;
+}
+
+

The etag field may be either required or optional. If it is set, +then the request must succeed if and only if the provided etag matches the +server-computed value, and must fail with an ABORTED error otherwise. The +update_mask field in the request does not affect the behavior of the etag +field, as it is not a field being updated.

+

Expensive fields

+

APIs sometimes encounter situations where some fields on a resource are +expensive or impossible to reliably return.

+

This can happen in a few situations:

+
    +
  • A resource may have some fields that are very expensive to compute, and that + are generally not useful to the customer on update requests.
  • +
  • A single resource sometimes represents an amalgamation of data from multiple + underlying (and eventually consistent) data sources. In these situations, it + is impossible to return authoritative information on the fields that were not + changed.
  • +
+

In this situation, an API may return back only the fields that were +updated, and omit the rest, and should document this behavior if they do +so.

+

Errors

+

See errors, in particular when to use PERMISSION_DENIED and +NOT_FOUND errors.

+

In addition, if the user does have proper permission, but the requested resource +does not exist, the service must error with NOT_FOUND (HTTP 404) unless +allow_missing is set to true.

+

Changelog

+
    +
  • 2025-10-03: Allow use of partial responses via AIP-157.
  • +
  • 2024-12-03: Add caveats to usage of full replacement update_mask.
  • +
  • 2024-03-14: Make update_mask optional field_behaviour guidance a must.
  • +
  • 2023-08-26: Adding consistency requirement.
  • +
  • 2023-07-17: Make update_mask name guidance a must.
  • +
  • 2022-11-04: Aggregated error guidance to AIP-193.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2021-11-04: Changed the permission check if allow_missing is set.
  • +
  • 2021-07-08: Added error guidance for resource not found case.
  • +
  • 2021-03-05: Changed the etag error from FAILED_PRECONDITION (which + becomes HTTP 400) to ABORTED (409).
  • +
  • 2020-10-06: Added guidance for declarative-friendly resources.
  • +
  • 2020-10-06: Added guidance for allow_missing.
  • +
  • 2020-08-14: Added error guidance for permission denied cases.
  • +
  • 2020-06-08: Added guidance on returning the full resource.
  • +
  • 2019-10-18: Added guidance on annotations.
  • +
  • 2019-09-10: Added a link to the long-running operations AIP + (AIP-151).
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
  • 2019-06-10: Added guidance for long-running update.
  • +
  • 2019-05-29: Added an explicit prohibition on arbitrary fields in standard + methods.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/135.html b/135.html new file mode 100644 index 0000000000..57c7529625 --- /dev/null +++ b/135.html @@ -0,0 +1,931 @@ + + + + AIP-135: Standard methods: Delete + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-135

+

Standard methods: Delete

+

In REST APIs, it is customary to make a DELETE request to a resource's URI +(for example, /v1/publishers/{publisher}/books/{book}) in order to delete +that resource.

+

Resource-oriented design (AIP-121) honors this pattern through the Delete +method. These RPCs accept the URI representing that resource and usually return +an empty response.

+

Guidance

+

APIs should generally provide a delete method for resources unless it is +not valuable for users to do so.

+

Delete methods are specified using the following pattern:

+
rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {
+  option (google.api.http) = {
+    delete: "/v1/{name=publishers/*/books/*}"
+  };
+  option (google.api.method_signature) = "name";
+}
+
+
    +
  • The RPC's name must begin with the word Delete. The remainder of the + RPC name should be the singular form of the resource's message name.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response message should be google.protobuf.Empty.
      +
    • If the resource is soft deleted, the response message + should be the resource itself.
    • +
    • If the delete RPC is long-running, the response + message must be a google.longrunning.Operation which resolves to the + correct response.
    • +
    +
  • +
  • The HTTP verb must be DELETE.
  • +
  • The request message field receiving the resource name should map to the + URI path.
      +
    • This field should be called name.
    • +
    • The name field should be the only variable in the URI path. All + remaining parameters should map to URI query parameters.
    • +
    +
  • +
  • There must not be a body key in the google.api.http annotation.
  • +
  • There should be exactly one google.api.method_signature annotation, + with a value of "name". If an etag or force field are used, they may be + included in the signature.
  • +
  • If the API is operating on the Management Plane, the operation should have + strong consistency: the completion of a delete operation must mean + that the existence of the resource has reached a steady-state and reading + resource state returns a consistent response.
  • +
  • The API must fail with a FAILED_PRECONDITION error if child resources + are present. See guidance on Cascading Delete if forcing + deletion of parent and child resources is necessary.
      +
    • If the only child resource type is a Singleton, deletion must + be allowed, because the lifecycle of a Singleton is tied to that of its + parent resource. This applies even if there are multiple different Singleton + resource types for the same parent resource.
    • +
    +
  • +
+

The Delete method should succeed if and only if a resource was present and +was successfully deleted. If the resource did not exist, the method should +send a NOT_FOUND error.

+

Request message

+

Delete methods implement a common request message pattern:

+
message DeleteBookRequest {
+  // The name of the book to delete.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+}
+
+
    +
  • A name field must be included. It should be called name. +
  • +
  • The comment for the field should document the resource pattern.
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
+

Soft delete

+

Note: This material was moved into its own document to provide a more +comprehensive treatment: AIP-164.

+

Long-running delete

+

Some resources take longer to delete a resource than is reasonable for a +regular API request. In this situation, the API should use a long-running +operation instead:

+
rpc DeleteBook(DeleteBookRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    delete: "/v1/{name=publishers/*/books/*}"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "google.protobuf.Empty"
+    metadata_type: "OperationMetadata"
+  };
+}
+
+
    +
  • The response type must be set to the appropriate return type if the RPC + was not long-running: google.protobuf.Empty for most Delete RPCs, or the + resource itself for soft delete (AIP-164).
  • +
  • Both the response_type and metadata_type fields must be specified + (even if they are google.protobuf.Empty).
  • +
+

Cascading delete

+

Sometimes, it may be necessary for users to be able to delete a resource as +well as all applicable child resources. However, since deletion is usually +permanent, it is also important that users not do so accidentally, as +reconstructing wiped-out child resources may be quite difficult.

+

If an API allows deletion of a resource that may have child resources, the API +should provide a bool force field on the request, which the user sets to +explicitly opt in to a cascading delete.

+
message DeletePublisherRequest {
+  // The name of the publisher to delete.
+  // Format: publishers/{publisher}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Publisher"
+    }];
+
+  // If set to true, any books from this publisher will also be deleted.
+  // (Otherwise, the request will only work if the publisher has no books.)
+  bool force = 2;
+}
+
+

The API must fail with a FAILED_PRECONDITION error if the force field +is false (or unset) and child resources are present.

+

Protected delete

+

Sometimes, it may be necessary for users to ensure that no changes have been +made to a resource that is being deleted. If a resource provides an etag, +the delete request may accept the etag (as either required or optional):

+
message DeleteBookRequest {
+  // The name of the book to delete.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+
+  // Optional. The etag of the book.
+  // If this is provided, it must match the server's etag.
+  string etag = 2;
+}
+
+

If the etag is provided and does not match the server-computed etag, the +request must fail with a ABORTED error code.

+

Note: Declarative-friendly resources (AIP-128) must provide the etag +field for Delete requests.

+

Delete if existing

+

If the service uses client-assigned resource names, Delete methods may +expose a bool allow_missing field, which will cause the method to succeed in +the event that the user attempts to delete a resource that is not present (in +which case the request is a no-op):

+
message DeleteBookRequest {
+  // The book to delete.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference).type = "library.googleapis.com/Book"
+  ];
+
+  // If set to true, and the book is not found, the request will succeed
+  // but no action will be taken on the server
+  bool allow_missing = 2;
+}
+
+

More specifically, the allow_missing flag triggers the following behavior:

+
    +
  • If the method call is on a resource that does not exist, the request is a + no-op.
      +
    • The etag field is ignored.
    • +
    +
  • +
  • If the method call is on a resource that already exists, the resource is + deleted (subject to other checks).
  • +
+

Note: Declarative-friendly resources (AIP-128) should expose the +bool allow_missing field.

+

Errors

+

If the user does not have permission to access the resource, regardless of +whether or not it exists, the service must error with PERMISSION_DENIED +(HTTP 403). Permission must be checked prior to checking if the resource +exists.

+

If the user does have proper permission, but the requested resource does not +exist, the service must error with NOT_FOUND (HTTP 404) unless +allow_missing is set to true.

+

Further reading

+
    +
  • For soft delete and undelete, see AIP-164.
  • +
  • For bulk deleting large numbers of resources based on a filter, see AIP-165.
  • +
+

Changelog

+
    +
  • 2024-06-11: Add deletion behavior for parent resource deletion requests without a force field.
  • +
  • 2023-08-24: Adding consistency requirement.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2022-02-02: Changed eTag error from FAILED_PRECONDITION to ABORTED making it consistent with change to AIP-154 & AIP-134 on 2021-03-05.
  • +
  • 2020-10-06: Added guidance for declarative-friendly resources.
  • +
  • 2020-10-06: Added guidance for allowing no-op delete for missing + resources.
  • +
  • 2020-10-06: Moved soft delete and undelete guidance into a new AIP-164.
  • +
  • 2020-06-08: Added guidance for Get of soft-deleted resources.
  • +
  • 2020-02-03: Added guidance for error cases.
  • +
  • 2019-10-18: Added guidance on annotations.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
  • 2019-06-10: Added guidance for long-running delete.
  • +
  • 2019-05-29: Added an explicit prohibition on arbitrary fields in standard + methods.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/136.html b/136.html new file mode 100644 index 0000000000..475c6cc1e5 --- /dev/null +++ b/136.html @@ -0,0 +1,885 @@ + + + + AIP-136: Custom methods + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-136

+

Custom methods

+

Resource-oriented design (AIP-121) uses custom methods to provide a means to +express arbitrary actions that are difficult to model using only the standard +methods. Custom methods are important because they provide a means for an API's +vocabulary to adhere to user intent.

+

Guidance

+

Custom methods should only be used for functionality that can not be easily +expressed via standard methods; prefer standard methods if possible, due to +their consistent semantics. (Of course, this only applies if the functionality +in question actually conforms to the normal semantics; it is not a good idea +to contort things to endeavor to make the standard methods "sort of work".)

+

While custom methods vary widely in how they are designed, many principles +apply consistently:

+
// Archives the given book.
+rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*}:archive"
+    body: "*"
+  };
+}
+
+

Note: The pattern above shows a custom method that operates on a specific +resource. Custom methods can be associated with resources, collections, or +services. The bullets below apply in all three cases.

+
    +
  • The name of the method should be a verb followed by a noun.
      +
    • The name must not contain prepositions ("for", "with", etc.).
    • +
    • The verb in the name should not contain any of the standard method verbs (Get, + List, Create, Update, Delete).
    • +
    • The name must not include the term Async. Instead, if the intention is + to differentiate between immediate and long-running RPCs, the suffix LongRunning + may be used for this purpose. For example, to create a long-running book creation + RPC (if the standard CreateBook method was designed before long-running aspects were + considered), a custom CreateBookLongRunning method could be introduced.
    • +
    +
  • +
  • The HTTP method must be GET or POST:
      +
    • GET must be used for methods retrieving data or resource state.
    • +
    • POST must be used if the method has side effects or mutates resources + or data.
    • +
    +
  • +
  • The HTTP URI must use a : character followed by the custom verb + (:archive in the above example), and the verb in the URI must match the + verb in the name of the RPC.
      +
    • If word separation is required, camelCase must be used.
    • +
    +
  • +
  • The body clause in the google.api.http annotation should be "*". +
  • +
  • Custom methods should take a request message matching the RPC + name, with a Request suffix.
  • +
  • Custom methods should return a response message matching the RPC + name, with a Response suffix.
      +
    • When operating on a specific resource, a custom method may return the + resource itself.
    • +
    +
  • +
+

Resource-based custom methods

+

Custom methods must operate on a resource if the API can be modeled +as such:

+
// Archives the given book.
+rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*}:archive"
+    body: "*"
+  };
+}
+
+
    +
  • The parameter for the resource's name must be called name, and + be the only variable in the URI path.
  • +
+

Collection-based custom methods

+

While most custom methods operate on a single resource, some custom methods +may operate on a collection instead:

+
// Sorts the books from this publisher.
+rpc SortBooks(SortBooksRequest) returns (SortBooksResponse) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:sort"
+    body: "*"
+  };
+}
+
+
    +
  • If the collection's resource has a parent, that resource must be called + parent and be the only variable in the URI path.
  • +
  • The collection key (books in the above example) must be literal.
  • +
+

Stateless methods

+

Some custom methods are not attached to resources at all. These methods are +generally stateless: they accept a request and return a response, and have no +permanent effect on data within the API.

+
// Translates the provided text from one language to another.
+rpc TranslateText(TranslateTextRequest) returns (TranslateTextResponse) {
+  option (google.api.http) = {
+    post: "/v1/{project=projects/*}:translateText"
+    body: "*"
+  };
+}
+
+
    +
  • If the method runs in a particular scope (such as a project, as in the above + example), the field name in the request message should be the name of the + scope resource. If word separators are necessary, snake_case must be + used.
  • +
  • The URI should place both the verb and noun after the : separator + (avoid a "faux collection key" in the URI in this case, as there is no + collection). For example, :translateText is preferable to text:translate.
  • +
  • Stateless methods must use POST if they involve billing.
  • +
+

Declarative-friendly resources

+

Declarative-friendly resources usually should not employ custom methods +(except specific declarative-friendly custom methods discussed in other AIPs), +because declarative-friendly tools are unable to automatically determine what +to do with them.

+

An exception to this is for rarely-used, fundamentally imperative operations, +such as a Move or Rename operation, for which there would not be an +expectation of declarative support.

+

Rationale

+

HTTP path

+

Similar to standard methods, a custom method that operates on a resource or +collection needs a name or parent parameter to indicate the resource that it +operates on. This convention allows clients to map custom methods to the +appropriate resource.

+

HTTP methods

+

Allowing both GET and POST HTTP verbs allows a clear distinction for +which methods do not mutate data, and which ones do. Methods that only +read data have first-class concepts in some clients (DataSources in +Terraform) and clearly indicate to a user which methods can be called +without risk of runtime impact.

+

Disallowing prepositions

+

Generally, method names with prepositions indicate that a new method is being +used where a field should instead be added to an existing method, or the method +should use a distinct verb. For example, if a CreateBook message already +exists and you are considering adding CreateBookFromDictation, consider a +TranscribeBook method instead. Similarly, if there is desire for a +property-specific look-up method, instead of GetBookByAuthor consider a +SearchBooks with an author field as a search dimension. This helps prevent +an explosion of hyper-focused methods that bloat API and client surfaces, and +add complexity to both managing and consuming the API.

+

RPC name

+

The term "async" is commonly used in programming languages to indicate whether +a specific method call is synchronous or asynchronous, including for making RPCs. +That sync/async aspect is at a different abstraction level to whether the RPC +itself is intended to start a long-running operation. Using "async" within the +RPC name itself causes confusion, and can even cause issues for client libraries +which generate both synchronous and asynchronous methods to call the RPC in some +languages.

+

Changelog

+
    +
  • 2025-05-12: Extend disallowing prepositions rationale.
  • +
  • 2025-01-09: Add original rationale for disallowing prepositions in names.
  • +
  • 2023-11-16: Included link to AIP-127 "HTTP and gRPC Transcoding" for guidance on body definition.
  • +
  • 2023-05-16: Added prohibition of the term "async" within RPC names.
  • +
  • 2023-05-09: Adding guidance for POST and GET, require parent instead of + the resource singular.
  • +
  • 2023-03-02: Explicitly discourage use of standard method verbs.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-10-06: Added declarative-friendly guidance.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/140.html b/140.html new file mode 100644 index 0000000000..3a8abc33f0 --- /dev/null +++ b/140.html @@ -0,0 +1,898 @@ + + + + AIP-140: Field names + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-140

+

Field names

+

Naming fields in a way that is intuitive to users can often be one of the most +challenging aspects of designing an API. This is true for many reasons; often a +field name that seems entirely intuitive to the author can baffle a reader.

+

Additionally, users rarely use only one API; they use many APIs together. As a +result, a single company using the same name to mean different things (or +different names to mean the same thing) can often cause unnecessary confusion, +because users can no longer take what they've already learned from one API and +apply that to another.

+

In short, APIs are easiest to understand when field names are simple, +intuitive, and consistent with one another.

+

Guidance

+

Field names should be in correct American English.

+

Field names should clearly and precisely communicate the concept being +presented and avoid overly general names that are ambiguous. That said, field +names should avoid including unnecessary words. In particular, avoid +including adjectives that always apply and add little cognitive value. For +example, a proxy_settings field might be as helpful as +shared_proxy_settings if there is no unshared variant.

+

Important: Field names often appear in generated client surfaces. Ensure they +are appropriately descriptive and of suitable length.

+

Case

+

Field definitions in protobuf files must use lower_snake_case names. +These names are mapped to an appropriate naming convention in JSON and in +generated code.

+

Additionally, each word in the field must not begin with a number, because +it creates ambiguity when converting between snake case and camel case. +Similarly, fields must not contain leading, trailing, or adjacent +underscores.

+

Uniformity

+

APIs should endeavor to use the same name for the same concept and +different names for different concepts wherever possible. This includes names +across multiple APIs, in particular if those APIs are likely to be used +together.

+

Repeated fields

+

Repeated fields must use the proper plural form, such as books or +authors. On the other hand, non-repeated fields should use the singular +form such as book or author. This implies that resource names should +use the singular form as well, since the field name should follow the resource +name (e.g., use repeated Book books, not Books books = 1).

+

Prepositions

+

Field names should not include prepositions (such as "with", "for", "at", +"by", etc). For example:

+
    +
  • error_reason (not reason_for_error)
  • +
  • author (not written_by)
  • +
+

It is easier for field names to match more often when following this +convention. Additionally, prepositions in field names may also indicate a +design concern, such as an overly-restrictive field or a sub-optimal data type. +This is particularly true regarding "with": a field named book_with_publisher +likely indicates that the book resource may be improperly structured and worth +redesigning.

+

Note: The word "per" is an exception to this rule. See AIP-141 for +guidance in the case where "per" is used as part of a unit (e.g. "miles per hour").

+

Abbreviations

+

For well known name abbreviations among software developers, such as "config" +and "spec", the abbreviations should be used in API definitions instead of +the full spelling. This will make the source code easy to read and write. +Examples:

+
    +
  • config (not configuration)
  • +
  • id (not identifier)
  • +
  • info (not information)
  • +
  • spec (not specification)
  • +
  • stats (not statistics)
  • +
+

Furthermore, well known abbreviations for units should be used in field names. +See AIP-141 for more guidance on fields that represent quantities. Examples:

+
    +
  • distance_km (not distance_kilometers)
  • +
  • width_px (not width_pixels)
  • +
+

Adjectives

+

For uniformity, field names that contain both a noun and an adjective +should place the adjective before the noun. For example:

+
    +
  • collected_items (not items_collected)
  • +
  • imported_objects (not objects_imported)
  • +
+

Verbs

+

Field names must not be named to reflect an intent or action. They +must not be verbs. Rather, because the field defines the desired +value for mutations, e.g. Create and Update, and the current value +for reads, e.g. Get and List, the name must be a noun. It defines +what is so, not what to do.

+
    +
  • collected_items (not collect_items)
  • +
  • disabled (not disable)
  • +
+

In contrast, method names, whether standard or custom, change facets of +resources and are named as verbs.

+

Booleans

+

Boolean fields should omit the prefix "is". For example:

+
    +
  • disabled (not is_disabled)
  • +
  • required (not is_required)
  • +
+

Note: Field names that would otherwise be reserved words +are an exception to this rule. For example, is_new (not new).

+

String vs. bytes

+

When using bytes, the contents of the field are base64-encoded when using +JSON on the wire. Services should use bytes when there is a need to send +binary contents over the wire, and should not ask the user to manually +base64-encode a field into a string field. The one exception is when the +API is designed to handle data that is meant to be base64-encoded at rest and +the double base64-encoding as a result of using bytes is undesirable - in +this case, services may use a string.

+

URIs

+

Field names representing arbitrary URIs should use uri. In particular, +note that URLs are URIs but not all URIs are URLs.

+

Field names may use a prefix in front of uri as appropriate.

+

Field names that can only represent a URL should use url.

+
message Book {
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // A URL pointing to an image of the book.
+  string image_url = 2;
+
+  // A URI identifying the book.
+  // This could be an ISBN or a URL.
+  string uri = 3;
+}
+
+

Note: APIs that have previously used uri for URL fields may continue to +do so to avoid unnecessary API changes and to preserve local consistency.

+

Reserved words

+

Field names should avoid using names that are likely to conflict with +keywords in common programming languages, such as new, class, function, +import, etc. Reserved keywords can cause hardship for developers using the +API in that language.

+

Conflicts

+

Messages should not include a field with the same name as the enclosing +message (ignoring case transformations). This causes conflicts when generating +code in some languages.

+

Display names

+

Many resources have a human-readable name, often used for display in UI. This +field should be called display_name, and should not have a uniqueness +requirement.

+

If an entity has an official, formal name (such as a company name or the title +of a book), an API may use title as the field name instead. The title +field should not have a uniqueness requirement.

+

Further reading

+
    +
  • For naming resource fields, see AIP-122.
  • +
  • For naming fields representing quantities, see AIP-141.
  • +
  • For naming fields representing time, see AIP-142.
  • +
+

Rationale

+

URI vs URL

+

The guidance itself mentions that all URLs are URIs, but not all URIs are URLs. +The goal of aligning on URI is to enable a more generalizable field, that can +handle a variety of use cases, as well as drive standardization across APIs, +creating a more coherent surface. At the same time, the requirement being a +should allows for more specific terms when it truly merits it.

+

Changelog

+
    +
  • 2025-10-23: Call out AIP-141 unit abbreviations as preferred.
  • +
  • 2025-03-10: Add rationale for URI guidance.
  • +
  • 2024-12-20: Copy over abbreviations guidance from old design site.
  • +
  • 2024-08-26: Codify exception to string and base64 guidance
  • +
  • 2024-05-18: Documented the effect of field names on client surfaces.
  • +
  • 2023-04-25: Field names must not be expressed as verbs.
  • +
  • 2021-07-12: Normalized display name guidance to "should".
  • +
  • 2021-04-07: Added base64 and bytes guidance.
  • +
  • 2021-03-05: Added prohibition on leading, trailing, or adjacent + underscores.
  • +
  • 2020-06-10: Added prohibition on starting any word with a number.
  • +
  • 2020-05-29: Added guidance around URIs.
  • +
  • 2020-03-24: Added guidance around conflicting field and message names.
  • +
  • 2020-01-30: Added guidance around display_name and title.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/141.html b/141.html new file mode 100644 index 0000000000..0ac4613036 --- /dev/null +++ b/141.html @@ -0,0 +1,790 @@ + + + + AIP-141: Quantities + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-141

+

Quantities

+

Many services need to represent a discrete quantity of items (number of bytes, +number of miles, number of nodes, etc.).

+

Guidance

+

Quantities with a clear unit of measurement (such as bytes, miles, and so on) +must include the unit of measurement as the suffix. When appropriate, units +should use generally accepted abbreviations, and abbreviations should not +be pluralized (for example, distance_km rather than distance_kilometers).

+
// A representation of a non-stop air route.
+message Route {
+  // The airport where the route begins.
+  string origin = 1;
+
+  // The destination airport.
+  string destination = 2;
+
+  // The distance between the origin and destination airports.
+  // This value is also used to determine the credited frequent flyer miles.
+  int32 distance_miles = 3;
+}
+
+

If the quantity is a number of items (for example, the number of nodes in a +cluster), then the field should use the suffix _count (not the prefix +num_):

+
// A cluster of individual nodes.
+message Cluster {
+  // The number of nodes in the cluster.
+  int32 node_count = 1;
+}
+
+

Note: Fields must not use unsigned integer types, because many +programming languages and systems do not support them well.

+

Compound units

+

Quantities with compound units of measurement may use separating underscores +between units as needed for clarity. Unabbreviated units must be separated. +Abbreviated units should not be separated unless otherwise ambiguous. +Compound units should be in plural form, with all component units in +singular form except for the final component unit, which should be in plural +form unless abbreviated.

+
    +
  • energy_kwh (not energy_kw_h)
  • +
  • energy_kw_fortnights (not energy_kwfortnight or energy_kw_fortnight)
  • +
+

Note: Metric prefixes must not be separated from their base unit.

+

Inverse units

+

Quantities with units of measurement that are or include inverse units +should indicate all inverse units as a compound unit after a compound +of any non-inverse units, separated by the word "per". +The inverse compound unit should be in singular form.

+
    +
  • speed_miles_per_hour (not speed_mph)
  • +
  • speed_meters_per_second (not speed_meters_per_seconds or speed_meter_per_second)
  • +
  • event_count_per_hour (not events_per_hour, event_counts_per_hour, or hourly_events)
  • +
  • price_per_kwh (using google.type.Money)
  • +
+

Note: This guidance does not apply in cases where generally accepted derived +units with special names and symbols exist for inverse quantities. For example, +the derived unit 'hertz' should be used when appropriate for reciprocal time.

+

Specialized messages

+

It is sometimes useful to create a message that represents a particular +quantity. This is particularly valuable in two situations:

+ +

APIs may create messages to represent quantities when appropriate. When +using these messages as fields, APIs should use the name of the message as +the suffix for the field name if it makes intuitive sense to do so.

+

Changelog

+
    +
  • 2025-07-09: Added guidance for compound units.
  • +
  • 2025-07-09: Clarified guidance to not pluralize abbreviated units.
  • +
  • 2025-07-09: Clarified guidance to use per_ prefix to represent inverse units.
  • +
  • 2019-09-13: Added the prohibition on uint and fixed types.
  • +
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/142.html b/142.html new file mode 100644 index 0000000000..43cbc87fb0 --- /dev/null +++ b/142.html @@ -0,0 +1,813 @@ + + + + AIP-142: Time and duration + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-142

+

Time and duration

+

Many services need to represent the concepts surrounding time. Representing +time can be challenging due to the intricacies of calendars and time zones, as +well as the fact that common exchange formats (such as JSON) lack a native +concept of time.

+

Guidance

+

Fields representing time should use the common, generally used components +(such as google.protobuf.Timestamp or +google.type.Date) for representing time or duration types. These +types are common components, and using them consistently allows +infrastructure and tooling to provide a better experience when interacting with +time values.

+

Timestamps

+

Fields that represent an absolute point in time (independent of any time zone +or calendar) should use the google.protobuf.Timestamp type, +(which uses UNIX timestamps under the hood and hold nanosecond precision).

+

These fields should have names ending in _time, such as create_time or +update_time. For repeated fields, the names should end in _times +instead.

+

Many timestamp fields refer to an activity (for example, create_time refers +to when the applicable resource was created). For these, the field should +be named with the {imperative}_time form. For example, if a book is being +published, the field storing the time when this happens would use the +imperative form of the verb "to publish" ("publish") resulting in a field +called publish_time. Fields should not be named using the past tense +(such as published_time, created_time or last_updated_time).

+

Durations

+

Fields that represent a span between two points in time (independent of any +time zone or calendar) should use the +google.protobuf.Duration type.

+

To illustrate the distinction between timestamps and durations, consider a +flight record:

+
// A representation of a (very incomplete) flight log.
+message FlightRecord {
+  // The absolute point in time when the plane took off.
+  google.protobuf.Timestamp takeoff_time = 1;
+
+  // The length (duration) of the flight, from takeoff to landing.
+  google.protobuf.Duration flight_duration = 2;
+}
+
+

Note: Observant readers may notice that the timestamp and duration +messages have the same structure (int64 seconds and int32 nanos). However, +the distinction between these is important, because they have different +semantic meaning. Additionally, tooling is able to base behavior off of which +message is used. For example, a Python-based tool could convert timestamps to +datetime objects and durations to timedelta +objects.

+

Relative time segments

+

In some cases, it may be necessary to represent a time segment inside a stream. +In these cases, the google.protobuf.Duration type should be +used, and the field name should end with _offset. To ensure that the +meaning is clear, the field must have a comment noting the point that the +offset is relative to.

+

To illustrate this, consider a resource representing a segment of an audio +stream:

+
message AudioSegment {
+  // The duration relative to the start of the stream representing the
+  // beginning of the segment.
+  google.protobuf.Duration start_offset = 1;
+
+  // The total length of the segment.
+  google.protobuf.Duration segment_duration = 2;
+}
+
+

Civil dates and times

+

Fields that represent a calendar date or wall-clock time should use the +appropriate common components:

+ +

Fields representing civil dates should have names ending in _date, while +fields representing civil times or datetimes should have names ending in +_time.

+

Note: Both the Date and TimeOfDay components are timezone-naïve. Fields +that require timezone-awareness should use DateTime (see below).

+

Civil timestamps

+

Fields that represent a civil timestamp (date and time, optionally with a time +zone) should use the google.type.DateTime component, and the +field name should end in _time.

+

Compatibility

+

Occasionally, APIs are unable to use the common structures for legacy or +compatibility reasons. For example, an API may conform to a separate +specification that mandates that timestamps be integers or ISO-8601 +strings.

+

In these situations, fields may use other types. If possible, the following +naming conventions apply:

+
    +
  • For integers, include the meaning (examples: time, duration, delay, + latency) and the unit of measurement (valid values: seconds, + millis, micros, nanos) as a final suffix. For example, + send_time_millis.
  • +
  • For strings, include the meaning (examples: time, duration, delay, + latency) but no unit suffix.
  • +
+

In all cases, clearly document the expected format, and the rationale for its +use.

+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/143.html b/143.html new file mode 100644 index 0000000000..5089587806 --- /dev/null +++ b/143.html @@ -0,0 +1,800 @@ + + + + AIP-143: Standardized codes + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-143

+

Standardized codes

+

Many common concepts, such as spoken languages, countries, currency, and so on, +have common codes (usually formalized by the International Organization for +Standardization) that are used in data communication and processing. +These codes address the issue that there are often different ways to express +the same concept in written language (for example, "United States" and "USA", +or "Español" and "Spanish").

+

Guidance

+

For concepts where a standardized code exists and is in common use, fields +representing these concepts should use the standardized code for both input +and output.

+
// A message representing a book.
+message Book {
+  // Other fields...
+
+  // The IETF BCP-47 language code representing the language in which
+  // the book was originally written.
+  // https://en.wikipedia.org/wiki/IETF_language_tag
+  string language_code = 99;
+}
+
+
    +
  • Fields representing standardized concepts must use the appropriate data + type for the standard code (usually string).
      +
    • Fields representing standardized concepts should not use enums, even if + they only allow a small subset of possible values. Using enums in this + situation often leads to frustrating lookup tables when using multiple APIs + together.
    • +
    • Fields representing standardized concepts must indicate which standard + they follow, preferably with a link (either to the standard itself, the + Wikipedia description, or something similar).
    • +
    +
  • +
  • The field name should end in _code or _type unless the concept has an + obviously clearer suffix.
  • +
  • When accepting values provided by users, validation should be + case-insensitive unless this would introduce ambiguity (for example, accept + both en-gb and en-GB). When providing values to users, APIs should + use the canonical case (in the example above, en-GB).
  • +
+

Content types

+

Fields representing a content or media type must use IANA media types. +For legacy reasons, the field should be called mime_type.

+

Countries and regions

+

Fields representing individual countries or nations must use the Unicode +CLDR region codes (list), such as US or CH, and the field +must be called region_code.

+

Important: Please read the rationale for this +requirement.

+

Currency

+

Fields representing currency must use ISO-4217 currency codes, +such as USD or CHF, and the field must be called currency_code.

+

Note: For representing an amount of money in a particular currency, rather +than the currency code itself, use google.type.Money.

+

Language

+

Fields representing spoken languages must use IETF BCP-47 language +codes (list), such as en-US or de-CH, and the field must +be called language_code.

+

Time zones

+

Fields representing a time zone should use the IANA TZ codes, and the +field must be called time_zone.

+

Fields also may represent a UTC offset rather than a time zone (note that +these are subtly different). In this case, the field must use the ISO-8601 +format to represent this, and the field must be named utc_offset.

+

Rationale

+

Country/region field naming

+

The use of region_code instead of country_code is critical to being able to +convey regions that are distinct from any country and to avoid any political +disputes associated with said region regarding their sovereignty or affiliation. +Google and many other companies are supporters of Unicode CLDR and standardize +their product internationalization efforts on Unicode CLDR, and APIs are no +different here. Furthermore, many of the values supported by Unicode CLDR are +not countries on their own, so using a more generic name is actually more +compatible with the specification.

+

Changelog

+
    +
  • 2024-12-03: Strengthen rationale of country/region field naming
  • +
  • 2024-11-12: Change country/region code list to CLDR list from IANA list
  • +
  • 2020-05-12: Replaced country_code guidance with region_code, + correcting an original error.
  • +
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/144.html b/144.html new file mode 100644 index 0000000000..598e93233c --- /dev/null +++ b/144.html @@ -0,0 +1,864 @@ + + + + AIP-144: Repeated fields + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-144

+

Repeated fields

+

Representing lists of data in an API is trickier than it often appears. Users +often need to modify lists in place, and longer data series within a single +resource pose a challenge for pagination.

+

Guidance

+

Resources may use repeated fields where appropriate.

+
message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  repeated string authors = 2;
+}
+
+
    +
  • Repeated fields must use a plural field name.
      +
    • If the English singular and plural words are identical ("moose", "info"), + the dictionary word must be used rather than attempting to coin a new + plural form.
    • +
    +
  • +
  • Repeated fields should have an enforced upper bound that will not cause a + single resource payload to become too large. A good rule of thumb is 100 + elements.
      +
    • If repeated data has the chance of being too large, the API should use + a sub-resource instead.
    • +
    +
  • +
  • Repeated fields must not represent the body of another resource inline. + Instead, the message should provide the resource names of the associated + resources.
  • +
+

Scalars and messages

+

Repeated fields should use a scalar type (such as string) if they are +certain that additional data will not be needed in the future, as using a +message type adds significant cognitive overhead and leads to more complicated +code.

+

However, if additional data is likely to be needed in the future, repeated +fields should use a message instead of a scalar proactively, to avoid +parallel repeated fields.

+

Update strategies

+

A resource may use two strategies to enable updating a repeated field: +direct update using the standard Update method, or custom Add +and Remove methods.

+

A standard Update method has one key limitation: the user is only able to +update the entire list. Field masks are unable to address individual entries +in a repeated field. This means that the user must read the resource, make +modifications to the repeated field value as needed, and send it back. This is +fine for many situations, particularly when the repeated field is expected to +have a small size (fewer than 10 or so) and race conditions are not an issue, +or can be guarded against with ETags.

+

Note: Declarative-friendly resources must use the standard Update +method, and not introduce Add and Remove methods. If declarative tools need +to reason about particular relationships while ignoring others, consider using +a subresource instead.

+

If atomic modifications are required, the API should define custom methods +using the verbs Add and Remove:

+

Note: If both of these strategies are too restrictive, consider using a +subresource instead.

+
rpc AddAuthor(AddAuthorRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{book=publishers/*/books/*}:addAuthor"
+    body: "*"
+  };
+}
+
+rpc RemoveAuthor(RemoveAuthorRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{book=publishers/*/books/*}:removeAuthor"
+    body: "*"
+  };
+}
+
+
    +
  • The data being added or removed should be a primitive (usually a + string).
      +
    • For more complex data structures with a primary key, the API should use + a map with the Update method instead.
    • +
    +
  • +
  • The RPC's name must begin with the word Add or Remove. The remainder + of the RPC name should be the singular form of the field being added.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response message should be the resource itself, unless there is useful + context to provide in the response, in which case the response message must + match the RPC name, with a Response suffix.
      +
    • When the response is the resource itself, it should include the + fully-populated resource.
    • +
    +
  • +
  • The HTTP verb must be POST, as is usual for custom methods.
  • +
  • The HTTP URI must end with :add* or :remove*, where * is the + snake-case singular name of the field being added or removed.
  • +
  • The request message field receiving the resource name should map to the + URI path.
      +
    • The HTTP variable should be the name of the resource (such as book) + rather than name or parent.
    • +
    • That variable should be the only variable in the URI path.
    • +
    +
  • +
  • The body clause in the google.api.http annotation should be "*".
  • +
  • If the data being added in an Add RPC is already present, the method + must error with ALREADY_EXISTS.
  • +
  • If the data being removed in a Remove RPC is not present, the method + must error with NOT_FOUND.
  • +
+

Request Message

+
message AddAuthorRequest {
+  // The name of the book to add an author to.
+  string book = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference).type = "library.googleapis.com/Book"
+  ];
+
+  string author = 2 [(google.api.field_behavior) = REQUIRED];
+}
+
+message RemoveAuthorRequest {
+  // The name of the book to remove an author from.
+  string book = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference).type = "library.googleapis.com/Book"
+  ];
+
+  string author = 2 [(google.api.field_behavior) = REQUIRED];
+}
+
+
    +
  • A resource field must be included. It should be the name of the + resource (such as book) rather than name or parent. +
  • +
  • A field for the value being added or removed must be included. It + should be the singular name of the field. +
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
+

Changelog

+
    +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-10-17: Recommended returning the resource itself in Add and Remove + RPCs over separate response types.
  • +
  • 2020-10-17: Added guidance for Add and Remove RPCs and requests.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/145.html b/145.html new file mode 100644 index 0000000000..34b3dfee2d --- /dev/null +++ b/145.html @@ -0,0 +1,784 @@ + + + + AIP-145: Ranges + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-145

+

Ranges

+

Services often need to represent ranges of discrete or continuous values. These +have wide differences in meaning, and come in many types: integers, floats, and +timestamps, just to name a few, and the expected meaning of a range can vary in +subtle ways depending on the type of range being discussed.

+

Guidance

+

A resource or message representing a range should ordinarily use two +separate fields of the same type, with prefixes start_ and end_:

+
// A representation of a chapter in a book.
+message Chapter {
+  string title = 1;
+
+  // The page where this chapter begins.
+  int32 start_page = 2;
+
+  // The page where the next chapter or section begins.
+  int32 end_page = 3;
+}
+
+

Inclusive or exclusive ranges

+

Fields representing ranges should use inclusive start values and exclusive +end values (half-closed intervals) in most situations; in interval notation: +[start_xxx, end_xxx).

+

Exclusive end values are preferable for the following reasons:

+
    +
  • It conforms to user expectations, particularly for continuous values such as + timestamps, and avoids the need to express imprecise "limit values" (e.g. + 2012-04-20T23:59:59).
  • +
  • It is consistent with most common programming languages, including C++, Java, + Python, and Go.
  • +
  • It is easier to reason about abutting ranges: [0, x), [x, y), [y, z), where + values are chainable from one range to the next.
  • +
+

Timestamp intervals

+

The following section describes the use of the google.type.Interval +type, found amongst the common protos that are described in AIP-213. +This type represents a range between two timestamps, with an inclusive start +value and exclusive end value.

+

Ranges between two timestamps which conform to the expectations of the +Interval message should use this rather than having separate start and +end fields. This allows client code to be written against the Interval +message (such as checking whether a given timestamp occurs within the interval) +and reused across multiple intervals in the same API, or even across multiple +APIs.

+

APIs may use start and end timestamp fields instead. In particular, if a +message within an API is inherently describing an interval with extra +information about that interval, the additional level of nesting introduced +by using the Interval message may be undesirable.

+

Exceptions

+

In some cases, there is significant colloquial precedent for inclusive start +and end values (closed intervals), to the point that using an exclusive end +value would be confusing even for people accustomed to them.

+

For example, when discussing dates (not to be confused with timestamps), most +people use inclusive end: a conference with dates "April 21-23" is expected to +run for three days: April 21, April 22, and April 23. This is also true for +days of the week: a business that is open "Monday through Friday" is open, not +closed, on Fridays.

+

In this situation, the prefixes first and last should be used instead:

+
// A representation of a chapter in a book.
+message Chapter {
+  string title = 1;
+
+  // The first page of the chapter.
+  int32 first_page = 2;
+
+  // The last page of the chapter.
+  int32 last_page = 3;
+}
+
+

Fields representing ranges with significant colloquial precedent for inclusive +start and end values should use inclusive end values with first_ and +last_ prefixes for those ranges only. The service should still use +exclusive end values for other ranges where this does not apply, and must +clearly document each range as inclusive or exclusive.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/146.html b/146.html new file mode 100644 index 0000000000..5245f2d69f --- /dev/null +++ b/146.html @@ -0,0 +1,773 @@ + + + + AIP-146: Generic fields + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-146

+

Generic fields

+

Most fields in any API, whether in a request, a resource, or a custom response, +have a specific type or schema. This schema is part of the contract that +developers write their code against.

+

However, occasionally it is appropriate to have a generic or polymorphic field +of some kind that can conform to multiple schemata, or even be entirely +free-form.

+

Guidance

+

While generic fields are generally rare, a service may introduce generic +field where necessary. There are several approaches to this depending on how +generic the field needs to be; in general, services should attempt to +introduce the "least generic" approach that is able to satisfy the use case.

+

Oneof

+

A oneof may be used to introduce a type union: the user or service is +able to specify one of the fields inside the oneof. Additionally, a oneof +may be used with the same type (usually strings) to represent a semantic +difference between the options.

+

Because the individual fields in the oneof have different keys, a developer +can programmatically determine which (if any) of the fields is populated.

+

A oneof preserves the largest degree of type safety and semantic meaning for +each option, and services should generally prefer them over other generic +or polymorphic options when feasible. However, the oneof construct is +ill-suited when there is a large (or unlimited) number of potential options, or +when there is a large resource structure that would require a long series of +"cascading oneofs".

+

Note: Adding additional possible fields to an existing oneof is a +non-breaking change, but moving existing fields into or out of a oneof is +breaking (it creates a backwards-incompatible change in Go protobuf stubs).

+

Maps

+

Maps may be used in situations where many values of the +same type are needed, but the keys are unknown or user-determined.

+

Maps are usually not appropriate for generic fields because the map values all +share a type, but occasionally they are useful. In particular, a map can +sometimes be suited to a situation where many objects of the same type are +needed, with different behavior based on the names of their keys (for example, +using keys as environment names).

+

Struct

+

The google.protobuf.Struct object may be used to represent arbitrary +nested JSON. Keys can be strings, and values can be floats, strings, booleans, +arrays, or additional nested structs, allowing for an arbitrarily nested +structure that can be represented as JSON (and is automatically represented as +JSON when using REST/JSON).

+

A Struct is most useful when the service does not know the schema in advance, +or when a service needs to store and retrieve arbitrary but structured user +data. Using a Struct is convenient for users in this case because they can +easily get JSON objects that can be natively manipulated in their environment +of choice.

+

If a service needs to reason about the schema of a Struct, it should +use JSONSchema for this purpose. Because JSONSchema is itself JSON, a valid +JSONSchema document can itself be stored in a Struct.

+

Any

+

The google.protobuf.Any object can be used to send an arbitrary +serialized protocol buffer and a type definition.

+

However, this introduces complexity, because an Any becomes useless for any +task other than blind data propagation if the consumer does not have access to +the proto. Additionally, even if the consumer does have the proto, the +consumer has to ensure the type is registered and then deserialize manually, +which is an often-unfamiliar process.

+

Because of this, Any should not be used unless other options are +infeasible.

+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/147.html b/147.html new file mode 100644 index 0000000000..b337d892f3 --- /dev/null +++ b/147.html @@ -0,0 +1,762 @@ + + + + AIP-147: Sensitive fields + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-147

+

Sensitive fields

+

Sometimes APIs need to collect sensitive information such as private encryption +keys meant to be stored by the underlying service but not intended to be +read after writing due to the sensitive nature of the data. For this type of +data, extra consideration is required for the representation of the sensitive +data in API requests and responses.

+

Guidance

+

If the sensitive information is required for the resource as a whole to +exist, the data should be accepted as an input-only field +with no corresponding output field. Because the sensitive data must be present +for the resource to exist, users of the API may assume that existence of the +resource implies storage of the sensitive data. For example:

+
message SelfManagedKeypair {
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The public key data in PEM-encoded form.
+  bytes public_key = 2;
+
+  // The private key data in PEM-encoded form.
+  bytes private_key = 3 [
+    (google.api.field_behavior) = INPUT_ONLY];
+}
+
+

If the sensitive information is optional within the containing resource, an +output-only boolean field with a postfix of _set should be used to +indicate whether or not the sensitive information is present. For example:

+
message Integration {
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+  string uri = 2;
+
+  // A secret to be passed in the `Authorization` header of the webhook.
+  string shared_secret = 3 [
+    (google.api.field_behavior) = INPUT_ONLY];
+
+  // True if a `shared_secret` has been set for this Integration.
+  bool shared_secret_set = 4 [
+    (google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+

If it is important to be able to identify the sensitive information without +allowing it to be read back entirely, a field of the same type with an +obfuscated_ prefix may be used instead of the boolean _set field to +provide contextual information about the sensitive information. The specific +nature of the obfuscation is outside the scope of this AIP. For example:

+
message AccountRecoverySettings {
+  // An email to use for account recovery.
+  string email = 1 [
+    (google.api.field_behavior) = INPUT_ONLY];
+
+  // An obfuscated representation of the recovery email. For example,
+  // `ada@example.com` might be represented as `a**@e*****e.com`.
+  string obfuscated_email = 2 [
+    (google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/148.html b/148.html new file mode 100644 index 0000000000..2b18dca1b3 --- /dev/null +++ b/148.html @@ -0,0 +1,847 @@ + + + + AIP-148: Standard fields + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-148

+

Standard fields

+

Certain concepts are common throughout any corpus of APIs. In these situations, +it is useful to have a standard field name and behavior that is used +consistently to communicate that concept.

+

Guidance

+

Standard fields should be used to describe their corresponding concept, and +should not be used for any other purpose.

+

Resource names and IDs

+

name

+

Every resource must have a string name field, used for the resource name +(AIP-122), which should be the first field in the resource.

+

Note: The _name suffix should not be used to describe other types of +names unless otherwise covered in this AIP.

+

parent

+

The string parent field refers to the resource name of the parent of a +collection, and should be used in most List (AIP-132) and Create +(AIP-133) requests.

+

Other names

+

display_name

+

The string display_name field must be a mutable, user-settable field +where the user can provide a human-readable name to be used in user interfaces. +Declarative-friendly resources should include this field.

+

Display names should not have uniqueness requirements, and should be +limited to <= 63 characters.

+

title

+

The string title field should be the official name of an entity, such as +a company's name. This is a more formal variant of string display_name.

+

given_name

+

The string given_name field must refer to a human or animal's given name. +Resources must not use first_name for this concept, because the given +name is not placed first in many cultures.

+

family_name

+

The string family_name field must refer to a human or animal's family +name. Resources must not use last_name for this concept, because the +family name is not placed last in many cultures.

+

Timestamps

+

create_time

+

The output only google.protobuf.Timestamp create_time field must +represent the timestamp when the resource was created. This may be either +the time creation was initiated or the time it was completed. +Declarative-friendly resources should include this field.

+

update_time

+

The output only google.protobuf.Timestamp update_time field must +represent the timestamp when the resource was most recently updated. Any change +to the resource made by users must refresh this value; changes to a +resource made internally by the service may refresh this value. +Declarative-friendly resources should include this field.

+

delete_time

+

The output only google.protobuf.Timestamp delete_time field must represent +the timestamp that a resource was soft deleted. This may correspond to either +the time when the user requested deletion, or when the service successfully +soft deleted the resource. If a resource is not soft deleted, the delete_time +field must be empty.

+

Resources that support soft delete (AIP-164) should provide this field.

+

expire_time

+

The google.protobuf.Timestamp expire_time field should represent the time +that a given resource or resource attribute is no longer useful or valid (e.g. a +rotating security key). It may be used for similar forms of expiration as +described in AIP-214.

+

Services may provide an expire_time value that is inexact, but the +resource must not expire before that time.

+

purge_time

+

The google.protobuf.Timestamp purge_time field should represent the time +when a soft deleted resource will be purged from the system (see AIP-164). +It may be used for similar forms of expiration as described in AIP-214. +Resources that support soft delete should include this field.

+

Services may provide a purge_time value that is inexact, but the resource +must not be purged from the system before that time.

+

Annotations

+

To store small amounts of arbitrary data, a map<string, string> annotations +field may be added.

+

The annotations field must use the Kubernetes limits to maintain wire +compatibility, and should require dot-namespaced annotation keys to prevent +tools from trampling over one another.

+

Examples of information that might be valuable to store in annotations include:

+
    +
  • For CI/CD, an identifier of the pipeline run or version control identifier + used to propagate.
  • +
+

Note: Annotations are distinct from various forms of labels. Labels can be +used by server-side policies, such as IAM conditions. Annotations exist to +allow client tools to store their own state information without requiring a +database.

+

Well known string fields

+

IP address

+

A field that represents an IP address must comply with the following:

+
    +
  • use type string
  • +
  • use the name ip_address or end with the suffix _ip_address e.g. + resolved_ip_address
  • +
  • specify the IP address version format via one of the supported formats IPV4, + IPV6, or if it can be either, IPV4_OR_IPV6 (see AIP-202)
  • +
+

uid

+

The output only string uid field refers to a system-assigned unique +identifier for a resource. When provided, this field must be a UUID4 +and must specify this format via the UUID4 format extension (see +AIP-202). Declarative-friendly resources should include this +field.

+

Further reading

+
    +
  • For standardized codes, see AIP-143.
  • +
  • For the etag field, see AIP-154.
  • +
  • For the request_id field, see AIP-155.
  • +
  • For the filter field, see AIP-160.
  • +
  • For fields related to resource revisions, see AIP-162.
  • +
  • For the validate_only field, see AIP-163.
  • +
  • For fields related to soft delete and undelete, see AIP-164.
  • +
+

Rationale

+

Well known string fields

+

Some fields represent very well defined concepts or artifacts that sometimes +also have strict governance of their semantics. For such fields, presenting an +equally standardized API surface is important. This enables development of +improved API consumer tools and documentation, as well as a more unified user +experience across the platform.

+

History

+

Before 2023-07, purge_time for soft-deleted resources was also called +expire_time. purge_time was introduced to reduce user confusion.

+

Changelog

+
    +
  • 2023-10-05: Introduce well known string fields with IP Address and uid.
  • +
  • 2023-08-14: Introduce the term annotations from AIP-128.
  • +
  • 2023-07-13: Introduce the term purge_time.
  • +
  • 2021-04-06: Require output only field behavior for uid and delete_time + fields.
  • +
+ + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/149.html b/149.html new file mode 100644 index 0000000000..d21e1ac99a --- /dev/null +++ b/149.html @@ -0,0 +1,772 @@ + + + + AIP-149: Unset field values + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-149

+

Unset field values

+

In many messages, many fields are optional: the user is not required to provide +them, or for output fields, the service might not populate the field.

+

In most cases, there is no meaningful difference between setting it to a +default value (such as 0) as opposed to not setting it at all; however, +occasionally this distinction is meaningful.

+

Guidance

+

Services defined in protocol buffers should use the optional keyword for +primitives if and only if it is necessary to distinguish setting the field to +its default value (0, false, or empty string) from not setting it at all:

+
// A representation of a book in a library.
+message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  // The name of the book.
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The rating for the book, from 0 to 5.
+  // 0 is distinct from no rating.
+  optional int32 rating = 2;
+}
+
+

Important: Services should not need to distinguish between the default +value and unset most of the time; if an alternative design does not require +such a distinction, it is usually preferred. In practice, this means optional +should only ever be used for integers and floats.

+

Important: Tracking field presence is not the same as documenting API +field behavior as defined in AIP-203. For example, a field labeled with +optional for presence tracking may also be annotated as +google.api.field_behavior = REQUIRED if the field must be set. If you only +want to document the server perceived behavior of a field, read AIP-203.

+

Backwards compatibility

+

It is a backwards incompatible change to add or remove the optional qualifier +to an existing field. This is because the compiled src API is changed (in some +languages). For example, in Golang, adding optional changes the field type of +primitives to be the pointer variant of their original type, e.g. a field +formerly of type string becomes *string, etc. Accordingly, this change +requires that both clients and servers update their usage of the changed field +in unison, which is risky and error prone. Additional information is +documented by Protobuf.

+

Rationale

+

field behavior and optional

+

The field behavior annotation and optional label are not mutually exclusive, +because they address different problems. The former, +google.api.field_behavior, focuses on communicating the server's perception of +a field within the API e.g. if it is required or not, if it is immutable, etc. +The latter, proto3's optional, is a wire format and code generation option +that is strictly for toggling field presence tracking. While it might be +confusing for a field to be simultaneously annotated with +google.api.field_behavior = REQUIRED and labeled as optional, they are +unrelated in practice and can reasonably be used together.

+

Changelog

+
    +
  • 2024-06-05: Add backwards compatibility considerations
  • +
  • 2023-06-20: Differentiate from field behavior documentation
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/151.html b/151.html new file mode 100644 index 0000000000..14a6e49775 --- /dev/null +++ b/151.html @@ -0,0 +1,863 @@ + + + + AIP-151: Long-running operations + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-151

+

Long-running operations

+

Occasionally, an API may need to expose a method that takes a significant +amount of time to complete. In these situations, it is often a poor user +experience to simply block while the task runs; rather, it is better to return +some kind of promise to the user and allow the user to check back in later.

+

The long-running operations pattern is roughly analogous to a Python +Future, or a Node.js Promise. Essentially, the user is given a token +that can be used to track progress and retrieve the result.

+

Guidance

+

Individual API methods that might take a significant amount of time to complete +should return a google.longrunning.Operation object instead of the +ultimate response message.

+
// Create a book.
+rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books"
+    body: "book"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "Book"
+    metadata_type: "OperationMetadata"
+  };
+}
+
+
    +
  • The response type must be google.longrunning.Operation. The Operation + proto definition must not be copied into individual APIs.
      +
    • The response must not be a streaming response.
    • +
    +
  • +
  • The method must include a google.longrunning.operation_info annotation, + which must define both response and metadata types.
      +
    • The response and metadata types must be defined in the file where the + RPC appears, or a file imported by that file.
    • +
    • If the response and metadata types are defined in another package, the + fully-qualified message name must be used.
    • +
    • The response type should not be google.protobuf.Empty (except for + Delete methods), unless it is certain that response data will + never be needed. If response data might be added in the future, define an + empty message for the RPC response and use that.
    • +
    • The metadata type is used to provide information such as progress, partial + failures, and similar information on each GetOperation call. The metadata + type should not be google.protobuf.Empty, unless it is certain that + metadata will never be needed. If metadata might be added in the future, + define an empty message for the RPC metadata and use that.
    • +
    +
  • +
  • APIs with messages that return Operation must implement the + Operations service. Individual APIs must not define their own + interfaces for long-running operations to avoid non-uniformity.
  • +
  • If an RPC supports a validate-only mode, the response to a + validation request must be one of the following:
      +
    • A successful response with an Operation which is already complete, with + the done field set to true, and a valid (but potentially empty) response + message in the response field, wrapped in a google.protobuf.Any message. + The name field may be empty, to avoid the service having to maintain + state for successful validation.
    • +
    • An immediate error response (typically "bad request")
    • +
    • An Operation with the done field set to false, to indicate + long-running validation. In this case, the name field must be set, + to allow clients to poll the long-running validation operation until it + has completed. Successful validation must eventually be represented by + an operation with done=true and a valid (but potentially empty) wrapped + response message in the response field. Unsuccessful validation must + eventually be represented by an operation with done=true and the error + details provided in the error field.
    • +
    +
  • +
+

Note: User expectations can vary on what is considered "a significant +amount of time" depending on what work is being done. A good rule of thumb is +10 seconds.

+

Standard methods

+

APIs may return an Operation from the Create, +Update, or Delete standard methods if appropriate. In +this case, the response type in the operation_info annotation must be the +standard and expected response type for that standard method.

+

When creating or deleting a resource with a long-running operation, the +resource should be included in List and Get +calls; however, the resource should indicate that it is not usable, +generally with a state enum.

+

Parallel operations

+

A resource may accept multiple operations that will work on it in parallel, +but is not obligated to do so:

+
    +
  • Resources that accept multiple parallel operations may place them in a + queue rather than work on the operations simultaneously.
  • +
  • Resources that do not permit multiple operations in parallel (denying any + new operation until the one that is in progress finishes) must return + ABORTED if a user attempts a parallel operation, and include an error + message explaining the situation.
  • +
  • Resources with declarative-friendly APIs may allow subsequent + updates to preempt existing operations. In this case, the latest update + begins processing and previous operations are marked as ABORTED with an + error message explaining the situation.
  • +
+

Expiration

+

APIs may allow their operation resources to expire after sufficient time +has elapsed after the operation completed.

+

Note: A good rule of thumb for operation expiry is 30 days.

+

Errors

+

Errors that prevent a long-running operation from starting must return an +error response (AIP-193), similar to any other method.

+

Operations that fail during their execution phase must return an +error response (AIP-193), placed in the Operation.error google.rpc.Status +field.

+

Non-terminal errors that occur over the course of an operation may be placed +in the metadata message and the field(s) must be AIP-193 compliant +google.rpc.Status.

+

Backwards compatibility

+

Changing either the response_type or metadata_type of a long-running operation +is a breaking change.

+

Rationale

+

Validate-only behavior

+

The guidance for validate-only responses comes from a tension +between clients, which benefit from "fully formed" operations that can +be treated uniformly, and servers, which don't wish to maintain +additional state for trivial operations. It seems counterintuitive +that just validating a request should generate more state, but a +full operation response that can be fetched later would either +require that or "special" singleton operation IDs. The guidance +provided is a compromise: by returning a "done" operation, clients +can use existing logic to check that the operation has completed +successfully (and therefore doesn't need to be fetched for an +updated status) but server don't need to maintain any additional state.

+ + + +

Changelog

+
    +
  • 2025-02-04: Clarified error propagation behavior for failures + that occur during long-running operations.
  • +
  • 2024-04-23: Provided pattern for validation on RPCs returning + long-running operations.
  • +
  • 2022-05-31: Added compatibility section.
  • +
  • 2020-08-24: Clarified that responses are not streaming responses.
  • +
  • 2020-06-24: Added guidance for parallel operations.
  • +
  • 2020-03-20: Clarified that both response_type and metadata_type are + required.
  • +
  • 2019-11-22: Added a short explanation of what metadata_type is for.
  • +
  • 2019-09-23: Added guidance on errors.
  • +
  • 2019-08-23: Added guidance about fully-qualified message names when the + message name is in another package.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/152.html b/152.html new file mode 100644 index 0000000000..d3c510ebbb --- /dev/null +++ b/152.html @@ -0,0 +1,823 @@ + + + + AIP-152: Jobs + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-152

+

Jobs

+

Occasionally, APIs may need to expose a task that takes significant time to +complete, and where a transient long-running operation is not +appropriate. For example, a task could need to run repeatedly, or have separate +permissions for configuring the task as opposed to running it.

+

Guidance

+

An API may define a Job resource to represent a particular task with +distinct setup, configuration, and execution:

+
message WriteBookJob {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/WriteBookJob"
+    pattern: "publishers/{publisher}/writeBookJobs/{write_book_job}"
+  };
+
+  // Name and other fields...
+}
+
+
    +
  • The name of the resource must end with the word "Job".
      +
    • The prefix should be a valid RPC name, with a verb and a noun.
    • +
    +
  • +
  • The service should define all five of the standard methods (AIP-131, + AIP-132, AIP-133, AIP-134, AIP-135), and use them as the + primary way to configure the job.
  • +
+

Run method

+

The service should define a Run custom method that executes the job +immediately:

+
rpc RunWriteBookJob(RunWriteBookJobRequest)
+    returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/writeBookJobs/*}:run"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "RunWriteBookJobResponse"
+    metadata_type: "RunWriteBookJobMetadata"
+  };
+}
+
+
    +
  • The RPC's name must begin with the word Run. The remainder of the + RPC name should be the singular form of the job resource being run.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The method should return a long-running operation, which + must resolve to a response message that includes the result of running + the job.
      +
    • The response message name must match the RPC name, with a Response + suffix.
    • +
    • The method may use any metadata message it wishes.
    • +
    +
  • +
  • The HTTP verb must be POST, as is usual for custom methods.
  • +
  • The body clause in the google.api.http annotation should be "*".
  • +
  • The URI path should contain a single name variable corresponding to the + name of the job resource being run.
  • +
  • The URI path must end with :run.
  • +
  • Errors that prevent execution of the job from starting must return an + error response (AIP-193), similar to any other method. Errors that occur + over the course of the job execution may be placed in the metadata + message. The errors themselves must still be represented with a + google.rpc.Status object.
  • +
+

Run request message

+

Run methods implement a common request message pattern:

+
message RunWriteBookJobRequest {
+  // The name of the job to run.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/WriteBookJob"
+    }];
+}
+
+ +

Executions and results

+

Ordinarily, the API should provide results to the user as the final +response of the Run method. However, this is sometimes insufficient; for +example, a job that runs on a recurring schedule in the background can not +deliver results to the user in this way.

+

The service may store resources representing individual executions along +with their result as a sub-collection of resources under the job, which allows +the user to list past job executions. A service that does this should +define the Get, List, and Delete methods for the execution resources:

+
message WriteBookJobExecution {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/WriteBookJobExecution"
+    pattern: "publishers/{publisher}/writeBookJobs/{write_book_job}/executions/{execution}"
+  };
+
+  // Name and other information about the execution, such as metadata, the
+  // result, error information, etc.
+}
+
+

In this case, the operation returned by job's Run method should refer to +the child resource.

+

Changelog

+
    +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-11-02: Expanded guidance on HTTP, field behavior, and resource + reference annotations and request format.
  • +
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/153.html b/153.html new file mode 100644 index 0000000000..7e6aee03ea --- /dev/null +++ b/153.html @@ -0,0 +1,860 @@ + + + + AIP-153: Import and export + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-153

+

Import and export

+

Many users want to be able to load data into an API, or get their existing data +out of an API. This is particularly important for enterprise users, who are +often concerned about vendor lock-in.

+

Guidance

+

APIs may support import and export operations, which may create +multiple new resources, or they may populate data into a single resource.

+

Multiple resources

+

Services may support importing and exporting multiple resources into or out +of an API, and should implement a common pattern to do so:

+
rpc ImportBooks(ImportBooksRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:import"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "ImportBooksResponse"
+    metadata_type: "ImportBooksMetadata"
+  };
+}
+
+rpc ExportBooks(ExportBooksRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:export"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "ExportBooksResponse"
+    metadata_type: "ExportBooksMetadata"
+  };
+}
+
+
    +
  • The method must return a long-running operation (see AIP-151) unless + the service can guarantee that it will never need more than a few seconds + to complete.
  • +
  • The HTTP verb must be POST, and the body must be "*".
  • +
  • A parent field should be included as part of the URI.
      +
    • If importing into or exporting from multiple resources is required, the API + should keep the parent field and allow the user to use the - + character to indicate multiple parents (see AIP-159).
    • +
    • On import, if the user provides a specific parent, the API must reject + any imported resources that would be added to a different parent.
    • +
    +
  • +
  • The URI suffix should be :import or :export.
  • +
+

Data for a single resource

+

Services may support importing and exporting data into or out of a single +resource, and should implement a common pattern to do so:

+
rpc ImportPages(ImportPagesRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{book=publishers/*/books/*}:importPages"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "ImportPagesResponse"
+    metadata_type: "ImportPagesMetadata"
+  };
+}
+
+rpc ExportPages(ExportPagesRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{book=publishers/*/books/*}:exportPages"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "ExportPagesResponse"
+    metadata_type: "ExportPagesMetadata"
+  };
+}
+
+
    +
  • The method must return a long-running operation (see AIP-151) unless + the service can guarantee that it will never need more than a few seconds + to complete.
  • +
  • The HTTP verb must be POST, and the body must be "*".
  • +
  • A field representing the resource that data is being imported into should + be included as part of the URI. The field should be named after the + resource (and should not be called name).
  • +
  • The URI suffix should include both the verb and a noun for the data itself, + such as :importPages or :exportPages.
  • +
+

Request object

+

Imports and exports often require two fundamentally different types of +configuration:

+
    +
  1. Configuration specific to the source or destination.
  2. +
  3. Configuration regarding the imported or exported data itself.
  4. +
+

Source or destination configuration should be grouped into a single message and +placed inside a oneof:

+
message ImportBooksRequest {
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+  oneof source {
+    AuthorSource author_source = 2;
+    TranslatorSource translator_source = 3;
+  }
+  string isbn_prefix = 4;
+}
+
+message ExportBooksRequest {
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+  oneof destination {
+    PrinterDestination printer_destination = 2;
+    TranslatorDestination translator_destination = 3;
+  }
+  string filter = 4;
+}
+
+
    +
  • The source configuration messages must be placed within a oneof source + (for import) or oneof destination (for export), even if there is only one. + (This maintains flexibility to add more later.)
  • +
  • Configuration related to the data itself (and therefore common across all + sources) must be placed at the top-level of the request message.
  • +
+

Note: The configuration for import and export may be different from one +another. (For example, it would be sensible to import from a file but export to +a directory.)

+

Inline sources

+

APIs may also permit import and export "inline", where the contents to be +imported or exported are provided in the request or response.

+
message InlineSource {
+  repeated Book books = 1;
+}
+
+
    +
  • The source or destination should be named InlineSource or + InlineDestination.
  • +
  • The message should include a repeated field representing the resource. + However, if the resource structure is complex, the API may use a separate + inline representation. In this situation, the same format must be used + for both import and export.
  • +
+

Partial failures

+

While partial failures are normally discouraged, import and export RPCs +should include partial failure information in the metadata object. Each +individual error should be a google.rpc.Status object describing the +error. For more on errors, see AIP-193.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/154.html b/154.html new file mode 100644 index 0000000000..14e55754e3 --- /dev/null +++ b/154.html @@ -0,0 +1,807 @@ + + + + AIP-154: Resource freshness validation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-154

+

Resource freshness validation

+

APIs often need to validate that a client and server agree on the current state +of a resource before taking some kind of action on that resource. For example, +two processes updating the same resource in parallel could create a race +condition, where the latter process "stomps over" the effort of the former one.

+

ETags provide a way to deal with this, by allowing the server to send a +checksum based on the current content of a resource; when the client sends that +checksum back, the server can ensure that the checksums match before acting on +the request.

+

Guidance

+

A resource may include an etag field on any resource where it is +important to ensure that the client has an up to date resource before acting on +certain requests:

+
// A representation of a book.
+message Book {
+  // Other fields...
+
+  // This checksum is computed by the server based on the value of other
+  // fields, and may be sent on update and delete requests to ensure the
+  // client has an up-to-date value before proceeding.
+  string etag = 99;
+}
+
+
    +
  • The etag field must be a string, and must be named etag.
  • +
  • The etag field on the resource should not be given any behavior + annotations.
  • +
  • The etag field must be provided by the server on output, and values + should conform to RFC 7232.
  • +
  • If a user sends back an etag which matches the current etag value, the + service must permit the request (unless there is some other reason for + failure).
  • +
  • If a user sends back an etag which does not match the current etag value, the + service must send an ABORTED error response (unless another error takes + precedence, such as PERMISSION_DENIED if the user is not authorized).
  • +
  • If the user does not send an etag value at all, the service should permit + the request. However, services with strong consistency or parallelism + requirements may require users to send etags all the time and reject the + request with an INVALID_ARGUMENT error in this case.
  • +
+

Note: ETag values should include quotes as described in RFC 7232. +For example, a valid etag is "foo", not foo.

+

Declarative-friendly resources

+

A resource that is declarative-friendly (AIP-128) must include an etag +field.

+

Etags on request methods

+

In some situations, the etag needs to belong on a request message rather than +the resource itself. For example, an Update standard method can "piggyback" +off the etag field on the resource, but the Delete standard method can not:

+
message DeleteBookRequest {
+  // The name of the book.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+
+  // The current etag of the book.
+  // If an etag is provided and does not match the current etag of the book,
+  // deletion will be blocked and an ABORTED error will be returned.
+  string etag = 2 [(google.api.field_behavior) = OPTIONAL];
+}
+
+

On a request message, the etag field should be given a behavior annotation +- either REQUIRED or OPTIONAL. See AIP-203 for more information.

+

An etag field may also be used on custom methods, similar to the example +above.

+

Strong and weak etags

+

ETags can be either "strongly validated" or "weakly validated":

+
    +
  • A strongly validated etag means that two resources bearing the same etag are + byte-for-byte identical.
  • +
  • A weakly validated etag means that two resources bearing the same etag are + equivalent, but may differ in ways that the service does not consider to be + important.
  • +
+

Resources may use either strong or weak etags, as it sees fit, but +should document the behavior. Additionally, weak etags must have a W/ +prefix as mandated by RFC 7232.

+

Further reading

+
    +
  • For how to retry on errors in client libraries, see AIP-194.
  • +
+

Changelog

+
    +
  • 2021-04-01: Updated an additional reference to FAILED_PRECONDITION + to ABORTED.
  • +
  • 2021-03-05: Changed the etag error from FAILED_PRECONDITION (which + becomes HTTP 400) to ABORTED (409).
  • +
  • 2020-10-06: Added declarative-friendly resource requirement.
  • +
  • 2020-09-02: Clarified that other errors may take precedence over + FAILED_PRECONDITION for etag mismatches.
  • +
  • 2020-09-02: Add guidance for etags on request messages.
  • +
  • 2019-09-23: Changed the title to "resource freshness validation".
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/155.html b/155.html new file mode 100644 index 0000000000..3621d9c946 --- /dev/null +++ b/155.html @@ -0,0 +1,800 @@ + + + + AIP-155: Request identification + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-155

+

Request identification

+

It is sometimes useful for an API to have a unique, customer-provided +identifier for particular requests. This can be useful for several purposes, +such as de-duplicating requests from parallel processes, ensuring the safety of +retries, or auditing.

+

The most important purpose for request IDs is to provide idempotency +guarantees: allowing the same request to be issued more than once without +subsequent calls having any effect. In the event of a network failure, the +client can retry the request, and the server can detect duplication and ensure +that the request is only processed once.

+

Guidance

+

APIs may add a string request_id parameter to request messages (including +those of standard methods) in order to uniquely identify particular requests.

+
message CreateBookRequest {
+  // The parent resource where this book will be created.
+  // Format: publishers/{publisher}
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The ID to use for the book, which will become the final component of
+  // the book's resource name.
+  //
+  // This value should be 4-63 characters, and valid characters
+  // are /[a-z][0-9]-/.
+  string book_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // The book to create.
+  Book book = 3 [(google.api.field_behavior) = REQUIRED];
+
+  // A unique identifier for this request. Restricted to 36 ASCII characters.
+  // A random UUID is recommended.
+  // This request is only idempotent if a `request_id` is provided.
+  string request_id = 4 [(google.api.field_info).format = UUID4];
+}
+
+
    +
  • Providing a request ID must guarantee idempotency.
      +
    • If a duplicate request is detected, the server should return the + response for the previously successful request, because the client most + likely did not receive the previous response.
    • +
    • APIs may choose any reasonable timeframe for honoring request IDs.
    • +
    +
  • +
  • The request_id field must be provided on the request message to which + it applies (and it must not be a field on resources themselves).
  • +
  • Request IDs should be optional.
  • +
  • Request IDs should be able to be UUIDs, and may allow UUIDs to be the + only valid format. The format restrictions for request IDs must be + documented.
      +
    • Request IDs that are UUIDs must be annotated with the + google.api.FieldInfo.Format value UUID4 using the extension + (google.api.field_info).format = UUID4. See AIP-202 for more.
    • +
    +
  • +
+

Stale success responses

+

In some unusual situations, it may not be possible to return an identical +success response. For example, a duplicate request to create a resource may +arrive after the resource has not only been created, but subsequently updated; +because the service has no other need to retain the historical data, it is no +longer feasible to return an identical success response.

+

In this situation, the method may return the current state of the resource +instead. In other words, it is permissible to substitute the historical success +response with a similar response that reflects more current data.

+

Further reading

+
    +
  • For which codes to retry, see AIP-194.
  • +
  • For how to retry errors in client libraries, see + AIP-4221.
  • +
+

Rationale

+

Using UUIDs for request identification

+

When a value is required to be unique, leaving the format open-ended can lead to +API consumers incorrectly providing a duplicate identifier. As such, +standardizing on a universally unique identifier drastically reduces the chance +for collisions when done correctly.

+

Changelog

+
    +
  • 2024-01-08: Add book_id to request message.
  • +
  • 2023-10-02: Add UUID format extension guidance.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/156.html b/156.html new file mode 100644 index 0000000000..8323e2cb5d --- /dev/null +++ b/156.html @@ -0,0 +1,824 @@ + + + + AIP-156: Singleton resources + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-156

+

Singleton resources

+

APIs sometimes need to represent a resource where exactly one instance of the +resource always exists within any given parent. A common use case for this is +for a config object.

+

Guidance

+

An API may define singleton resources. A singleton resource must +always exist by virtue of the existence of its parent, with one and exactly one +per parent.

+

For example:

+
message Config {
+  option (google.api.resource) = {
+    type: "api.googleapis.com/Config"
+    pattern: "users/{user}/config"
+    singular: "config"
+    plural: "configs"
+  };
+
+  // additional fields including name
+}
+
+

The Config singleton would have the following RPCs:

+
rpc GetConfig(GetConfigRequest) returns (Config) {
+  option (google.api.http) = {
+    get: "/v1/{name=users/*/config}"
+  };
+}
+
+rpc UpdateConfig(UpdateConfigRequest) returns (Config) {
+  option (google.api.http) = {
+    patch: "/v1/{config.name=users/*/config}"
+    body: "config"
+  };
+}
+
+
    +
  • Singleton resources must not have a user-provided or system-generated ID; + their resource name includes the name of their parent followed by + one static-segment.
      +
    • Example: users/1234/config
    • +
    +
  • +
  • Singleton resources are always singular.
      +
    • Example: users/1234/thing
    • +
    +
  • +
  • Singleton resource definitions must provide both the singular and + plural fields (see above example).
  • +
  • Singleton resources may parent other resources.
  • +
  • Singleton resources must not define the Create or + Delete standard methods. The singleton is implicitly created or + deleted when its parent is created or deleted.
  • +
  • Singleton resources should define the Get and + Update methods, and may define custom methods as + appropriate.
      +
    • However, singleton resources must not define the Update + method if all fields on the resource are output only.
    • +
    +
  • +
  • Singleton resources may define the List method, but must + implement it according to AIP-159. See the example below.
      +
    • The trailing segment in the path pattern that typically represents the + collection should be the plural form of the Singleton resource e.g. + /v1/{parent=users/*}/configs.
    • +
    • If a parent resource ID is provided instead of the hyphen - as per + AIP-159, then the service should return a collection of one Singleton + resource corresponding to the specified parent resource.
    • +
    +
  • +
+
rpc ListConfigs(ListConfigsRequest) returns (ListConfigsResponse) {
+  option (google.api.http) = {
+    get: "/v1/{parent=users/*}/configs"
+  };
+}
+
+message ListConfigsRequest {
+  // To list all configs, use `-` as the user id.
+  // Formats:
+  // * `users/-`
+  // * `users/{user}`
+  //
+  // Note: Specifying an actual user id will return a collection of one config.
+  // Use GetConfig instead.
+  string parent = 1 [
+    (google.api.resource_reference).child_type = "api.googleapis.com/Config"];
+
+  // other standard pagination fields...
+}
+
+

Rationale

+

Support for Standard List

+

While Singleton resources are not directly part of a collection themselves, they +can be viewed as part of their parent's collection. The one-to-one relationship +of parent-to-singleton means that for every one parent there is one singleton +instance, naturally enabling some collection-based methods when combined with +the pattern of Reading Across Collections. The Singleton can present +as a collection to the API consumer as it is indirectly one based on its parent. +Furthermore, presenting the Singleton resource as a pseudo-collection in such +methods enables future expansion to a real collection, should a Singleton be +found lacking.

+

Including plural definition

+

While a Singleton is by definition singular, there are certain cases where +a Singleton resource may appear in a plural form e.g., if the service supports +Standard List (as defined here). As such, it is better to forward declare the +plural form of the Singleton resource type than to not have it when needed.

+

Changelog

+
    +
  • 2024-04-15: Singletons must specify singular and plural in resource.
  • +
  • 2023-08-10: Add Standard List support.
  • +
  • 2023-07-26: Clarified that read-only singletons should not have Update.
  • +
  • 2021-11-02: Added an example message and state parent eligibility.
  • +
  • 2021-01-14: Changed example from settings to config for clarity.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/157.html b/157.html new file mode 100644 index 0000000000..6ca8fddc72 --- /dev/null +++ b/157.html @@ -0,0 +1,826 @@ + + + + AIP-157: Partial responses + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-157

+

Partial responses

+

Sometimes, a resource can be either large or expensive to compute, and the API +needs to give the user control over which fields it sends back.

+

Guidance

+

APIs may support partial responses in one of two ways:

+

Field masks parameter

+

Field masks (google.protobuf.FieldMask) can be used for granting the user +fine-grained control over what fields are returned. An API should support the mask in a side channel. +For example, the parameter can be specified either using an HTTP query +parameter, an HTTP header, or a gRPC metadata entry. Google Cloud APIs specify field masks as a system parameter.

+

Field masks should not be specified in the request.

+
    +
  • The value of the field mask parameter must be a google.protobuf.FieldMask.
  • +
  • The field mask parameter must be optional:
      +
    • An explicit value of "*" should be supported, and must return all + fields.
    • +
    • If the field mask parameter is omitted, it must default to "*", unless otherwise documented.
    • +
    +
  • +
  • An API may allow read masks with non-terminal repeated fields (unlike + update masks), but is not obligated to do so.
  • +
+

Note: Changing the default value of the field mask parameter is a breaking change.

+

View enumeration

+

Alternatively, an API may support partial responses with view enums. +View enums are useful for situations where an API only wants to expose a small +number of permutations to the user:

+
enum BookView {
+  // The default / unset value.
+  // The API will default to the BASIC view.
+  BOOK_VIEW_UNSPECIFIED = 0;
+
+  // Include basic metadata about the book, but not the full contents.
+  // This is the default value (for both ListBooks and GetBook).
+  BOOK_VIEW_BASIC = 1;
+
+  // Include everything.
+  BOOK_VIEW_FULL = 2;
+}
+
+
    +
  • The enum should be specified as a view field on the request message.
  • +
  • The enum should be named something ending in -View
  • +
  • The enum should at minimum have values named BASIC and FULL (although + it may have values other than these).
  • +
  • The UNSPECIFIED value must be valid (not an error), and the API + must document what the unspecified value will do.
      +
    • For List RPCs, the effective default value should be BASIC.
    • +
    • For the following RPC types, the effective default value should be + either BASIC or FULL:
        +
      • Get
      • +
      • Create
      • +
      • Update
      • +
      • Soft Delete
      • +
      • Custom Method
      • +
      +
    • +
    +
  • +
  • The enum should be defined at the top level of the proto file (as it is + likely to be needed in multiple requests, e.g. both Get and List). See + AIP-126 for more guidance on top-level enumerations.
  • +
  • +

    APIs may add fields to a given view over time. APIs must not remove a + field from a given view (this is a breaking change).

    +

    Note: If a service requires (or might require) multiple views with +overlapping but distinct values, there is a potential for a namespace +conflict. In this situation, the service should nest the view enum within +the individual resource.

    +

    Note: Having a partial response be the default of standard methods can +degrade the effectiveness of declarative clients. Providing a mechanism to +request the full resource be populated in the response, like this View +pattern, is preferred if partial responses are deemed necessary.

    +
  • +
+

Read masks as a request field

+

Warning: Read mask as a single, explicit field on the request message is +DEPRECATED for Google APIs. The system parameter +must be used instead. The following guidance is for the benefit of existing +legacy Google and external non-Google usage.

+

An API may support read masks as a single field on the request message: +google.protobuf.FieldMask read_mask.

+
    +
  • The read mask must be a google.protobuf.FieldMask and should be + named read_mask.
  • +
  • The field mask should be optional:
      +
    • An explicit value of "*" should be supported, and must return all + fields.
    • +
    • If the field mask parameter is not provided, all fields must be + returned.
    • +
    +
  • +
  • An API may allow read masks with non-terminal repeated fields (unlike + update masks), but is not obligated to do so.
  • +
+

Rationale

+

Deprecating read_mask in request messages

+

As mentioned, Google API infrastructure implements a service-wide response +field filtering mechanism, so there is no need for individual API methods to +specify a read_mask in their request schema. Doing so is both redundant and a +potential point of conflict for the client or service.

+

Changelog

+
    +
  • 2025-10-03: Added default view guidance for other RPC types, and + declarative client warning.
  • +
  • 2025-06-16: Reinstate read mask guidance as historical/external reference.
  • +
  • 2023-05-09: Fix top-level enum example and link to AIP-126.
  • +
  • 2022-03-14: Updated guidance on default value and how to specify a read mask.
  • +
  • 2021-10-06: Updated the guidance with system parameters.
  • +
  • 2021-03-04: Added guidance for conflicting view enums.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/158.html b/158.html new file mode 100644 index 0000000000..71f50dfc91 --- /dev/null +++ b/158.html @@ -0,0 +1,893 @@ + + + + AIP-158: Pagination + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-158

+

Pagination

+

APIs often need to provide collections of data, most commonly in the List +standard method. However, collections can often be arbitrarily sized, and also +often grow over time, increasing lookup time as well as the size of the +responses being sent over the wire. Therefore, it is important that collections +be paginated.

+

Guidance

+

RPCs returning collections of data must provide pagination at the outset, +as it is a backwards-incompatible change to add +pagination to an existing method.

+
// The request structure for listing books.
+message ListBooksRequest {
+  // The parent, which owns this collection of books.
+  // Format: publishers/{publisher}
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The maximum number of books to return. The service may return fewer than
+  // this value.
+  // If unspecified, at most 50 books will be returned.
+  // The maximum value is 1000; values above 1000 will be coerced to 1000.
+  int32 page_size = 2;
+
+  // A page token, received from a previous `ListBooks` call.
+  // Provide this to retrieve the subsequent page.
+  //
+  // When paginating, all other parameters provided to `ListBooks` must match
+  // the call that provided the page token.
+  string page_token = 3;
+}
+
+// The response structure from listing books.
+message ListBooksResponse {
+  // The books from the specified publisher.
+  repeated Book books = 1;
+
+  // A token that can be sent as `page_token` to retrieve the next page.
+  // If this field is omitted, there are no subsequent pages.
+  string next_page_token = 2;
+}
+
+
    +
  • Request messages for collections should define an int32 page_size + field, allowing users to specify the maximum number of results to return.
      +
    • The page_size field must not be required.
    • +
    • If the user does not specify page_size (or specifies 0), the API + chooses an appropriate default, which the API should document. The API + must not return an error.
    • +
    • If the user specifies page_size greater than the maximum permitted by the + API, the API should coerce down to the maximum permitted page size.
    • +
    • If the user specifies a negative value for page_size, the API must + send an INVALID_ARGUMENT error.
    • +
    • The API may return fewer results than the number requested (including + zero results), even if not at the end of the collection.
    • +
    +
  • +
  • Request messages for collections should define a string page_token + field, allowing users to advance to the next page in the collection.
      +
    • The page_token field must not be required.
    • +
    • If the user changes the page_size in a request for subsequent pages, the + service must honor the new page size.
    • +
    • The user is expected to keep all other arguments to the RPC the same; if + any arguments are different, the API should send an INVALID_ARGUMENT + error.
    • +
    +
  • +
  • The response must not be a streaming response.
  • +
  • Response messages for collections should define a + string next_page_token field, providing the user with a page token that may + be used to retrieve the next page.
      +
    • The field containing pagination results should be the first field in + the message and have a field number of 1. It should be a repeated + field containing a list of resources constituting a single page of results.
    • +
    • If the end of the collection has been reached, the next_page_token field + must be empty. This is the only way to communicate + "end-of-collection" to users.
    • +
    • If the end of the collection has not been reached (or if the API can not + determine in time), the API must provide a next_page_token.
    • +
    +
  • +
  • Response messages for collections may provide an int32 total_size + field, providing the user with the total number of items in the list.
      +
    • This total may be an estimate (but the API should explicitly + document that).
    • +
    +
  • +
+

Skipping results

+

The request definition for a paginated operation may define an int32 skip +field to allow the user to skip results.

+

The skip value must refer to the number of individual resources to skip, +not the number of pages.

+

For example:

+
    +
  • A request with no page token and a skip value of 30 returns a single page + of results starting with the 31st result.
  • +
  • A request with a page token corresponding to the 51st result (because the + first 50 results were returned on the first page) and a skip value of 30 + returns a single page of results starting with the 81st result.
  • +
+

If a skip value is provided that cannot be fulfilled e.g. due to latency of +querying a massive data set, the response must be 200 OK with an empty +result set. If it is known to put the cursor beyond the total size of the +collection, the response must not include a next_page_token.

+

Opacity

+

Page tokens provided by APIs must be opaque (but URL-safe) strings, and +must not be user-parseable. This is because if users are able to +deconstruct these, they will do so. This effectively makes the implementation +details of your API's pagination become part of the API surface, and it becomes +impossible to update those details without breaking users.

+

Warning: Base-64 encoding an otherwise-transparent page token is not a +sufficient obfuscation mechanism.

+

For page tokens which do not need to be stored in a database, and which do not +contain sensitive data, an API may obfuscate the page token by defining an +internal protocol buffer message with any data needed, and send the serialized +proto, base-64 encoded.

+

Page tokens must be limited to providing an indication of where to continue +the pagination process only. They must not provide any form of +authorization to the underlying resources, and authorization must be +performed on the request as with any other regardless of the presence of a page +token.

+

Expiring page tokens

+

Many APIs store page tokens in a database internally. In this situation, APIs +may expire page tokens a reasonable time after they have been sent, in +order not to needlessly store large amounts of data that is unlikely to be +used. It is not necessary to document this behavior.

+

Note: While a reasonable time may vary between APIs, a good rule of thumb +is three days.

+

Backwards compatibility

+

Adding pagination to an existing RPC is a backwards-incompatible change. This +may seem strange; adding fields to proto messages is generally backwards +compatible. However, this change is behaviorally incompatible.

+

Consider a user whose collection has 75 resources, and who has already written +and deployed code. If the API later adds pagination fields, and sets the +default to 50, then that user's code breaks; it was getting all resources, and +now is only getting the first 50 (and does not know to advance pagination). +Even if the API set a higher default limit, such as 100, the user's collection +could grow, and then the code would break.

+

Additionally, client libraries implement automatic +pagination, typically representing paginated +RPCs using different method signatures to unpaginated ones. This means that +adding pagination to a previously-unpaginated method causes a breaking change +in those libraries.

+

For this reason, it is important to always add pagination to RPCs returning +collections up front; they are consistently important, and they can not be +added later without causing problems for existing users.

+

Warning: This also entails that, in addition to presenting the pagination +fields, they must be actually implemented with a non-infinite default +value. Implementing an in-memory version (which might fetch everything then +paginate) is reasonable for initially-small collections.

+

Rationale

+

Degraded skip response

+

Large collections, complex queries, and globally distributed data can all +contribute to a paginated method being unable to quickly or confidently fulfill +a given skip request. Backend queries can timeout, data collation can take +time, and the end user experience need not suffer as a result. In such cases, +the pagination interface can be leveraged to keep the client engaged by +providing a next_page_token, while the service collects an appropriate result. +When the service has definitively determined that the requested skip exceeds +the available results, the pagination interface is again applied and +next_page_token is omitted to signal the end of results.

+

Changelog

+
    +
  • 2025-07-08: Clarify degraded skip response guidance
  • +
  • 2020-05-24: Clarified that adding pagination breaks client + libraries.
  • +
  • 2020-05-13: Added guidance for skipping results.
  • +
  • 2020-08-24: Clarified that responses are not streaming responses.
  • +
  • 2020-06-24: Clarified that page size is always optional for users.
  • +
  • 2019-02-12: Added guidance on the field being paginated over.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
  • 2019-07-19: Update the opacity requirement from "should" to "must".
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/159.html b/159.html new file mode 100644 index 0000000000..25e5404c36 --- /dev/null +++ b/159.html @@ -0,0 +1,770 @@ + + + + AIP-159: Reading across collections + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-159

+

Reading across collections

+

Sometimes, it is useful for a user to be able to retrieve resources across +multiple collections, or retrieve a single resource without needing to know +what collection it is in.

+

Guidance

+

APIs may support reading resources across multiple collections by allowing +users to specify a - (the hyphen or dash character) as a wildcard character +in a standard List method:

+
GET /v1/publishers/-/books?filter=...
+
+
    +
  • The URI pattern must still be specified with * and permit the + collection to be specified; a URI pattern must not hard-code the - + character.
  • +
  • The method must explicitly document that this behavior is supported.
  • +
  • The resources provided in the response must use the canonical name of the + resource, with the actual parent collection identifiers (instead of -).
  • +
  • Services may support reading across collections on List requests + regardless of whether the identifiers of the child resources are guaranteed + to be unique. However, services must not support reading across + collections on Get requests if the child resources might have a collision.
  • +
  • Cross-parent requests should not support order_by. If they do, the + field must document that it is best effort. This is because cross-parent + requests introduce ambiguity around ordering, especially if there is + difficulty reaching a parent (see AIP-217).
  • +
+

Important: If listing across multiple collections introduces the +possibility of partial failures due to unreachable parents (such as when +listing across locations), the method must indicate this following the +guidance in AIP-217.

+

Unique resource lookup

+

Sometimes, a resource within a sub-collection has an identifier that is unique +across parent collections. In this case, it may be useful to allow a +Get method to retrieve that resource without knowing which parent +collection contains it. In such cases, APIs may allow users to specify the +wildcard collection ID - (the hyphen or dash character) to represent any +parent collection:

+
GET https://example.googleapis.com/v1/publishers/-/books/{book}
+
+
    +
  • The URI pattern must still be specified with * and permit the + collection to be specified; a URI pattern must not hard-code the - + character.
  • +
  • The method must explicitly document that this behavior is supported.
  • +
  • The resource name in the response must use the canonical name of the + resource, with actual parent collection identifiers (instead of -). For + example, the request above returns a resource with a name like + publishers/123/books/456, not publishers/-/books/456.
  • +
  • The resource ID must be unique within parent collections.
  • +
+

Further reading

+
    +
  • For partial failures due to unreachable resources, see AIP-217.
  • +
+

Changelog

+
    +
  • 2019-08-26: Added a reference to guidance for unreachable resources.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/160.html b/160.html new file mode 100644 index 0000000000..83a7439236 --- /dev/null +++ b/160.html @@ -0,0 +1,1035 @@ + + + + AIP-160: Filtering + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-160

+

Filtering

+

Often, when listing resources (using a list method as defined in AIP-132 or +something reasonably similar), it is desirable to filter over the collection +and only return results that the user is interested in.

+

It is tempting to define a structure to handle the precise filtering needs for +each API. However, filtering requirements evolve frequently, and therefore it +is prudent to use a string field with a structured syntax accessible to a +non-technical audience. This allows updates to be able to be made +transparently, without waiting for UI or client updates.

+

Note: Because list filters are intended for a potentially non-technical +audience, they sometimes borrow from patterns of colloquial speech rather than +common patterns found in code.

+

Guidance

+

APIs may provide filtering to users on List methods (or similar methods +to query a collection, such as Search). If they choose to do so, they +should follow the common specification for filters discussed here. The +syntax is formally defined in the EBNF grammar.

+

When employing filtering, a request message should have exactly one +filtering field, string filter. Filtering of related objects is handled +through traversal or functions.

+

Note: List Filters have fuzzy matching characteristics with support for +result ranking and scoring. For developers interested in deterministic +evaluation of list filters, see CEL.

+

Literals

+

A bare literal value (examples: "42", "Hugo") is a value to be matched against. +Literals appearing alone (with no specified field) should usually be +matched anywhere it may appear in an object's field values.

+

However, a service may choose to only consider certain fields; if so, it +must document which fields it considers. A service may include new +fields over time, but should do so judiciously and consider impact on +existing users.

+

Note: Literals separated by whitespace are considered to have a fuzzy +variant of AND. Therefore, Victor Hugo is roughly equivalent to +Victor AND Hugo.

+

Logical Operators

+

Filtering implementations should provide the binary operators:

+ + + + + + + + + + + + + + + + + + + + +
OperatorExampleMeaning
ANDa AND bTrue if a and b are true.
ORa OR b OR cTrue if any of a, b, c are true.
+

Note: To match common patterns of speech, the OR operator has higher +precedence than AND, unlike what is found in most programming languages. The +expression a AND b OR c evaluates: a AND (b OR c). API documentation and +examples should encourage the use of explicit parentheses to avoid +confusion, but should not require explicit parentheses.

+

Negation Operators

+

Filtering implementations should provide the unary operators NOT and -. +These are used interchangeably, and a service that supports negation must +support both formats.

+ + + + + + + + + + + + + + + + + + + + +
OperatorExampleMeaning
NOTNOT aTrue if a is not true.
--aTrue if a is not true.
+

Comparison Operators

+

Filtering implementations should provide the binary comparison operators +=, !=, <, >, <=, and >= for string, numeric, timestamp, and +duration fields (but should not provide them for booleans or enums).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OperatorExampleMeaning
=a = trueTrue if a is true.
!=a != 42True unless a equals 42.
<a < 42True if a is a numeric value below 42.
>a > "foo"True if a is lexically ordered after "foo".
<=a <= "foo"True if a is "foo" or lexically before it.
>=a >= 42True if a is a numeric value of 42 or higher.
+

Note: Unlike in most programming languages, field names must appear on +the left-hand side of a comparison operator; the right-hand side only accepts +literals and logical operators.

+

Because filters are accepted as query strings, type conversion takes place to +translate the string to the appropriate strongly-typed value:

+
    +
  • Enums expect the enum's string representation (case-sensitive).
  • +
  • Booleans expect true and false literal values.
  • +
  • Numbers expect the standard integer or float representations. For floats, + exponents are supported (e.g. 2.997e9).
  • +
  • Durations expect a numeric representation followed by an s suffix (for + seconds). Examples: 20s, 1.2s.
  • +
  • Timestamps expect an RFC-3339 formatted string (e.g. + 2012-04-21T11:30:00-04:00). UTC offsets are supported.
  • +
+

Warning: The identifiers true, false, and null only carry intrinsic +meaning when used in the context of a typed field reference.

+

Additionally, when comparing strings for equality, services should support +wildcards using the * character; for example, a = "*.foo" is true if a +ends with ".foo".

+

Traversal operator

+

Filtering implementations should provide the . operator, which indicates +traversal through a message, map, or struct.

+ + + + + + + + + + + + + + + + + + + + + +
ExampleMeaning
a.b = trueTrue if a has a boolean b field that is true.
a.b > 42True if a has a numeric b field that is above 42.
a.b.c = "foo"True if a.b has a string c field that is "foo".
+

Traversal must be written using the field names from the resource. If a +service wishes to support "implicit fields" of some kind, they must do so +through well-documented functions. A service may specify a +subset of fields that are supported for traversal.

+

If a user attempts to traverse to a field that is not defined on the message, +the service should return an error with INVALID_ARGUMENT. A service +may permit traversal to undefined keys on maps and structs, and should +document how it behaves in this situation.

+

When evaluating an expression involving a traversal, if any non-primitive field +in the chain is not set on the entry being evaluated, the entry should be +skipped i.e. not match the filter expression. This applies even when the +comparison is a !=, which would imply matching on empty values. In the +examples above, if resource field a is not set on the resource instance, that +instance is skipped as a non-match.

+

Important: The . operator must not be used to traverse through a +repeated field or list, except for specific use with the : operator.

+

Has Operator

+

Filtering implementations must provide the : operator, which means "has". +It is usable with collections (repeated fields or maps) as well as messages, +and behaves slightly differently in each case.

+

Repeated fields query to see if the repeated structure contains a matching +element:

+ + + + + + + + + + + + + + + + + +
ExampleMeaning
r:42True if r contains 42.
r.foo:42True if r contains an element e such that e.foo = 42.
+

Important: Filters can not query a specific element on a repeated field +for a value. For example, e.0.foo = 42 and e[0].foo = 42 are not valid +filters.

+

Maps, structs, messages can query either for the presence of a field in the map +or a specific value:

+ + + + + + + + + + + + + + + + + + + + + +
ExampleMeaning
m:fooTrue if m contains the key "foo".
m.foo:*True if m contains the key "foo".
m.foo:42True if m.foo is 42.
+

There are two slight distinctions when parsing messages:

+
    +
  • When traversing messages, a field is only considered to be present if it has + a non-default value.
  • +
  • When traversing messages, field names are snake case, although + implementations may choose to support automatic conversion between camel + case and snake case.
  • +
+

For all aforementioned types, simply checking for the presence of a top-level +resource field is possible with the * value:

+ + + + + + + + + + + + + + + + + + + + + +
ExampleMeaning
r:*True if repeated field r is present.
p:*True if map field p is present.
m:*True if message field m is present.
+

Note: For map and repeated fields, there is no semantic difference +between an unset field and "set with empty value" - they both resolve to "not +present".

+

Functions

+

The filtering language supports a function call syntax in order to support +API-specific extensions. An API may define a function using the +call(arg...) syntax, and must document any specific functions it +supports.

+

Limitations

+

A service may specify further structure or limitations for filter queries, +above what is defined here. For example, a service may support the logical +operators but only permit a certain number of them (to avoid "queries of death" +or other performance concerns).

+

Further structure or limitations must be clearly documented, and +must not violate requirements set forth in this document.

+

Validation

+

If a non-compliant or schematically invalid filter string is specified, +the API should error with INVALID_ARGUMENT. Wherever validation is relaxed +for filter, the API must document the difference.

+

Schematic validation refers, but is not limited to, the following:

+
    +
  • Fields referenced in the filter must exist on the filtered schema
  • +
  • Field values provided in the filter must align to the type of the field
      +
    • For example, for a field int32 age a filter like "age=hello" is + invalid
    • +
    +
  • +
  • Field values for bounded data types e.g. enum provided in the filter + must be a valid value in the set
  • +
  • Field values for standardized types e.g. Timestamp must conform to the + documented standard (see Comparison Operators for a + list of such types)
  • +
+ + + +

Changelog

+
    +
  • 2025-10-03: Clarify top-level field has operator behavior.
  • +
  • 2025-01-07: Clarify behavior for unset field in traversal operator chain.
  • +
  • 2024-12-11: Move non-compliant filter guidance to Validation section.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/161.html b/161.html new file mode 100644 index 0000000000..1de1c9e429 --- /dev/null +++ b/161.html @@ -0,0 +1,836 @@ + + + + AIP-161: Field masks + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-161

+

Field masks

+

Often, when updating resources (using an update method as defined in AIP-134 or +something reasonably similar), it is desirable to specify exactly which fields +are being updated, so that the service can ignore the rest, even if the user +sends new values.

+

It is tempting to define a mask format to handle the precise needs for each +API. However, masking requirements evolve, and therefore it is prudent to use a +structured syntax. This allows updates to be able to be made transparently, +without waiting for UI or client updates.

+

Guidance

+

These masks of field names are called "field masks". Fields representing a field +mask must use the google.protobuf.FieldMask type. Field masks are most +common on Update requests (AIP-134).

+

Field masks must always be relative to the resource:

+

Warning: Read masks as a single field on the request message, for +example: google.protobuf.FieldMask read_mask are DEPRECATED. Instead, see +AIP-157.

+
message UpdateBookRequest {
+  // The book to update.
+  //
+  // The book's `name` field is used to identify the book to update.
+  // Format: publishers/{publisher}/books/{book}
+  Book book = 1 [(google.api.field_behavior) = REQUIRED];
+
+  // The list of fields to update.
+  // Fields are specified relative to the book
+  // (e.g. `title`, `rating`; *not* `book.title` or `book.rating`).
+  google.protobuf.FieldMask update_mask = 2;
+}
+
+

Read-write consistency

+

Read and write behavior for field masks must be self-consistent if a mask +is present:

+
    +
  • If a user updates a resource with a given mask, and then reads the same + resource with the same mask, the exact same data must be returned. +
  • +
  • Similarly, reading a resource with a given mask and then updating the + resource with the returned data and the same mask must be a no-op.
  • +
+

Note: This implies that any mask that is valid for either read or write +must be valid for both.

+

Specifying specific fields

+

Field masks must permit the specification of specific fields in a defined +struct, using the . character for traversal.

+

Because field masks are always relative to the resource, direct fields on the +resource require no traversal (examples: title, rating). Traversal is used +when resources contain messages (example: author.given_name).

+

Note: A user must be able to specify either a field as a whole, or one +of its subfields: author and author.given_name are both valid.

+

Map fields

+

Field masks may permit the specification of specific fields in a map, if +and only if the map's keys are either strings or integers, using the . +character for traversal.

+

Field masks should support string keys that contain characters that are +problematic for the field mask syntax, using the backtick character.

+
message Book {
+  // The name of the book.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1;
+
+  // Reviews for the back cover. The key is the author of the review,
+  // and the value is the text of the review.
+  //
+  // Valid field masks: reviews, reviews.smith, reviews.`John Smith`
+  map<string, string> reviews = 2;
+}
+
+

Wildcards

+

Field masks may permit the use of the * character on a repeated field or +map to indicate the specification of particular sub-fields in the collection:

+
message Book {
+  option (google.api.resource) = {
+    type: "library.googleapis.com/Book"
+    pattern: "publishers/{publisher}/books/{book}"
+  };
+
+  // The name of the book.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+  // The author or authors of the book.
+  // Valid field masks: authors, authors.*.given_name, authors.*.family_name
+  // Invalid field masks: authors.0, authors.0.given_name
+  repeated Author authors = 2;
+}
+
+message Author {
+  // The author's given name.
+  string given_name = 1;
+
+  // The author's family name.
+  string family_name = 2;
+}
+
+

Note: Field masks must not permit accessing a particular element of a +repeated field by index, and must return an INVALID_ARGUMENT error if +this is attempted.

+

Output only fields

+

If a user includes an output only field in an update mask indirectly (by using +a wildcard or specifying an overall message that includes an output-only +subfield), the service must ignore any output only fields provided as +input, even if they are cleared or modified.

+

If a user directly specifies an output only field in an update mask, the +service must ignore the output only fields provided as input, even if +they are cleared or modified, to permit the same field mask to be used for +input and output.

+

Invalid field mask entries

+

When reading data, field masks may ignore entries that point to a value +that can not exist (either a field that does not exist, or a map key that the +service considers invalid).

+

When writing data, field masks should return an INVALID_ARGUMENT error if +an entry points to a value that can not exist; however, the service may +permit deletions.

+

Changelog

+
    +
  • 2023-10-18: Update guidance for presence of output only fields in update + mask.
  • +
  • 2023-07-17: Move update_mask guidance to AIP-134.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/162.html b/162.html new file mode 100644 index 0000000000..69259b8135 --- /dev/null +++ b/162.html @@ -0,0 +1,959 @@ + + + + AIP-162: Resource Revisions + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+

+ This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

+

AIP-162

+

Resource Revisions

+

Some APIs need to have resources with a revision history, where users can +reason about the state of the resource over time. There are several reasons for +this:

+
    +
  • Users may want to be able to roll back to a previous revision, or diff + against a previous revision.
  • +
  • An API may create data which is derived in some way from a resource at a + given point in time. In these cases, it may be desirable to snapshot the + resource for reference later.
  • +
+

Note: We use the word revision to refer to a historical reference for a +particular resource, and intentionally avoid the term version, which refers +to the version of an API as a whole.

+

Guidance

+

APIs may store a revision history for a resource. Examples of when it is +useful include:

+
    +
  • When it is valuable to expose older versions of a resource via an API. This + can avoid the overhead of the customers having to write their own API to store + and enable retrieval of revisions.
  • +
  • Other resources depend on different revisions of a resource.
  • +
  • There is a need to represent the change of a resource over time.
  • +
+

APIs implementing resources with a revision history should abstract resource +revisions as nested collection of the resource. Sometimes, the revisions +collection can be a top level collection, exceptions include:

+
    +
  • If resource revisions are meant to have longer lifespan than the parent +resource. In other words, resource revisions exist after resource deletion.
  • +
+
message BookRevision {
+  // The name of the book revision.
+  string name = 1;
+
+  // The snapshot of the book
+  Book snapshot = 2
+    [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // The timestamp that the revision was created.
+  google.protobuf.Timestamp create_time = 3
+    [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Other revision IDs that share the same snapshot.
+  repeated string alternate_ids = 4
+    [(google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+
    +
  • The message must be annotated as a resource (AIP-123).
  • +
  • The message name must be named {ResourceType}Revision.
  • +
  • The resource revision must contain a field with a message type of the + parent resource, with a field name of snapshot.
      +
    • The value of snapshot must be the configuration of the parent + at the point in time the revision was created.
    • +
    +
  • +
  • The resource revision must contain a create_time field (see AIP-142).
  • +
  • The resource revision may contain a repeated field alternate_ids, which would + contain a list of resource IDs that the revision is also known by (e.g. latest)
  • +
+

Creating Revisions

+

Depending on the resource, different APIs may have different strategies for

+
    +
  • Create a new revision any time that there is a change to the parent resource
  • +
  • Create a new revision when important system state changes
  • +
  • Create a new revision when specifically requested
  • +
+

APIs may use any of these strategies. APIs must +document their revision creation strategy.

+

Resource names for revisions

+

When referring to specific revision of a resource, the subcollection name +must be named revisions. Resource revisions have names with the format +{resource_name}/revisions/{revision_id}. For example: +

publishers/123/books/les-miserables/revisions/c7cfa2a8
+

+

Server-specified Aliases

+

Services may reserve specific IDs to be aliases (e.g. +latest). These are read-only and managed by the service.

+
GET /v1/publishers/{publisher}/books/{book}/revisions/{revision_id}
+
+
    +
  • If a latest ID exists, it must represent the most recently created +revision. The content of publishers/{publisher}/books/{book}/revisions/latest +and publishers/{publisher}/books/{book} can differ, as the latest revision may +be different from the current state of the resource.
  • +
+

User-Specified Aliases

+

APIs may provide a mechanism for users to assign an alias ID to an +existing revision with a custom method "alias":

+
rpc AliasBookRevision(AliasBookRevisionRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*/revisions/*}:alias"
+    body: "*"
+  };
+}
+
+
message AliasBookRevisionRequest {
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/BookRevision"
+    }];
+
+  // The ID of the revision to alias to, e.g. `CURRENT` or a semantic
+  // version.
+  string alias_id = 2 [(google.api.field_behavior) = REQUIRED];
+}
+
+
    +
  • The request message must have a name field: +
  • +
  • The request message must have a alias_id field: +
  • +
  • If the user calls the method with an existing alias_id, the request must + succeed and the alias will be updated to refer to the provided revision. This + allows users to write code against a specific alias (e.g. published) and the + revision can change with no code change.
  • +
+

Rollback

+

A common use case for a resource with a revision history is the ability to roll +back to a given revision. APIs should handle this with a Rollback custom +method:

+
rpc RollbackBook(RollbackBookRequest) returns (BookRevision) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*/revisions/*}:rollback"
+    body: "*"
+  };
+}
+
+
    +
  • The method must use the POST HTTP verb.
  • +
  • The method should return a resource revision.
  • +
+
message RollbackBookRequest {
+  // The revision that the book should be rolled back to.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/BookRevision"
+    }];
+}
+
+
    +
  • The request message must have a name field, referring to the resource + revision whose configuration the resource should be rolled back to. +
  • +
+

Child resources

+

Resources with a revision history may have child resources. If they do, +there are two potential variants:

+
    +
  • Child resources where each child resource is a child of the parent resource + as a whole.
  • +
  • Child resources where each child resource is a child of a single revision + of the parent resource.
  • +
+

APIs should not include multiple levels of resources with revisions, as +this quickly becomes difficult to reason about.

+

Standard methods

+

Any standard methods must implement the corresponding AIPs (AIP-131, +AIP-132, AIP-133, AIP-134, AIP-135), with the following additional behaviors:

+
    +
  • List methods: By default, revisions in the list response must be ordered + in reverse chronological order. User can supply order_by to override the + default behavior.
  • +
  • If the revision supports aliasing, a delete method with the resource name + of the alias (e.g. revisions/1.0.2) must remove the alias instead of + deleting the resource.
  • +
+

As revisions are nested under the resource, also see cascading delete.

+

Rationale

+

Abstract revisions as nested collection

+

Revisions being resources under nested collection make revisions a first class +citizen.

+
    +
  • Revisions can offer standard get, list, and delete methods.
  • +
  • It retains the flexibility of extending new fields to revision in addition to + the resource message.
  • +
+

Tagging to Aliases

+

Previously, a concept of tag existed. This concept was redundant with that of +an alias, and the terms were consolidated to reduce complexity in the AIPs.

+

Output only resource configuration

+

Although it was an option to have the revision take in the resource +configuration as part of the create method, doing so would have allowed users to +submit resource configuration for a revision that the resource was never in.

+

OUTPUT_ONLY and requiring that a created revision represents the resource at +current point in time eliminates that issue.

+

History

+

Switching from a collection extension to a subcollection

+

In 2023-09, revisions are abstracted as a nested resource collection. Prior to +this, revisions are more like extension of an existing resource by using @ +symbol. List and delete revisions were custom methods on the resource +collection. A single Get method was used to retrieve either the resource +revision, or the resource.

+

Its primary advantage was allowing a resource reference to seamlessly refer to +a resource, or its revision.

+

It also had several disadvantages:

+
    +
  • List revisions is a custom method (:listRevisions) on the resource collection
  • +
  • Delete revision is a custom method on the resource collection
  • +
  • Not visible in API discovery doc
  • +
  • Resource ID cannot use @
  • +
+

The guidance was modified ultimately to enable revisions to behave like a +resource, which reduces the users cognitive load and allows resource-oriented +clients to easily list, get, create, and update revisions.

+

Using resource ID instead of tag

+

In the previous design, revisions had a separate identifer for a revision known +as a tag, that would live in a revision.

+

Tags were effectively a shadow resource ID, requiring methods to create, get and +filter revisions based on the value of the tag.

+

By consolidating the concept of a tag into the revision ID, the user no longer +needs to be familiar with a second set of retrieval and identifier methods.

+

Changelog

+
    +
  • 2023-09-01: AIP was updated to be a sub-collection.
  • +
  • 2021-04-27: Added guidance on returning the resource from Delete Revision.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/163.html b/163.html new file mode 100644 index 0000000000..779a1494e4 --- /dev/null +++ b/163.html @@ -0,0 +1,746 @@ + + + + AIP-163: Change validation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-163

+

Change validation

+

Occasionally, a user wants to validate an intended change to see what the +result will be before actually making the change. For example, a request to +provision new servers in a fleet will have an impact on the overall fleet size +and cost, and could potentially have unexpected downstream effects.

+

Guidance

+

APIs may provide an option to validate, but not actually execute, a +request, and provide the same response (status code, headers, and response +body) that it would have provided if the request was actually executed.

+

To provide this option, the method should include a bool validate_only +field in the request message:

+
message ReviewBookRequest {
+  string name = 1 [(google.api.resource_reference) = {
+    type: "library.googleapis.com/Book"
+  }];
+  int32 rating = 2;
+  string comment = 3;
+
+  // If set, validate the request and preview the review, but do not actually
+  // post it.
+  bool validate_only = 4;
+}
+
+

The API must perform permission checks and any other validation that would +be performed on a "live" request; a request using validate_only must fail +if it determines that the actual request would fail.

+

Note: It may occasionally be infeasible to provide the full output. For +example, if creating a resource would create an auto-generated ID, it does not +make sense to do this on validation. APIs should omit such fields on +validation requests in this situation.

+

Declarative-friendly resources

+

A resource that is declarative-friendly (AIP-128) must include a +validate_only field on methods that mutate the resource.

+

Changelog

+
    +
  • 2020-10-06: Added declarative-friendly resource requirement.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/164.html b/164.html new file mode 100644 index 0000000000..9dc92cb4db --- /dev/null +++ b/164.html @@ -0,0 +1,904 @@ + + + + AIP-164: Soft delete + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-164

+

Soft delete

+

There are several reasons why a client could desire soft delete and undelete +functionality, but one over-arching reason stands out: recovery from mistakes. +A service that supports undelete makes it possible for users to recover +resources that were deleted by accident.

+

Guidance

+

APIs may support the ability to "undelete", to allow for situations where +users mistakenly delete resources and need the ability to recover.

+

If a resource needs to support undelete, the Delete method must simply +mark the resource as having been deleted, but not completely remove it from the +system. If the method behaves this way, it should return the updated +resource instead of google.protobuf.Empty.

+

Resources that support soft delete should have both a delete_time and +purge_time field as described in AIP-148. Additionally, resources should +include a DELETED state value if the resource includes a state field +(AIP-216).

+

Undelete

+

A resource that supports soft delete should provide an Undelete method:

+
rpc UndeleteBook(UndeleteBookRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*}:undelete"
+    body: "*"
+  };
+}
+
+
    +
  • The HTTP verb must be POST.
  • +
  • The body clause must be "*".
  • +
  • The response message must be the resource itself. There is no + UndeleteBookResponse.
      +
    • The response should include the fully-populated resource unless it is + infeasible to do so.
    • +
    • If the undelete RPC is long-running, the response + message must be a google.longrunning.Operation which resolves to the + resource itself.
    • +
    +
  • +
+

Undelete request message

+

Undelete methods implement a common request message pattern:

+
message UndeleteBookRequest {
+  // The name of the deleted book.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference).type = "library.googleapis.com/Book"];
+}
+
+
    +
  • A name field must be included. It should be called name.
      +
    • The field should be annotated as required.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
+

Long-running undelete

+

Some resources take longer to undelete a resource than is reasonable for a +regular API request. In this situation, the API should use a long-running +operation (AIP-151) instead:

+
rpc UndeleteBook(UndeleteBookRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*}:undelete"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "Book"
+    metadata_type: "OperationMetadata"
+  };
+}
+
+
    +
  • The response type must be set to the resource (what the return type would + be if the RPC was not long-running).
  • +
  • Both the response_type and metadata_type fields must be specified.
  • +
+

Expunge

+

Resources that support soft delete may provide an Expunge custom method to +allow users to trigger immediate permanent deletion of a resource. This method can +operate on resources that are currently in a CREATING, READY or SOFT_DELETED +state (e.g., delete_time is set).

+
// Permanently deletes a soft-deleted Book.
+rpc ExpungeBook(ExpungeBookRequest) returns (google.protobuf.Empty) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*}:expunge"
+    body: "*"
+  };
+  option (google.api.method_signature) = "name";
+}
+
+
    +
  • The URI must use a custom method with the :expunge suffix.
  • +
  • The HTTP verb must be POST and the body clause must be "*".
  • +
  • The response message must be google.protobuf.Empty or a google.longrunning.Operation.
  • +
+

Long-running expunge

+

If the expunge process takes significant time, the method may be a +google.longrunning.Operation (AIP-151) instead:

+
// Permanently deletes a soft-deleted Book.
+rpc ExpungeBook(ExpungeBookRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*}:expunge"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "google.protobuf.Empty"
+    metadata_type: "OperationMetadata"
+  };
+  option (google.api.method_signature) = "name";
+}
+
+

Expunge request message

+

Expunge methods implement a common request message pattern:

+
message ExpungeBookRequest {
+  // The name of the soft-deleted book to expunge.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference).type = "library.googleapis.com/Book"
+  ];
+}
+
+
    +
  • The request message must refer to the resource to be expunged by name.
  • +
  • There should not be any other request fields.
  • +
+

List and Get

+

Soft-deleted resources should not be returned in List (AIP-132) responses +by default (unless bool show_deleted is true). Get (AIP-131) requests for +soft-deleted resources should return the resource (rather than a +NOT_FOUND error).

+

APIs that soft delete resources may choose a reasonable strategy for +purging those resources, including automatic purging after a reasonable time +(such as 30 days), allowing users to set an expiry time (AIP-214), or retaining +the resources indefinitely. Regardless of what strategy is selected, the API +should document when soft deleted resources will be completely removed.

+

Declarative-friendly resources

+

Soft-deletable resources have a poorer experience than hard-deleted resources in +declarative clients: since an ID on a soft-deleted resource is not re-usable +unless a custom method (undelete) is called, an imperative client must be +introduced or hand-written code is required to incorporate the usage of the +custom method.

+

Errors

+

If the user does not have permission to access the resource, regardless of +whether or not it exists, the service must error with PERMISSION_DENIED +(HTTP 403). Permission must be checked prior to checking if the resource +exists.

+

If the user does have proper permission, but the requested resource does not +exist (either it was never created or already expunged), the service must +error with NOT_FOUND (HTTP 404).

+

If the user calling a soft Delete has proper permission, but the requested +resource is already deleted, the service must succeed if allow_missing is +true, and should error with NOT_FOUND (HTTP 404) if allow_missing is +false.

+

If the user calling Undelete has proper permission, but the requested +resource is not deleted, the service must respond with ALREADY_EXISTS +(HTTP 409).

+

If the user calling Expunge requests a resource that does not exist (was never +created or already expunged), the method must return NOT_FOUND (HTTP 404).

+

If the resource exists but is not in a ready or soft-deleted state, the method +must return FAILED_PRECONDITION (HTTP 400).

+

Standard permission errors (PERMISSION_DENIED) apply. Services must require +an explicit expunge permission that is separate from standard delete permissions +(e.g., <service>.<resource>.expunge).

+

Further reading

+
    +
  • For the Delete standard method, see AIP-135.
  • +
  • For long-running operations, see AIP-151.
  • +
  • For resource freshness validation (etag), see AIP-154.
  • +
  • For change validation (validate_only), see AIP-163.
  • +
+

Changelog

+
    +
  • 2026-04-28: Added guidance for the Expunge custom method.
  • +
  • 2024-09-24: Included missing requirement for delete_time.
  • +
  • 2023-07-13: Renamed overloaded expire_time to purge_time.
  • +
  • 2021-07-12: Added error behavior when soft deleting a deleted resource.
  • +
  • 2021-07-12: Clarified that ALREADY_EXISTS errors apply to Undelete.
  • +
  • 2021-07-12: Changed the expire_time field to "should" for consistency + with AIP-148.
  • +
  • 2020-09-23: Soft delete material in AIP-135 migrated to this AIP.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/165.html b/165.html new file mode 100644 index 0000000000..0b1f10b930 --- /dev/null +++ b/165.html @@ -0,0 +1,832 @@ + + + + AIP-165: Criteria-based delete + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-165

+

Criteria-based delete

+

Occasionally, an API may need to provide a mechanism to delete a large number +of resources based on some set of filter parameters, rather than requiring the +individual resource name of the resources to be deleted.

+

This is a rare case, reserved for situations where users need to delete +thousands or more resources at once, in which case the normal Batch Delete +pattern (AIP-235) becomes unwieldy and inconvenient.

+

Guidance

+

Important: Most APIs should use only Delete (AIP-135) or Batch +Delete (AIP-235) for deleting resources, and should not implement +deleting based on criteria. This is because deleting is generally irreversible +and this type of operation makes it easy for a user to accidentally lose +significant amounts of data.

+

An API may implement a Purge method to permit deleting a large number of +resources based on a filter string; however, this should only be done if +the Batch Delete (AIP-235) pattern is insufficient to accomplish the +desired goal:

+
rpc PurgeBooks(PurgeBooksRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:purge"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "PurgeBooksResponse"
+    metadata_type: "PurgeBooksMetadata"
+  };
+}
+
+
    +
  • The RPC's name must begin with the word Purge. The remainder of the + RPC name should be the plural form of the resource being purged.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response type must be a google.longrunning.Operation (see + AIP-151) that resolves to a message whose name matches the RPC name, with + a Response suffix.
  • +
  • The HTTP verb must be POST, and the body must be "*".
  • +
  • The URI path should represent the collection for the resource.
  • +
  • The parent field should be included in the URI. If the API wishes to + support deletion across multiple parents, it should accept the - + character consistent with AIP-159.
  • +
+

Request message

+

Purge methods implement a common request message pattern:

+
message PurgeBooksRequest {
+  // The publisher to purge books from.
+  // To purge books across publishers, send "publishers/-".
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // A filter matching the books to be purged.
+  string filter = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // Actually perform the purge.
+  // If `force` is set to false, the method will return a sample of
+  // resource names that would be deleted.
+  bool force = 3;
+}
+
+
    +
  • A singular string parent field should be included, unless the resource + is top-level. +
  • +
  • A singular string filter field must be included and must follow the + same semantics as in List methods (AIP-160).
      +
    • It should be annotated as required.
    • +
    • A wildcard value of "*" may be supported for deleting everything.
    • +
    +
  • +
  • A singular bool force field must be included. If it is not set, the API + must return a count of the resources that would be deleted as well as a + sample of those resources, without actually performing the deletion.
  • +
+

Response message

+

Purge methods implement a common response message pattern:

+
message PurgeBooksResponse {
+  // The number of books that this request deleted (or, if `force` is false,
+  // the number of books that will be deleted).
+  int32 purge_count = 1;
+
+  // A sample of the resource names of books that will be deleted.
+  // Only populated if `force` is set to false.
+  repeated string purge_sample = 2 [(google.api.resource_reference) = {
+    type: "library.googleapis.com/Book"
+  }];
+}
+
+
    +
  • A singular int32 purge_count field should be included, and provide the + number of resources that were deleted (or would be deleted). This count + may be an estimate similar to total_size in AIP-158 (but the service + should document this if so).
  • +
  • A repeated string purge_sample field should be included: If force is + false, it should provide a sample of resource names that will be + deleted. If force is true, this field should not be populated.
      +
    • The sample should be a sufficient size to catch clearly obvious + mistakes: A good rule of thumb is 100. The API should document the + size, and should document that it is a maximum (it is possible to send + fewer).
    • +
    • The sample may be random or may be deterministic (such as the first + matched resource names). The API should document which approach is + used.
    • +
    • The field should identify the resource type that it + references.
    • +
    +
  • +
+

Note: Even if purge_count and purge_sample are not included, the +force field must still be included in the request.

+

Changelog

+
    +
  • 2025-07-23: Explicitly state filter wildcard may be supported.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-10-29: Expanded guidance on HTTP, field behavior, and resource + reference annotations.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/180.html b/180.html new file mode 100644 index 0000000000..725588dfa3 --- /dev/null +++ b/180.html @@ -0,0 +1,965 @@ + + + + AIP-180: Backwards compatibility + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-180

+

Backwards compatibility

+

APIs are fundamentally contracts with users, and users often write code against +APIs that is then launched into a production service with the expectation that +it continues to work (unless the API has a stability level that +indicates otherwise). Therefore, it is important to understand what constitutes +a backwards compatible change and what constitutes a backwards incompatible +change.

+

Guidance

+

Existing client code must not be broken by a service updating to a new +minor or patch release. Old clients must be able to work against newer +servers (with the same major version number).

+

Important: It is not always clear whether a change is compatible or not. +The guidance here should be treated as indicative, rather than as a +comprehensive list of every possible change.

+

There are three distinct types of compatibility to consider:

+
    +
  1. Source compatibility: Code written against a previous version must + compile against a newer version, and successfully run with a newer version + of the client library.
  2. +
  3. Wire compatibility: Code written against a previous version must be able + to communicate correctly with a newer server. In other words, not only are + inputs and outputs compatible, but the serialization and deserialization + expectations continue to match.
  4. +
  5. Semantic compatibility: Code written against a previous version must + continue to receive what most reasonable developers would expect. (This can + be tricky in practice, however, and sometimes determining what users will + expect can involve a judgment call.)
  6. +
+

Note: In general, the specific guidance here assumes use of protocol +buffers and JSON as transport formats. Other transport formats may have +slightly different rules.

+

Note: This guidance assumes that APIs are intended to be called from a +range of consumers, written in multiple languages and with no control over +how and when consumers update. Any API which has a more limited scope (for +example, an API which is only called by client code written by the same team +as the API producer, or deployed in a way which can enforce updates) should +carefully consider its own compatibility requirements.

+

Adding components

+

In general, new components (interfaces, methods, messages, fields, enums, or +enum values) may be added to existing APIs in the same major version.

+

However, keep the following guidelines in mind when doing this:

+
    +
  • Code written against the previous surface (and thus is unaware of the new + components) must continue to be treated the same way as before.
      +
    • New required fields must not be added to existing request messages or + resources.
    • +
    • Any field being populated by clients must have a default behavior + matching the behavior before the field was introduced.
        +
      • This can be tricky to do in some cases. For example, adding pagination + after the fact where previously all items were returned (i.e. page_size + is infinite, which is not advised). If the default for the new page_size + field is less than what was previously returned, older clients will + incorrectly assume all results were returned.
      • +
      +
    • +
    • Any field previously populated by the server must continue to be + populated, even if it introduces redundancy.
    • +
    +
  • +
  • For enum values specifically, be aware that it is possible that user code + does not handle new values gracefully.
      +
    • Enum values may be freely added to enums which are only used in request + messages.
    • +
    • Enums that are used in response messages or resources and which are + expected to receive new values should document this. Enum values still + may be added in this situation; however, appropriate caution should + be used.
    • +
    +
  • +
+

Note: It is possible when adding a component closely related to an existing +component (for example, string foo_value when string foo already exists) to +enter a situation where generated code will conflict. Service owners should +be aware of subtleties in the tooling they or their users are likely to use +(and tool authors should endeavor to avoid such subtleties if possible).

+

Removing or renaming components

+

Existing components (interfaces, methods, messages, fields, enums, or enum +values) must not be removed from existing APIs in the same major version. +Removing a component is a backwards incompatible change.

+

Important: Renaming a component is semantically equivalent to "remove and +add". In cases where these sorts of changes are desirable, a service may +add the new component, but must not remove the existing one. In situations +where this can allow users to specify conflicting values for the same semantic +idea, the behavior must be clearly specified.

+

Moving components between files

+

Existing components must not be moved between files.

+

Moving a component from one proto file to another within the same package is +wire compatible, however, the code generated for languages like C++ or Python +will result in breaking change since import and #include will no longer +point to the correct code location.

+

Moving into oneofs

+

Existing fields must not be moved into or out of a oneof. This is a +backwards-incompatible change in the Go protobuf stubs.

+

Changing the type of fields

+

Existing fields and messages must not have their type changed, even if the +new type is wire-compatible, because type changes alter generated code in a +breaking way.

+

Changing string length

+

APIs should avoid increasing the upper bound for the size or limit (if +accepted as input) of string fields. APIs should treat expected size upper +bound increases as incompatible changes (see Changing resource +names as an example). APIs may pad out values with +filler characters if reserving a consistent size is necessary, but this must +be documented if done.

+

Changing resource names

+

A resource must not change its name.

+

Unlike most breaking changes, this affects major versions as well: in order for +a client to expect to use v2.0 access a resource that was created in v1.0 or +vice versa, the same resource name must be used in both versions.

+

More subtly, the set of valid resource names should not change either, for +the following reasons:

+
    +
  • If resource name formats become more restrictive, a request that would + previously have succeeded will now fail.
  • +
  • If resource name formats become less restrictive than previously documented, + then code making assumptions based on the previous documentation could break. + Users are very likely to store resource names elsewhere, in ways that may be + sensitive to the set of permitted characters and the length of the name. + Alternatively, users might perform their own resource name validation to + follow the documentation.
      +
    • For example, Amazon gave customers a lot of warning and had a + migration period when they started allowing longer EC2 resource IDs.
    • +
    +
  • +
+

Semantic changes

+

Code will often depend on API behavior and semantics, even when such behavior +is not explicitly supported or documented. Therefore, APIs must not change +visible behavior or semantics in ways that are likely to break reasonable user +code, as such changes will be seen as breaking by those users.

+

Note: This does involve some level of judgment; it is not always clear +whether a proposed change is likely to break users, and an expansive reading of +this guidance could ostensibly prevent any change (which is not the intent).

+

Changing value format or construction

+

APIs must not change the expected format or algorithm used to construct the +value of an existing field - even if the field is OUTPUT_ONLY and populated by +the API service - within an API version. Doing so requires a new API version.

+

For example, changing the format of a field ip_address conforming to IPv4 +format to instead contain IPv6 values is a breaking change.

+

Default values must not change

+

Default values are the values set by servers for resources when they are not +specified by the client. This section only applies to static default values within +fields on resources and does not apply to dynamic defaults such as the default IP +address of a resource.

+

Changing the default value is considered breaking and must not be done. The +default behavior for a resource is determined by its default values, and this +must not change across minor versions.

+

For example:

+
message Book {
+    // google.api.resource and other annotations and fields
+
+    // The genre of the book
+    // If this is not set when the book is created, the field will be given a value of FICTION.
+    enum Genre {
+      UNSPECIFIED = 0;
+      FICTION = 1;
+      NONFICTION = 2;
+    }
+}
+
+

Changing to:

+
message Book {
+    // google.api.resource and other annotations and fields
+
+    // The genre of the book
+    // If this is not set when the book is created, the field will be given a value of NONFICTION.
+    enum Genre {
+      UNSPECIFIED = 0;
+      FICTION = 1;
+      NONFICTION = 2;
+    }
+}
+
+

would constitute a breaking change.

+

Serializing defaults

+

APIs must not change the way a field with a default value is serialized. For +example if a field does not appear in the response if the value is equal to the +default, the serialization must not change to include the field with the +default. Clients may depend on the presence or absence of a field in a resource +as semantically meaningful, so a change to how serialization is done for absent +values must not occur in a minor version.

+

Consider the following proto, where the default value of wheels is 2:

+
// A representation of an automobile
+message Automobile {
+    // google.api.resource and other annotations and fields
+
+    // The number of wheels on the automobile.
+    // The default value is 2, when no value is sent by the client.
+    int wheels = 2;
+}
+
+

First the proto serializes to JSON when the value of wheels is 2 as follows:

+
{
+    "name": "my-car"
+}
+
+

Then, the API service changes the serialization to include wheel even if the +value is equal to the default value, 2 as follows:

+
{
+    "name": "my-car",
+    "wheels": 2
+}
+
+

This constitutes a change that is not backwards compatible within a major +version.

+

Further reading

+
    +
  • For compatibility around field behavior, see AIP-203.
  • +
  • For compatibility around pagination, see AIP-158.
  • +
  • For compatibility around long-running operations, see AIP-151.
  • +
  • For understanding stability levels and expectations, see AIP-181.
  • +
  • For compatibility with client library resource name parsing, see AIP-4231
  • +
  • For compatibility with client library method signatures, see AIP-4232
  • +
  • For compatibility around field presence changes, see AIP-149.
  • +
  • For compatibility around resource types, see AIP-123.
  • +
+

Rationale

+

Risk of string length changes

+

End users may store resource properties, like the name, in a dedicated +database column with a limited length. If the service starts returning values +for the name that are twice the originally documented/observed length, this +may unexpectedly break the customer's database. Furthermore, string properties +that appear in URLs (including query parameters) are especially likely to have +client-side limits, making them more sensitive to length changes.

+

Risk of changing value format or construction

+

Customers often depend on the format or algorithmic construction of a field for +client-side parsing, hashing, or database table construction. Changing it in +an existing field could break that client-side consumption.

+

Changelog

+
    +
  • 2025-10-21: Added guidance for string length changes, changing formats, + and an example for carefully adding components.
  • +
  • 2024-08-07: Added reference to resource type compatibility.
  • +
  • 2024-06-05: Added reference to field presence compatibility.
  • +
  • 2023-07-26: Added reference to field behavior compatibility.
  • +
  • 2023-07-26: Added note on APIs which have limited clients.
  • +
  • 2022-08-11: Added "Moving components between files" section.
  • +
  • 2022-06-01: Added more links to other AIPs with compatibility concerns
  • +
  • 2019-12-16: Clarified that moving existing fields into oneofs is + breaking.
  • +
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/181.html b/181.html new file mode 100644 index 0000000000..983982272e --- /dev/null +++ b/181.html @@ -0,0 +1,772 @@ + + + + AIP-181: Stability levels + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-181

+

Stability levels

+

While different organizations (both inside Google and outside) have different +product life cycles, AIPs refer to the stability of an API component using +the following terms.

+

Note: These stability levels roughly correspond to the product launch +stages (alpha, beta, GA) in Google Cloud, but are not identical. GCP imposes +its own additional expectations and commitments on top of what is outlined +here.

+

Alpha

+

An alpha component undergoes rapid iteration with a known set of users who +must be tolerant of change. The number of users should be a +curated, manageable set, such that it is feasible to communicate with all +of them individually.

+

Breaking changes must be both allowed and expected in alpha components, and +users must have no expectation of stability.

+

Beta

+

A beta component must be considered complete and ready to be declared +stable, subject to public testing. Beta components should be exposed to an +unknown and potentially large set of users. In other words, beta components +should not be behind an allowlist; instead, they should be available to +the public.

+

Because users of beta components tend to have a lower tolerance of change, beta +components should be as stable as possible; however, the beta component +must be permitted to change over time. These changes should be minimal +but may include backwards-incompatible changes to beta components. +Backwards-incompatible changes must be made only after a reasonable +deprecation period to provide users with an opportunity to migrate their code. +This deprecation period must be defined at the time of being marked beta.

+

Beta components should be time-boxed and promoted to stable if no issues +are found in the specified timeframe, which should be specified at the time +of being marked beta. A reasonable time period may vary, but a good rule of +thumb is 90 days.

+

Stable

+

A stable component must be fully-supported over the lifetime of the major +API version. Because users expect such stability from components marked stable, +there must be no breaking changes to these components, subject to the +caveats described below.

+

Major versions

+

When breaking changes become necessary, the API producer should create the +next major version of the API, and start a deprecation clock on the existing +version.

+

Turn-down of any version containing stable components must have a formal +process defined at the time of being marked stable. This process must +specify a deprecation period for users which provides them with reasonable +advance warning.

+

Isolated changes

+

On very rare occasions, it could be preferable to make a small, isolated +breaking change, if this will only cause inconvenience to a small subset of +users. (Creating a new major version is an inconvenience to all users.) In this +case, the API producer may deprecate the component, but must continue +to support the component for the normal turndown period for a stable component.

+

Important: Making an in-place breaking change in a stable API is considered +an extreme course of action, and should be treated with equal or greater +gravity as creating a new major version. For example, at Google, this requires +the approval of the API Governance team.

+

Emergency changes

+

In certain exceptional cases, such as security concerns or regulatory +requirements, any API component may be changed in a breaking manner +regardless of its stability level, and a deprecation is not promised in these +situations.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/182.html b/182.html new file mode 100644 index 0000000000..3187e10015 --- /dev/null +++ b/182.html @@ -0,0 +1,756 @@ + + + + AIP-182: External software dependencies + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+

+ This AIP is currently under review. This means that the editors have read it + and are in high-level concurrence, and while it is not yet fully approved, we + have a good faith expectation that the AIP will be approved in something + close to its current state. +

+

AIP-182

+

External software dependencies

+

Some services have a particular type of dependency on external software: they +allow users to create resources that run on or expose the external software in +some way. For example:

+
    +
  • A database admin service can allow users to create databases running on a + particular version of a particular database engine (for example, PostgreSQL + 13.4).
  • +
  • A virtual machine service can allow users to create VMs running a particular + operating system (for example, Ubuntu 20.04).
  • +
  • An application or function platform service can allow users to write code + that runs against a particular version of a programming language (for + example, Node.js 16.6).
  • +
+

Services that provide external software to users in this way will eventually +need to address the fact that all of these types of software have release +lifecycles, and the versions they currently expose will eventually reach +end-of-life.

+

Guidance

+

Services that expose external software dependencies should allow users to +create resources using any currently-supported LTS (long-term support) version +of the supported software, and may allow users to create resources using +non-LTS versions.

+

Services should not indefinitely allow users to create new resources using +versions that have reached end-of-life, although they may have a transition +period between when the software version reaches end-of-life and when support +for creating new resources with that version is removed.

+

Note: Restricting or removing the ability to create resources using +end-of-life versions of software is not considered a breaking change for +the service for the purpose of AIP-181, even though it actually is one. +However, because the change can break existing users' workflows, services +must notify users who are using resources approaching end-of-life.

+

If possible, services should allow previously-created resources to remain, +and may warn users of the risks associated with continuing to use +end-of-life software. Services should not proactively remove resources +using end-of-life software, or impose other restrictions on existing resources, +unless critical security concerns require the service to do so.

+

Continued support

+

If supporting a version that has reached end-of-life is necessary for business +reasons (usually because the end-of-life software still has significant +adoption), the service may choose to officially support the end-of-life +version, but must take on the responsibility of patching and maintaining +the software if it does so.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/185.html b/185.html new file mode 100644 index 0000000000..7b3bb41a29 --- /dev/null +++ b/185.html @@ -0,0 +1,842 @@ + + + + AIP-185: API Versioning + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-185

+

API Versioning

+

This topic describes the versioning strategies used by Google APIs. In +general, these strategies apply to all Google-managed services.

+

Guidance

+

All Google API interfaces must provide a major version number, which is +encoded at the end of the protobuf package, and included as the first part of +the URI path for REST APIs. In the event an API needs to make an incompatible +change, consult AIP-180 and AIP-181 for necessary steps based on the +stability level of the surface in question.

+

Note: The use of the term "major version number" above is taken from +semantic versioning. However, unlike in traditional semantic versioning, +Google APIs must not expose minor or patch version numbers. For +example, Google APIs use v1, not v1.0, v1.1, or v1.4.2. From a user's +perspective, major versions are updated in place with minor/patch equivalent +changes, and users receive new functionality without migration.

+

A new major version of an API must not depend on a previous major version of +the same API. An API surface must not depend on other APIs, except for in +the cases outlined in AIP-213 and AIP-215.

+

Different versions of the same API must be able to work at the same time +within a single client application for a reasonable transition period. This time +period allows the client to transition smoothly to the newer version. An older +version must go through a reasonable, well-communicated deprecation period +before being shut down.

+

For releases which have alpha or beta stability, APIs must append +the stability level after the major version number in the protobuf package and +URI path using one of these strategies:

+
    +
  • Channel-based versioning (recommended)
  • +
  • Release-based versioning
  • +
  • Visibility-based versioning
  • +
+

Channel-based versioning

+

A stability channel is a long-lived release at a given stability level that +receives in-place updates. There is no more than one channel per stability level +for a major version. Under this strategy, there are up to three channels +available: alpha, beta, and stable.

+

The alpha and beta channel must have their stability level appended to the +version, but the stable channel must not have the stability level appended. +For example, v1 is an acceptable version for the stable channel, but v1beta +or v1alpha are not. Similarly, v1beta or v1alpha are acceptable versions +for the respective beta and alpha channel, but v1 is not acceptable for +either. Each of these channels receives new features and updates "in-place".

+

The beta channel's functionality must be a superset of the stable channel's +functionality, and the alpha channel's functionality must be a superset of +the beta channel's functionality.

+

Deprecating API functionality

+

API elements (fields, messages, RPCs) may be marked deprecated in any +channel to indicate that they should no longer be used:

+
// Represents a scroll. Books are preferred over scrolls.
+message Scroll {
+  option deprecated = true;
+
+  // ...
+}
+
+

Deprecated API functionality must not graduate from alpha to beta, nor beta +to stable. In other words, functionality must not arrive "pre-deprecated" +in any channel.

+

The beta channel's functionality may be removed after it has been deprecated +for a sufficient period; we recommend 180 days. For functionality that exists +only in the alpha channel, deprecation is optional, and functionality may be +removed without notice. If functionality is deprecated in an API's +alpha channel before removal, the API should apply the same annotation, and +may use any timeframe it wishes.

+

Release-based versioning

+

Important: This pattern is not commonly used for new services. There are +existing services that follow it, but Channel-based Versioning is the preferred +mechanism.

+

An individual release is an alpha or beta release that is expected to be +available for a limited time period before its functionality is incorporated +into the stable channel, after which the individual release will be shut down. +When using release-based versioning strategy, an API may have any number of +individual releases at each stability level.

+

Note: Both the channel-based and release-based strategies update the stable +version in-place. There is a single stable channel, rather than individual +stable releases, even when using the release-based strategy.

+

Alpha and beta releases must have their stability level appended to the +version, followed by an incrementing release number. For example, v1beta1 or +v1alpha5. APIs should document the chronological order of these versions +in their documentation (such as comments).

+

Each alpha or beta release may be updated in place with backwards-compatible +changes. For beta releases, backwards-incompatible updates should be made by +incrementing the release number and publishing a new release with the change. +For example, if the current version is v1beta1, then v1beta2 is released +next.

+

Alpha and beta releases should be shut down after their functionality +reaches the stable channel. An alpha release may be shut down at any time, +while a beta release should allow users a reasonable transition period; we +recommend 180 days.

+

Visibility-based versioning

+

API visibility is an advanced feature provided by Google API infrastructure. +It allows API producers to expose multiple external API views from one internal +API surface, and each view is associated with an API visibility label, such +as:

+
import "google/api/visibility.proto";
+
+message Resource {
+  string name = 1;
+
+  // Preview. Do not use this feature for production.
+  string display_name = 2
+    [(google.api.field_visibility).restriction = "PREVIEW"];
+}
+
+

A visibility label is a case-sensitive string that can be used to tag any API +element. By convention, visibility labels should always use UPPER case. +An implicit PUBLIC label is applied to all API elements unless an explicit +visibility label is applied as in the example above.

+

Each visibility label is an allow-list. API producers need to grant visibility +labels to API consumers for them to use API features associated with the labels. +In other words, an API visibility label is like an ACL'ed API version.

+

Multiple visibility labels may be applied to an element by using a +comma-separated string (e.g. "PREVIEW,TRUSTED_TESTER"). When multiple +visibility labels are used, then the client needs only one of the visibility +labels (logical OR).

+

By default, the visibility labels granted to the API consumer are used to verify +incoming requests. However, a client can send requests with an explicit +visibility label as follows:

+
GET /v1/projects/my-project/topics HTTP/1.1
+Host: pubsub.googleapis.com
+Authorization: Bearer y29....
+X-Goog-Visibilities: PREVIEW
+
+

A single API request can specify at most one visibility label.

+

API producers can use API visibility for API versioning, such as +INTERNAL and PREVIEW. A new API feature starts with the INTERNAL label, +then moves to the PREVIEW label. When the feature is stable and becomes +generally available, all API visibility labels are removed from the API +definition.

+

In general, API visibility is easier to implement than API versioning for +incremental changes, but it depends on sophisticated API infrastructure support. +Google Cloud APIs often use API visibility for Preview features.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/190.html b/190.html new file mode 100644 index 0000000000..8400dd08c4 --- /dev/null +++ b/190.html @@ -0,0 +1,857 @@ + + + + AIP-190: Naming conventions + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-190

+

Naming conventions

+

This topic describes the naming conventions used in Google APIs. In +general, these conventions apply to all Google-managed services.

+

Guidance

+

In order to provide consistent developer experience across many APIs and +over a long period of time, all names used by an API should be:

+
    +
  • straightforward
  • +
  • intuitive
  • +
  • consistent
  • +
+

This includes names of interfaces, resources, collections, methods, and +messages.

+

Since English is a second language for many developers, one goal of these +naming conventions is to make every API name understandable to the majority of +developers. It does this by encouraging the use of a simple, consistent, and +small vocabulary when naming methods and resources.

+
    +
  • Names used in APIs should be in correct American English. For + example, license (instead of licence), color (instead of colour).
  • +
  • Commonly accepted short forms or abbreviations of long words may + be used for brevity. For example, API is preferred over Application + Programming Interface.
  • +
  • Unless otherwise specified, definitions must use UpperCamelCase names, + as defined by + Google Java Style.
  • +
  • Use intuitive, familiar terminology where possible. For example, + when describing removing (and destroying) a resource, delete is + preferred over erase.
  • +
  • Use the same name or term for the same concept, including for + concepts shared across APIs.
  • +
  • Avoid name overloading. Use different names for different concepts.
  • +
  • Avoid overly general names that are ambiguous within the context of + the API and the larger ecosystem of Google APIs. They can lead to + misunderstanding of API concepts. Rather, choose specific names that + accurately describe the API concept. This is particularly important + for names that define first-order API elements, such as resources. + There is no definitive list of names to avoid, as every name must be + evaluated in the context of other names. Instance, info, and service + are examples of names that have been problematic in the past. Names + chosen should describe the API concept clearly (for example: + instance of what?) and distinguish it from other relevant concepts + (for example: does "alert" mean the rule, the signal, or the + notification?).
  • +
  • Carefully consider use of names that may conflict with keywords in + common programming languages. Such names may be used but will + likely trigger additional scrutiny during API review. Use them + judiciously and sparingly.
  • +
+

Interface names

+

To avoid confusion with Service Names such as +pubsub.googleapis.com, the term interface name refers to the name +used when defining a service in a .proto file:

+
// Library is the interface name.
+service Library {
+  rpc ListBooks(...) returns (...);
+  rpc ...
+}
+
+

You can think of the service name as a reference to the actual +implementation of a set of APIs, while the interface name refers to +the abstract definition of an API.

+

An interface name should use an intuitive noun such as Calendar or +BlobStore. The name should not conflict with any well-established +concepts in programming languages and their runtime libraries (for +example, File).

+

In the rare case where an interface name would conflict with another +name within the API, a suffix (for example Api or Service) +should be used to disambiguate.

+

Method names

+

A service may, in its IDL specification, define one or more API +methods that correspond to methods on collections and resources. The +method names should follow the naming convention of VerbNoun in +UpperCamelCase, where the noun is typically the resource type.

+

Standard methods, and their Batch variants, define their naming guidance in +the following documents:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodStandardBatch
GetAIP-131AIP-231
ListAIP-132N/A
CreateAIP-133AIP-233
UpdateAIP-134AIP-234
DeleteAIP-135AIP-235
+

All other methods are considered Custom Methods and adhere to AIP-136 naming +guidance.

+

Message names

+

Message names should be short and concise. Avoid unnecessary or redundant +words. Adjectives can often be omitted if there is no corresponding message +without the adjective. For example, the Shared in SharedProxySettings is +unnecessary if there are no unshared proxy settings.

+

Message names should not include prepositions (e.g. "With", "For"). +Generally, message names with prepositions are better represented with +optional fields on the message.

+

Request and response messages

+

For request and response message names, see AIP-136 for custom methods and the +appropriate AIP for +standard methods.

+

Further reading

+
    +
  • For proto and language package naming, see AIP-191.
  • +
  • For collection ID naming conventions, see + AIP-122.
  • +
  • For Enum names, see AIP-126.
  • +
  • For field names, see AIP-140.
  • +
  • For repeated field names, see AIP-140.
  • +
  • For fields representing times and durations, see AIP-142.
  • +
  • For fields representing dates and times of day, see + AIP-142.
  • +
  • For fields representing a quantity, see AIP-141.
  • +
  • For the canonical List method filter field, see + AIP-132.
  • +
  • For the canonical List response message, see + AIP-132.
  • +
  • For well known abbreviations, see AIP-140.
  • +
+ + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/191.html b/191.html new file mode 100644 index 0000000000..3e449fd432 --- /dev/null +++ b/191.html @@ -0,0 +1,859 @@ + + + + AIP-191: File and directory structure + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-191

+

File and directory structure

+

A consistent file and directory structure, while making minimal difference +technically, makes API surface definitions easier for users and reviewers to +read.

+

Guidance

+

Note: The following guidance applies to APIs defined in protocol buffers, +such as those used throughout Google. While the spirit of this guidance applies +to APIs defined using other specification languages or formats, some of the +particular recommendations might be irrelevant.

+

Syntax

+

APIs defined in protocol buffers must use proto3 syntax.

+

Single package

+

APIs defined in protocol buffers must define each individual API in a +single package, which must end in a version component. For example:

+
syntax = "proto3";
+
+package google.cloud.translation.v3;
+
+

Google APIs must reside in a directory that matches the protocol buffer +package directive. For example, the package above dictates that the directory +be google/cloud/translation/v3.

+

File names

+

It is often useful to divide API definitions into multiple files. File names +must use snake_case.

+

APIs should have an obvious "entry" file, generally named after the API +itself. An API with a small number of discrete services (Google Cloud Pub/Sub's +Publisher and Subscriber is a good example) may have a separate entry +file per service.

+

APIs with only one file should use a filename corresponding to the name of +the API.

+

API service definitions and associated RPC request and response message +definitions should be defined in the same file.

+

Bear in mind that the file names often become module names in client libraries, +and customers use them in import or use statements. Therefore, choosing a +descriptive and language keyword-free filename does matter. For example, a file +called import.proto may be problematic in Python.

+

Note: The version must not be used as a filename, because this creates +bizarre imports in client libraries. Filenames such as v3.proto or +v1beta1.proto are prohibited.

+

File layout

+

Individual files should place higher level and more important definitions +before lower level and less important definitions.

+

In a proto file, components should be in the following order, and each of +these should be separated by a blank line:

+
    +
  • Copyright and license notice (if applicable).
  • +
  • The proto syntax statement.
  • +
  • The proto package statement.
  • +
  • Any import statements, in alphabetical order.
  • +
  • Any file-level option statements.
  • +
  • Any service definitions.
      +
    • Methods should be grouped by the resource they impact, and standard + methods should precede custom methods.
    • +
    +
  • +
  • Resource message definitions. A parent resource must be defined before + its child resources.
  • +
  • The RPC request and response message definitions, in the same order of the + corresponding methods. Each request message must precede its + corresponding response message (if any).
  • +
  • Any remaining message definitions.
  • +
  • Any top-level enum definitions.
  • +
+

Packaging annotations

+

Protocol buffers ships with annotations to declare the package or namespace +(depending on the vocabulary of the target language) of the generated files. +For example, setting go_package or csharp_namespace will override the +inferred package name.

+

When defining APIs, the following rules apply:

+
    +
  • Java
      +
    • The java_package annotation must be set. The correct value is usually + the proto package with the appropriate TLD prefixed. Example: + com.google.example.v1.
    • +
    • The java_multiple_files annotation must be set to true.
    • +
    • The java_outer_classname annotation must be set, and should be + set to the name of the proto filename, in PascalCase, with Proto + appended. Example: LibraryProto.
    • +
    +
  • +
  • Other languages
      +
    • Package or namespace directives for other languages must be set either + in every file in the proto package, or none of them. If they are set, the + values must be identical in every file.
    • +
    • If any part of the protobuf package is a compound name (such as + accessapproval), C#, Ruby and PHP options must be specified in order + to take account of the word breaks using PascalCase (UpperCamelCase). + Example: +
      option csharp_namespace = "Google.Cloud.AccessApproval.V1";
      +option php_namespace = "Google\\Cloud\\AccessApproval\\V1";
      +option ruby_package = "Google::Cloud::AccessApproval::V1";
      +
    • +
    • The go_package value depends directly on how the Go code is managed i.e. + if the module name is based on the VCS provider or using a remote import + path, but often has a consistent structure.
        +
      • The module may differ based on product area e.g. + google.cloud.accessapproval.v1 would be in module + cloud.google.com/go/accessapproval.
      • +
      • The package import path should be derived from the proto package.
      • +
      • An API version in the proto package should be prefixed with api e.g. + the proto package segment v1 becomes apiv1.
      • +
      • The terminal import path segment should be based on the product name + found within the proto package and must be suffixed with pb e.g. + accessapproval becomes accessapprovalpb.
      • +
      • This value should be left to the team owning the generated code to + decide on.
      • +
      +
    • +
    +
  • +
+

All packaging annotations should be specified in alphabetical order of +name. Refer to the Protobuf documentation for more about +language package options.

+

Important: While languages other than Java have sensible defaults for APIs +which don't include compound names, be aware that adding this annotation +(with a value not equivalent to the default) constitutes a breaking change in +that language. When releasing protos, be sure that omissions are intentional.

+

Rationale

+

Java packaging options

+

Set the option, java_multiple_files, to true to get a cleaner file structure. +Doing so instructs protoc to create one output file per Protobuf type, which +allows for more fine-grained imports. The option, java_outer_classname, is +required in combination with java_multiple_files. It instructs protoc to +wrap each compiled Protobuf type in a Java class whose name is the value of the +option. This prevents potential naming collisions between generated types.

+

Go packaging option

+

The Go packaging option needs to be decided by the team that owns the generated +code, because it is directly tied to the source code management practices of the +team. Allowing every proto package to decide on their own Go package creates +inconsistencies and friction in management of the code. Within that owning team, +having a consistent structure in the Go package naming is critical to a +consistent end user experience.

+

Changelog

+
    +
  • 2024-06-13: Added guidance for Go packaging annotation.
  • +
  • 2024-06-05: Added rationale for Java packaging options.
  • +
  • 2023-02-24: Added guidance on protobuf syntax.
  • +
  • 2022-10-18: Added guidance on Ruby/PHP/C# options.
  • +
  • 2019-11-18: Added guidance on the packaging annotations.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/192.html b/192.html new file mode 100644 index 0000000000..d66b2a36aa --- /dev/null +++ b/192.html @@ -0,0 +1,847 @@ + + + + AIP-192: Documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-192

+

Documentation

+

Documentation is one of the most critical aspects of API design. Users of your +API are unable to dig into the implementation to understand the API better; +often, the API surface definition and its corresponding documentation will be +the only things a user has. Therefore, it is important that documentation be as +clear, complete, and unambiguous as possible.

+

Guidance

+

In APIs defined in protocol buffers, public comments must be included over +every component (service, method, message, field, enum, and enum value) using +the protocol buffers comment format. This is important even in cases where the +comment is terse and uninteresting, as numerous tools read these comments and +use them.

+

Services, in particular, should have descriptive comments that explain what +the service is and what users are able to do with it.

+

Note: Many readers will not be native English speakers. Comments should +avoid jargon, slang, complex metaphors, pop culture references, or anything +else that will not easily translate. Additionally, many readers will have +different backgrounds and viewpoints; if writing examples involving people, +comments should use people who are non-controversial and no longer alive.

+

Style

+

Comments should be in grammatically correct American English. However, the +first sentence of each comment should omit the subject and be in the +third-person present tense:

+
// Creates a book under the given publisher.
+rpc CreateBook(CreateBookRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books"
+    body: "book"
+  };
+}
+
+

Descriptions

+

Descriptions of messages and fields should be brief but complete. Sometimes +comments are necessarily perfunctory because there is little to be said; +however, before jumping to that conclusion, consider whether some of the +following questions are relevant:

+
    +
  • What is it?
  • +
  • How do you use it?
  • +
  • What does it do if it succeeds? What does it do if it fails?
  • +
  • Is it idempotent?
  • +
  • What are the units? (Examples: meters, degrees, pixels)
  • +
  • What are the side effects?
  • +
  • What are common errors that may break it?
      +
    • What is the expected input format?
    • +
    • What range of values does it accept? (Examples: [0.0, 1.0), [1, 10])
        +
      • Is the range inclusive or exclusive?
      • +
      +
    • +
    • For strings, what is the minimum and maximum length, and what characters + are allowed?
        +
      • If a value is above the maximum length, do you truncate or send an error?
      • +
      +
    • +
    +
  • +
  • Is it always present? (Example: "Container for voting information. Present + only when voting information is recorded.")
  • +
  • Does it have a default setting? (Example: "If page_size is omitted, the + default is 50.")
  • +
+

Formatting

+

Any formatting in comments must be in CommonMark. Headings and tables +must not be used, as these cause problems for several tools, and are +unsuitable for client library reference documentation.

+

Comments should use code font for field or method names and for literals +(such as true).

+

Raw HTML must not be used.

+

"ASCII art" attempts to present a diagram within the protos must not be +used. The Markdown within the protos is consumed by a large number of renderers, +and any ASCII art is very unlikely to be well-presented by all of them. If +a diagram is useful in order to understand the API, include a link to a +documentation page containing the diagram as an image.

+

Cross-references

+

A comment can "link" to another component (service, method, message, field, +enum, or enum value) as a Markdown reference link. The reference must be one +of the following forms:

+
    +
  • The fully-qualified name of the element e.g. [Book][google.example.v1.Book]
  • +
  • A scope-relative reference qualified e.g. [Sci-Fi genre][Genre.GENRE_SCI_FI]
  • +
  • An implied reference e.g. [Book][] which equates to [Book][Book]
  • +
+

These references are resolved as per name resolution rules.

+

Containing fields names must not be used in references. They will not +resolve. The original definition must be referenced instead. For example, +[author][Book.author.family_name] where author is a field of Book, will +not resolve, but [author][Author.family_name] will.

+ +

Comments may link to external pages to provide background information +beyond what is described in the public comments themselves. External links +must use absolute (rather than relative) URLs, including the protocol +(usually https), and should not assume the documentation is located on +any particular host. For example: +[Spanner Documentation](https://cloud.google.com/spanner/docs)

+

Trademarked names

+

When referring to the proper, trademarked names of companies or products in +comments, acronyms should not be used, unless the acronym is such dominant +colloquial use that avoiding it would obscure the reference (example: IBM).

+

Comments should spell and capitalize trademarked names consistent with the +trademark owner's current branding.

+

Deprecations

+

To deprecate a component (service, method, message, field, enum, or enum value), +the deprecated option +must be set to true, and the first line of the respective comment +must start with "Deprecated: " and provide alternative solutions for +developers. If there is no alternative solution, a deprecation reason must +be given.

+

Internal comments

+ + +

Comments may be explicitly marked as internal by wrapping internal content +in (-- and --).

+

Non-public links, internal implementation notes (such as TODO and FIXME +directives), and other such material must be marked as internal.

+

Note: Comments should use only leading comments (not trailing comments +or detached comments). In particular, comments must not use both a leading +and trailing comment to describe any component, because this is a common source +of inadvertent omissions of the internal content annotation.

+

Changelog

+
    +
  • 2024-10-29: Include cross-reference resolution rules.
  • +
  • 2023-08-11: Expand deprecated comment requirement to all components.
  • +
  • 2021-04-20: Added guidance for deprecated services and RPCs.
  • +
  • 2020-04-01: Added guidance requiring absolute URLs for external links.
  • +
  • 2020-02-14: Added guidance around the use of trademarked names.
  • +
  • 2019-09-23: Added guidance about not using both leading and trailing + comments.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/193.html b/193.html new file mode 100644 index 0000000000..0b03da8e2b --- /dev/null +++ b/193.html @@ -0,0 +1,1088 @@ + + + + AIP-193: Errors + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-193

+

Errors

+

Effective error communication is an important part of designing simple +and intuitive APIs. Services returning standardized error responses +enable API clients to construct centralized common error handling logic. +This common logic simplifies API client applications and eliminates the +need for cumbersome custom error handling code.

+

Guidance

+

Services must return a google.rpc.Status message when an +API error occurs, and must use the canonical error codes defined in +google.rpc.Code. More information about the particular codes +is available in the gRPC status code documentation.

+

Error messages should help a reasonably technical user understand +and resolve the issue, and should not assume that the user is an +expert in your particular API. Additionally, error messages must not +assume that the user will know anything about its underlying +implementation.

+

Error messages should be brief but actionable. Any extra information +should be provided in the details field. If even more information +is necessary, you should provide a link where a reader can get more +information or ask questions to help resolve the issue. It is also +important to set the right tone when writing messages.

+

The following sections describe the fields of google.rpc.Status.

+

Status.message

+

The message field is a developer-facing, human-readable "debug message" +which should be in English. (Localized messages are expressed using +a LocalizedMessage within the details field. See +LocalizedMessage for more details.) Any dynamic aspects of +the message must be included as metadata within the ErrorInfo that appears +in details.

+

The message is considered a problem description. It is intended for +developers to understand the problem and is more detailed than +ErrorInfo.reason, discussed later.

+

Messages should use simple descriptive language that is easy to understand +(without technical jargon) to clearly state the problem that results in an +error, and offer an actionable resolution to it.

+

For pre-existing (brownfield) APIs which have previously returned errors +without machine-readable identifiers, the value of message must +remain the same for any given error. For more information, see +Changing Error Messages.

+

Status.code

+

The code field is the status code, which must be the numeric value of +one of the elements of the google.rpc.Code enum.

+

For example, the value 5 is the numeric value of the NOT_FOUND +enum element.

+

Status.details

+

The details field allows messages with additional error information to +be included in the error response, each packed in a google.protobuf.Any +message.

+

Google defines a set of standard detail payloads for error +details, which cover most common needs for API errors. +Services should use these standard detail payloads when feasible.

+

Each type of detail payload must be included at most once. For +example, there must not be more than one BadRequest +message in the details, but there may be a BadRequest and a +PreconditionFailure.

+

All error responses must include an ErrorInfo within details. This +provides machine-readable identifiers so that users can write code against +specific aspects of the error.

+

The following sections describe the most common standard detail payloads.

+

ErrorInfo

+

The ErrorInfo message is the primary way to send a +machine-readable identifier. Contextual information should be +included in metadata in ErrorInfo and must be included if it +appears within an error message.

+

The reason field is a short snake_case description of the cause of the +error. Error reasons are unique within a particular domain of errors. +The reason must be at most 63 characters and match a regular expression of +[A-Z][A-Z0-9_]+[A-Z0-9]. (This is UPPER_SNAKE_CASE, without leading +or trailing underscores, and without leading digits.)

+

The reason should be terse, but meaningful enough for a human reader to +understand what the reason refers to.

+

Good examples:

+
    +
  • CPU_AVAILABILITY
  • +
  • NO_STOCK
  • +
  • CHECKED_OUT
  • +
  • AVAILABILITY_ERROR
  • +
+

Bad examples:

+
    +
  • THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE (overly verbose)
  • +
  • ERROR (too general)
  • +
+

The domain field is the logical grouping to which the reason belongs. +The domain must be a globally unique value, and is typically the name of the service +that generated the error, e.g. pubsub.googleapis.com.

+

The (reason, domain) pair form a machine-readable way of identifying a particular error. +Services must use the same (reason, domain) pair for the same error, and +must not use the same (reason, domain) pair for logically different errors. +The decision about whether two errors are "the same" or not is not always clear, but +should generally be considered in terms of the expected action a client might take +to resolve them.

+

The metadata field is a map of key/value pairs providing additional +dynamic information as context. Each key within metadata must be at most +64 characters long, and conform to the regular expression [a-z][a-zA-Z0-9-_]+.

+

Any request-specific information which contributes to the Status.message or +LocalizedMessage.message messages must be represented within metadata. +This practice is critical so that machine actors do not need to parse error +messages to extract information.

+

For example consider the following message:

+
+

An <e2-medium> VM instance with <local-ssd=3,nvidia-t4=2> is currently unavailable +in the <us-east1-a> zone. Consider trying your request in the <us-central1-f,us-central1-c> +zone(s), which currently has/have capacity to accommodate your request. Alternatively, +you can try your request again with a different VM hardware configuration +or at a later time. For more information, see the troubleshooting documentation.

+
+

The ErrorInfo.metadata map for the same error could be:

+
    +
  • "zone": "us-east1-a"
  • +
  • "vmType": "e2-medium"
  • +
  • "attachment": "local-ssd=3,nvidia-t4=2"
  • +
  • "zonesWithCapacity": "us-central1-f,us-central1-c"
  • +
+

Additional contextual information that does not appear in an error message +may also be included in metadata to allow programmatic use by the client.

+

The metadata included for any given (reason,domain) pair can evolve over time:

+
    +
  • New keys may be included
  • +
  • All keys that have been included must continue to be included (but may have empty values)
  • +
+

In other words, once a user has observed a given key for a (reason, domain) pair, the +service must allow them to rely on it continuing to be present in the future.

+

The set of keys provided in each (reason, domain) pair is independent from other pairs, +but services should aim for consistent key naming. For example, two error reasons +within the same domain should not use metadata keys of vmType and virtualMachineType.

+

LocalizedMessage

+

google.rpc.LocalizedMessage is used to provide an error +message which should be localized to a user-specified locale where +possible.

+

If the Status.message field has a sub-optimal value +which cannot be changed due to the constraints in the +Changing Error Messages section, LocalizedMessage +may be used to provide a better error message even when no user-specified +locale is available.

+

Regardless of how the locale for the message was determined, both the locale +and message fields must be populated.

+

The locale field specifies the locale of the message, +following IETF bcp47 (Tags for +Identifying Languages). Example values: "en-US", "fr-CH", "es-MX".

+

The message field contains the localized text itself. This +should include a brief description of the error and a call to action +to resolve the error. The message should include contextual information +to make the message as specific as possible. Any contextual information +in the message must be included in ErrorInfo.metadata. See +ErrorInfo for more details of how contextual information +may be included in a message and the corresponding metadata.

+

The LocalizedMessage payload should contain the complete resolution +to the error. If more information is needed than can reasonably fit in this +payload, then additional resolution information must be provided in +a Help payload. See the Help section for guidance.

+

Help

+

When other textual error messages (in Status.message or +LocalizedMessage.message) don't provide the user sufficient +context or actionable next steps, or if there are multiple points of +failure that need to be considered in troubleshooting, a link to +supplemental troubleshooting documentation must be provided in the +Help payload.

+

Provide this information in addition to a clear problem definition and +actionable resolution, not as an alternative to them. The linked +documentation must clearly relate to the error. If a single page +contains information about multiple errors, the +ErrorInfo.reason value must be used to narrow down +the relevant information.

+

The description field is a textual description of the linked information. +This must be suitable to display to a user as text for a hyperlink. +This must be plain text (not HTML, Markdown etc).

+

Example description value: "Troubleshooting documentation for STOCKOUT errors"

+

The url field is the URL to link to. This must be an absolute URL, +including scheme.

+

Example url value: +"https://cloud.google.com/compute/docs/resource-error"

+

For publicly-documented services, even those with access controls on actual +usage, the linked content must be accessible without authentication.

+

For privately-documented services, the linked content may require +authentication.

+

Error messages

+

Textual error messages can be present in both Status.message and +LocalizedMessage.message fields. Messages should be succinct but +actionable, with request-specific information (such as a resource name +or region) providing precise details where appropriate. Any request-specific +details must be present in ErrorInfo.metadata.

+

Changing error messages

+

Changing the content of Status.message over time must be done carefully, +to avoid breaking clients who have previously had to rely on the message +for all information. See the rationale section +for more details.

+

For a given RPC:

+
    +
  • If the RPC has always returned ErrorInfo with machine-readable + information, the content of Status.message may change over time. + (For example, the API producer may provide a clearer explanation, + or more request-specific information.)
  • +
  • Otherwise, the content of Status.message must be stable, + providing the same text with the same request-specific information. + Instead of changing Status.message, the API should include a + LocalizedMessage within Status.details.
  • +
+

Even if an RPC has always returned ErrorInfo, the API may keep +the existing Status.message stable and add a +LocalizedMessage within Status.details.

+

The content of LocalizedMessage.details may change over time.

+

Partial errors

+

APIs should not support partial errors. Partial errors add +significant complexity for users, because they usually sidestep the use +of error codes, or move those error codes into the response message, +where the user must write specialized error handling logic to +address the problem.

+

However, occasionally partial errors are necessary, particularly in bulk +operations where it would be hostile to users to fail an entire large +request because of a problem with a single entry.

+

Methods that require partial errors should use long-running +operations, and the method should put partial failure information +in the metadata message. The errors themselves must still be +represented with a google.rpc.Status object.

+

Permission Denied

+

If the user does not have permission to access the resource or parent, +regardless of whether or not it exists, the service must error with +PERMISSION_DENIED (HTTP 403). Permission must be checked prior to +checking if the resource or parent exists.

+

If the user does have proper permission, but the requested resource or +parent does not exist, the service must error with NOT_FOUND (HTTP +404).

+

HTTP/1.1+JSON representation

+

When clients use HTTP/1.1 as per AIP-127, the error information +is returned in the body of the response, as a JSON object. For backward +compatibility reasons, this does not map precisely to google.rpc.Status, +but contains the same core information. The schema is defined in the following proto:

+
message Error {
+  message Status {
+    // The HTTP status code that corresponds to `google.rpc.Status.code`.
+    int32 code = 1;
+    // This corresponds to `google.rpc.Status.message`.
+    string message = 2;
+    // This is the enum version for `google.rpc.Status.code`.
+    google.rpc.Code status = 4;
+    // This corresponds to `google.rpc.Status.details`.
+    repeated google.protobuf.Any details = 5;
+  }
+
+  Status error = 1;
+}
+
+

The most important difference is that the code field in the JSON is an HTTP status code, +not the direct value of google.rpc.Status.code. For example, a google.rpc.Status +message with a code value of 5 would be mapped to an object including the following +code-related fields (as well as the message, details etc):

+
{
+  "error": {
+    "code": 404,          // The HTTP status code for "not found"
+    "status": "NOT_FOUND" // The name in google.rpc.Code for value 5
+  }
+}
+
+

The following JSON shows a fully populated HTTP/1.1+JSON representation of an error response.

+
{
+  "error": {
+    "code": 429,
+    "message": "The zone 'us-east1-a' does not have enough resources available to fulfill the request. Try a different zone, or try again later.",
+    "status": "RESOURCE_EXHAUSTED",
+    "details": [
+      {
+        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
+        "reason": "RESOURCE_AVAILABILITY",
+        "domain": "compute.googleapis.com",
+        "metadata": {
+          "zone": "us-east1-a",
+          "vmType": "e2-medium",
+          "attachment": "local-ssd=3,nvidia-t4=2",
+          "zonesWithCapacity": "us-central1-f,us-central1-c"
+        }
+      },
+      {
+        "@type": "type.googleapis.com/google.rpc.LocalizedMessage",
+        "locale": "en-US",
+        "message": "An <e2-medium> VM instance with <local-ssd=3,nvidia-t4=2> is currently unavailable in the <us-east1-a> zone. Consider trying your request in the <us-central1-f,us-central1-c> zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation."
+      },
+      {
+        "@type": "type.googleapis.com/google.rpc.Help",
+        "links": [
+          {
+            "description": "Additional information on this error",
+            "url": "https://cloud.google.com/compute/docs/resource-error"
+          }
+        ]
+      }
+    ]
+  }
+}
+
+

Rationale

+

Requiring ErrorInfo

+

ErrorInfo is required because it further identifies an error. With +only approximately twenty available values for Status.status, +it is difficult to disambiguate one error from another across an entire +API Service.

+

Also, error messages often contain dynamic segments that express +variable information, so there needs to be machine-readable component of +every error response that enables clients to use such information +programmatically.

+

Including LocalizedMessage

+

LocalizedMessage was selected as the location to present alternate +error messages. While LocalizedMessage may use a locale specified +in the request, a service may provide a LocalizedMessage even without +a user-specified locale, typically to provide a better error message in +situations where Status.message cannot be changed. +Where the locale is not specified by the user, it should be en-US +(US English).

+

A service may include LocalizedMessage even when the same message is +provided in Status.message and when localization into a user-specified locale +is not supported. Reasons for this include:

+
    +
  • An intention to support user-specified localization in the near future, allowing + clients to consistently use LocalizedMessage and not change their error-reporting + code when the functionality is introduced.
  • +
  • Consistency across all RPCs within a service: if some RPCs include + LocalizedMessage and some only use Status.message for error messages, clients + have to be aware of which RPCs will do what, or implement a fall-back mechanism. + Providing LocalizedMessage on all RPCs allows simple and consistent client code + to be written.
  • +
+

Updating Status.message

+

If a client has ever observed an error with Status.message populated +(which it always will be) but without ErrorInfo, the developer of that client +may well have had to resort to parsing Status.message in order to find out +information beyond just what Status.code conveys. That information may be +found by matching specific text (e.g. "Connection closed with unknown cause") +or by parsing the message to find out metadata values (e.g. a region with +insufficient resources). At that point, Status.message is implicitly part +of the API contract, so must not be updated - that would be a breaking +change. This is one reason for introducing LocalizedMessage into the +Status.details.

+

RPCs which have always included ErrorInfo are in a better position: +the contract is then more about the stability of ErrorInfo for any given +error. The reason and domain need to be consistent over time, and the +metadata provided for any given (reason,domain) can only be expanded. +It's still possible that clients could be parsing Status.message instead of +using ErrorInfo, but they will always have had a more robust option +available to them.

+

Further reading

+
    +
  • For which error codes to retry, see AIP-194.
  • +
  • For how to retry errors in client libraries, see + AIP-4221.
  • +
+

Changelog

+
    +
  • 2024-10-18: Rewrite/restructure for clarity.
  • +
  • 2024-01-10: Incorporate guidance for writing effective messages.
  • +
  • 2023-05-17: Change the recommended language for Status.message to be + the service's native language rather than English.
  • +
  • 2023-05-17: Specify requirements for changing error messages.
  • +
  • 2023-05-10: Require ErrorInfo for all error responses.
  • +
  • 2023-05-04: Require uniqueness by message type for error details.
  • +
  • 2022-11-04: Added guidance around PERMISSION_DENIED errors previously + found in other AIPs.
  • +
  • 2022-08-12: Reworded/Simplified intro to add clarity to the intent.
  • +
  • 2020-01-22: Added a reference to the ErrorInfo message.
  • +
  • 2019-10-14: Added guidance restricting error message mutability to if + there is a machine-readable identifier present.
  • +
  • 2019-09-23: Added guidance about error message strings being able to + change.
  • +
+ + + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/194.html b/194.html new file mode 100644 index 0000000000..6fb6253fd9 --- /dev/null +++ b/194.html @@ -0,0 +1,790 @@ + + + + AIP-194: Automatic retry configuration + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-194

+

Automatic retry configuration

+

RPCs sometimes fail. When one does, the client performing the RPC needs to know +whether it is safe to retry the operation. When status codes are used +consistently across multiple APIs, clients can respond to failures +appropriately.

+

Guidance

+

Clients should automatically retry requests for which repeated runs would +not cause unintended state changes, which are non-transactional, and which are +unary.

+

Clients should not automatically retry transactional requests; instead +these requests should have application-level retry logic that retries the +entire transaction block from the start.

+

Clients should not automatically retry requests in which repeated runs +would cause unintended state changes.

+

Note: This AIP does not cover client streaming or bi-directional streaming.

+

Note: For client side retry behavior in the client libraries: see +AIP-4221.

+

Retryable codes

+

For methods listed as retryable above, clients should retry the following +error codes:

+
    +
  • UNAVAILABLE: This code generally results from network hiccups, and is + generally transient. It is retryable under the expectation that the + connection will become available (soon).
  • +
+

Non-retryable codes

+

The following codes should not be automatically retried for any request:

+
    +
  • OK: The request succeeded.
  • +
  • CANCELLED: An application can cancel a request, which must be honored.
  • +
  • DEADLINE_EXCEEDED: An application can set a deadline, which must be + honored.
  • +
  • INVALID_ARGUMENT: Retrying a request with an invalid argument will never + succeed.
  • +
  • DATA_LOSS: This is an unrecoverable error and must immediately be + surfaced to the application.
  • +
+

Generally non-retryable codes:

+

The following codes generally should not be automatically retried for any +request:

+
    +
  • RESOURCE_EXHAUSTED: This code may be a signal that quota is exhausted. + Retries therefore may not be expected to work for several hours; meanwhile + the retries may have billing implications. If RESOURCE_EXHAUSTED is used + for other reasons than quota and the expected time for the resource to become + available is much shorter, it may be retryable.
  • +
  • INTERNAL: This code generally means that some internal part of the system + has failed, and usually means a bug should be filed against the system. These + should immediately be surfaced to the application.
  • +
  • UNKNOWN: Unlike INTERNAL, this code is reserved for truly + unknown-to-the-system errors, and therefore may not be safe to retry. These + should immediately be surfaced to the application.
  • +
  • ABORTED: This code typically means that the request failed due to a + sequencer check failure or transaction abort. These should not be retried + for an individual request; they should be retried at a level higher (the + entire transaction, for example).
  • +
+

Some codes may be automatically retried if a system is designed without +synchronization or signaling between various components. For example, client +might retry NOT_FOUND on a read operation, which is designed to hang forever +until the resource is created. However, these types of systems are generally +discouraged.

+

Therefore, the following codes should not be automatically retried for any +request:

+
    +
  • NOT_FOUND: A client should not retry until a resource is created.
  • +
  • ALREADY_EXISTS: A client should not retry until a resource is deleted.
  • +
  • PERMISSION_DENIED: A client should not retry until it has permission.
  • +
  • UNAUTHORIZED: A client should not retry until it is authorized.
  • +
  • UNAUTHENTICATED: A client should not retry until it is authenticated.
  • +
  • FAILED_PRECONDITION: A client should not retry until system state + changes.
  • +
  • OUT_OF_RANGE: A client should not retry until the range is extended.
  • +
  • UNIMPLEMENTED: A client should not retry until the RPC is implemented.
  • +
+

Further reading

+
    +
  • For parallel or retried request disambiguation, see AIP-154.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/2.html b/2.html new file mode 100644 index 0000000000..f34b5bda83 --- /dev/null +++ b/2.html @@ -0,0 +1,756 @@ + + + + AIP-2: AIP Numbering + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-2

+

AIP Numbering

+

The AIP system provides a mechanism to index and have a single source of truth +for API Improvement Proposals, as well as iterate on them collaboratively and +transparently.

+

This document describes the AIP numbering system.

+

Assigning AIP Numbers

+

The AIP editors (see AIP-1) are responsible for assigning a number +to each AIP when it is accepted as a draft for review. Importantly, all AIPs +have numbers, not just approved ones. The AIP Index clearly delineates +which AIPs are approved and binding and which are under discussion.

+

The editors may decide to reserve a specific block of numbers for groups of +AIPs that are related in some way (for example, that are only scoped to a +specific subset of APIs).

+

Beyond this, AIP numbers are assigned arbitrarily. In general, the editors will +take the next AIP number off of the stack to assign to a draft AIP, but +occasionally may use a special/joke number if useful for mnemonic or other +reasons.

+

AIP Blocks

+

Currently recognized blocks of AIP numbers are:

+

Generally Applicable

+
    +
  • 1-99: Reserved for meta-AIPs (generally process-related).
  • +
  • 100-999: General API design guidance
  • +
+

Google Product Areas

+
    +
  • 2700-2799: Apps (Google Workspace)
  • +
  • 2500-2599: Cloud
  • +
  • 3000-3099: Actions on Google
  • +
  • 3200-3299: Firebase
  • +
  • 4100-4199: Auth libraries
  • +
  • 4200-4299: Client libraries
  • +
  • 4600-4699: Geo
  • +
+

To request a block for a specific team that is publishing API guidance or +documentation germane to that specific team, reach out to api-editors@.

+

Changelog

+
    +
  • 2019-10-03: The 3000-3099 block was assigned to Actions on Google.
  • +
  • 2019-01-26: The general API design guidance block was expanded to include + 100-199.
  • +
  • 2018-10-24: The 4600-4699 block was assigned to Google Geo.
  • +
  • 2018-10-02: The 2500-2599 block was assigned to Google Cloud Platform.
  • +
  • 2018-10-02: The 2700-2799 block was assigned to Google Workspace.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/200.html b/200.html new file mode 100644 index 0000000000..2fdea3766a --- /dev/null +++ b/200.html @@ -0,0 +1,822 @@ + + + + AIP-200: Precedent + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-200

+

Precedent

+

Many times, APIs are written in ways that do not match new guidance that is +added to these standards after those APIs have already been released. +Additionally, sometimes it can make sense to intentionally violate standards +for particular reasons, such as maintaining consistency with established +systems, meeting stringent performance requirements, or other practical +concerns. Finally, as carefully as everyone reviews APIs before they are +released, sometimes mistakes can slip through.

+

Since it often is not feasible to fix past mistakes or make the standards serve +every use case, APIs may be stuck with these exceptions for quite some time. +Further, since new APIs often base their designs (names, types, structures, +etc) on existing APIs, it is possible that a standards violation in one API +could spill over into other APIs, even if original reason for the exception is +not applicable to the other APIs.

+

As a result of this problem, it is important to "stop the bleeding" of these +standards exceptions into new APIs, and additionally document the reasons for +each exception so that historical wisdom is not lost.

+

Guidance

+

If an API violates the AIP standards for any reason, there must be an +internal comment linking to this document using its descriptive link +(aip.dev/not-precedent) to ensure others do not copy the violations or cite +the errors as precedent of a "previously approved API".

+

The comment should also include an explanation of what violates standards and +why it is necessary. For example:

+
message DailyMaintenanceWindow {
+  // Time within the maintenance window to start the maintenance operations.
+  // It must use the format "HH MM", where HH : [00-23] and MM : [00-59] GMT.
+  // (-- aip.dev/not-precedent: This was designed for consistency with crontab,
+  //     and preceded the AIP standards.
+  //     Ordinarily, this type should be `google.type.TimeOfDay`. --)
+  string start_time = 2;
+
+  // Output only. Duration of the time window, automatically chosen to be
+  // smallest possible in the given scenario.
+  // (-- aip.dev/not-precedent: This preceded the AIP standards.
+  //     Ordinarily, this type should be `google.protobuf.Duration`. --)
+  string duration = 3;
+}
+
+

Important: APIs should only be considered to be precedent-setting if they +are in beta or GA.

+

Local consistency

+

If an API violates a standard throughout, it would be jarring and frustrating +to users to break the existing pattern only for the sake of adhering to the +global standard.

+

For example, if all of an API's resources use creation_time (instead of the +standard field create_time described in AIP-142), a new resource in that +API should continue to follow the local pattern.

+

However, others who might otherwise copy that API should be made aware that +this is contra-standard and not something to cite as precedent when launching +new APIs.

+
// ...
+message Book {
+  // (-- aip.dev/not-precedent: This field was present before there was a
+  //     standard field.
+  //     Ordinarily, it should be spelled `create_time`. --)
+  google.protobuf.Timestamp creation_time = 1;
+}
+
+// ...
+message Author {
+  // (-- aip.dev/not-precedent: `Book` had `creation_time` before there was
+  //     a standard field, so we match that here for consistency. Ordinarily,
+  //     this would be spelled `create_time`. --)
+  google.protobuf.Timestamp creation_time = 1;
+}
+
+

Pre-existing functionality

+

Standards violations are sometimes overlooked before launching, resulting in +APIs that become stable and therefore can not easily be modified. Additionally, +a stable API may pre-date a standards requirement.

+

In these scenarios, it is difficult to make the API fit the standard. However, +the API should still cite that the functionality is contra-standard so that +other APIs do not copy the mistake and cite the existing API as a reason why +their design should be approved.

+

Adherence to external spec

+

Occasionally, APIs must violate standards because specific requests are +implementations of an external specification (for example, OAuth), and their +specification may be at odds with AIP guidelines. In this case, it is likely to +be appropriate to follow the external specification.

+

Adherence to existing systems

+

Similar to the example of an external specification above, it may be proper for +an API to violate AIP guidelines to fit in with an existing system in some way. +This is a fundamentally similar case where it is wise to meet the customer +where they are. A potential example of this might be integration with or +similarity to a partner API.

+

Expediency

+

Sometimes there are users who need an API surface by a very hard deadline or +money walks away. Since most APIs serve a business purpose, there will be times +when an API could be better but cannot get it that way and into users' hands +before the deadline. In those cases, API review councils may grant +exceptions to ship APIs that violate guidelines due to time and business +constraints.

+

Technical concerns

+

Internal systems sometimes have very specific implementation needs (e.g., they +rely on operation transforms that speak UTF-16, not UTF-8) and adhering to AIP +guidelines would require extra work that does not add significant value to API +consumers. Future systems which are likely to expose an API at some point +should bear this in mind to avoid building underlying infrastructure which +makes it difficult to follow AIP guidelines.

+

Changelog

+
    +
  • 2020-03-27: Reworded much of this AIP to follow AIP-8, and remove + first and second person. No semantic changes.
  • +
  • 2019-05-04: Changed to a public link (aip.dev/not-precedent), and + changed references to "the style guide" to use the more generic term + "standards" (to account for a general shift to AIPs).
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/202.html b/202.html new file mode 100644 index 0000000000..929b5bd9a2 --- /dev/null +++ b/202.html @@ -0,0 +1,780 @@ + + + + AIP-202: Fields + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-202

+

Fields

+

The google.api.FieldInfo type, through its accompanying +extension google.api.field_info, enriches a field's schema beyond the basic +name and type information.

+

Guidance

+

Decorating a field with google.api.field_info is only necessary when +explicitly stated in this AIP or another that leverages google.api.FieldInfo +information. As such, the guidance herein applies to those scenarios as well.

+

Format

+

Fields with a primitive type can still have a specific format. To convey that +type format, the FieldInfo.Format enumeration is used via the +(google.api.field_info).format extension field. The following guidance conveys +the meaning of and requirements for use of each FieldInfo.Format value.

+

UUID4

+

The UUID4 format represents a UUID version 4 value as governed by +RFC 4122. It must only be used on a field of type string.

+

Such a value may be normalized by the service to entirely lowercase letters. +For example, the value F47AC10B-58CC-0372-8567-0E02B2C3D479 would be +normalized to f47ac10b-58cc-0372-8567-0e02b2c3d479.

+

As such, equivalence comparison must not be done via primitive text +comparison. Instead, an RFC 4122 compliant implementation must be used.

+

IPv4

+

The IPV4 format represents an IP v4 address as governed by RFC 791. It +must only be used on a field of type string.

+

Such a value may be condensed by the service, with leading zeros in each +octet stripped. For example, 001.022.233.040 would be condensed to +1.22.233.40.

+

As such, equivalence comparison must not be done via primitive text +comparison. Instead, an RFC 791 compliant implementation must be used.

+

IPv6

+

The IPV6 format represents an IP v6 address as governed by RFC 4291. It +must only be used on a field of type string.

+

Such a value may be normalized by the service to entirely lowercase letters +with zeros compressed, following RFC 5952. For example, the value +2001:0DB8:0::0 would be normalized to 2001:db8::.

+

As such, equivalence comparison must not be done via primitive text +comparison. Instead, an RFC 4291 compliant implementation must be used.

+

IPv4 or IPv6

+

The IPV4_OR_IPV6 value indicates that the field can be either an IP v4 or v6 +address, as described in the IPv4 and IPv6 sections.

+

Format Compatibility

+

Adding a format specifier to an existing, unspecified field is not backwards +compatible, unless the field in question has always conformed to the format +being specified.

+

Changing an existing format specifier to a different one in all cases is not +backwards compatible.

+

Extending Format

+

Any new FieldInfo.Format value must be governed by an +IETF-approved RFC or a Google-approved AIP.

+

Rationale

+

Why add a format specifier?

+

The format of a primitive-typed field can be critical to its usability. Some +programming languages may convey a specific type format as a standalone type, +as Java does with UUID. Most have specific structural requirements +that are validated by the service, so conveying the format to the user ahead of +time is critical to their experience.

+

Why discourage primitive equality comparisons?

+

The text representations of the supported formats have many nuances and +transforming the value into a canonical representation is non-trivial. As such, +aligning implementations between each consumer and each service without any +issue is infeasible.

+

Why document value normalizations?

+

While primitive comparison is not recommended for any of the supported formats, +uniform normalization of values is important to set consumer expectations, and +create a user-friendly surface.

+

Why require an RFC or AIP for new formats?

+

Those formats which are sufficiently standardized to merit an RFC or AIP are +stable enough and widely enough known to be incorporated as a supported value +and see usage in Google APIs. Requiring such extra guidance means that governing +the format specification is not the responsibility of the FieldInfo.Format +enumeration itself.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/203.html b/203.html new file mode 100644 index 0000000000..5e811291df --- /dev/null +++ b/203.html @@ -0,0 +1,964 @@ + + + + AIP-203: Field behavior documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-203

+

Field behavior documentation

+

When defining fields in protocol buffers, it is customary to explain to users +certain aspects of the field's behavior (such as whether it is required or +optional). Additionally, it can be useful for other tools to understand this +behavior (for example, to optimize client library signatures).

+

Guidance

+

APIs use the google.api.field_behavior annotation to describe well-understood +field behavior, such as a field being required or immutable.

+
// The audio data to be recognized.
+RecognitionAudio audio = 2 [(google.api.field_behavior) = REQUIRED];
+
+
    +
  • APIs must apply the google.api.field_behavior annotation on every field + on a message or sub-message used in a request.
      +
    • An exception to this is the AIP-154 etag field on a resource message, + which should not have any google.api.field_behavior assigned.
    • +
    +
  • +
  • The annotation must include any google.api.FieldBehavior values that + accurately describe the behavior of the field.
      +
    • FIELD_BEHAVIOR_UNSPECIFIED must not be used.
    • +
    +
  • +
  • APIs must at minimum use one of REQUIRED, OPTIONAL, or OUTPUT_ONLY.
  • +
+

Warning: Although field_behavior does not impact proto-level behavior, +many clients (e.g. CLIs and SDKs) rely on them to generate code. Thoroughly +review and consider which values are relevant when adding a new field.

+

Fields with no annotation are interpreted as OPTIONAL for +backwards-compatility. Nontheless, this annotation must not be omitted.

+

Note: The vocabulary given in this document is for descriptive purposes +only, and does not itself add any validation. The purpose is to consistently +document this behavior for clients.

+

field behavior of nested messages

+

google.api.field_behavior annotations on a nested message are independent of +the annotations of the parent.

+

For example, a nested message can have a field behavior of REQUIRED while the +parent field can be OPTIONAL:

+
message Title {
+  string text = 1 [(google.api.field_behavior) = REQUIRED];
+}
+
+message Slide {
+  Title title = 1 [(google.api.field_behavior) = OPTIONAL];
+}
+
+

In the case above, if a title is specified, the text field is required.

+

Vocabulary

+

Identifier

+

The use of IDENTIFIER indicates that a field within a resource message is used +to identify the resource. It must be attached to the name field and must +not be attached to any other field (see fields representing resource names).

+

The IDENTIFIER value conveys that the field is not accepted as input (i.e. +OUTPUT_ONLY) in the context of a create method, while also being considered +IMMUTABLE and accepted as input for mutation methods that accept the +resource as the primary input e.g. Standard Update.

+

This annotation must not be applied to references to other resources within +a message.

+

Immutable

+

The use of IMMUTABLE indicates that a field on a resource cannot be changed +after its creation. This can apply to either fields that are input or outputs, +required or optional.

+

When a service receives an immutable field in an update request (or similar), +even if included in the update mask, the service should ignore the field if +the value matches, but should error with INVALID_ARGUMENT if a change is +requested.

+

Potential use cases for immutable fields (this is not an exhaustive list) are:

+
    +
  • Attributes of resources that are not modifiable for the lifetime of the + application (e.g. a disk type).
  • +
+

Note: Fields which are "conditionally immutable" must not be given the +immutable annotation.

+

Input only

+

The use of INPUT_ONLY indicates that the field is provided in requests and +that the corresponding field will not be included in output.

+

Additionally, a field should only be described as input only if it is a +field in a resource message or a field of a message included within a resource +message. Notably, fields in request messages (a message which only ever acts as +an argument to an RPC, with a name usually ending in Request) should not +be described as input only because this is already implied.

+

Potential use cases for input only fields (this is not an exhaustive list) are:

+
    +
  • The ttl field as described in AIP-214.
  • +
+

Warning: Input only fields are rare and should be considered carefully +before use.

+

Optional

+

The use of OPTIONAL indicates that a field is not required.

+

A field may be described as optional if it is a field on a request message +(a message that is an argument to an RPC, usually ending in Request), or a +field on a submessage.

+

Output only

+

The use of OUTPUT_ONLY indicates that the field is provided in responses, but +that including the field in a message in a request does nothing (the server +must clear out any value in this field and must not throw an error as a +result of the presence of a value in this field on input). Similarly, services +must ignore the presence of output only fields in update field masks (see: +AIP-161).

+

Additionally, a field should only be described as output only if it is a +field in a resource message, or a field of a message farther down the tree. +Notably, fields in response messages (a message which only ever acts as a +return value to an RPC, usually ending in Response) should not be +described as output only because this is already implied.

+

Output only fields may be set to empty values if appropriate to the API.

+

Potential use cases for output only fields (this is not an exhaustive list) +are:

+
    +
  • Create or update timestamps.
  • +
  • Derived or structured information based on original user input.
  • +
  • Properties of a resource assigned by the service which can not be altered.
  • +
+

Required

+

The use of REQUIRED indicates that the field must be present (and set to +a non-empty value) on the request or resource.

+

A field should only be described as required if either:

+
    +
  • It is a field on a resource that a user provides somewhere as input. In this + case, the resource is only valid if a "truthy" value is stored.
      +
    • When creating the resource, a value must be provided for the + field on the create request.
    • +
    • When updating the resource, the user may omit the field + provided that the field is also absent from the field mask, indicating no + change to the field (otherwise it must be provided).
    • +
    +
  • +
  • It is a field on a request message (a message that is an argument to an RPC, + with a name usually ending in Request). In this case, a value must be + provided as part of the request, and failure to do so must cause an error + (usually INVALID_ARGUMENT).
  • +
+

We define the term "truthy" above as follows:

+
    +
  • For primitives, values other than 0, 0.0, empty string/bytes, and false
  • +
  • For repeated fields maps, values with at least one entry
  • +
  • For messages, any message with at least one "truthy" field.
  • +
+

Fields should not be described as required in order to signify:

+
    +
  • A field which will always be present in a response.
  • +
  • A field which is conditionally required in some situations.
  • +
  • A field on any message (including messages that are resources) which is never + used as user input.
  • +
+

Note: In most cases, empty values (such as false for booleans, 0 for +integers, or the unspecified value for enums) are indistinguishable from unset +values, and therefore setting a required field to a falsy value yields an +error. A corollary to this is that a required boolean must be set to true.

+

Unordered List

+

The use of UNORDERED_LIST on a repeated field of a resource indicates that +the service does not guarantee the order of the items in the list.

+

A field should be described as an unordered list if the service does not +guarantee that the order of the elements in the list will match the order that +the user sent, including a situation where the service will sort the list on +the user's behalf.

+

A resource with an unordered list may return the list in a stable order, or +may return the list in a randomized, unstable order.

+

Backwards compatibility

+

Adding or changing google.api.field_behavior values can represent a semantic +change in the API that is perceived as incompatible for existing clients. The +following are examples of backwards incompatible changes with +google.api.field_behavior:

+
    +
  • Adding REQUIRED to an existing field previously considered OPTIONAL +(implicitly or otherwise)
  • +
  • Adding a new field annotated as REQUIRED to an existing request message
  • +
  • Adding OUTPUT_ONLY to an existing field previously accepted as input
  • +
  • Adding INPUT_ONLY to an existing field previously emitted as output
  • +
  • Adding IMMUTABLE to an existing field previously considered mutable
  • +
  • Removing OUTPUT_ONLY from an existing field previously ignored as input
  • +
  • Removing IDENTIFIER from an existing field.
  • +
+

There are some changes that are backwards compatible, which are as follows:

+
    +
  • Adding OPTIONAL to an existing field
  • +
  • Adding IDENTIFIER to an existing name field
  • +
  • Changing from REQUIRED to OPTIONAL on an existing field
  • +
  • Changing from OUTPUT_ONLY and/or IMMUTABLE to IDENTIFIER on an existing + field
  • +
  • Removing REQUIRED from an existing field
  • +
  • Removing INPUT_ONLY from an existing field previously excluded in responses
  • +
  • Removing IMMUTABLE from an existing field previously considered immutable
  • +
+

Rationale

+

Identifier field behavior

+

Resource names, the primary identifiers for any compliant resource, are never +fully constructed by the user on create. Such fields are typically assigned +OUTPUT_ONLY field behavior. They are, however, also often consumed as +the primary identifier in scenarios where the resource itself is the primary +request payload. Such fields could not be considered OUTPUT_ONLY. +Furthermore, in mutation requests, like Standard Update, the resource name as +the primary identifier cannot be changed in place. Such fields are typically +assigned IMMUTABLE field behavior. These conflicting and context-dependent +field behaviors meant that a new value was necessary to single out and convey +the behavior of the resource name field.

+

Required set of annotations

+

A field used in a request message must be either an input or an output.

+

In the case of an output, the OUTPUT_ONLY annotation is sufficient.

+

In the case of an input, a field is either required or optional, and therefore +should have at least the REQUIRED or OPTIONAL annotation, respectively. +Only providing INPUT_ONLY does not convey the necessity of the field, so +specifying either REQUIRED or OPTIONAL is still necessary.

+

Requiring field behavior

+

By including the field behavior annotation for each field, the overall behavior +that the resource exhibits is more clearly defined. Clearly defined field +behavior improves programmatic clients and user understanding.

+

Requiring the annotation also forces the API author to explicitly consider the +behavior when initially authoring of the API.

+

Modifying field behavior after initial authoring can result in +backwards-incompatible changes in clients. For example, making an optional field +required results in backwards-incompatible changes in the method signature of an +RPC or a resource in a Declarative client. See the +Backwards compatibility section for more detailed +compatibility guidance.

+

History

+

In 2023-05 field_behavior was made mandatory. Prior to this change, the +annotation was often omitted. Its values are relied upon to produce high quality +clients. Furthermore, adding or changing some of the field_behavior values after +the fact within a major version can be backwards-incompatible. See the +Backwards compatibility section for more detailed +compatibility guidance.

+

The benefits of requiring field_behavior at the time that the API is authored +surpass the costs to clients and API users of not doing so.

+

Changelog

+
    +
  • 2023-09-14: Clarify that nested behavior and parent behavior are + independent.
  • +
  • 2023-08-25: Add guidance on IDENTIFIER.
  • +
  • 2023-07-20: Describe compatibility guidance with new section.
  • +
  • 2023-05-24: Clarify that IMMUTABLE does not imply input nor required.
  • +
  • 2023-05-10: Added guidance to require the annotation.
  • +
  • 2020-12-15: Added guidance for UNORDERED_LIST.
  • +
  • 2020-05-27: Clarify behavior when receiving an immutable field in an + update.
  • +
  • 2019-12-05: Added guidance on output only fields in field masks.
  • +
  • 2019-06-18: Use the machine-readable annotation, not comments.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/205.html b/205.html new file mode 100644 index 0000000000..91bd04ce2f --- /dev/null +++ b/205.html @@ -0,0 +1,735 @@ + + + + AIP-205: Beta-blocking changes + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-205

+

Beta-blocking changes

+

APIs often release an Alpha version of their API in order to get early feedback +from customers. This API is provisional and can change many times before the +important feedback is incorporated and the API is made stable for Beta.

+

Since the purpose of Alpha is to gather feedback, the API does not need to be +perfect yet, and it's not strictly necessary for API authors to address every +usability concern or address every point in the API standards. Often, API +authors and API reviewers will not agree on the best design, and the best way +to find out is by having users try out the API.

+

However, once the feedback has been collected and the API is going to be +promoted to Beta, usability concerns and style issues do need to be addressed. +In order to ensure that these issues are not forgotten, they should be +explicitly documented in the API.

+

Guidance

+

If an API has usability concerns or violates API standards, and the present +design should receive additional scrutiny before being carried through to the +Beta version, there must be an internal comment linking to this document +using its descriptive link (aip.dev/beta-blocker) to ensure that the design +is corrected before the API is released to Beta.

+

The comment must also indicate what kind of change should be made for Beta. +For example:

+
message InputConfig {
+  // Parameters for input.
+  // (-- aip.dev/beta-blocker: Convert well-known parameters into explicit
+  //     fields before the Beta launch. --)
+  map<string, string> parameters = 1;
+}
+
+

If an exception to API standards does need to be carried through to Beta and +GA, see AIP-200.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/210.html b/210.html new file mode 100644 index 0000000000..a37ca159aa --- /dev/null +++ b/210.html @@ -0,0 +1,846 @@ + + + + AIP-210: Unicode + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-210

+

Unicode

+

APIs should be consistent on how they explain, limit, and bill for string +values and their encodings. This ranges from little ambiguities (like fields +"limited to 1024 characters") all the way to billing confusion (are names and +values of properties in Datastore billed based on characters or bytes?).

+

In general, if we talk about limits measured in bytes, we are discriminating +against non-ASCII text since it takes up more space. On the other hand, if we +talk about "characters", we are ambiguous about whether those are Unicode "code +points", "code units" for a particular encoding (e.g. UTF-8 or UTF-16), +"graphemes", or "grapheme clusters".

+

Unicode primer

+

Character encoding tends to be an area we often gloss over, so a quick primer:

+
    +
  • Strings are just bytes that represent numbers according to some encoding + format.
  • +
  • When we talk about characters, we sometimes mean Unicode code points, + which are numbers in the Unicode spec (up to 21 bits).
  • +
  • Other times we might mean graphemes or grapheme clusters, which may + have multiple numeric representations and may be represented by more than one + code point. For example, á may be represented as a composition of + U+0061 + U+0301 (the a + the accent combining mark) or as a single code + point, U+00E1.
  • +
  • Protocol buffers uses UTF-8 ("Unicode Transformation Format") which is a + variable-length encoding scheme using up to 4 code units (8-bit bytes) + per code point.
  • +
+

Guidance

+

Character definition

+

TL;DR: In our APIs, "characters" means "Unicode code points".

+

In API documentation (e.g., API reference documents, blog posts, marketing +documentation, billing explanations, etc), "character" must be defined as a +Unicode code point.

+

Length units

+

TL;DR: Set size limits in "characters" (as defined above).

+

All string field length limits defined in API comments must be measured and +enforced in characters as defined above. This means that there is an underlying +maximum limit of (4 * characters) bytes, though this limit will only be hit +when using exclusively characters that consist of 4 UTF-8 code units (32 bits).

+

If you use a database system (e.g. Spanner) which allows you to define a limit +in characters, it is safe to assume that this byte-defined requirement is +handled by the underlying storage system.

+

Billing units

+

APIs may use either code points or bytes (using the UTF-8 encoding) as the +unit for billing or quota measurement (e.g., Cloud Translation chooses to use +characters). If an API does not define this, the assumption is that the unit of +billing is characters (e.g., $0.01 per character, not $0.01 per byte).

+

Unique identifiers

+

TL;DR: Unique identifiers should limit to ASCII, generally only +letters, numbers, hyphens, and underscores, and should not start with a +number.

+

Strings used as unique identifiers should limit inputs to ASCII characters, +typically letters, numbers, hyphens, and underscores +([a-zA-Z][a-zA-Z0-9_-]*). This ensures that there are never accidental +collisions due to normalization. If an API decides to allow all valid Unicode +characters in unique identifiers, the API must reject any inputs that are +not in Normalization Form C. Generally, unique identifiers should not start +with a number as that prefix is reserved for Google-generated identifiers and +gives us an easy way to check whether we generated a unique numeric ID for or +whether the ID was chosen by a user.

+

Unique identifiers should use a maximum length of 64 characters, though +this limit may be expanded as necessary. 64 characters should be sufficient for +most purposes as even UUIDs only require 36 characters.

+

Note: See AIP-122 for recommendations about resource ID segments.

+

Normalization

+

TL;DR: Unicode values should be stored in Normalization Form C.

+

Values should always be normalized into Normalization Form C. Unique +identifiers must always be stored in Normalization Form C (see the next +section).

+

Imagine we're dealing with Spanish input "estaré" (the accented part +will be bolded throughout). This text has what we might visualize as 6 +"characters" (in this case, they are grapheme clusters). It has two possible +Unicode representations:

+
    +
  • Using 6 code points: U+0065 U+0073 U+0074 U+0061 U+0072 + U+00E9
  • +
  • Using 7 code points: U+0065 U+0073 U+0074 U+0061 U+0072 U+0065 + U+0301
  • +
+

Further, when encoding to UTF-8, these code points have two different +serialized representations:

+
    +
  • Using 7 code-units (7 bytes): 0x65 0x73 0x74 0x61 0x72 0xC3 + 0xA9
  • +
  • Using 8 code-units (8 bytes): 0x65 0x73 0x74 0x61 0x72 0x65 + 0xCC 0x81
  • +
+

To avoid this discrepancy in size (both code units and code points), use +Normalization Form C which provides a canonical representation for strings.

+

Uniqueness

+

TL;DR: Unicode values must be normalized to Normalization Form C +before checking uniqueness.

+

For the purposes of unique identification (e.g., name, id, or parent), +the value must be normalized into Normalization Form C (which happens +to be the most compact). Otherwise we may have what is essentially "the same +string" used to identify two entirely different resources.

+

In our example above, there are two ways of representing what is essentially +the same text. This raises the question about whether the two representations +should be treated as equivalent or not. In other words, if someone were to use +both of those byte sequences in a string field that acts as a unique +identifier, would it violate a uniqueness constraint?

+

The W3C recommends using Normalization Form C for all content moving across the +internet. It is the most compact normalized form on Unicode text, and avoids +most interoperability problems. If we were to treat two Unicode byte sequences +as different when they have the same representation in NFC, we'd be required to +reply to possible "Get" requests with content that is not in normalized +form. Since that is definitely unacceptable, we must treat the two as +identical by transforming any incoming string data into Normalized Form C or +rejecting identifiers not in the normalized form.

+

There is some debate about whether we should view strings as sequences of code +points represented as bytes (leading to uniqueness determined based on the +byte-representation of said string) or to interpret strings as a higher level +abstraction having many different possible byte-representations. The stance +taken here is that we already have a field type for handling that: bytes. +Fields of type string already express an opinion of the validity of an input +(it must be valid UTF-8). As a result, treating two inputs that have identical +normalized forms as different due to their underlying byte representation seems +to go against the original intent of the string type. This distinction +typically doesn't matter for strings that are opaque to our services (e.g., +description or display_name), however when we rely on strings to uniquely +identify resources, we are forced to take a stance.

+

Put differently, our goal is to allow someone with text in any encoding (ASCII, +UTF-16, UTF-32, etc) to interact with our APIs without a lot of "gotchas".

+

References

+ + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/211.html b/211.html new file mode 100644 index 0000000000..7739f22fd0 --- /dev/null +++ b/211.html @@ -0,0 +1,777 @@ + + + + AIP-211: Authorization checks + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-211

+

Authorization checks

+

The majority of operations, whether reads or writes, require authorization: +permission to do the thing the user is asking to do. Additionally, it is +important to be careful how much information is provided to unauthorized +users, since leaking information can be a security concern.

+

Guidance

+

Services must check authorization before validating any request, to ensure +both a secure API surface and a consistent user experience. An operation +may require multiple permissions or preconditions in order to grant +authorization.

+

If a request can not pass the authorization check for any reason, the service +must error with PERMISSION_DENIED, and the corresponding error message +should look like: "Permission '{p}' denied on resource '{r}' (or it +might not exist)." This avoids leaking resource existence.

+

If it is not possible to determine authorization for a resource because the +resource does not exist, the service should check authorization to read +children on the parent resource, and return NOT_FOUND if the authorization +check passes.

+

Multiple operations

+

A service could encounter a situation where it has two different operations +with two different permissions, either of which would reveal the existence of a +resource if called, but a user only has permission to call one of them.

+

In this situation, the service should still only check for authorization +applicable to the operation being called, and should not try to "help out" +by checking for related authorization that would provide permission to reveal +existence, because such algorithms are complicated to implement correctly and +prone to accidental leaks.

+

For example, posit a scenario where:

+
    +
  • A resource exists within a given collection that a user is unable to read.
  • +
  • The user does have the ability to create other resources, and the + collection uses user-specified IDs (meaning that a failure because of a + duplicate ID would reveal existence).
  • +
+

In this situation, the get or create methods should still only check +their permissions when determining what error to return, and not one +another's.

+

Rationale

+

RFC 7231 §6.5.3 states that services are permitted to use 404 Not Found +in lieu of 403 Forbidden in situations where the service does not want to +divulge existence, whereas this AIP argues for the use of PERMISSION_DENIED +(which corresponds to 403 Forbidden in HTTP) instead. We take this position +for the following reasons:

+
    +
  • The practice of "getting 404 Not Found until you have enough permission to + get 403 Forbidden" is counter-intuitive and increases the difficulty of + troubleshooting.
      +
    • A service could ameliorate this by sending information about missing + permissions while still using the 404 Not Found status code, but this + constitutes a mixed message.
    • +
    +
  • +
  • While 403 Forbidden is essentially always an error requiring manual action, + 404 Not Found is often a valid response that the application can handle + (e.g. "get or create"); overloading it for permission errors deprives + applications of this benefit.
  • +
  • RFC 7231 §6.5.4 states that 404 Not Found results are cacheable, but + permission errors are not generally cacheable. Sending explicit cache + controls on a conditional basis could ameliorate this, but would defeat the + purpose.
  • +
  • The guidance here is more consistent with most other real-world authorization + systems.
  • +
+

Changelog

+
    +
  • 2021-05-11: Added a more detailed "Rationale" section.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/213.html b/213.html new file mode 100644 index 0000000000..1172d4f134 --- /dev/null +++ b/213.html @@ -0,0 +1,895 @@ + + + + AIP-213: Common components + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-213

+

Common components

+

As specified in AIP-215, APIs must be self-contained except for the use +of "common component" packages which are intended for use by multiple APIs.

+

There are two kinds of common component packages:

+
    +
  • Organization-specific common components, covering organization-specific + concepts such as a "viewport" in Maps.
  • +
  • Global common components which are generic (i.e. not domain-specific), + such as "timestamp" or "postal address".
  • +
+

Where it is safe to share a single representation across multiple APIs, +common components can make it easier for clients to interact with those APIs. +Concept-specific client code can be written once, and messages can be used from +the response of one API in the request of another without clunky copying, for +example.

+

This benefit comes with significant restrictions and limitations, however, +and should not be attempted lightly.

+

Note that even if the domain of a component is common, the requirements of +a component may be organization-specific. For example, some organizations may +have particular requirements of how financial values are represented, leading +to multiple finance-oriented organization-specific common components - because +any global common component would either not meet the organization-specific +requirements, or be too complex for general use.

+

Guidance

+
    +
  • Organization-wide common component packages must end with .type, e.g. + google.geo.type or google.shopping.type.
  • +
  • Organizations must consult the API design team before creating a new + organization-wide common component package.
  • +
  • Organization-wide common component packages must be published in the + googleapis repository.
  • +
  • Organizations creating and publishing a new organization-wide common component + package must update this AIP to include it in the + list below.
  • +
  • Organizations must not define generic components in organization-specific + common component packages, instead preferring global common components.
  • +
  • Common components must not be "moved" (that is, deleted from one common + component package and added to a different one) from an organization-specific + common component package to a global common component package or vice versa.
      +
    • A common component may be copied from an organization-specific common + component package to a global common component package (without deleting the + original component) if it is found to be more widely-applicable than + originally expected.
    • +
    +
  • +
  • Fields should not be added to existing messages.
  • +
  • Values should not be added to existing enums.
  • +
  • Fields must not be removed from existing messages.
  • +
  • Values must not be removed from existing enums.
  • +
  • While documentation may be clarified, it should not change the + meanings of existing values, including the validity of any given message + or set of messages.
  • +
  • New proto messages and enums may be added to common component packages.
      +
    • API teams should allow sufficient time for propagation to clients + before using the new messages and enums in their APIs. Fields may take some + time for any changes to propagate through publication to client libraries + and other surfaces.
    • +
    • API teams should consult widely within their organization, and ideally + with the API design team, before adding a new message or enum, due to the + limitations listed above.
    • +
    +
  • +
+

Existing global common components

+

The global common components, which public-facing protos for an API may safely +import, are as follows:

+ +

Note that some common components may have internal-only fields. APIs should +generally only rely on fields which have been +released into open source.

+

Google APIs may also import google.iam.v1.*, which provides the +IAM messages used throughout Google.

+ +

Note: Many APIs also import components from other packages for internal-only +use (e.g. to apply visibility labels or provide instructions to internal +infrastructure). This is acceptable provided that the public components do not +contain such references.

+

Protobuf types

+

The google.protobuf package is somewhat special in that it is shipped with +protocol buffers itself, rather than with API tooling. (For most API designers, +this should be an implementation detail).

+

This package includes a small library of types useful for representing common +programming language constructs:

+
    +
  • google.protobuf.Duration: Durations, with nanosecond-level + precision. The protobuf runtime provides helper functions to convert to and + from language-native duration objects where applicable (such as Python's + timedelta).
  • +
  • google.protobuf.Struct: JSON-like structures (a dictionary of + primitives, lists, and other dictionaries). The protobuf runtime provides + helper functions in most languages to convert struct objects to and from + JSON.
  • +
  • google.protobuf.Timestamp: Timestamps, with nanosecond-level + precision. The protobuf runtime provides helper functions in most languages + to convert to and from language-native timestamp objects (such as Python's + datetime).
  • +
+ + + +

API Types

+

The google.type package provides a "standard library" of types useful for +representing common concepts in APIs. While types are added from time to time +and the definitive list is always the code, several types deserve note:

+ + + + +

Adding to common protos

+

Occasionally, it may be useful to add protos to these packages or to add to the +list of commonly-available protos. In order to do this, open an issue on +the AIP repository in GitHub, noting the guidelines above.

+

Existing organization-specific common component packages

+

The following organization-specific common component packages exist and conform with the above guidance:

+ +

Non-conformant common component packages

+

The following common component packages exist, but do not conform with the above guidance, +and do not form a precedent for further such packages.

+ +

Rationale

+

Common components are effectively unversioned: APIs evolve independently of +each other, both in terms of definition and implementation. A change such as +adding a field is backward-compatible and predictable in specific APIs, and the +API team can ensure that the server implementation is available before the API +definition is published. By contrast, a change in a common component would +effectively be universally available even if most API implementations did not +take it into account.

+

Adding a new message or enum is backward-compatible, as it does not affect +existing APIs that may import other messages or enums from the same common +component package.

+

Consultation with the API design team is required for global common components +and suggested for organization-specific common components as the border between +"generic" and "organization-specific" is a gray area; some generic concepts +have organization-specific use cases which surface through the components.

+

Changelog

+
    +
  • 2023-06-27: Restructured AIPs 215 and 213 for clarity, and introduced the + concept of organization-wide common protos more formally.
  • +
  • 2018-08-17: Initial AIP written.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/214.html b/214.html new file mode 100644 index 0000000000..5449d550b6 --- /dev/null +++ b/214.html @@ -0,0 +1,772 @@ + + + + AIP-214: Resource expiration + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-214

+

Resource expiration

+

Customers often want to provide the time that a given resource or resource +attribute is no longer useful or valid (e.g. a rotating security key). Currently +we recommend that customers do this by specifying an exact "expiration time" +into a google.protobuf.Timestamp expire_time field; however, this adds +additional strain on the user when they want to specify a relative time offset +until expiration rather than a specific time until expiration.

+

Furthermore, the world understands the concept of a "time-to-live", often +abbreviated to TTL, but the typical format of this field (an integer, measured +in seconds) results in a sub-par experience when using an auto-generated client +library.

+

Guidance

+
    +
  1. APIs wishing to convey an expiration must rely on a + google.protobuf.Timestamp field called expire_time.
  2. +
  3. APIs wishing to allow a relative expiration time must define a oneof + called expiration (or {something}_expiration) containing both the + expire_time field and a separate google.protobuf.Duration + field called ttl, the latter marked as input only.
  4. +
  5. APIs must always return the expiration time in the expire_time field + and leave the ttl field blank when retrieving the resource.
  6. +
  7. APIs that rely on the specific semantics of a "time to live" (e.g., DNS + which must represent the TTL as an integer) may use an int64 ttl + field (and should provide an aip.dev/not-precedent comment + in this case).
  8. +
+

Example

+
message ExpiringResource {
+  // google.api.resource and other annotations and fields
+
+  oneof expiration {
+    // Timestamp in UTC of when this resource is considered expired.
+    // This is *always* provided on output, and is calculated using
+    // the value of [ttl][] if set when created.
+    google.protobuf.Timestamp expire_time = 2;
+
+    // Input only. The TTL for this resource.
+    google.protobuf.Duration ttl = 3 [(google.api.field_behavior) = INPUT_ONLY];
+  }
+}
+
+

Rationale

+

Alternatives considered

+

A new standard field called ttl

+

We considered allowing a standard field called ttl as an alternative way of +defining the expiration, however doing so would require that API services +continually update the field, like a clock counting down. This could +potentially cause problems with the read-modify-write lifecycle where a +resource is being processed for some time, and effectively has its life +extended as a result of that processing time.

+

Always use expire_time

+

This is the current state of the world with a few exceptions. In this scenario, +we could potentially push the computation of now + ttl = expire_time into +client libraries; however, this leads to a somewhat frustrating experience in +the command-line and using REST/JSON. Leaving things as they are is typically +the default, but it seems many customers want the ability to define relative +expiration times as it is quite a bit easier and removes questions of time +zones, stale clocks, and other silly mistakes.

+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/215.html b/215.html new file mode 100644 index 0000000000..801630d97d --- /dev/null +++ b/215.html @@ -0,0 +1,753 @@ + + + + AIP-215: API-specific protos + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-215

+

API-specific protos

+

APIs are mostly defined in terms of protos which are API-specific, with +occasional dependencies on common components. Keeping APIs isolated from each +other avoids versioning problems and client library packaging problems.

+

Guidance

+
    +
  • All protos specific to an API must be within a package with a major version + (e.g., google.library.v1).
  • +
  • References to resources in other APIs must be expressed in terms of + resource names (AIP-122), rather than using the resource messages.
  • +
  • When two versions of an API use effectively the same (API-specific) proto + that proto must be duplicated in each version. (In other words, APIs + must not create their own "API-specific common component" packages.)
  • +
  • Organization-specific common components may be placed in a common package, + as described in AIP-213, but must not be used by any API outside + that organization.
  • +
  • Global common components (also described in AIP-213) may be freely used by any API.
  • +
+

Rationale

+

When one API depends on protos defined by another API, this introduces uncertainty +in terms of customer-expected behavior and client library dependency management. +Suppose google.cloud.library.v1 depends on the protos (rather than abstract resources) +in google.cloud.movies.v2. Any change to google.cloud.movies.v2 can cause problems.

+

For example:

+
    +
  • If a field is added to a message in google.cloud.movies.v2, should customers using + google.cloud.library.v1 expect to see it? If so, how soon after the field has + been added? What about other API changes?
  • +
  • If the whole major version google.cloud.movies.v2 is deprecated + (typically after v3 has been released), does that mean google.cloud.library.v1 has + to change to use google.cloud.movies.v3, and if so, does that require a new major version + for the library API as well?
  • +
  • How should client library versioning reflect changes to dependent APIs?
  • +
+

Keeping APIs isolated from each other, with a limited set of common components which are +maintained in a highly disciplined way, reduces a lot of the issues with dependencies.

+

API-specific common components shared across versions add complexity for client +library generation and packaging, and are inflexible in terms of versioning. +When protos are duplicated because they start off the same in multiple versions, +they can still diverge over time as they are isolated from each other.

+

Changelog

+
    +
  • 2023-06-27: Restructured AIPs 215 and 213 for clarity.
  • +
  • 2023-05-11: Changed "PA" to "organization".
  • +
  • 2018-10-01: Initial AIP written.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/216.html b/216.html new file mode 100644 index 0000000000..3aacad80eb --- /dev/null +++ b/216.html @@ -0,0 +1,916 @@ + + + + AIP-216: States + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-216

+

States

+

Many API resources carry a concept of "state": ordinarily, the resource's place +in its life cycle. For example, a virtual machine may be being provisioned, +available for use, being spun down, or potentially be in one of several other +situations. A job or query may be preparing to run, be actively running, have +completed, and so on.

+

Guidance

+

Resources needing to communicate their state should use an enum, which +should be called State (or, if more specificity is required, end in the +word State). This enum should be nested within the message it describes +when only used as a field within that message.

+

Important: We use the term State, and not Status (which is reserved +for the HTTP and gRPC statuses).

+

Enum values

+

Ideally, Google APIs use the same terminology throughout when expressing the +same semantic concepts. There are usually many words available to express a +given state, but our customers often use multiple APIs together, and it is +easier for them when our terms are consistent.

+

At a high level:

+
    +
  • Resources that are available for use are ACTIVE (preferred over terms such + as "ready" or "available").
  • +
  • Resources that have completed a (usually terminal) requested action use past + participles (usually ending in -ED), such as SUCCEEDED (not + "successful"), FAILED (not "failure"), DELETED, SUSPENDED, and so on.
  • +
  • Resources that are currently undergoing a state change use present + participles (usually ending in -ING), such as RUNNING, CREATING, + DELETING, and so on. In this case, it is expected that the state is + temporary and will resolve to another state on its own, with no further user + action.
  • +
+

Note: Remember to only add states that are useful to customers. Exposing a +large number of states simply because they exist in your internal system is +unnecessary and adds confusion for customers. Each state must come with a use +case for why it is necessary.

+

Output only

+

The field referencing the State enum in a resource should behave and be +documented as "Output only", in accordance with AIP-203.

+

APIs should not allow a State enum to be directly updated through an +"update" method (or directly set through the "create" method), and should +instead use custom state transition methods.

+

This is because update methods are generally not expected to have side effects, +and also because updating state directly implies that it is possible to set the +state to any available value, whereas states generally reflect a resource's +progression through a lifecycle.

+

State transition methods

+

State transition methods are a special type of custom method that are +responsible for transitioning a state field from one enum value to another. As +part of the transition, other fields may also change, e.g. an update_time +field. The method definition should look like the following:

+
// Publishes a book.
+// The `state` of the book after publishing is `PUBLISHED`.
+// `PublishBook` can be called on Books in the state `DRAFT`; Books in a
+// different state (including `PUBLISHED`) returns an error.
+rpc PublishBook(PublishBookRequest) returns (Book) {
+  option (google.api.http) = {
+    post: "/v1/{name=publishers/*/books/*}:publish"
+    body: "*"
+  };
+}
+
+
    +
  • The name of the method should be a verb followed by the singular form of + the resource's message name.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response message should be the resource itself.
      +
    • If the RPC is long-running, the response message should be a + google.longrunning.Operation which resolves to the resource itself.
    • +
    +
  • +
  • The HTTP verb must be POST.
  • +
  • The HTTP URI must use a : character followed by the custom verb + (:publish in the above example), and the verb in the URI must match the + verb in the name of the RPC.
      +
    • If word separation is required, camelCase must be used.
    • +
    +
  • +
  • The body clause in the google.api.http annotation must be "*".
  • +
  • The request message field receiving the resource name should map to the + URI path.
      +
    • This field should be called name.
    • +
    • The name field should be the only variable in the URI path. All + remaining parameters should map to URI query parameters.
    • +
    +
  • +
  • If the state transition is not allowed, the service must error with + FAILED_PRECONDITION (HTTP 400).
  • +
+

The request message should look like this:

+
message PublishBookRequest {
+  // The name of the book to publish.
+  // Format: publishers/{publisher}/books/{book}
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+}
+
+
    +
  • A resource name field must be included. It should be called name.
  • +
  • The comment for the field should document the resource pattern.
  • +
  • Other fields may be included.
  • +
+

Additional Guidance

+

Default value

+

The zero value of each state enum should adhere to the following +convention:

+
enum State {
+  // The default value. This value is used if the state is omitted.
+  STATE_UNSPECIFIED = 0;
+
+  // Other values...
+}
+
+

Resources should not provide an unspecified state to users, and this value +should not actually be used.

+

Value uniqueness

+

Multiple top-level enums within the same package must not share the same +values. This is because the C++ protoc code generator flattens top-level enum +values into a single namespace.

+

State enums should live inside the resource definition.

+

Prefixes

+

Using a STATE_ prefix on every enum value is unnecessary. State enum values +should not be prefixed with the enum name, except for the default value +STATE_UNSPECIFIED.

+

Breaking changes

+

TL;DR: Clearly communicate to users that state enums may receive new values +in the future, and be conscientious about adding states to an existing enum.

+

Even though adding states to an existing states enum can break existing user +code, adding states is not considered a breaking change. Consider a state with +only two values: ACTIVE and DELETED. A user may add code that checks +if state == ACTIVE, and in the else cases simply assumes the resource is +deleted. If the API later adds a new state for another purpose, that code will +break.

+

We ultimately can not control this behavior, but API documentation should +actively encourage users to code against state enums with the expectation that +they may receive new values in the future.

+

APIs may add new states to an existing State enum when appropriate, and +adding a new state is not considered a breaking change.

+

When to avoid states

+

Sometimes, a State enum may not be what is best for your API, particularly in +situations where a state has a very small number of potential values, or when +states are not mutually exclusive.

+

Consider the example of a state with only ACTIVE and DELETED, as discussed +above. In this situation, the API may be better off exposing a +google.protobuf.Timestamp delete_time, and instructing users to rely on +whether it is set to determine deletion.

+

Common states

+

The following is a list of states in common use. APIs should consider prior +art when determining state names, and should value local consistency above +global consistency in the case of conflicting precedent.

+

Resting states

+

"Resting states" are lifecycle states that, absent user action, are expected to +remain indefinitely. However, the user can initiate an action to move a +resource in a resting state into certain other states (resting or active).

+
    +
  • ACCEPTED
  • +
  • ACTIVE
  • +
  • CANCELLED
  • +
  • DELETED
  • +
  • FAILED
  • +
  • SUCCEEDED
  • +
  • SUSPENDED
  • +
  • VERIFIED
  • +
+

Active states

+

"Active states" are lifecycle states that typically resolve on their own into a +single expected resting state.

+

Note: Remember only to expose states that are useful to customers. Active +states are valuable only if the resource will be in that state for a sufficient +period of time. If state changes are immediate, active states are not +necessary.

+
    +
  • CREATING (usually becomes ACTIVE)
  • +
  • DELETING (usually becomes DELETED)
  • +
  • PENDING (usually becomes RUNNING)
  • +
  • REPAIRING (usually becomes ACTIVE)
  • +
  • RUNNING (usually becomes SUCCEEDED)
  • +
  • SUSPENDING (usually becomes SUSPENDED)
  • +
+

Further reading

+
    +
  • For information on enums generally, see AIP-126.
  • +
+

Changelog

+
    +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-10-20: Added guidance on prefixing enum values with enum name.
  • +
  • 2020-09-02: Clarified that states are not directly set on create either.
  • +
  • 2019-12-05: Changed guidance on state transition methods, downgrading + must to should on the response type.
  • +
  • 2019-08-16: Added guidance for state transition methods.
  • +
  • 2019-07-18: Added explicit guidance on the unspecified value.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/217.html b/217.html new file mode 100644 index 0000000000..6a82cde845 --- /dev/null +++ b/217.html @@ -0,0 +1,986 @@ + + + + AIP-217: Unreachable resources + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-217

+

Unreachable resources

+

Occasionally, a user may ask for a list of resources, and some set of resources +in the list are temporarily unavailable. The most typical use case is while +supporting Reading Across Collections. For example, a user may ask to +list resources across multiple parent locations, but one of those locations is +temporarily unreachable. In this situation, it is still desirable to provide +the user with all the available resources, while indicating that something is +missing.

+

Guidance

+

If a method to retrieve data is capable of partially failing due to one or more +resources being temporarily unreachable, the response message must include +a field to indicate this:

+
message ListBooksResponse {
+  // The books matching the request.
+  repeated Book books = 1;
+
+  // The next page token, if there are more books matching the
+  // request.
+  string next_page_token = 2;
+
+  // Unreachable resources.
+  repeated string unreachable = 3 [
+    (google.api.field_behavior) = UNORDERED_LIST
+  ];
+}
+
+
    +
  • The field must be a repeated string, and should be named + unreachable.
  • +
  • The field must contain the resource names of the resources that are + unreachable or those that impede reaching the requested collection, such as + the parent resource of the collection that could not be reached.
      +
    • For example, if an entire location is unreachable, preventing access to the + localized collection of resources requested, the location resource is + included.
    • +
    +
  • +
  • The field must contain service-relative resource names, and must not + contain full resource names, resource URIs, or simple resource IDs. See + AIP-122 for definitions.
      +
    • For example, if a Book resource is unreachable, the service-relative + resource name "shelves/scifi1/books/starwars4" is included in + unreachable, as opposed to the full resource name + "//library.googleapis.com/shelves/scifi1/books/starwars4", the + parent-relative resource "books/starwars4", the resource ID + "starwars4", or the resource URI.
    • +
    +
  • +
  • The response must not provide any other information about the issue(s) + that made the listed resources unreachable.
      +
    • For example, the response cannot contain an extra field with error reasons + for each unreachable entry.
    • +
    +
  • +
  • The service must provide a way for the user to make a more specific + request and receive an error with additional information e.g. via a Standard + Get or a Standard List targeted at the unreachable collection parent.
      +
    • The service must also allow the user to repeat the original call with + more restrictive parameters.
    • +
    +
  • +
  • The resource names that appear in unreachable may be heterogeneous.
      +
    • The unreachable field definition should document what potential + resources could be provided in this field, and note that it might expand + later.
    • +
    • For example, if both an entire location and a specific resource in a + different location are unreachable, the unreachable location's name + e.g. "projects/example123/locations/us-east1" and the unreachable + resource's name e.g. + "projects/example123/locations/europe-west2/instances/example456" will + both appear in unreachable.
    • +
    +
  • +
  • The unreachable field must not have semantically meaningful ordering or + structure within the list. Put differently, unreachable must be an + unordered list.
      +
    • As such, the unreachable field must be annotated with UNORDERED_LIST + field behavior (see AIP-203).
    • +
    +
  • +
+

Important: If a single unreachable location or resource prevents returning +any data by definition (for example, a list request for a single publisher +where that publisher is unreachable), the service must fail the entire +request with an error.

+

Pagination

+

While preparing a page of results to fulfill a page fetch RPC e.g. an +AIP-132 Standard List call, if the service encounters any unreachable +resources or collections they must do the following:

+
    +
  • Include the resource name for the unreachable resource in the unreachable + response field.
      +
    • The resource name must be the most appropriately scoped for the + unreachable resource or collection.
        +
      • For example, if a specific zone within a region is unreachable, the + unreachable resource name would be a zonal Location e.g. + projects/example/locations/us-west1-a, but if an entire region is + unreachable, the resource name would be a regional Location e.g. + projects/example/locations/us-west1.
      • +
      +
    • +
    • The resource name must be included, regardless of restrictive paging + parameters e.g. order_by, when it is identified as unreachable.
    • +
    +
  • +
  • Populate results that were previously considered unreachable on a following + page if their availability is restored and the paging parameters allow for + their inclusion.
      +
    • Determining inclusion eligibility based on paging parameters also includes + any documented default ordering behavior in the absence of user-specified + ordering in the request.
    • +
    • For example, if region projects/example/locations/us-west1 was unavailable + in the first page of an ordered paging call, and including its resources + would violate the ordering, those out-of-order resources are not included in + the following page.
    • +
    • Similarly, if the same exact request is made, and resources previously + considered unreachable are available again, they must be populated, + within the constraints of the paging parameters.
    • +
    +
  • +
  • Limit the number of unreachable resource names returned in a given response + if, even after up-scoping the unreachable resource name, the number of + unreachable resource names exceeds a documented maximum.
      +
    • This maximum must be documented in the unreachable field comments + directly.
    • +
    • This is independent of the page_size set by the caller.
    • +
    +
  • +
+

Retaining previous behavior

+

Services may continue with previously implemented unreachable pagination +behavior where changing it would induce an incompatible change as per +AIP-180, but must document said behavior on the unreachable +field(s) directly.

+

Adopting partial success

+

In order for an existing API that has a default behavior differing from the +aforementioned guidance i.e. the API call returns an error status instead of a +partial result, to adopt the unreachable pattern the API must do the +following:

+
    +
  • The default behavior must be retained to avoid incompatible behavioral + changes
      +
    • For example, if the default behavior is to return an error if any location + is unreachable, that default behavior must be retained.
    • +
    +
  • +
  • The request message must have a bool return_partial_success field
  • +
  • The response message must have the standard + repeated string unreachable field
  • +
  • The two aforementioned fields must be added simultaneously
  • +
+

When the bool return_partial_success field is set to true in a request, the +API must behave as described in the aforementioned guidance with regards to +populating the repeated string unreachable response field.

+
message ListBooksRequest {
+  // Standard List request fields...
+
+  // Setting this field to `true` will opt the request into returning the
+  // resources that are reachable, and into including the names of those that
+  // were unreachable in the [ListBooksResponse.unreachable] field. This can
+  // only be `true` when reading across collections e.g. when `parent` is set to
+  //  `"projects/example/locations/-"`.
+  bool return_partial_success = 4;
+}
+
+message ListBooksResponse {
+  // Standard List Response fields...
+
+  // Unreachable resources. Populated when the request opts into
+  // `return_partial_success` and reading across collections e.g. when
+  // attempting to list all resources across all supported locations.
+  repeated string unreachable = 3 [
+    (google.api.field_behavior) = UNORDERED_LIST
+  ];
+}
+
+

Partial success granularity

+

If the bool return_partial_success field is set to true in a request that is +scoped beyond the supported granualirty of the API's ability to reasonably +report unreachable resources, the API should return an INVALID_ARGUMENT +error with details explaining the issue. For example, if the API only supports +return_partial_success when Reading Across Collections, it returns +an INVALID_ARGUMENT error when given a request scoped to a specific parent +resource collection. The supported granularity must be documented on the +return_partial_success field.

+

Rationale

+

Using service-relative resource names

+

In general, relative resource names, as defined in AIP-122, are the best +practice for referring to resources by name within a service and in other +services when that other service is obvious. The full resource name format is +strictly less consumable (e.g., requires extra parsing client side), and +over-specified for the uses of unreachable. Resource URIs are not transport +agnostic, as they are unusable in standard methods for gRPC users, and simple +resource IDs do not provide enough information about exactly which resource +was unreachable in a heterogenous list of resources.

+

Minimizing extra error details in response

+

The context in which an unreachable resource is discovered may be sensitive and +the state of the system fluid between calls. As such, it is preferred to defer +to the service by making a more specific RPC to get more details about a +specific resource or parent. This allows the parent to handle all necessary RPC +checks and system state resolution on at time of request, rather than by +shoehorning potentially privileged or stale information into the broader list +call it was unreachable for.

+

Unordered unreachable contents

+

It is important for broad API consistency that the contents of unreachable not +have a specific or order semantic structure. If each API baked a specific +ordering into a standard field, no single implementation, client or server side, +would be correct.

+

Per page unreachable resources

+

Populating unreachable resources on a per page basis allows end users to +identify immediately when a page is incomplete, rather than after paging +through all results. Paging to completion is not guaranteed, so it is important +to communicate as soon as possible when there are unreachable resource missing +from a given page. Furthermore, it allows users to identify when there is a +potential issue that they need to account for in subsequent calls. Finally, +retaining unreachable resources until the end of paging results requires +services to retain the state for what should be indepedent and fully isolated +API calls.

+

Using request field to opt-in

+

Introducing a new request field as means of opting into the partial success +behavior is the best way to communicate user intent while keeping the +default behavior backwards compatible. The alternative, changing the default +behavior with the introduction of the unreachable response field, presents +a backwards incompatible change. Users that previously expected failure when any +resource was unreachable, assume the successful response means all resources +are accounted for in the response.

+

Introducing fields simultaneously

+

Introducing the request and response fields simultaneously is to prevent an +invalid intermediate state that is presented by only adding one or the other. If +only unreachable is added, then it could be assumed that it being empty means +all resources were returned when that may not be true. If only +return_partial_success is added, then the user wouldn't have a means of +knowing which resources were unreachable.

+

Partial success granularity limitations

+

At a certain level of request scope granularity, an API is simply unable to +enumerate the resources that are unreachable. For example, global-only APIs may +be unable to provide granularity at a localized collection level. In such a +case, preemptively returning an error when return_partial_success=true +protects the user from the risks of the alternative - expecting unreachable +resources if there was an issue, but not getting any, thus falsely assuming +everything was retrieved. This aligns with guidance herein that suggests failing +requests that cannot be fulfilled preemptively.

+

History

+

Pagination guidance

+

The original guidance for how to populate the unreachable field revolved +around consuming the contents as if they were the paged results. This meant that +paged resources and unreachable resources couldn't be returned in the same +response i.e. page, and users needed to completely page through all results +in order to see if any were unreachable. See the Rationale section for the +reasoning around the changes.

+

Further reading

+
    +
  • For listing across collections, see AIP-159.
  • +
+

Changelog

+
    +
  • 2024-07-29: Reformat guidance, add explicit resource name format
  • +
  • 2024-07-26: Change pagination guidance. + requirement.
  • +
  • 2024-07-19: Add guidance for brownfield adoption of partial success.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/231.html b/231.html new file mode 100644 index 0000000000..d9006d21ba --- /dev/null +++ b/231.html @@ -0,0 +1,882 @@ + + + + AIP-231: Batch methods: Get + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-231

+

Batch methods: Get

+

Some APIs need to allow users to get a specific set of resources at a +consistent time point (e.g. using a read transaction). A batch get method +provides this functionality.

+

Guidance

+

APIs may support Batch Get using the following pattern:

+
rpc BatchGetBooks(BatchGetBooksRequest) returns (BatchGetBooksResponse) {
+  option (google.api.http) = {
+    get: "/v1/{parent=publishers/*}/books:batchGet"
+  };
+}
+
+
    +
  • The RPC's name must begin with BatchGet. The remainder of the RPC name + should be the plural form of the resource being retrieved.
  • +
  • The request and response messages must match the RPC name, with + Request and Response suffixes.
  • +
  • The HTTP verb must be GET.
  • +
  • The HTTP URI must end with :batchGet.
  • +
  • The URI path should represent the collection for the resource, matching + the collection used for simple CRUD operations. If the operation spans + parents, a dash (-) may be accepted as a wildcard.
  • +
  • There must not be a body key in the google.api.http annotation.
  • +
  • The operation must be atomic: it must fail for all resources or + succeed for all resources (no partial success). For situations requiring + partial failures, List (AIP-132) methods should be used.
      +
    • If the operation covers multiple locations and at least one location is + down, the operation must fail.
    • +
    +
  • +
+

Request message

+

The request for a batch get method should be specified with the following +pattern:

+
message BatchGetBooksRequest {
+  // The parent resource shared by all books being retrieved.
+  // Format: publishers/{publisher}
+  // If this is set, the parent of all of the books specified in `names`
+  // must match this field.
+  string parent = 1 [
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The names of the books to retrieve.
+  // A maximum of 1000 books can be retrieved in a batch.
+  // Format: publishers/{publisher}/books/{book}
+  repeated string names = 2 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+}
+
+
    +
  • A parent field should be included, unless the resource being retrieved + is a top-level resource, to facilitate inclusion in the URI as + well to permit a single permissions check. If a caller sets this field, and + the parent collection in the name of any resource being retrieved does not + match, the request must fail.
      +
    • This field should be required if only 1 parent per request is allowed.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • The request message must include a repeated field which accepts the + resource names specifying the resources to retrieve. The field should be + named names.
      +
    • If no resource names are provided, the API should error with + INVALID_ARGUMENT.
    • +
    • The field should be required.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • Other fields besides name may be "hoisted" from the standard Get + request. There is no way to allow for these fields to + accept different values for different resources; if this is needed, use the + alternative request message form.
  • +
  • Batch get should not support pagination because transactionality across + API calls would be extremely difficult to implement or enforce, and the + request defines the exact scope of the response anyway.
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
  • The comment above the names field should document the maximum number of + requests allowed.
  • +
+

Response message

+

The response for a batch get method should be specified with the following +pattern:

+
message BatchGetBooksResponse {
+  // Books requested.
+  repeated Book books = 1;
+}
+
+
    +
  • The response message must include one repeated field corresponding to the + resources being retrieved.
  • +
  • The order of books in the response must be the same as the names in the + request.
  • +
+

Nested request objects

+

If the standard Get request message contains a field besides +the resource name that needs to be different between different resources being +requested, the batch message may alternatively hold a repeated field of +the standard Get request message. This is generally +discouraged unless your use case really requires it.

+

The request for a batch get method using this approach should be specified +with the following pattern:

+
message BatchGetBooksRequest {
+  // The parent resource shared by all books being retrieved.
+  // Format: publishers/{publisher}
+  // If this is set, the parent field in the GetBookRequest messages
+  // must either be empty or match this field.
+  string parent = 1 [
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The requests specifying the books to retrieve.
+  // A maximum of 1000 books can be retrieved in a batch.
+  repeated GetBookRequest requests = 2
+    [(google.api.field_behavior) = REQUIRED];
+}
+
+
    +
  • A parent field should be included. If a caller sets this field, and the + parent collection in the name of any resource being retrieved does not match, + the request must fail.
      +
    • This field should be required if only 1 parent per request is allowed.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • The request message must include a repeated field which accepts the + request messages specifying the resources to retrieve, as specified for + standard Get methods. The field should be named + requests.
      +
    • The field should be required.
    • +
    +
  • +
  • Other fields may be "hoisted" from the standard Get + request, which means that the field can be set at either + the batch level or child request level. Similar to parent, if both the + batch level and child request level are set for the same field, the values + must match.
  • +
  • Batch get should not support pagination because transactionality across + API calls would be extremely difficult to implement or enforce, and the + request defines the exact scope of the response anyway.
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
  • The comment above the requests field should document the maximum number + of requests allowed.
  • +
+

Changelog

+
    +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-09-16: Suggested annotating parent, names, and requests fields.
  • +
  • 2020-08-27: Removed parent recommendations for top-level resources.
  • +
  • 2020-03-24: Clarified behavior if no resource names are sent.
  • +
  • 2019-09-11: Changed the primary recommendation to specify a repeated + string instead of a repeated standard Get request message. Moved the original + recommendation into its own section.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/233.html b/233.html new file mode 100644 index 0000000000..1b3f01d60e --- /dev/null +++ b/233.html @@ -0,0 +1,939 @@ + + + + AIP-233: Batch methods: Create + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-233

+

Batch methods: Create

+

Some APIs need to allow users to create multiple resources in a single +transaction. A batch create method provides this functionality.

+

Guidance

+

APIs may support Batch Create using the following two patterns:

+

Returning the response synchronously

+
rpc BatchCreateBooks(BatchCreateBooksRequest) returns (BatchCreateBooksResponse) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:batchCreate"
+    body: "*"
+  };
+}
+
+

Returning an Operation which resolves to the response asynchronously

+
rpc BatchCreateBooks(BatchCreateBooksRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:batchCreate"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "BatchCreateBooksResponse"
+    metadata_type: "BatchCreateBooksOperationMetadata"
+  };
+}
+
+
    +
  • The RPC's name must begin with BatchCreate. The remainder of the RPC + name should be the plural form of the resource being created.
  • +
  • The request and response messages must match the RPC name, with + Request and Response suffixes.
  • +
  • If the batch method returns an google.longrunning.Operation, both the + response_type and metadata_type fields must be specified.
  • +
  • The HTTP verb must be POST.
  • +
  • The HTTP URI must end with :batchCreate.
  • +
  • The URI path should represent the collection for the resource, matching + the collection used for simple CRUD operations. If the operation spans + parents, a dash (-) may be accepted as a wildcard.
  • +
  • The body clause in the google.api.http annotation should be "*".
  • +
+

Atomic vs. Partial Success

+
    +
  • The batch create method may support atomic (all resources created or none + are) or partial success behavior. To make a choice, consider the following + factors:
      +
    • Complexity of Ensuring Atomicity: Operations that are simple + passthrough database transactions should use an atomic operation, + while operations that manage complex resources should use partial + success operations.
    • +
    • End-User Experience: Consider the perspective of the API consumer. + Would atomic behavior be preferable for the given use case, even if it + means that a large batch could fail due to issues with a single or a few + entries?
    • +
    +
  • +
  • Synchronous batch create must be atomic.
  • +
  • Asynchronous batch create may support atomic or partial success. +
  • +
+

Request message

+

The request for a batch create method should be specified with the +following pattern:

+
message BatchCreateBooksRequest {
+  // The parent resource shared by all books being created.
+  // Format: publishers/{publisher}
+  // If this is set, the parent field in the CreateBookRequest messages
+  // must either be empty or match this field.
+  string parent = 1 [
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The request message specifying the resources to create.
+  // A maximum of 1000 books can be created in a batch.
+  repeated CreateBookRequest requests = 2
+    [(google.api.field_behavior) = REQUIRED];
+}
+
+
    +
  • A parent field should be included, unless the resource being created is + a top-level resource. If a caller sets this field, and the + parent field of any child request message does not match, the request + must fail. The parent field of child request messages can be omitted if + the parent field in this request is set.
      +
    • This field should be required if only 1 parent per request is allowed.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • The request message must include a repeated field which accepts the + request messages specifying the resources to create, as specified for + standard Create methods. The field should be named + requests.
      +
    • The field should be required.
    • +
    +
  • +
  • Other fields may be "hoisted" from the standard Create + request, which means that the field can be set at either + the batch level or child request level. Similar to parent, if both the + batch level and child request level are set for the same field, the values + must match.
      +
    • Fields which must be unique cannot be hoisted (e.g. Customer-provided id + fields).
    • +
    +
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
  • The comment above the requests field should document the maximum number + of requests allowed.
  • +
+

Response message

+

The response for a batch create method should be specified with the +following pattern:

+
message BatchCreateBooksResponse {
+  // Books created.
+  repeated Book books = 1;
+}
+
+
    +
  • The response message must include one repeated field corresponding to the + resources that were created.
  • +
+

Operation metadata message

+
    +
  • The metadata_type message must either match the RPC name with + OperationMetadata suffix, or be named with Batch prefix and + OperationMetadata suffix if the type is shared by multiple Batch methods.
  • +
  • If batch create method supports partial success, the metadata message must + include a map<int32, google.rpc.Status> failed_requests field to communicate + the partial failures.
      +
    • The key in this map is the index of the request in the requests field in + the batch request.
    • +
    • The value in each map entry must mirror the error(s) that would normally + be returned by the singular Standard Create method.
    • +
    • If a failed request can eventually succeed due to server side retries, such + transient errors must not be communicated using failed_requests.
    • +
    • When all requests in the batch fail, Operation.error must be set with + code = google.rpc.Code.Aborted and message = "None of the requests + succeeded, refer to the BatchCreateBooksOperationMetadata.failed_requests + for individual error details"
    • +
    +
  • +
  • The metadata message may include other fields to communicate the + operation progress.
  • +
+

Adopting Partial Success

+

In order for an existing Batch API to adopt the partial success pattern, the API +must do the following:

+
    +
  • The default behavior must be retained to avoid incompatible behavioral + changes.
  • +
  • If the API returns an Operation:
      +
    • The request message must have a bool return_partial_success field.
    • +
    • The Operation metadata_type must include a + map<int32, google.rpc.Status> failed_requests field.
    • +
    • When the bool return_partial_success field is set to true in a request, + the API should allow partial success behavior, otherwise it should continue + with atomic behavior as default.
    • +
    +
  • +
  • If the API returns a direct response synchronously:
      +
    • Since the existing clients will treat a success response as an atomic + operation, the existing version of the API must not adopt the partial + success pattern.
    • +
    • A new version must be created instead that returns an Operation and + follows the partial success pattern described in this AIP.
    • +
    +
  • +
+

Rationale

+

Restricting synchronous batch methods to be atomic

+

The restriction that synchronous batch methods must be atomic is a result of +the following considerations.

+

The previous iteration of this AIP recommended batch methods must be atomic. +There is no clear way to convey partial failure in a sync response status code +because an OK implies it all worked. Therefore, adding a new field to the +response to indicate partial failure would be a breaking change because the +existing clients would interpret an OK response as all resources created.

+

On the other hand, as described in AIP-193, Operations +are more capable of presenting partial states. The response status code for an +Operation does not convey anything about the outcome of the underlying operation +and a client has to check the response body to determine if the operation was +successful.

+

Communicating partial failures

+

The AIP recommends using a map<int32, google.rpc.Status> failed_requests field +to communicate partial failures, where the key is the index of the failed +request in the original batch request. The other options considered were:

+
    +
  • A repeated google.rpc.Status field. This was rejected because it is not + clear which entry corresponds to which request.
  • +
  • A map<string, google.rpc.Status> field, where the key is the request id of + the failed request. This was rejected because:
      +
    • Client will need to maintain a map of request_id -> request in order to use + the partial success response.
    • +
    • Populating a request id for the purpose of communicating errors could + conflict with AIP-155 if the service can not + guarantee idempotency for an individual request across multiple batch + requests.
    • +
    +
  • +
  • A repeated FailedRequest field, where FailedRequest contains the individual + create request and the google.rpc.Status. This was rejected because echoing + the request payload back in response is discouraged due to additional + challenges around user data sensitivity.
  • +
+

Changelog

+
    +
  • 2025-03-06: Added detailed guidance for partial success behavior, and + decision framework for choosing between atomic and partial success
  • +
  • 2023-04-18: Changed the recommendation to allow returning partial + successes.
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-09-16: Suggested annotating parent and requests fields.
  • +
  • 2020-08-27: Removed parent recommendations for top-level resources.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/234.html b/234.html new file mode 100644 index 0000000000..5116b95c1c --- /dev/null +++ b/234.html @@ -0,0 +1,937 @@ + + + + AIP-234: Batch methods: Update + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-234

+

Batch methods: Update

+

Some APIs need to allow users to modify a set of resources in a single +transaction. A batch update method provides this functionality.

+

Guidance

+

APIs may support Batch Update using the following two patterns:

+

Returning the response synchronously

+
rpc BatchUpdateBooks(BatchUpdateBooksRequest) returns (BatchUpdateBooksResponse) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:batchUpdate"
+    body: "*"
+  };
+}
+
+

Returning an Operation which resolves to the response asynchronously

+
rpc BatchUpdateBooks(BatchUpdateBooksRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:batchUpdate"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "BatchUpdateBooksResponse"
+    metadata_type: "BatchUpdateBooksOperationMetadata"
+  };
+}
+
+
    +
  • The RPC's name must begin with BatchUpdate. The remainder of the RPC + name should be the plural form of the resource being updated.
  • +
  • The request and response messages must match the RPC name, with + Request and Response suffixes.
  • +
  • If the batch method returns an google.longrunning.Operation, both the + response_type and metadata_type fields must be specified.
  • +
  • The HTTP verb must be POST.
  • +
  • The HTTP URI must end with :batchUpdate.
  • +
  • The URI path should represent the collection for the resource, matching + the collection used for simple CRUD operations. If the operation spans + parents, a dash (-) may be accepted as a wildcard.
  • +
  • The body clause in the google.api.http annotation should be "*".
  • +
+

Atomic vs. Partial Success

+
    +
  • The batch update method may support atomic (all resources updated or none + are) or partial success behavior. To make a choice, consider the following + factors:
      +
    • Complexity of Ensuring Atomicity: Operations that are simple + passthrough database transactions should use an atomic operation, + while operations that manage complex resources should use partial + success operations.
    • +
    • End-User Experience: Consider the perspective of the API consumer. + Would atomic behavior be preferable for the given use case, even if it + means that a large batch could fail due to issues with a single or a few + entries?
    • +
    +
  • +
  • Synchronous batch update must be atomic.
  • +
  • Asynchronous batch update may support atomic or partial success. +
  • +
+

Request message

+

The request for a batch update method should be specified with the +following pattern:

+
message BatchUpdateBooksRequest {
+  // The parent resource shared by all books being updated.
+  // Format: publishers/{publisher}
+  // If this is set, the parent field in the UpdateBookRequest messages
+  // must either be empty or match this field.
+  string parent = 1 [
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The request message specifying the resources to update.
+  // A maximum of 1000 books can be modified in a batch.
+  repeated UpdateBookRequest requests = 2
+    [(google.api.field_behavior) = REQUIRED];
+}
+
+
    +
  • A parent field should be included, unless the resource being updated is + a top-level resource. If a caller sets this field, and the + parent collection in the name of any resource being updated does not match, + the request must fail.
      +
    • This field should be required if only 1 parent per request is allowed.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • The request message must include a repeated field which accepts the + request messages specifying the resources to update, as specified for + standard Update methods. The field should be named + requests.
      +
    • The field should be required.
    • +
    +
  • +
  • Other fields may be "hoisted" from the standard Update + request, which means that the field can be set at either + the batch level or child request level. Similar to parent, if both the + batch level and child request level are set for the same field, the values + must match.
      +
    • The update_mask field is a good candidate for hoisting.
    • +
    +
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
  • The comment above the requests field should document the maximum number of + requests allowed.
  • +
+

Response message

+

The response for a batch update method should be specified with the +following pattern:

+
message BatchUpdateBooksResponse {
+  // Books updated.
+  repeated Book books = 1;
+}
+
+
    +
  • The response message must include one repeated field corresponding to the + resources that were updated.
  • +
+

Operation metadata message

+
    +
  • The metadata_type message must either match the RPC name with + OperationMetadata suffix, or be named with Batch prefix and + OperationMetadata suffix if the type is shared by multiple Batch methods.
  • +
  • If batch update method supports partial success, the metadata message must + include a map<int32, google.rpc.Status> failed_requests field to communicate + the partial failures.
      +
    • The key in this map is the index of the request in the requests field + in the batch request.
    • +
    • The value in each map entry must mirror the error(s) that would normally + be returned by the singular Standard Update method.
    • +
    • If a failed request can eventually succeed due to server side retries, such + transient errors must not be communicated using failed_requests.
    • +
    • When all requests in the batch fail, Operation.error must be set with + code = google.rpc.Code.Aborted and message = "None of the requests + succeeded, refer to the BatchUpdateBooksOperationMetadata.failed_requests + for individual error details"
    • +
    +
  • +
  • The metadata message may include other fields to communicate the + operation progress.
  • +
+

Adopting Partial Success

+

In order for an existing Batch API to adopt the partial success pattern, the API +must do the following:

+
    +
  • The default behavior must be retained to avoid incompatible behavioral + changes.
  • +
  • If the API returns an Operation:
      +
    • The request message must have a bool return_partial_success field.
    • +
    • The Operation metadata_type must include a + map<int32, google.rpc.Status> failed_requests field.
    • +
    • When the bool return_partial_success field is set to true in a request, + the API should allow partial success behavior, otherwise it should continue + with atomic behavior as default.
    • +
    +
  • +
  • If the API returns a direct response synchronously:
      +
    • Since the existing clients will treat a success response as an atomic + operation, the existing version of the API must not adopt the partial + success pattern.
    • +
    • A new version must be created instead that returns an Operation and + follows the partial success pattern described in this AIP.
    • +
    +
  • +
+

Rationale

+

Restricting synchronous batch methods to be atomic

+

The restriction that synchronous batch methods must be atomic is a result of +the following considerations.

+

The previous iteration of this AIP recommended batch methods must be atomic. +There is no clear way to convey partial failure in a sync response status code +because an OK implies it all worked. Therefore, adding a new field to the +response to indicate partial failure would be a breaking change because the +existing clients would interpret an OK response as all resources updated.

+

On the other hand, as described in AIP-193, Operations +are more capable of presenting partial states. The response status code for an +Operation does not convey anything about the outcome of the underlying operation +and a client has to check the response body to determine if the operation was +successful.

+

Communicating partial failures

+

The AIP recommends using a map<int32, google.rpc.Status> failed_requests field +to communicate partial failures, where the key is the index of the failed +request in the original batch request. The other options considered were:

+
    +
  • A repeated google.rpc.Status field. This was rejected because it is not + clear which entry corresponds to which request.
  • +
  • A map<string, google.rpc.Status> field, where the key is the request id of + the failed request. This was rejected because:
      +
    • Client will need to maintain a map of request_id -> request in order to use + the partial success response.
    • +
    • Populating a request id for the purpose of communicating errors could + conflict with AIP-155 if the service can not + guarantee idempotency for an individual request across multiple batch + requests.
    • +
    +
  • +
  • A repeated FailedRequest field, where FailedRequest contains the individual + update request and the google.rpc.Status. This was rejected because echoing + the request payload back in response is discouraged due to additional + challenges around user data sensitivity.
  • +
+

Changelog

+
    +
  • 2025-03-06: Changed recommendation to allow partial success, along with + detailed guidance
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-09-16: Suggested annotating parent and requests fields.
  • +
  • 2020-08-27: Removed parent recommendations for top-level resources.
  • +
  • 2019-09-11: Fixed the wording about which child field the parent field + should match.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/235.html b/235.html new file mode 100644 index 0000000000..ec560972a8 --- /dev/null +++ b/235.html @@ -0,0 +1,1011 @@ + + + + AIP-235: Batch methods: Delete + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-235

+

Batch methods: Delete

+

Some APIs need to allow users to delete a set of resources in a single +transaction. A batch delete method provides this functionality.

+

Guidance

+

APIs may support Batch Delete using the following two patterns:

+

Returning the response synchronously

+
rpc BatchDeleteBooks(BatchDeleteBooksRequest) returns (google.protobuf.Empty) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:batchDelete"
+    body: "*"
+  };
+}
+
+

Returning an Operation which resolves to the response asynchronously

+
rpc BatchDeleteBooks(BatchDeleteBooksRequest) returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{parent=publishers/*}/books:batchDelete"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "google.protobuf.Empty"
+    metadata_type: "BatchDeleteBooksOperationMetadata"
+  };
+}
+
+
    +
  • The RPC's name must begin with BatchDelete. The remainder of the RPC + name should be the plural form of the resource being deleted.
  • +
  • The request message must match the RPC name, with a Request suffix.
  • +
  • The response message should be google.protobuf.Empty.
      +
    • If the resource is soft deleted, the response message + should be a response message containing the updated resources.
    • +
    +
  • +
  • If the batch method returns an google.longrunning.Operation, both the + response_type and metadata_type fields must be specified.
      +
    • If the resource is soft deleted, the response_type + should be a response message containing the updated resources.
    • +
    +
  • +
  • The HTTP verb must be POST (not DELETE).
  • +
  • The HTTP URI must end with :batchDelete.
  • +
  • The URI path should represent the collection for the resource, matching + the collection used for simple CRUD operations. If the operation spans + parents, a dash (-) may be accepted as a wildcard.
  • +
  • The body clause in the google.api.http annotation should be "*".
  • +
+

Atomic vs. Partial Success

+
    +
  • The batch delete method may support atomic (all resources deleted or none + are) or partial success behavior. To make a choice, consider the following + factors:
      +
    • Complexity of Ensuring Atomicity: Operations that are simple + passthrough database transactions should use an atomic operation, + while operations that manage complex resources should use partial + success operations.
    • +
    • End-User Experience: Consider the perspective of the API consumer. + Would atomic behavior be preferable for the given use case, even if it + means that a large batch could fail due to issues with a single or a few + entries?
    • +
    +
  • +
  • Synchronous batch delete must be atomic.
  • +
  • Asynchronous batch delete may support atomic or partial success. +
  • +
+

Request message

+

The request for a batch delete method should be specified with the +following pattern:

+
message BatchDeleteBooksRequest {
+  // The parent resource shared by all books being deleted.
+  // Format: publishers/{publisher}
+  // If this is set, the parent of all of the books specified in `names`
+  // must match this field.
+  string parent = 1 [
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The names of the books to delete.
+  // A maximum of 1000 books can be deleted in a batch.
+  // format: publishers/{publisher}/books/{book}
+  repeated string names = 2 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "library.googleapis.com/Book"
+    }];
+}
+
+
    +
  • A parent field should be included, unless the resource being deleted is + a top-level resource. If a caller sets this field, and the + parent collection in the name of any resource being deleted does not match, + the request must fail.
      +
    • This field should be required if only 1 parent per request is allowed.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • The request message must include a repeated field which accepts the + resource names specifying the resources to delete. The field should be + named names.
      +
    • The field should be required.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • Other fields besides name may be "hoisted" from the standard Delete + request. There is no way to allow for these fields to + accept different values for different resources; if this is needed, use the + alternative request message form.
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
  • The comment above the names field should document the maximum number of + requests allowed.
  • +
  • Filter-based matching must not be supported.
  • +
+

Request message containing standard delete request messages

+

If the standard Delete request message contains a field +besides the resource name that needs to be different between different +resources being requested, the batch message may alternatively hold a +repeated field of the standard Delete request message. +This is generally discouraged unless your use case really requires it.

+

The request for a batch delete method should be specified with the +following pattern:

+
message BatchDeleteBooksRequest {
+  // The parent resource shared by all books being deleted.
+  // Format: publishers/{publisher}
+  // If this is set, the parent of all of the books specified in the
+  // DeleteBookRequest messages must match this field.
+  string parent = 1 [
+    (google.api.resource_reference) = {
+      child_type: "library.googleapis.com/Book"
+    }];
+
+  // The requests specifying the books to delete.
+  // A maximum of 1000 books can be deleted in a batch.
+  repeated DeleteBookRequest requests = 2
+    [(google.api.field_behavior) = REQUIRED];
+}
+
+
    +
  • A parent field should be included. If a caller sets this field, and the + parent collection in the name of any resource being deleted does not match, + the request must fail.
      +
    • This field should be required if only 1 parent per request is allowed.
    • +
    • The field should identify the resource type that it + references.
    • +
    • The comment for the field should document the resource pattern.
    • +
    +
  • +
  • The request message must include a repeated field which accepts the + request messages specifying the resources to delete, as specified for + standard Delete methods. The field should be named + requests.
      +
    • The field should be required.
    • +
    +
  • +
  • Other fields may be "hoisted" from the standard Delete + request, which means that the field can be set at either + the batch level or child request level. Similar to parent, if both the + batch level and child request level are set for the same field, the values + must match.
      +
    • Fields which must be unique cannot be hoisted (e.g. etag).
    • +
    +
  • +
  • The request message must not contain any other required fields, and + should not contain other optional fields except those described in this + or another AIP.
  • +
  • The comment above the requests field should document the maximum number + of requests allowed.
  • +
  • Filter-based matching must not be supported unless it is infeasible to + support critical use cases without it, because it makes it too easy for users + to accidentally delete important data. If it is unavoidable, see AIP-165.
  • +
+

Response message (soft-delete only)

+

In the case where a response message is necessary because the resource is +soft-deleted, the response should be specified with the following pattern:

+
message BatchDeleteBooksResponse {
+  // Books deleted.
+  repeated Book books = 1;
+}
+
+
    +
  • The response message must include one repeated field corresponding to the + resources that were soft-deleted.
  • +
+

Operation metadata message

+
    +
  • The metadata_type message must either match the RPC name with + OperationMetadata suffix, or be named with Batch prefix and + OperationMetadata suffix if the type is shared by multiple Batch methods.
  • +
  • If batch delete method supports partial success, the metadata message must + include a map<int32, google.rpc.Status> failed_requests field to communicate + the partial failures.
      +
    • The key in this map is the index of the request in the requests field in + the batch request.
    • +
    • The value in each map entry must mirror the error(s) that would normally + be returned by the singular Standard Delete method.
    • +
    • If a failed request can eventually succeed due to server side retries, such + transient errors must not be communicated using failed_requests.
    • +
    • When all requests in the batch fail, Operation.error must be set with + code = google.rpc.Code.Aborted and message = "None of the requests + succeeded, refer to the BatchDeleteBooksOperationMetadata.failed_requests + for individual error details"
    • +
    +
  • +
  • The metadata message may include other fields to communicate the + operation progress.
  • +
+

Adopting Partial Success

+

In order for an existing Batch API to adopt the partial success pattern, the API +must do the following:

+
    +
  • The default behavior must be retained to avoid incompatible behavioral + changes.
  • +
  • If the API returns an Operation:
      +
    • The request message must have a bool return_partial_success field.
    • +
    • The Operation metadata_type must include a + map<int32, google.rpc.Status> failed_requests field.
    • +
    • When the bool return_partial_success field is set to true in a request, + the API should allow partial success behavior, otherwise it should continue + with atomic behavior as default.
    • +
    +
  • +
  • If the API returns a direct response synchronously:
      +
    • Since the existing clients will treat a success response as an atomic + operation, the existing version of the API must not adopt the partial + success pattern.
    • +
    • A new version must be created instead that returns an Operation and + follows the partial success pattern described in this AIP.
    • +
    +
  • +
+

Rationale

+

Restricting synchronous batch methods to be atomic

+

The restriction that synchronous batch methods must be atomic is a result of +the following considerations.

+

The previous iteration of this AIP recommended batch methods must be atomic. +There is no clear way to convey partial failure in a sync response status code +because an OK implies it all worked. Therefore, adding a new field to the +response to indicate partial failure would be a breaking change because the +existing clients would interpret an OK response as all resources created.

+

On the other hand, as described in AIP-193, Operations +are more capable of presenting partial states. The response status code for an +Operation does not convey anything about the outcome of the underlying operation +and a client has to check the response body to determine if the operation was +successful.

+

Communicating partial failures

+

The AIP recommends using a map<int32, google.rpc.Status> failed_requests field +to communicate partial failures, where the key is the index of the failed +request in the original batch request. The other options considered were:

+
    +
  • A repeated google.rpc.Status field. This was rejected because it is not + clear which entry corresponds to which request.
  • +
  • A map<string, google.rpc.Status> field, where the key is the request id of + the failed request. This was rejected because:
      +
    • Client will need to maintain a map of request_id -> request in order to use + the partial success response.
    • +
    • Populating a request id for the purpose of communicating errors could + conflict with AIP-155 if the service can not + guarantee idempotency for an individual request across multiple batch + requests.
    • +
    +
  • +
  • A repeated FailedRequest field, where FailedRequest contains the individual + create request and the google.rpc.Status. This was rejected because echoing + the request payload back in response is discouraged due to additional + challenges around user data sensitivity.
  • +
+

Changelog

+
    +
  • 2025-03-06: Changed recommendation to allow partial success, along with + detailed guidance
  • +
  • 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
  • +
  • 2020-09-16: Suggested annotating parent, names, and requests fields.
  • +
  • 2020-08-27: Removed parent recommendations for top-level resources.
  • +
  • 2020-03-27: Added reference to AIP-165 for criteria-based deletion.
  • +
  • 2019-10-11: Changed the primary recommendation to specify a repeated + string instead of a repeated standard Delete message. Moved the original + recommendation into its own section.
  • +
  • 2019-09-11: Fixed the wording about which child field the parent field + should match.
  • +
  • 2019-08-01: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/236.html b/236.html new file mode 100644 index 0000000000..28e9aac2b6 --- /dev/null +++ b/236.html @@ -0,0 +1,1095 @@ + + + + AIP-236: Policy preview + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-236

+

Policy preview

+

A policy is a resource that provides rules that admit or deny access to other +resources. Generally, the outcome of a policy can be evaluated to a specific set +of outcomes.

+

Changes to policies without proper validation may have unintended consequences +that can severely impact a customer’s overall infrastructure setup. To safely +update resources, it is beneficial to test these changes via policy rollout +APIs.

+

Preview is a rollout safety mechanism for policy resources, which gives the +customer the ability to validate the effect of their proposed changes against +production traffic prior to the changes going live. The result of the policy +evaluation against traffic is logged in order to give the customer the data +required to test the correctness of the change.

+

Firewall policies exemplify a case that is suitable for previewing. A new +configuration can be evaluated against traffic to observe which IPs would be +allowed or denied. This gives the customer the data to guide a decision on +whether to promote the proposed changes to live.

+

The expected flow for previewing a policy is as follows:

+
    +
  1. The user creates an experiment containing a new policy configuration + intended to replace the live policy.
  2. +
  3. The user uses the "startPreview" method to start generating logs which compare + the live and experiment policy evaluations against live traffic.
  4. +
  5. The user inspects the logs to determine whether the experiment has the + intended result.
  6. +
  7. The user uses the "commit" method to promote the experiment to live.
  8. +
+

Guidance

+

Non-goals

+

This proposal is for a safety mechanism for policy rollouts only. Safe rollouts +for non-policy resources are not in scope.

+

Experiments

+

A new configuration of a policy to be previewed is stored as a nested collection +under the policy. These nested collections are known as experiments.

+

A hypothetical policy resource called, Policy, is used throughout. It has the +following resource name pattern:

+

projects/{project}/locations/{location}/policies/{policy}

+

The experimental versions of the resource used for previewing or other safe +rollout practices are represented as a nested collection under Policy using a +new resource type. The resource type must follow the naming convention +RegularResourceTypeExperiment.

+

The following pattern is used for the experiment collection:

+

projects/{project}/locations/{location}/policies/{policy}/experiments/{experiment}

+

A proto used to represent an experiment must contain the following:

+
1. The required top-level fields for a resource, like `name` and `etag`
+2. The policy message that is being tested itself
+3. The field, `preview_metadata`, which contains metadata specific to
+   previewing the experiment of a specific resource type.
+
+
message PolicyExperiment {
+
+  // google.api.resource, name, and other annotations and fields
+
+  // The policy experiment. This Policy will be used to preview the effects of
+  // the change but will not affect live traffic.
+  Policy policy = 2;
+
+  // The metadata associated with this policy experiment.
+  PolicyPreviewMetadata preview_metadata = 3
+      [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Allows clients to store small amounts of arbitrary data.
+  map<string, string> annotations = 4;
+}
+
+
    +
  • The experiment proto must have a top-level field with the same type as the + live policy.
      +
    • It must be named as the live resource type. For example, if the + experiment is for FirewallPolicy, then this field must be named + firewall_policy.
    • +
    • The name inside the embedded policy message must be the name of the + live policy.
    • +
    +
  • +
  • When the user is ready to promote an experiment, they must copy the + policy message into the live policy and delete the experiment. This can be + done manually or via a "commit" custom method.
  • +
  • A product may support multiple experiments concurrently being previewed + for a single live policy.
      +
    • Each experiment must generate logs having each entry preceded by log_prefix + so that the user can compare the results of the experiment with the behavior + of the live policy.
    • +
    • The number of experimental configurations for a given live policy may be + capped at a certain number and the cap must be documented.
    • +
    +
  • +
  • Cascading deletes must occur: if the live policy is deleted, all + experiments must also be deleted.
  • +
  • map<string,string> annotations must allow clients + to store small amounts of arbitrary data.
  • +
+

Metadata

+

preview_metadata tracks all metadata of previewing the experiment. The +messages must follow the convention: RegularResourceTypePreviewMetadata. +This is so the proto can be defined uniquely for each resource type in the +same service with experiments.

+
message PolicyPreviewMetadata {
+  // Possible values of the state of previewing the experiment.
+  enum State {
+    // Default value. This value is unused.
+    STATE_UNDEFINED = 0;
+
+    // The experiment is actively previewing.
+    ACTIVE = 1;
+
+    // The previewing of the experiment has been stopped.
+    SUSPENDED = 2;
+  }
+
+  // The state of previewing the experiment.
+  State state = 1;
+
+  // An identifying string common to all logs generated when previewing the
+  // experiment. Searching all logs for this string will isolate the results.
+  string log_prefix = 2;
+
+  // The most recent time at which this experiment started previewing.
+  google.protobuf.Timestamp start_time = 3;
+
+  // The most recent time at which this experiment stopped previewing.
+  google.protobuf.Timestamp stop_time = 4;
+}
+
+
    +
  • PolicyPreviewMetadata must have the fields defined in the proto above.
      +
    • It may have additional fields if the service or resource requires it.
    • +
    +
  • +
  • When an experiment is first previewed, preview_metadata must be + absent.
      +
    • It is present on the experiment once the "startPreview" method is used.
    • +
    +
  • +
  • All preview_metadata fields must be output only.
  • +
  • state changes between ACTIVE and SUSPENDED when previewing is started + or stopped. This happens when the "startPreview" or "stopPreview custom methods + are invoked, respectively.
  • +
  • The first time the "startPreview" custom method is used, the system must + create preview_metadata and do the following:
      +
    • It must set the state to ACTIVE
    • +
    • It must populate start_time with the current time.
        +
      • start_time must be updated every time state is changed to + ACTIVE.
      • +
      +
    • +
    • It must set a system generated log_prefix string, which is a + predefined constant hard coded by the system developers.
    • +
    • The same value is used for previewing experiments for the given resource + type. For example, "FirewallPolicyPreviewLog" for FirewallPolicy.
    • +
    +
  • +
  • When the "stopPreview" custom method is used, the system must do the + following:
      +
    • It must set the state to SUSPENDED
    • +
    • It must populate the stop_time with the current time.
    • +
    +
  • +
+

Methods

+

create

+
    +
  • The resource must be created using long-running + Create and + google.longrunning.operation_info.response_type must be + PolicyExperiment.
  • +
  • Creating a new experiment to preview must support the following use +cases:
      +
    • Preview a new policy.
    • +
    • Preview an update to an already live policy.
    • +
    • Preview a deletion of a current policy.
    • +
    +
  • +
  • For the update and delete use cases, the policy field in the experiment + must have the full payload of the live policy copied into it, including + the name.
      +
    • The user must set the rules to the new intended state to preview an + update.
    • +
    • The user must set set the rules to represent a no-op to preview a + delete.
    • +
    +
  • +
  • To preview a new policy, the system must do the following:
      +
    • If the system does not support a nested collection without a live policy, + the user must create a live policy and set the rules to represent a + no-op. For example, the rules of a no-op policy may be empty.
        +
      • An experiment is created as a child of the no-op policy.
      • +
      +
    • +
    +
  • +
  • If the system supports previewing multiple experiments for a live policy, + calling "create" more than once must create multiple experiments.
  • +
+

update

+
    +
  • The resource must be updated using long-running + Update and + google.longrunning.operation_info.response_type must be + PolicyExperiment.
  • +
  • The name inside policy must not change but the other fields can in + order to change the experiment being previewed because this policy is + intended to replace the live policy, and the name of the live policy + must not change.
  • +
  • The system must set the state to SUSPENDED if the state was ACTIVE + at the time of an update.
      +
    • This is so the user can easily distinguish between different versions of + the experiment being previewed.
    • +
    +
  • +
+

get

+
    +
  • The standard method, Get, must be included for + PolicyExperiment resource types.
  • +
+

list

+
    +
  • The standard method, List, must be included for + PolicyExperiment resource types.
  • +
  • Filtering on PolicyPreviewMetadata indicates which experiments are actively + previewed.
      +
    • For example, the following filter string returns a List response with + experiments being previewed: preview_metadata.state = ACTIVE.
    • +
    +
  • +
+

delete

+
    +
  • The resource must be deleted using long-running + Delete and + google.longrunning.operation_info.response_type must be + PolicyExperiment.
  • +
+

startPreview

+
// Starts previewing a PolicyExperiment. This triggers the system to start
+// generating logs to evaluate the PolicyExperiment.
+rpc StartPreviewPolicyExperiment(StartPreviewPolicyExperimentRequest)
+    returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{name=policies/*/experiments/*}:startPreview"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "PolicyExperiment"
+    metadata_type: "StartPreviewPolicyExperimentMetadata"
+  };
+}
+
+// The request message for the startPreview custom method.
+message StartPreviewPolicyExperimentRequest {
+  // The name of the PolicyExperiment.
+  string name = 1;
+}
+
+
    +
  • This custom method is required.
  • +
  • google.longrunning.Operation.metadata_type must follow guidance on + Long-running operations
  • +
  • This method must trigger the system to start generating logs to preview + the experiment.
  • +
  • Whenever the method is called successfully, the system must set the + following values in the PolicyPreviewMetadata:
      +
    • log_prefix to the predefined constant.
    • +
    • start_time to the current time
    • +
    • state to ACTIVE.
    • +
    +
  • +
  • If the method is called on an experiment with the rules representing a no-op, + then the system must preview the deletion of the live policy.
  • +
+

stopPreview

+
// Stops previewing a PolicyExperiment. This triggers the system to stop
+// generating logs to evaluate the PolicyExperiment.
+rpc StopPreviewPolicyExperiment(StopPreviewPolicyExperimentRequest)
+    returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{name=policies/*/experiments/*}:stopPreview"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "PolicyExperiment"
+    metadata_type: "StopPreviewPolicyExperimentMetadata"
+  };
+}
+
+// The request message for the stopPreview custom method.
+message StopPreviewPolicyExperimentRequest {
+  // The name of the PolicyExperiment.
+  string name = 1;
+}
+
+
    +
  • This custom method is required.
  • +
  • google.longrunning.Operation.metadata_type must follow guidance on + Long-running operations
  • +
  • This method must trigger the system to stop generating logs to preview the + experiment.
  • +
  • Whenever the method is called successfully, the system must set the + following values in the PolicyPreviewMetadata:
      +
    • stop_time to the current time
    • +
    • state to SUSPENDED
    • +
    +
  • +
+

commit

+

The resource may expose a new custom method called "commit" to promote an +experiment. The system copies policy from the experiment into the live policy +and then deletes the experiment.

+

Declarative clients may manually copy fields from an experiment into the +live policy and then delete the experiment rather than calling "commit" if +preferable.

+
// Commits a PolicyExperiment. This copies the PolicyExperiment's policy message
+// to the live policy then deletes the PolicyExperiment.
+rpc CommitPolicyExperiment(CommitPolicyExperimentRequest)
+    returns (google.longrunning.Operation) {
+  option (google.api.http) = {
+    post: "/v1/{name=policies/*/experiments/*}:commit"
+    body: "*"
+  };
+  option (google.longrunning.operation_info) = {
+    response_type: "google.protobuf.Empty"
+    metadata_type: "CommitPolicyExperimentMetadata"
+  };
+}
+
+// The request message for the commit custom method.
+message CommitPolicyExperimentRequest {
+  string name = 1;
+  string etag = 2;
+  string parent_etag = 3;
+}
+
+
    +
  • google.longrunning.Operation.metadata_type must follow guidance on + Long-running operations
  • +
  • The method must atomically copy policy from the experiment into the live + policy, and then delete the experiment.
  • +
  • If any experiment fails "commit", previewing it must not stop, and the + live policy must not be updated.
  • +
  • The method can be called on an experiment in any state.
  • +
  • The etag must match that of the experiment in order for commit to be + successful. This is so the user does not commit an unintended version of the + experiment.
      +
    • If no etag is provided, the API must not succeed to prevent the user + from unintentionally committing a different version of the experiment as + intended.
    • +
    • A parent_etag may be provided to guarantee that the experiment + overwrites a specific version of the live policy.
    • +
    +
  • +
  • The method is not idempotent and calling it twice on the same experiment + must return a 404 NOT_FOUND as the experiment is deleted as part of the + first call.
  • +
+

Changes to live policy API methods

+

delete

+
    +
  • A delete of the live policy must delete all experiments.
  • +
  • To maintain the experiments while negating the effect of the live policy, the + live policy must be changed to a no-op policy instead of using this + method.
  • +
+

Logging

+

Logging is crucial for the user to evaluate whether an experiment should be +promoted to live.

+

Logs must contain the results of the evaluated experiment, the etag +associated with that experiment alongside that of the live policy, and be +preceded by the value of log_prefix. + - The etag fields help the user identify which + configurations of the live and experiment are evaluated in the log. + - log_prefix helps the user separate logs specifically generated for + previewing the experiment from other use cases.

+

Overall, these logs help the user make a decision about whether to promote the +experiment to live.

+

Changelog

+
    +
  • 2023-04-27: Methods for start and stop renamed. State to enum. Annotations + added.
  • +
  • 2023-03-30: Initial AIP written.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/2510.html b/2510.html new file mode 100644 index 0000000000..f9bf570fa0 --- /dev/null +++ b/2510.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2602.html b/2602.html new file mode 100644 index 0000000000..721de2b7ff --- /dev/null +++ b/2602.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2603.html b/2603.html new file mode 100644 index 0000000000..c55202bce9 --- /dev/null +++ b/2603.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2604.html b/2604.html new file mode 100644 index 0000000000..c4104955ba --- /dev/null +++ b/2604.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2712.html b/2712.html new file mode 100644 index 0000000000..9122e48dd4 --- /dev/null +++ b/2712.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2713.html b/2713.html new file mode 100644 index 0000000000..d69a5ee382 --- /dev/null +++ b/2713.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2715.html b/2715.html new file mode 100644 index 0000000000..e0fe81fb71 --- /dev/null +++ b/2715.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2716.html b/2716.html new file mode 100644 index 0000000000..49d7c4c152 --- /dev/null +++ b/2716.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2717.html b/2717.html new file mode 100644 index 0000000000..7ec98475e2 --- /dev/null +++ b/2717.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/2718.html b/2718.html new file mode 100644 index 0000000000..0222bdf06b --- /dev/null +++ b/2718.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3.html b/3.html new file mode 100644 index 0000000000..bb86a14e66 --- /dev/null +++ b/3.html @@ -0,0 +1,738 @@ + + + + AIP-3: AIP Versioning + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-3

+

AIP Versioning

+

This AIP defines the versioning scheme of the AIPs.

+

Guidance

+
    +
  • The AIPs must be versioned by date, using the ISO-8601 format of + YYYY-MM-DD, that corresponds to the + date the version was added.
  • +
  • AIPs versions must be available as a tag on the source control system used + to store the AIPs, of the format v{version}. Example: v2023-03-28.
  • +
  • The AIPs must have a new version when there is a significant change to one + or more AIPs.
  • +
  • Each AIP must include a changelog section, with the date the change was + made and a short description.
  • +
+

Rationale

+

Versions serve as reference points to AIPs at a specific point in time. They are +crucial since guidance on an AIP can be reversed, or include significant changes +such that they are no longer similar to the original design. APIs using AIPs may +need to reference older AIP guidance to justify their design choice.

+

Rationale for date-based versioning

+

With date-based versioning, a client can easily find the AIP guidance at the +time an API was authored.

+

Why not individually versioned AIPs

+

An alternative to a universal version is to have specific versions attached to +each AIP.

+

AIPs often cross-reference one another. If each AIP had a specific version, then +cross-references would also have to specify specific versions of those +referenced AIPs to provide complete guidance.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/3001.html b/3001.html new file mode 100644 index 0000000000..8e14ac43f0 --- /dev/null +++ b/3001.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3010.html b/3010.html new file mode 100644 index 0000000000..06f3e2b575 --- /dev/null +++ b/3010.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3020.html b/3020.html new file mode 100644 index 0000000000..fdc39c777e --- /dev/null +++ b/3020.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3021.html b/3021.html new file mode 100644 index 0000000000..49942fa5d7 --- /dev/null +++ b/3021.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3022.html b/3022.html new file mode 100644 index 0000000000..863337c738 --- /dev/null +++ b/3022.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3201.html b/3201.html new file mode 100644 index 0000000000..fe01bcb7e0 --- /dev/null +++ b/3201.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3260.html b/3260.html new file mode 100644 index 0000000000..28a4907c05 --- /dev/null +++ b/3260.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3270.html b/3270.html new file mode 100644 index 0000000000..ef4d02fa3a --- /dev/null +++ b/3270.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3271.html b/3271.html new file mode 100644 index 0000000000..6a7dd8d30f --- /dev/null +++ b/3271.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3272.html b/3272.html new file mode 100644 index 0000000000..14e691b5ad --- /dev/null +++ b/3272.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3273.html b/3273.html new file mode 100644 index 0000000000..179906bd1b --- /dev/null +++ b/3273.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3274.html b/3274.html new file mode 100644 index 0000000000..c6812485f5 --- /dev/null +++ b/3274.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3275.html b/3275.html new file mode 100644 index 0000000000..d8715f8e0a --- /dev/null +++ b/3275.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/3276.html b/3276.html new file mode 100644 index 0000000000..434cbfc48d --- /dev/null +++ b/3276.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4110.html b/4110.html new file mode 100644 index 0000000000..9620f07af1 --- /dev/null +++ b/4110.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4111.html b/4111.html new file mode 100644 index 0000000000..3683b7acf8 --- /dev/null +++ b/4111.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4112.html b/4112.html new file mode 100644 index 0000000000..a539e5501f --- /dev/null +++ b/4112.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4113.html b/4113.html new file mode 100644 index 0000000000..7a6f7f5973 --- /dev/null +++ b/4113.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4114.html b/4114.html new file mode 100644 index 0000000000..91c96e96da --- /dev/null +++ b/4114.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4115.html b/4115.html new file mode 100644 index 0000000000..3919e18325 --- /dev/null +++ b/4115.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4116.html b/4116.html new file mode 100644 index 0000000000..4f396d5d35 --- /dev/null +++ b/4116.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4117.html b/4117.html new file mode 100644 index 0000000000..ff76ac974f --- /dev/null +++ b/4117.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4118.html b/4118.html new file mode 100644 index 0000000000..3d51b8bc2f --- /dev/null +++ b/4118.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4119.html b/4119.html new file mode 100644 index 0000000000..71200fd768 --- /dev/null +++ b/4119.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4210.html b/4210.html new file mode 100644 index 0000000000..4a905c37b9 --- /dev/null +++ b/4210.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4221.html b/4221.html new file mode 100644 index 0000000000..173dcc6dde --- /dev/null +++ b/4221.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4222.html b/4222.html new file mode 100644 index 0000000000..72d903ac46 --- /dev/null +++ b/4222.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4223.html b/4223.html new file mode 100644 index 0000000000..286aef9aec --- /dev/null +++ b/4223.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4231.html b/4231.html new file mode 100644 index 0000000000..90750c87f8 --- /dev/null +++ b/4231.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4232.html b/4232.html new file mode 100644 index 0000000000..99e0a14a37 --- /dev/null +++ b/4232.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4233.html b/4233.html new file mode 100644 index 0000000000..ded8136602 --- /dev/null +++ b/4233.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4234.html b/4234.html new file mode 100644 index 0000000000..e1af5781f2 --- /dev/null +++ b/4234.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4235.html b/4235.html new file mode 100644 index 0000000000..6d7a1bc350 --- /dev/null +++ b/4235.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4236.html b/4236.html new file mode 100644 index 0000000000..53011fe486 --- /dev/null +++ b/4236.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/4290.html b/4290.html new file mode 100644 index 0000000000..006c71eb7a --- /dev/null +++ b/4290.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ Click here if you are not redirected. + + \ No newline at end of file diff --git a/8.html b/8.html new file mode 100644 index 0000000000..a18a3a8e12 --- /dev/null +++ b/8.html @@ -0,0 +1,935 @@ + + + + AIP-8: AIP Style and Guidance + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-8

+

AIP Style and Guidance

+

AIP stands for API Improvement Proposal, which is a design document +providing high-level, concise documentation for API design and development. The +goal is for these documents to serve as the source of truth for API-related +documentation at Google and the way API teams discuss and come to consensus on +API guidance.

+

AIPs are most useful when they are clear and concise, and cover a single topic +or inquiry well. In the same way that AIPs describe consistent patterns and +style for use in APIs, they also follow consistent patterns and style.

+

Guidance

+
    +
  • AIPs must cover a single, discrete topic, and provide clear, actionable + guidance.
  • +
  • AIPs must not duplicate or contradict guidance in another AIP.
  • +
  • AIPs may also cover what not to do, but should not cover only + anti-patterns.
  • +
  • If AIP guidance is conditional (e.g. a design pattern such as Jobs), the + guidance must clearly explain under what conditions the guidance should be + followed.
  • +
+

Guidance contained within an AIP must be beneficial to one or more +types of clients or their authors, including but not limited to:

+
    +
  • Asset inventories which can be used to audit and analyze resources.
  • +
  • Command line interfaces for exploration and simple automation.
  • +
  • Custom controllers (e.g. auto-scalers) which poll live state and adjust + resource configuration accordingly.
  • +
  • IaC clients for orchestration and automation of multiple resources.
  • +
  • Recommendation tools which provide guidance on which APIs are useful for + specific use cases, and how to use them.
  • +
  • SDKs to interact with an API from a programming language, often used heavily + for data-plane operations.
  • +
  • Security orchestration, automation, and remediation tools.
  • +
  • Simple scripts to automate or orchestrate tasks.
  • +
  • Test frameworks.
  • +
  • Tools that operate on resource data at rest.
  • +
  • Visual User Interfaces for visualization and one-off manual actions.
  • +
  • Users.
  • +
+

Examples of improvements include:

+
    +
  • Requiring new proto annotations that enable more descriptive interfaces on + clients (e.g. requiring singular and plural on a google.api.resource + annotation).
  • +
+

AIP guidance must not be a significant detriment to a client's usability or +implementation difficulty, or maintenance difficulty.

+

Examples of detriments include:

+
    +
  • Introduction of a non-uniform pattern in a standard method such that all + clients must introduce additional code without sufficient benefit (e.g. List + behaves like this except for resources that start with the name Foo).
  • +
  • Renames of well-established fields for minor improvements in readability (e.g. + rename expire_time to lapse_time since lapse is a common term in my + service).
  • +
+

While the length of AIPs will necessarily vary based on the complexity of the +question, most AIPs should be able to cover their content in roughly two +printed pages.

+

File structure

+

AIPs must be written in Markdown, and must be named using their +four-digit number (example: 0008.md). AIPs that serve a specific scope +must be in the subdirectory for that scope.

+

AIPs must have appropriate front matter.

+
---
+id: 8
+state: reviewing
+created: 2019-05-28
+permalink: /8
+redirect_from:
+  - /08
+  - /008
+  - /0008
+---
+
+

Front matter for AIPs must include:

+
    +
  • The aip key:
      +
    • id: Required. The ID for the given AIP, as an integer.
    • +
    • state: Required. The current state of the AIP, in all lower-case. The + valid states are listed in AIP-1, and common states are draft, + reviewing, and approved.
    • +
    • created: Required. The ISO-8601 date (yyyy-mm-dd) when the AIP was + originally drafted, with no quotes.
    • +
    • updated: The ISO-8601 date (yyyy-mm-dd) when the AIP was last revised.
    • +
    • scope: The scope for the AIP. This must match the directory name for + that scope. Required for AIPs with IDs >= 1000, prohibited otherwise.
    • +
    +
  • +
  • The permalink key (required): This must be set to + /{aip.scope}/{aip.id}. If there is no scope, use /{aip.id} instead.
  • +
  • The redirect_from key: This should include a list of any /{aip.id} + permutations that a reader would be likely to enter, including:
      +
    • /{aip.id} (for AIPs where the permalink includes the scope)
    • +
    • AIP IDs with zero-padding, for each level of zero-padding up to four digits + (for example: /08, /008, /0008).
    • +
    +
  • +
+

Document structure

+

AIPs must begin with a top-level heading with the AIP's title (# Title). +The title should be a noun (not an imperative). For example, "Bad API +precedents" not "Avoid breaking API precedent".

+

AIPs should then begin with an introduction (with no additional heading), +followed by a ## Guidance heading. If necessary, the AIP may include any +of the following after the guidance, in the following order:

+
    +
  • "Further reading" is a bulleted list of links to other AIPs that are useful to + fully understand the current AIP.
  • +
  • "Appendices" covering further explanation in the same AIP. These are + relatively rare but are important in cases where an AIP requires a lot of + justification for the decision. Often this is primarily an explanation of + alternatives considered to help explain the guidance.
  • +
  • "Changelog" is a bulleted list of changes made to the AIP since the first + writing.
  • +
+

The guidance section may include subsections that elaborate further on +details. Subsections will automatically create an entry in the table of +contents, and an anchor for citations.

+

Below is an example AIP shell that uses each major section:

+
# AIP title
+
+The introductory text explains the background and reason why the AIP exists. It
+lays out the basic question, but does not tell the reader what to do.
+
+## Guidance
+
+The "guidance" section helps the reader know what to do. A common format for
+the guidance section is a high-level imperative, followed by an example,
+followed by a bulleted list explaining the example.
+
+### Subsection
+
+Individual subsections can be cited individually, and further elaborate
+details.
+
+## Rationale
+
+The "rationale" section is optional, and helps the reader understand the
+motivation behind specific guidance within the AIP.
+
+Deeper explanations of design justification and tradeoffs **must** be in the
+rationale instead of other sections, to ensure the rest of the document acts as
+an easily actionable reference.
+
+## History
+
+The "history" section is optional, and documents events and context around a
+significant edit to an AIP. For example, explanation of rewrite would be
+included in this section
+
+While the changelog is a dotted list of one-line summaries of changes to an AIP,
+the history section should elaborate on significant events in a descriptive
+format.
+
+The section **must not** be used to exhaustively enumerate all changes. This
+is what the changelog provides.
+
+## Further reading
+
+A bulleted list of (usually) other AIPs, in the following format:
+
+- [AIP-1](/1): AIP purpose and guidelines
+
+## Changelog
+
+A bulleted list of changes in reverse chronological order, using the following
+format:
+
+- **2020-02-18**: Specified ordering.
+- **2019-07-01**: Added a subsection clarifying XYZ.
+
+

AIPs should attempt to follow this overall format if possible, but AIPs +may deviate from it if necessary (in particular, if the AIP would be more +difficult to understand, even for a reader already accustomed to reading AIPs in +the usual format).

+

Note: Except for the title, AIPs must only use the second heading level +(##) and above. AIPs should only use the second and third heading levels +(##, ###).

+

Requirement keywords

+

AIPs should use the following requirement level keywords: "MUST", "MUST +NOT", "SHOULD", "SHOULD NOT", and "MAY", which are to be interpreted as +described in RFC 2119.

+

When using these terms in AIPs, they must be lower-case and bold. These +terms should not be used in other ways.

+

If "SHOULD" or "SHOULD NOT" are used, they must include valid examples of +where other concerns may override the guidance.

+

Important: If rationale is used, it exists to provide background and a more +complete understanding, but must not contain guidance (and RFC-2119 terms +must not be used).

+

Code examples

+

API design examples in AIPs should use protocol buffers. Examples +should cover only enough syntax to explain the concept. When using RPCs in +examples, a google.api.http annotation should be included.

+

Referencing AIPs

+

When AIPs reference other AIPs, the prosaic text must use the format +AIP-XXXX without zero-padding (e.g., [AIP-8](/8), not AIP-0008), and must +link to the relevant AIP. AIP links may point to a particular section of the +AIP if appropriate.

+

Important: AIP links must use the relative path to the file in the +repository (such as /8 for core AIPs, or /8 for AIPs in a +subdirectory); this ensures that the link works both on the AIP site, when +viewing the Markdown file on GitHub, using the local development server, or a +branch.

+

Rationale

+

Designing for a broad set of clients

+

API guidance, similar to any software, is most beneficial when there is a clear +purpose and target beneficiary.

+

The beneficiaries of improved API design are users. These users interact with +APIs via a variety of clients, depending on their use case as enumerated above.

+

API guidance must in turn consider the impact broadly across these clients.

+

Changelog

+
    +
  • 2023-05-20: Increase API guidance scope to include broad set of clients.
  • +
  • 2023-03-30: Removed appendix, added rationale and history to the template.
  • +
  • 2020-02-18: Specified reverse chronological ordering for changelog items.
  • +
  • 2019-08-23: Added guidance for internal AIP links.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/9.html b/9.html new file mode 100644 index 0000000000..ee6051a0cd --- /dev/null +++ b/9.html @@ -0,0 +1,845 @@ + + + + AIP-9: Glossary + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-9

+

Glossary

+

In the name of brevity, this AIP defines some common terminology here rather +than in each AIP individually.

+

Guidance

+

The following terminology should be used consistently throughout AIPs.

+

API

+

Application programming interface. This can be a local interface (such as a +client library) or a Network API (defined below).

+

API backend

+

A set of servers and related infrastructure that implements the business logic +for an API service. An individual API backend server is often called an API +server.

+

API consumer

+

The entity that consumes an API service. For Google APIs, it typically is a +Google project that owns the client application or the server resource.

+

API definition

+

The definition of an API, usually defined in a Protocol Buffer service. An API +definition can be implemented by any number of API services.

+

API frontend

+

A set of servers plus related infrastructure that provides common functionality +across API services, such as load balancing and authentication. An individual +API frontend server is often called an API proxy.

+

Note: the API frontend and the API backend may run next to each other or far +away from each other. In some cases, they can be compiled into a single +application binary and run inside a single process.

+

API interface

+

The element of an API specification IDL that groups API methods, such as a +Protocol Buffers service definition. It is typically mapped to a similar high +level grouping mechanism in most programming languages, like a class or +interface.

+

API method

+

An individual operation within an API. It is typically represented in Protocol +Buffers by an rpc definition, and is mapped to a function in the API in most +programming languages.

+

API producer

+

The entity that produces an API service. For Google APIs, it typically is a +Google team responsible for the API service.

+

API product

+

An API service and its related components, such as Terms of Service, +documentation, client libraries, and service support, are collectively presented +to customers as a API product. For example, Google Calendar API.

+

Note: people sometimes refer to an API product simply as an API.

+

API service

+

A deployed implementation of one or more APIs, exposed on one or more network +addresses, such as the Cloud Pub/Sub API.

+

API service definition

+

The combination of API definitions (.proto files) and API service +configurations (.yaml files) used to define an API service. The schema for +Google API service definition is google.api.Service.

+

API service endpoint

+

Refers to a network address that an API service uses to handle incoming API +requests. One API service may have multiple API service endpoints, such as +https://pubsub.googleapis.com and https://content-pubsub.googleapis.com.

+

API service name

+

Refers to the logical identifier of an API service. Google APIs use RFC 1035 DNS +compatible names as their API service names, such as pubsub.googleapis.com.

+

API title

+

Refers to the user-facing product title of an API service, such as "Cloud Pub/Sub +API".

+

API request

+

A single invocation of an API method. It is often used as the unit for billing, +logging, monitoring, and rate limiting.

+

API version

+

The version of an API or a group of APIs if they are defined together. An API +version is often represented by a string, such as "v1", and presents in API +requests and Protocol Buffers package names.

+

Client

+

Clients are programs that perform a specific tasks by calling an API or generic +tools, such as CLIs, that expose the API in a user-accessible fashion or operate +on resource data at rest.

+

Examples of clients include the following:

+
    +
  • Command line interfaces
  • +
  • Libraries, such as an SDK for a particular programming language
  • +
  • Scripts that operates on a JSON representation of a resource after reading it + from an API
  • +
  • Tools, such as a Declarative clients
  • +
  • Visual UIs, such as a web application
  • +
+

Google API

+

A Network API exposed by a Google service. Most of these are hosted on the +googleapis.com domain. It does not include other types of APIs, such as client +libraries and SDKs.

+

Declarative Clients

+

Declarative Clients, also known as Infrastructure as Code (IaC), describes a +category of clients that consumes a markup language or code that represents +resources exposed by an API, and executes the appropriate imperative actions to +drive the resource to that desired state. To determine what changes to make and +if a set of updates was successful a declarative client compares server side +resource attributes with client defined values. The comparison feature ensures +accuracy of a creation or an update but it requires services to treat the client +set fields as read-only and diligently preserve those values.

+

Examples of complexities that declarative clients abstract away include:

+
    +
  • Determining the appropriate imperative action (create / update / delete) to + achieve desired state.
  • +
  • Ordering of these imperative actions.
  • +
+

Terraform is an example of such a client.

+

User

+

A human being which is using an API directly, such as with cURL. This term is +defined to differentiate usage in the AIPs between a human user and a +programmatic client.

+

Network API

+

An API that operates across a network of computers. Network APIs communicate +using network protocols including HTTP, and are frequently produced by +organizations separate from those that consume them.

+

Changelog

+
    +
  • 2025-08-13: Add API inteface entry
  • +
  • 2024-12-18: Downcase headings and terms as per dev docs style
  • +
  • 2024-10-23: Add API Title entry
  • +
  • 2023-07-24: Rename IaC to Declarative Clients
  • +
  • 2023-04-01: Adding definition of IaC
  • +
  • 2023-03-24: Reformatting content to include anchor links.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index b1e89518b8..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,81 +0,0 @@ -# Contributing - -We'd love to accept your patches and contributions to this project. - -## Development Environment - -If you are contributing AIP content (rather than code) and want to be able to -view it in your browser, the easiest way to do so is to run the provided -development server. - -We use [GitHub Pages][1] to make this documentation available, and a specific -[site generator][2] to build the site. - -If you have [Docker][3] installed, clone this repository and run the `serve.sh` -file at the root of the repository. This script does two things: - -- It builds the provided Docker image (unless you already have it) and tags it - as `aip-site`. -- It runs the `aip-site` image. - -The development server uses port 4000; point your web browser to -`http://localhost:4000`, and you should see the site. - -**Note:** After building the Docker image for the first time, you may -experience issues if Python dependencies change underneath you. If this -happens, remove your Docker image (`docker rmi aip-site`) and run `serve.sh` -again. - -### Arguments - -Any arguments provided to `serve.sh` (or `docker run`) are forwarded (however, -the current site generator does not honor any; this may change in the future). - -### Hot reloading - -The development server recognizes when files change (including static files) -and local changes will be automatically reflected in your browser upon reload. - -### Local Installation - -It is possible to run the development server locally also. The general gist of -how to do so correctly is: - -- Install Python 3.8 if you do not already have it (direct install is fine, but - [pyenv][5] is probably the best way if you have other Python projects). -- Create a Python 3.8 [venv][6]. Once it is created, activate it in your shell - (`source path/to/venv/bin/activate`). -- `pip install git+https://github.com/aip-dev/site-generator.git` -- `aip-site-serve .` - -## Contributor License Agreement - -Contributions to this project must be accompanied by a Contributor License -Agreement. You (or your employer) retain the copyright to your contribution, -this simply gives us permission to use and redistribute your contributions as -part of the project. Head over to to see -your current agreements on file or to sign a new one. - -You generally only need to submit a CLA once, so if you have already submitted -one (even if it was for a different project), you probably do not need to do it -again. - -## Code reviews - -All submissions, including submissions by project members, require review. We -use GitHub pull requests for this purpose. Consult -[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more -information on using pull requests. - -### Formatting - -We use [prettier][4] to format Markdown, JavaScript, and (most) HTML, in order -to ensure a consistent style throughout our source. You can add prettier as a -plugin in most development environments. - -[1]: https://pages.github.com/ -[2]: https://github.com/aip-dev/site-generator -[3]: https://docker.com/ -[4]: https://prettier.io/ -[5]: https://github.com/pyenv/pyenv -[6]: https://docs.python.org/3/library/venv.html diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a83adef2ce..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM python:3.8-alpine - -# Define the working directory. -# Note: There is no code here; it is pulled from the repository by mounting -# the directory (see `serve.sh`). -WORKDIR /code/ - -# Install Python packages for this project. -COPY requirements.txt /code/requirements.txt -RUN apk add git && \ - pip install -r requirements.txt && \ - apk del git - -# Set environment variables. -ENV FLASK_ENV development - -# Expose appropriate ports. -EXPOSE 4000 -EXPOSE 35729 - -# Run the development server. -# Reminder: Use -p with `docker run` to publish ports (see `serve.sh`). -ENTRYPOINT ["aip-site-serve", "."] diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 00b03d3de7..0000000000 --- a/LICENSE.md +++ /dev/null @@ -1,543 +0,0 @@ -Except as otherwise noted, the content of this repository is licensed under the -[Creative Commons Attribution 4.0 License][1], and code samples are licensed -under the [Apache 2.0 License][2]. For details, see the developer.google.com -[Site Policies][3]. - - [1]: https://creativecommons.org/licenses/by/4.0/ - [2]: https://www.apache.org/licenses/LICENSE-2.0 - [3]: https://developers.google.com/terms/site-policies - ---- - -The Creative Commons Attribution 4.0 License reads: - -``` -Creative Commons Attribution 4.0 International Public License - -By exercising the Licensed Rights (defined below), You accept and agree -to be bound by the terms and conditions of this Creative Commons -Attribution 4.0 International Public License ("Public License"). To the -extent this Public License may be interpreted as a contract, You are -granted the Licensed Rights in consideration of Your acceptance of -these terms and conditions, and the Licensor grants You such rights in -consideration of benefits the Licensor receives from making the -Licensed Material available under these terms and conditions. - - -Section 1 -- Definitions. - - a. Adapted Material means material subject to Copyright and Similar - Rights that is derived from or based upon the Licensed Material - and in which the Licensed Material is translated, altered, - arranged, transformed, or otherwise modified in a manner requiring - permission under the Copyright and Similar Rights held by the - Licensor. For purposes of this Public License, where the Licensed - Material is a musical work, performance, or sound recording, - Adapted Material is always produced where the Licensed Material is - synched in timed relation with a moving image. - - b. Adapter's License means the license You apply to Your Copyright - and Similar Rights in Your contributions to Adapted Material in - accordance with the terms and conditions of this Public License. - - c. Copyright and Similar Rights means copyright and/or similar rights - closely related to copyright including, without limitation, - performance, broadcast, sound recording, and Sui Generis Database - Rights, without regard to how the rights are labeled or - categorized. For purposes of this Public License, the rights - specified in Section 2(b)(1)-(2) are not Copyright and Similar - Rights. - - d. Effective Technological Measures means those measures that, in the - absence of proper authority, may not be circumvented under laws - fulfilling obligations under Article 11 of the WIPO Copyright - Treaty adopted on December 20, 1996, and/or similar international - agreements. - - e. Exceptions and Limitations means fair use, fair dealing, and/or - any other exception or limitation to Copyright and Similar Rights - that applies to Your use of the Licensed Material. - - f. Licensed Material means the artistic or literary work, database, - or other material to which the Licensor applied this Public - License. - - g. Licensed Rights means the rights granted to You subject to the - terms and conditions of this Public License, which are limited to - all Copyright and Similar Rights that apply to Your use of the - Licensed Material and that the Licensor has authority to license. - - h. Licensor means the individual(s) or entity(ies) granting rights - under this Public License. - - i. Share means to provide material to the public by any means or - process that requires permission under the Licensed Rights, such - as reproduction, public display, public performance, distribution, - dissemination, communication, or importation, and to make material - available to the public including in ways that members of the - public may access the material from a place and at a time - individually chosen by them. - - j. Sui Generis Database Rights means rights other than copyright - resulting from Directive 96/9/EC of the European Parliament and of - the Council of 11 March 1996 on the legal protection of databases, - as amended and/or succeeded, as well as other essentially - equivalent rights anywhere in the world. - - k. You means the individual or entity exercising the Licensed Rights - under this Public License. Your has a corresponding meaning. - - -Section 2 -- Scope. - - a. License grant. - - 1. Subject to the terms and conditions of this Public License, - the Licensor hereby grants You a worldwide, royalty-free, - non-sublicensable, non-exclusive, irrevocable license to - exercise the Licensed Rights in the Licensed Material to: - - a. reproduce and Share the Licensed Material, in whole or - in part; and - - b. produce, reproduce, and Share Adapted Material. - - 2. Exceptions and Limitations. For the avoidance of doubt, where - Exceptions and Limitations apply to Your use, this Public - License does not apply, and You do not need to comply with - its terms and conditions. - - 3. Term. The term of this Public License is specified in Section - 6(a). - - 4. Media and formats; technical modifications allowed. The - Licensor authorizes You to exercise the Licensed Rights in - all media and formats whether now known or hereafter created, - and to make technical modifications necessary to do so. The - Licensor waives and/or agrees not to assert any right or - authority to forbid You from making technical modifications - necessary to exercise the Licensed Rights, including - technical modifications necessary to circumvent Effective - Technological Measures. For purposes of this Public License, - simply making modifications authorized by this Section 2(a) - (4) never produces Adapted Material. - - 5. Downstream recipients. - - a. Offer from the Licensor -- Licensed Material. Every - recipient of the Licensed Material automatically - receives an offer from the Licensor to exercise the - Licensed Rights under the terms and conditions of this - Public License. - - b. No downstream restrictions. You may not offer or impose - any additional or different terms or conditions on, or - apply any Effective Technological Measures to, the - Licensed Material if doing so restricts exercise of the - Licensed Rights by any recipient of the Licensed - Material. - - 6. No endorsement. Nothing in this Public License constitutes or - may be construed as permission to assert or imply that You - are, or that Your use of the Licensed Material is, connected - with, or sponsored, endorsed, or granted official status by, - the Licensor or others designated to receive attribution as - provided in Section 3(a)(1)(A)(i). - - b. Other rights. - - 1. Moral rights, such as the right of integrity, are not - licensed under this Public License, nor are publicity, - privacy, and/or other similar personality rights; however, to - the extent possible, the Licensor waives and/or agrees not to - assert any such rights held by the Licensor to the limited - extent necessary to allow You to exercise the Licensed - Rights, but not otherwise. - - 2. Patent and trademark rights are not licensed under this - Public License. - - 3. To the extent possible, the Licensor waives any right to - collect royalties from You for the exercise of the Licensed - Rights, whether directly or through a collecting society - under any voluntary or waivable statutory or compulsory - licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties. - - -Section 3 -- License Conditions. - -Your exercise of the Licensed Rights is expressly made subject to the -following conditions. - - a. Attribution. - - 1. If You Share the Licensed Material (including in modified - form), You must: - - a. retain the following if it is supplied by the Licensor - with the Licensed Material: - - i. identification of the creator(s) of the Licensed - Material and any others designated to receive - attribution, in any reasonable manner requested by - the Licensor (including by pseudonym if - designated); - - ii. a copyright notice; - - iii. a notice that refers to this Public License; - - iv. a notice that refers to the disclaimer of - warranties; - - v. a URI or hyperlink to the Licensed Material to the - extent reasonably practicable; - - b. indicate if You modified the Licensed Material and - retain an indication of any previous modifications; and - - c. indicate the Licensed Material is licensed under this - Public License, and include the text of, or the URI or - hyperlink to, this Public License. - - 2. You may satisfy the conditions in Section 3(a)(1) in any - reasonable manner based on the medium, means, and context in - which You Share the Licensed Material. For example, it may be - reasonable to satisfy the conditions by providing a URI or - hyperlink to a resource that includes the required - information. - - 3. If requested by the Licensor, You must remove any of the - information required by Section 3(a)(1)(A) to the extent - reasonably practicable. - - 4. If You Share Adapted Material You produce, the Adapter's - License You apply must not prevent recipients of the Adapted - Material from complying with this Public License. - - -Section 4 -- Sui Generis Database Rights. - -Where the Licensed Rights include Sui Generis Database Rights that -apply to Your use of the Licensed Material: - - a. for the avoidance of doubt, Section 2(a)(1) grants You the right - to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database; - - b. if You include all or a substantial portion of the database - contents in a database in which You have Sui Generis Database - Rights, then the database in which You have Sui Generis Database - Rights (but not its individual contents) is Adapted Material; and - - c. You must comply with the conditions in Section 3(a) if You Share - all or a substantial portion of the contents of the database. - -For the avoidance of doubt, this Section 4 supplements and does not -replace Your obligations under this Public License where the Licensed -Rights include other Copyright and Similar Rights. - - -Section 5 -- Disclaimer of Warranties and Limitation of Liability. - - a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE - EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS - AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF - ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, - IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, - WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, - ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT - KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT - ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. - - b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE - TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, - NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, - INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, - COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR - USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR - DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR - IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. - - c. The disclaimer of warranties and limitation of liability provided - above shall be interpreted in a manner that, to the extent - possible, most closely approximates an absolute disclaimer and - waiver of all liability. - - -Section 6 -- Term and Termination. - - a. This Public License applies for the term of the Copyright and - Similar Rights licensed here. However, if You fail to comply with - this Public License, then Your rights under this Public License - terminate automatically. - - b. Where Your right to use the Licensed Material has terminated under - Section 6(a), it reinstates: - - 1. automatically as of the date the violation is cured, provided - it is cured within 30 days of Your discovery of the - violation; or - - 2. upon express reinstatement by the Licensor. - - For the avoidance of doubt, this Section 6(b) does not affect any - right the Licensor may have to seek remedies for Your violations - of this Public License. - - c. For the avoidance of doubt, the Licensor may also offer the - Licensed Material under separate terms or conditions or stop - distributing the Licensed Material at any time; however, doing so - will not terminate this Public License. - - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public - License. - - -Section 7 -- Other Terms and Conditions. - - a. The Licensor shall not be bound by any additional or different - terms or conditions communicated by You unless expressly agreed. - - b. Any arrangements, understandings, or agreements regarding the - Licensed Material not stated herein are separate from and - independent of the terms and conditions of this Public License. - - -Section 8 -- Interpretation. - - a. For the avoidance of doubt, this Public License does not, and - shall not be interpreted to, reduce, limit, restrict, or impose - conditions on any use of the Licensed Material that could lawfully - be made without permission under this Public License. - - b. To the extent possible, if any provision of this Public License is - deemed unenforceable, it shall be automatically reformed to the - minimum extent necessary to make it enforceable. If the provision - cannot be reformed, it shall be severed from this Public License - without affecting the enforceability of the remaining terms and - conditions. - - c. No term or condition of this Public License will be waived and no - failure to comply consented to unless expressly agreed to by the - Licensor. - - d. Nothing in this Public License constitutes or may be interpreted - as a limitation upon, or waiver of, any privileges and immunities - that apply to the Licensor or You, including from the legal - processes of any jurisdiction or authority. - -``` - ---- - -The Apache 2.0 License reads: - -``` - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -``` diff --git a/README.md b/README.md deleted file mode 100644 index 2f0f5e1d01..0000000000 --- a/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# API Improvement Proposals - -**TL;DR:** AIPs are lots of documents on how Google does APIs. - -## Overview - -AIP stands for **API Improvement Proposal**, which is a design document -providing high-level, concise documentation for API development. The goal is -for these documents to serve as the source of truth for API-related -documentation at Google and the way API teams discuss and come to consensus on -API guidance. The program is named and styled after Python's enhancement -proposals (PEPs) which have seemed to work pretty well over the years. - -### Specific areas inside Google - -While much of the API-related guidance is general and spans across all the -different products at Google, we've found that some teams working in different -areas may have different customs, styles, or guidance. To accommodate these -historical differences, we've provided separate blocks of numbers for those -areas where they might override or extend the more general guidance. - -## Getting started - -### New to AIPs? - -If you're **new to AIPs**, check out the [Frequently Asked Questions][] which -answer some common questions about how AIPs work and what you need to know. - -### Want to use this in your company? - -If you like what you see and **want to adopt the general AIPs for your -organization**, check out our guide on [Adopting AIPs in your company][]. This -guide walks you through how to start using AIPs and write your own guidance -specific to your organization. - -### Have an idea for an AIP? - -If you **have an idea for an AIP that isn't written yet** (yes, there are -plenty!) check out [Contributing to the project][] to see how you can write -AIPs for others to follow. - -[frequently asked questions]: https://google.aip.dev/faq -[adopting aips in your company]: https://google.aip.dev/adopting -[contributing to the project]: ./CONTRIBUTING.md - -## License - -Except as otherwise noted, the content of this repository is licensed under the -[Creative Commons Attribution 4.0 License][1], and code samples are licensed -under the [Apache 2.0 License][2]. - -For the full text of each license, see [`LICENSE.md`](./LICENSE.md). For -additional details, see the developer.google.com [Site Policies][3]. - -[1]: https://creativecommons.org/licenses/by/4.0/ -[2]: https://www.apache.org/licenses/LICENSE-2.0 -[3]: https://developers.google.com/terms/site-policies diff --git a/adopting.html b/adopting.html new file mode 100644 index 0000000000..69bf6695aa --- /dev/null +++ b/adopting.html @@ -0,0 +1,770 @@ + + + + Adopting AIPs in your company + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ +
+ + +
+
+ +
+

Adopting AIPs in your company

+

Note: We're working on some tooling to make this better. Keep an eye on +this GitHub issue for progress.

+

While AIPs originated at Google and were aimed for Googlers writing Google +APIs, much of the guidance documented is useful outside of Google. This +document describes how you might adopt AIPs as the way you document your own +APIs even if you don't work at Google.

+

The problem

+

Sometimes private organizations might have API guidance that they don't want or +care to share with the rest of the world. For example, maybe in your company +(let's say, Acme, Inc), you identify your resources with a special field called +string acme_id.

+

This rule could be written as an AIP, but there's no reason to share this rule +with everyone -- it's only for you and your development team. However, you +don't want this to conflict with a future AIP (e.g., if you make this AIP-1234, +maybe that AIP will get written in the future and then you'll have a conflict). +So what do you do?

+

The 9000 block

+

Much like the Unicode specification, we've reserved the 9000 block of AIP +numbers (that is, AIP-9000 through AIP-9999) to be for "internal use". This +means that these AIPs will never have public documentation and are free for +private companies to use for their own API guidance. As a result, all you have +to do is write your AIPs as usual and give them a number in the 9000 block.

+

Custom AIP domains

+

We're working on a separate fork-able repository that you can copy and use as +your 9000 block AIP repository. The page rendered by GitHub Pages will serve +only the AIPs in that block and redirect all other pages to [aip.dev][].

+

In short, this means that you can create your own AIP domain (e.g., +aip.example.com) and point that to the forked GitHub repository which will +redirect for all well-known AIPs and serve all internal AIPs from your own +repository. Once you've done that, you can cite all AIPs specifically using +that domain name (e.g., aip.example.com/1234) and you'll always get sent to +the right place.

+

Forking AIP

+

You can fork the AIP project and run it in your own domain if necessary. This +will allow you to customize the AIPs to your organization's needs. Or you could +use the infrastructure to create your own set of AIPs.

+

Updating the URL

+

To run the AIP infrastructure as a GitHub Page in a another repository, the +_config.yaml file must be updated to work correctly in the new repo.

+

If a new custom domain and CNAME have been created for your AIP, only the url +property will need to be updated to the new domain.

+
url: https://aip.dev
+
+

If you are not creating a new domain, it will be necessary to add the baseurl +property to the _config.yaml. This property should contain any additional +path information that may be appended to the domain in the url.

+

For example, assume GitHub user jdoe123 forked the aip project into a +repository named my-aips. If this user served the content from their master +branch, the url to the GitHub pages would be +https://jdoe123.github.io/my-aips/. The accompanying _config.yaml would be +configured as follows:

+
url: https://jdoe123.github.io
+baseurl: /my-aips
+
+

For more information about about how these values are used by GitHub Pages, see +the release notes that standardized these configurations in Jekyll.

+

Configuring Navigation

+

The navigation headers and bar are generated dynamically based on the +_data/header.yaml and _data/nav.yaml files respectively.

+

The schema for the navigation bar can be viewed under +assets/schemas/nav-schema.yaml. It supports two types of navigation +components; static_group and matter_group. A static_group menu component +will always show the same navigation elements, regardless of the content of the +page and the repository. A matter_group component is generated dynamically +based on the AIPs in the domain, or the current page in the site. The +configurations for a matter_group can be viewed in the +assets/schemas/nav-components.yaml#defintions/matter_group schema.

+

The header is just a specially rendered static_group component. The schema +can be viewed at assets/schemas/static_group.yaml.

+

Testing Configuration

+

The tests folder contains an npm test module that will validate your data +files. Running these tests requires npm and mocha. Once these are installed +that tests can be ran with the npm test command.

+ + + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/aip/aog/3001.md b/aip/aog/3001.md deleted file mode 100644 index b973ee6a4d..0000000000 --- a/aip/aog/3001.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -id: 3001 -state: approved -created: 2019-10-03 -js_scripts: - - /assets/js/graphviz/viz.js - - /assets/js/graphviz/lite.render.js - - /assets/js/aip/aip-graphviz.js ---- - -# Actions on Google AIP Process - -This AIP extends [AIP-1][] with details specific to Actions on Google AIPs. Any -details of [AIP-1][] not modified or contradicted by this AIP also apply to -Actions on Google AIPs. - -## Stakeholders - -As with any process there are many different stakeholders when it comes to -reviewing and working with AIPs. Below is a summary of the escalation path -starting with the API producer. - -```graphviz -digraph d_front_back { - rankdir=BT; - ranksep=0.3; - node [ style="filled,solid" shape=box fontname="Roboto" ]; - - producer [ label="API Producer" ]; - editors [ label="AIP Editors" ]; - aog_editors [ label="Actions on Google AIP Editors" ]; - tl_infra [ label="Infrastructure TL" ]; - tl_design [ label="Design TL" ]; - tl [ label="TL" ]; - - producer -> aog_editors; - aog_editors -> editors; - editors -> tl_infra -> tl; - editors -> tl_design -> tl; -} -``` - -### Actions on Google Editors - -The Actions on Google editors are the set of people who make decisions on -Actions on Google AIPs before escalation to the general editors defined in -[AIP-1][]. - -The list of Actions on Google AIP editors is currently: - -- Ali Ibrahim ([@ahahibrahim][]) -- Richard Frankel ([@rofrankel][]) -- Shuyang Chen ([@Canain][]) - -The Actions on Google editors have the same responsibilities as the general -editors. They also have the additional responsibility of establishing -correctness of, and leadership support for, the contents of Actions on Google -AIPs. - -Actions on Google AIP editorship is by invitation of the current Actions on -Google editors. - -[aip-1]: ../0001.md -[@ahahibrahim]: https://github.com/ahahibrahim -[@rofrankel]: https://github.com/rofrankel -[@canain]: https://github.com/Canain diff --git a/aip/aog/3010.md b/aip/aog/3010.md deleted file mode 100644 index 9b897c9224..0000000000 --- a/aip/aog/3010.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -id: 3010 -state: approved -created: 2020-01-14 ---- - -# Actions on Google Vertical Integration Webhook Format - -If an action is part of a vertical program that requires a webhook for Google -to integrate with the action, the webhook format **must** follow this AIP. - -## Guidance - -### Custom method name - -Custom methods in a vertical program are defined by Google and implemented by -third-party actions. Guidelines related to names of custom methods in -[AIP-136](../0136.md) **should** be applied. - -- The name of the method **should** be a verb followed by a noun. -- The name **must not** contain prepositions (“for”, “with”, etc.). -- If word separation is required for the method name, `lowerCamelCase` - **should** be used. - -Examples: - -- `getAccountBalance` -- `completeTransaction` - -### Base URL in Action Package - -The base URL configured in Action Package defines the common part of the actual -execution URL of the webhook. - -- The base URL **may** include a trailing slash, but **must** work if - `:customMethodName` is appended directly. - - Google Cloud Functions base URLs without a trailing slash do not work, - because the first segment of the path is used to identify the webhook. -- The endpoint **must** be HTTPS and **must** have a valid certificate. - -Examples: - -- `https://us-central1.cloudfunctions.net/myWebhook/` (**not** - `https://us-central1.cloudfunctions.net/myWebhook`) -- `https://test.com/assistant/api` - -### Actual execution URL - -The vertical program **must** compute the actual execution URL by appending -`baseUrl` with `:customMethodName`. - -Examples: - -- `https://us-central1.cloudfunctions.net/myWebhook/:completeTransaction` -- `https://test.com/assistant/api:completeTransaction` diff --git a/aip/aog/3020.md b/aip/aog/3020.md deleted file mode 100644 index b3edc67fac..0000000000 --- a/aip/aog/3020.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -id: 3020 -state: approved -created: 2020-03-11 ---- - -# BII Schema Principles - -Built-in intents (BIIs) allow third party developers to declare what their -Actions can do. When a developer registers an Action for a BII, Google can then -invoke that action to fulfill user requests matching that built-in intent. - -## Terminology - -In the general principles below, we use the following terms: - -- **Built-in intents (BII)**: Fulfillment schemas that are used to call - compatible APIs to perform Actions in response to a user query. Built-in - intents allow your service to express its fulfillment capabilities to Google. - By registering for built-in intents and mapping intent parameters to the - fulfillment, it becomes possible for the Google Assistant to invoke the - service to perform a task in response to natural language queries. - - A BII comprises an operation (full list below) and a Schema.org entity, - otherwise known as a type. For example, `CREATE_RESERVATION` would be a BII - for initiating a new reservation; this intent applies to various domains such - as airline, hotel, restaurant, and other reservations. - -- **Operation**: An Action which acts as a wrapper around a type. -- **Type**: The object on which the operation is acting upon. - -## General principles - -Each BII **should** be treated like an API. While BIIs are technically -fulfillment schemas, they fill the same role as an API, in that they tell third -party developers about the structure of the request that their Action handles. - -This AIP details principles for schema creation, with operation-specific and -type-specific information, followed by a list of operations for BIIs. - -### Schema creation - -- Existing Schema.org types and properties **should** be reused whenever the - semantics needed already exist. -- The formula for naming a BII **must** be: - - **Operation + Type** `:=` `VERB` ["Operation" from list below] + '\_' + - `NOUN` ["Type" from Schema.org]. - - Types can be compound nouns which have more than one token. Types with more - than one token have tokens separated by '\_'. - - _Example: `CREATE` + '\_' + `MONEY_TRANSFER` = `CREATE_MONEY_TRANSFER`_ -- BII names **must** be in CAPITAL_SNAKE_CASE (e.g. VERB_NOUN_NOUN). -- For more detail, see [here](https://schema.org/docs/documents.html). - -#### Operations - -- Operations comprise a small catalog of simple, generalizable verbs. These can - be found at the bottom of the AIP under "List of BII Operations." -- There **must not** be overlap between the scope covered by any operations - (mutual exclusivity). - - _Example: `GET` and `CREATE` do not overlap in scope; while both involve - presenting an object, `GET` is for retrieving an existing object, while - `CREATE` assumes no object yet exists and creates one._ -- Operation + type combos **should** make semantic sense. If there is no - operation that can work with the type chosen, either: - - Choose a new type that is in semantic scope for the Action to attach to an - existing operation, with a semantically sensible result. - - _Example: Say you want to fulfill a request for checking into a - reservation. `CREATE_CHECKIN` does not seem to make the most semantic - sense, since nothing is being created. Upon further thought, you decide - to choose a different operation and call the BII `UPDATE_RESERVATION` - instead, which makes more sense with the semantics of checking into a - reservation._ - - Or, Create a new operation. Take this step only when there is no operation - in the list that can cover the Action requested for the schema. - - _Example: Imagine you only had the operations `START`, `STOP`, and - `RESUME` for controlling an ongoing activity. A fulfillment request comes - in for temporarily stopping an ongoing activity of media playback but not - terminating it. You try to create a BII called `STOP_MEDIA`, but then - realize that this operation means the API must terminate the activity. - You then create a new operation, `PAUSE`, which acts to "temporarily - stop/pause activity", and does not overlap in scope with the existing - operation, `STOP`. Your new BII is `PAUSE_MEDIA`._ - -#### Types - -- Types **must** be defined as Schema.org types. -- The type **must** be the _object_ upon which the operation is carried out. -- Semantic scope of the type **should** be generalizable, specificity **may** - be in properties. - - _Example: [Reservation][] is a type, which has a property named `provider`. - The `provider` property specifies the service provider, service operator, - or service performer. This ensures that any BII created using the type - [Reservation][] is generalizable to any service provider, and that the - service provider information is still passed forward through - [Reservation][]’s property `provider`._ -- Different types **should** take distinctly different properties. -- BIIs **must** be specific enough to avoid semantic ambiguity when calling an - API. That is, we shouldn’t inadvertently trigger an Action that the user - isn’t expecting. - - _Example: brokerage account vs. account: If we do not specify brokerage - account, a `GET_ACCOUNT` BII could call an API that fulfills the Action for - getting another sort of account’s information, such as a social media - account. `GET_BROKERAGE_ACCOUNT` ensures the correct scope of financial - account is retrieved by the API._ -- The function prototype/set of parameters **should** be bound to the - operation. That is, the operation decides the fulfillment boundaries of the - Action. -- Each BII operation **must** take a Schema.org type. -- In BII schemas, the same Schema.org type, when combined with different verbs, - **may** take different properties. - - _Example: `GET_MESSAGE` and `CREATE_MESSAGE` use a different but - overlapping set of properties of [Message][]._ - -## Handling User Queries - -- Generic/unresolved search criteria at the level of an object **should** be - passed through the Description field. -- If a query argument can be recognized as a property of a type, it **should** - be passed through as a property; if, on the other hand, an argument is - recognized as just a description of the type, it **should** be passed through - Description field. - - _Example: "find funky blues songs on YouTube" -> - get_media_object(description="funky blues")._ - -## List of BII Operations - -| Verb | Definition | Example BII schema | -| ------ | ------------------------------------------------------------- | ------------------ | -| GET | retrieve & present an object; if ambiguous, a list of objects | GET_CALL_HISTORY | -| CREATE | create an object | CREATE_ORDER | -| DELETE | remove or terminate an existing object | DELETE_RESERVATION | -| START | control an ongoing activity: start activity | START_GAME | -| STOP | control an ongoing activity: stop activity | STOP_ALARM | -| PAUSE | control an ongoing activity: temporarily stop/pause activity | PAUSE_SONG | -| RESUME | control an ongoing activity: continue activity | RESUME_TIMER | - - -[message]: http://schema.org/Message -[reservation]: http://schema.org/Reservation - diff --git a/aip/aog/3021.md b/aip/aog/3021.md deleted file mode 100644 index d6aa7e9876..0000000000 --- a/aip/aog/3021.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -id: 3021 -state: approved -created: 2019-10-04 ---- - -# Type protos in Actions on Google APIs - -Many Actions on Google fulfillment APIs need to represent typed data (datetime, -money, etc.). In some cases, there are common components for representing these -types. - -## Guidance - -Fulfillment APIs **must** use the Actions on Google common types when -applicable, and **must not** use alternative type protos. For example, an API -which needs to represent a monetary amount **must** use -[google.type.Money][money], and **must not** use an alternative representation. - -APIs **may** wrap existing types in new protos. This may be useful in order to -define compound types, provide additional metadata, provide semantic signals -(if the typed value was obtained from a user query), etc. - -## Actions on Google common types - -The Actions on Google common types include all the protobuf types and API types -defined in [AIP-213][], as well as all the protos in -[google.actions.type.\*][actions-type]. - -### Adding new types - -If a given API needs a type for which there is no existing common type, and the -type is not conceptually specific to that API, and the type is well understood -enough to be modeled in a permanent/unversioned way, then API author **should** -consider proposing a new Actions on Google common type in -[google.actions.type.\*][actions-type]. - -The guidance in [AIP-213][] also applies to creating new -Actions on Google common types. Specifically, API authors proposing new types -**should** consider whether a new type should be a Google-wide common type -rather than an Actions on Google common type. One exception to this is that new -Actions on Google common types are not proposed by opening a GitHub ticket. -Instead, Actions on Google API authors who want to create a new type should -email the owners of the //google/actions/type directory directly. - - -[aip-213]: ../0213.md -[date]: https://github.com/googleapis/googleapis/tree/master/google/type/date.proto -[timeofday]: https://github.com/googleapis/googleapis/tree/master/google/type/timeofday.proto -[duration]: https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/duration.proto -[money]: https://github.com/googleapis/googleapis/tree/master/google/type/money.proto -[postaladdress]: https://github.com/googleapis/googleapis/tree/master/google/type/postal_address.proto -[type]: https://github.com/googleapis/googleapis/tree/master/google/type/ -[actions-type]: https://github.com/googleapis/googleapis/tree/master/google/actions/type/ - diff --git a/aip/aog/3022.md b/aip/aog/3022.md deleted file mode 100644 index fca3976f42..0000000000 --- a/aip/aog/3022.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -id: 3022 -state: approved -created: 2020-01-30 ---- - -# Built-in intent arguments and fulfillment APIs - -Actions on Google's [built-in intents][bii] (BIIs) are a _fulfillment schema_, -and use Schema.org as a foreign vocabulary. BIIs are _not_ a fulfillment API, -and do not use the Actions on Google common types defined in [AIP-3021][]. - -Actions on Google has two types of generic fulfillment APIs: - -- URI-based APIs like [App Actions][], which can only support string arguments. -- Google standard APIs, which support JSON primitive types like `string` and - the Actions on Google common types. - -These APIs do not support Schema.org JSON-LD objects. These APIs **should** -support BII arguments by mapping them, or their properties, to the argument -type schema they _do_ support. For example, a BII argument of type -[MonetaryAmount][schema-monetaryamount] may be mapped to an API field of type -[Money][]. - -## BII argument paths - -Only certain Schema.org entity types should be mapped to a given common type. -In order to support BII arguments with types that cannot be mapped to an -appropriate type, APIs **may** support configuration via BII argument paths, -strings which allow users to specify a property of a Schema.org entity which -_can_ be mapped to an appropriate type. - -APIs which support BII argument paths **should** use the syntax defined in this -section. - -BII argument paths are dot-delimited strings that identify a specific -Schema.org entity within the list of arguments to the BII. - -For example, take the following hypothetical BII arguments `grant` and `date`: - -```json -{ - "grant": { - "@context": "http://schema.org", - "@type": "MonetaryGrant", - "funder": { - "@type": "Organization", - "name": "Google" - }, - "amount": { - "@type": "MonetaryAmount", - "currency": "USD", - "value": 100 - } - }, - "date": "2000-01-01" -} -``` - -There is no common type to which `MonetaryGrant` can be mapped, but the `grant` -argument contains an `amount` property of type -[MonetaryAmount][schema-monetaryamount], which _can_ be mapped to [Money][]. -This property can be referenced with the path string `"grant.amount"`. -Similarly, `grant.name` can be mapped to a string field. - -A URI-based API which does not support [Money][] would instead need to use the -path strings `"grant.amount.currency"` and `"grant.amount.value"` to map -`grant.amount` to two separate URI parameters. - -On the other hand, `date` can be mapped to [DateTime][], and so the path string -`"date"` would be sufficient for either URI-based APIs or string fields in JSON -APIs. - -### Properties with multiple values - -Since any Schema.org property may have multiple values, values other than the -first may be referenced by indexing with square brackets. For example, take -this hypothetical BII argument: - -```json -{ - "menuItem": { - "@context": "http://schema.org", - "@type": "MenuItem", - "name": "pizza", - "menuAddOn": { - "@type": "MenuItem", - "name": "pineapple" - }, - "menuAddOn": { - "@type": "MenuItem", - "name": "extra cheese" - } - }, - "date": "2000-01-01" -} -``` - -In this example, the path `"menuItem.menuAddOn[1].name"` would evaluate to -`"extra cheese"`. - -When there are no square brackets, the first value is assumed; using `[0]` is a -no-op. That is, `"menuItem.menuAddOn.name"` and `"menuItem.menuAddOn[0].name"` -are equivalent, and would _both_ evaluate to `"pineapple"`. - -## BII argument to common type mappings - -Google standard APIs which support BII argument mapping **should** support at -least these type mappings from Schema.org entity type to Actions on Google -common types: - -| Common type | Schema.org entity types | -| ----------------- | ------------------------------------------------------------ | -| [Date][] | [Date][schema-date] | -| [DateTime][] | [DateTime][schema-datetime] | -| [TimeOfDay][] | [Time][schema-time] | -| [Duration][] | [Duration][schema-duration] | -| [Money][] | [MonetaryAmount][schema-monetaryamount] | -| [PostalAddress][] | [Place][schema-place], [PostalAddress][schema-postaladdress] | - -## BII argument to JSON type mappings - -Google standard APIs which support BII argument mapping **should** support at -least these type mappings from Schema.org entity type to JSON type: - -| JSON type | Schema.org entity types | -| --------- | ------------------------- | -| `string` | [Text][schema-text] | -| `number` | [Number][schema-number] | -| `bool` | [Boolean][schema-boolean] | - -## BII argument to string mappings - -URI-based fulfillment APIs like [App Actions][] can only map BII arguments to -strings (URI parameters). These APIs **should** support mapping at least the -following Schema.org entity types to URI parameters: - -- [Text][schema-text] -- [Number][schema-number] -- [Boolean][schema-boolean] -- [Date][schema-date] -- [DateTime][schema-datetime] -- [Time][schema-time] - - -[aip-3021]: ./3021.md -[date]: https://github.com/googleapis/googleapis/tree/master/google/type/date.proto -[datetime]: https://github.com/googleapis/googleapis/blob/master/google/type/datetime.proto -[timeofday]: https://github.com/googleapis/googleapis/tree/master/google/type/timeofday.proto -[duration]: https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/duration.proto -[money]: https://github.com/googleapis/googleapis/tree/master/google/type/money.proto -[postaladdress]: https://github.com/googleapis/googleapis/tree/master/google/type/postal_address.proto -[app actions]: https://developers.google.com/assistant/app/intents#handling_intent_parameters -[schema-date]: https://schema.org/Date -[schema-datetime]: https://schema.org/DateTime -[schema-time]: https://schema.org/Time -[schema-duration]: http://schema.org/Duration -[schema-monetaryamount]: https://schema.org/MonetaryAmount -[schema-place]: https://schema.org/Place -[schema-postaladdress]: https://schema.org/PostalAddress -[schema-text]: https://schema.org/Text -[schema-number]: https://schema.org/Number -[schema-boolean]: https://schema.org/Boolean -[bii]: https://developers.google.com/assistant/app/reference/built-in-intents/ - diff --git a/aip/aog/scope.yaml b/aip/aog/scope.yaml deleted file mode 100644 index b3259a1afc..0000000000 --- a/aip/aog/scope.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Actions on Google -order: 60 diff --git a/aip/apps/2712.md b/aip/apps/2712.md deleted file mode 100644 index 966d58f65f..0000000000 --- a/aip/apps/2712.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: 2712 -state: approved -created: 2018-07-13 ---- - -# API completeness - -Our customers expect that they can be as productive in their Apps programs as -they can be sitting at the UI. When they can not, this is surprising and -disappointing. Historically, Google Workspace has not insisted on this kind of -completeness. However, we want to move towards that goal, hence this -requirement for a plan, while we only advise completeness itself. - -For major changes, however, the desire for completeness will be amplified. - -## Guidance - -Each action that can be performed in the UI **should** be possible to do via a -public API. For example, if there is a button in the UI to add a widget, there -**should** be some way to add a widget using the API. This simplifies the -user's understanding of the API, and makes it easier to record UI actions to be -replayed via the API. - -The question of _when_ the completeness ought to be achieved is not fixed. Each -team **must** have a plan for API completeness, even if it is a simple -statement, such as, "When we are given resources to do so." (We would prefer -more, but if that is your plan, then so be it.) diff --git a/aip/apps/2713.md b/aip/apps/2713.md deleted file mode 100644 index 18d1987ce7..0000000000 --- a/aip/apps/2713.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 2713 -state: approved -created: 2018-07-13 ---- - -# One team owns each type - -This guidance supplements [AIP-213][]. - -Sharing types is tempting, and it is possible. However, it is surrounded by -some complicated issues. - -We will consider making shared types for classes that are useful across -multiple Apps APIs, we just will not do it lightly. If you feel you have a case -for this, please contact us at apps-api-reviewers@google.com. - -## Guidance - -Each API owns its own types. - -If your API needs to reference another API's objects, your API **must** contain -a reference ([resource name][aip-122] or ID) that can be used to get the -information from that other API. For example, if your API wants to reference a -relevant Gmail message, you **must** store a Gmail message name, and the -message itself will be accessed via the Gmail API, passing in that name. Your -API **must not** contain an actual Gmail message object. - -For smaller types, it is also reasonable to make a copy of the class. - -[aip-122]: ../0122.md -[aip-213]: ../0213.md diff --git a/aip/apps/2715.md b/aip/apps/2715.md deleted file mode 100644 index bd3a9e6750..0000000000 --- a/aip/apps/2715.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -id: 2715 -state: reviewing -created: 2018-09-10 ---- - -# Documenting authorization changes - -Authorization is critical to manage well. Understanding an API includes -understanding not only what operations do, but when one is allowed to do them. -Authorization changes, either new authorization constructs or new uses of -existing authorization constructs, should be easy to find in a design rather -than scattered through the document in individual sections. - -In order to make it easy to see what (if any) authorization constructs are -being modified in your design, we want to be able to find them in a single, -clear place. - -**Note:** This is _not_ talking about RPC-level permissions, like those covered -by `RpcSecurityPolicy`, but about authorization constructs used by your API for -its own purposes. - -## Definitions - -There are a couple of common types of authorization construct: - -A **role** refers to an authorization construct which is granted to an -_identity_ or an _identity group_ on a _resource_. The most well known examples -of roles in G Suite are the `commenter`, `reader`, `writer`, and `owner` roles -from Drive. - -A **permission** refers to an authorization construct which is used to check -whether a particular _identity_ can execute some _operation_. For example, to -check whether the current user can delete a file, the application may check -whether the user has the `file.delete` permission on the file. Permissions are -most often assigned to roles, so that only roles are granted to identities or -identity groups, but some systems allow permissions to be granted directly. -Applications often only use each permission to authorize a single operation on -a resource, but there are cases where an application may use a permission to -authorize multiple different operations. - -Within an application, authorization checks are made using only one of these -authorization constructs (typically permissions, if the application has that -concept). For example, in order to determine if a user can read a document, an -application would _either_ check whether the user has a `doc.read` permission -_or_ has the `reader` role, but not both. - -## Guidance - -If your design creates new authorization constructs or extends/modifies the use -of any existing authorization constructs, you **must** have a separate section -in your design document that describes this. You **may** additionally discuss -these in any other place in your document. - -It is not important whether this is a top-level section or subsection. It is -important that all such changes are listed together in a distinct section so -they are easy to find and analyze. - -If the identifier of an authorization construct that is new or modified is -visible to users or developers, the way that it is identified should also be in -your document. Examples of this are: - -- If access is granted using roles and a new role is being added, the way that - the role is identified in the role granting RPCs should be in your document. -- If there is an API that allows permissions assigned to roles to be - manipulated, the way that the permission is identified in the role - manipulation RPCs should be in your document. diff --git a/aip/apps/2716.md b/aip/apps/2716.md deleted file mode 100644 index 076e7535ff..0000000000 --- a/aip/apps/2716.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -id: 2716 -state: approved -created: 2018-09-10 ---- - -# Standard terms in names - -APIs have a lot of identifier names (fields, constants, methods, ...), that -often contain terms for things, such as `url` (`getUrl()`, `doc_url`, ...) or -`id` (`lookupId()`, `student_id`). - -It is useful to have a standard set of terms for common concepts in these -various names. This makes it easier for developers to understand new APIs based -on previous experience. It is not (for example) that `id` is a better term than -`uid` or other options, but it also is not worse, and having different choices -in different APIs is confusing and unnecessary. - -This AIP defines terms to use for such common concepts. These terms should be -used for the same concept in identifier names. - -This is supplemental to the API design guide, which lists [standard field -names][] and has other rules about identifiers. - -[standard field names]: https://cloud.google.com/apis/design/standard_fields - -## Guidance - -Absent other, more specific guidance, APIs **should** use the following -standard terms (as opposed to alternatives) as parts of identifier names to -refer to common concepts, and **must not** use them to refer to other things: - -- `uri` for URIs/URLs (as opposed to `url`, `link`, `href`, etc.) -- `id` for a unique identifier, either globally unique or within a specified - context -- `index` to indicate an ordinal number of an item within a collection, such as - `message_index` on a message to say what place it occupies in a stream of - message (unless there is a more specific name to use, such as if the number - also is used as an ID, use `id`). - -APIs **should** avoid use of the term `resource` in fields that have resource -names, as this is redundant. - -Any more specific guidance overrides these rules. For example, the [AIP-122][] -rule to use `name` for the resource name overrides using the term `id` for -unique identifiers. - -[aip-122]: ../0122.md - -## Fallback to schema.org - -If you are looking for standard terms for things, [schema.org][] is a good -place to look for terms that have been fairly widely vetted as being normal, -customary, and/or clear. You **should** consult it when choosing identifier -names when other strategies fail. - -[schema.org]: https://schema.org/ diff --git a/aip/apps/2717.md b/aip/apps/2717.md deleted file mode 100644 index 83950506fb..0000000000 --- a/aip/apps/2717.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: 2717 -state: reviewing -created: 2018-09-10 ---- - -# Patterns for generic fields - -Developers have several options for how to represent generic values in proto -messages. There are reasons to choose one over the other. Understanding them -will lead to better and more consistent APIs. - -## Guidance - -APIs **should** follow a consistent application of `oneof` vs. -`map` vs. `Any` vs. `Struct`. - -### `oneof` - -A `oneof` is used to create a restriction on a set of optional fields, -enforcing that only one of them may be set (these fields are still separate -individual fields). A common pattern is to have a message that contains a -single `oneof` collection of various message types. Such a `oneof` message is -conceptually similar to a C `union`, or C++ `std::variant`. These **should** be -used in most places where a generic message type is needed, in preference to -other approaches. - -**Note:** Adding additional possible values to an existing `oneof` is a -non-breaking change, but moving existing fields into or out of a `oneof` is -breaking (it creates a backwards-incompatible change in Go protobuf stubs). - -### `map` - -If a more generic structure is needed, a map of strings to objects **may** be -used. Such a map is represented by a normal JSON object, such as -`{"a": "foo", "b": "bar"}`. The downside to such maps is that they are limited -to flat structures, and they can be difficult to work with because many string -constants may be needed. - -### `Any` - -An [`Any`][any] allows any message to be packed into the field. This is -conceptually similar to a "bytes" field containing a serialized message. The -advantage of an `Any` is that a user-defined proto message can be stored along -with type information. The user must be able to know which kind of object is in -the `Any`, which complicates the design. The disadvantage is that working with -and debugging any protos is much more complicated since the code may or may not -know how to deserialize the packed message. Also, the developer must contend -with unexpected types of messages in the `Any`. - -`Any` **should not** be used as a request parameter. Request parameters will -either be a fixed set of types, in which case a `oneof` **should** be used, or -a type descriptor would need to be sent along, in which case a struct -**should** be used, which achieves essentially the same thing with much simpler -semantics. - - -[any]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto - -### `Struct` - -The [`Struct`][struct] message can be used to represent arbitrary nested JSON. -For example, given the following code: - -```java -Struct.Builder builder = Struct.newBuilder(); -Value town = Value.newBuilder().setStringValue("Springfield").build(); -Value population = Value.newBuilder().setNumberValue(273).build(); -builder.putFields("town", town); -builder.putFields("population", population); -Struct survey = builder.build(); -``` - -`survey` would serialize as the actual JSON -`{"town": "Springfield": "population": 273}`. This message type is fairly -uncommon, and **should** only be used rarely. - - -[struct]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto diff --git a/aip/apps/2718.md b/aip/apps/2718.md deleted file mode 100644 index bb9092f170..0000000000 --- a/aip/apps/2718.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: 2718 -state: draft -created: 2018-11-08 ---- - -# References to objects in other APIs - -Your API may need to refer to objects in other APIs. For example, a Sheets cell -may want to refer to the Slides deck that explains its meaning. This kind of -cross reference should be as natural to use as possible with the target API. - -## Guidance - -When your API refers to an object accessed via another API (the "target" API), -the reference your API provides depends upon whether the reference is compliant -with One Platform or not. - -- If a field always holds a compliant reference to a single specific target - API, the reference you provide **must** be a relative URI from the top level - of the target API's naming hierarchy. For example, if the full URL of the - object is `https://koalas.googleapis.com/koalas/123435` the reference you - return to it **must** be the relative URI `koalas/123435`. Further, your - documentation must make clear that the reference is used with - `koalas.googleapis.com`. - - This provides the developer with a natural way to use the reference, using - the returned path directly. It also ensures that they know which API - understands that reference. - -- If a field always holds a compliant reference, but is not limited to a single - target API, the reference you provide **must** be a relative URI that - includes the path of its specific target API, such as - `koalas.googleapis.com/koalas/123435`. This provides the developer with the - correct target in a formalized, usable way. - -- Otherwise, the reference you return **must** be chosen to be as natural to - use as possible with the target API, and the API and its version must be - documented. For example, if the Apiary-based Koala API uses an ID in its - `GetKoalaData` method, you **must** return the ID that can be used as a - parameter, as well as documenting that you are using IDs that work in Koala - API 1.0. - -### Naming - -For compliant references, you **should** avoid the use of the terms "reference" -and "name" in the field name. That is, `koala` is preferred to -`koala_reference` or `koala_name` -(see [AIP-122][]). - -For other target APIs, you **should** echo that API's terminology in the name -for clarity. For example, if the target API's `GetKoalaDataRequest` has a -`koala_num` field, your field name **should** probably be `koala_num`, or it -would include `koala_num` in its name, such as `responsible_koala_num`. diff --git a/aip/apps/scope.yaml b/aip/apps/scope.yaml deleted file mode 100644 index d7cd2afa31..0000000000 --- a/aip/apps/scope.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Workspace -order: 50 diff --git a/aip/auth/4110.md b/aip/auth/4110.md deleted file mode 100644 index aba4888271..0000000000 --- a/aip/auth/4110.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -id: 4110 -scope: auth -state: approved -created: 2018-06-24 -placement: - category: auth - order: 10 -js_scripts: - - /assets/js/graphviz/viz.js - - /assets/js/graphviz/lite.render.js - - /assets/js/aip/aip-graphviz.js ---- - -# Application Default Credentials - -Google auth libraries use a strategy called _Application Default Credentials -(ADC)_ to detect and select credentials based on environment or context. With -ADC, developers should be able to run the code in different environments and the -supporting systems fetch the appropriate credentials based on each environment -in an effortless manner. - -Auth libraries following the standards in these AIPs are known as _"Google -Unified Auth Clients"_, or _GUAC_ for short. The resulting libraries are -colloquially called _GUACs_. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -### Credential Types - -This section outlines the supported credential types of the ADC. - -- **Gcloud Credential**: A credential provided by the [Gcloud tool][0] that -identifies a human user that needs to authenticate to access Google APIs. The -auth libraries **must** support this credential type. - -- **Service Account Key**: A credential that identifies a non-human user that -needs to authenticate to access Google APIs. The auth libraries **must** support -this credential type. - -- **OAuth Client ID**: A credential that identifies the client application which -allows human users to sign-in through [3-legged OAuth flow][1], which grants the -permissions to the application to access Google APIs on behalf of the human -user. The auth libraries **may** support this credential type. - -- **External Account Credential**: A configuration file identifying -[external non-Google credentials][8] that can be exchanged for Google access -tokens to access Google APIs. The auth libraries **must** support this -credential type. - -### Environment Variables - -The auth libraries **must** support the following environment variables to allow -developers to provide authentication configuration for their application: - -- **GOOGLE_APPLICATION_CREDENTIALS**: The specified value will be used as the -full path for ADC to locate the credentials file. The credentials file -**should** be one of the following types: - - - Gcloud credentials - - Service account key - - External account credentials - - The credentials **may** be the OAuth Client ID if it is supported by the - auth library. Credentials file path specified at the program level (e.g. via - client options) **must** have priority over the value of this environment - variable. - -- **GOOGLE_API_USE_CLIENT_CERTIFICATE:** The specified value **must** be -either true or false. The client certificate **must** be ignored if this -variable is set to false. The default value is false if the value is unset. - -``` -GOOGLE_API_USE_CLIENT_CERTIFICATE=[true|false] -``` - -- **GOOGLE_CLOUD_QUOTA_PROJECT:** The quota project id to be set on the credential. -The value from the environment variable will override any quota project that is -present in the credential detected by the ADC mechanism. - -### Inputs & Outputs - -From the input/output perspective, the inputs of _ADC_ **should** be the -credentials as well as the underlying environment such as environment variables -or metadata service that provides these credentials. - -For example, the `GOOGLE_APPLICATION_CREDENTIALS` environment variable can provide -the default credential JSON as the input here, or the well-known path that -gCloud uses to store the default user credential JSON. The output is the access -token that application can use to access the Google APIs. This access token -__may__ be a bearer token, a certificate-bound token, or an identity-bound token -depending on the chosen authentication flow. - -## Expected Behavior - -This section outlines the expected behavior of the ADC. Auth libraries **must** -implement these concepts in order to be considered complete. - -```graphviz -digraph d_front_back { - rankdir=TB; - ranksep=0.3; - node [ style="filled,solid" shape=box fontname="Roboto" ]; - - check_env_var [ label="1. Check Environment Variables" ]; - load_credentials [ label="2. Load Credentials" ]; - check_metadata [ label="3. Check workload credentials" ]; - auth_flows [ label="4. Determine Auth Flows" ]; - execute [ label="5. Execute Auth Flows" ]; - post_processing [ label="6. Post Processing" ]; - - check_env_var -> load_credentials -> check_metadata -> auth_flows -> execute -> post_processing; - load_credentials -> auth_flows; - check_metadata -> post_processing; -} -``` - -1. **Check environment variables** - 1. Check GOOGLE_APPLICATION_CREDENTIALS - 1. If set, go to step (2.2) - 1. If not set, go to step (2) -1. **Load credentials** - 1. Check [gcloud default credentials][5] through its default path - 1. If found go to step (2.2) - 1. Otherwise go to step (3) - 1. Check the provided credential type - 1. If the credential is gcloud credentials, go to step (4) - 1. If the credential is [a service account key][6] JSON, go to step (4) - 1. If the credential is [an external account][8] JSON, go to step (4) - 1. If the credential is unknown type, return an error saying that _[END]_ - 1. Credentials not found _[END]_ -1. **Check workload credentials (on GCE, GKE, GAE and Serverless)** - 1. If true, - 1. If identity binding is enabled, by meeting the requirements in - [mTLS Token Binding][9], use the mTLS Token Binding flow to fetch an - identity-bound access token. Go to step(6). - 1. If there is an issue when obtaining bound access tokens, return an error - indicating that _[END]_ - 1. If identity binding is not enabled, use the [virtual machine flow][3] to - fetch an auth token associated with the current environment - 1. If target audience is provided by the developer, get an [identity token][7]. Go to step(6). - 1. Otherwise, get an access token. Go to step(6). - 1. If false, go to step (2.3) -1. **Determine auth flows** - 1. If the credential is gcloud credential go to step (5.3) - 1. If target audience or scope is provided by the developer go to step (5.1) - 1. If the credential is an external account go to step (5.4) - 1. Otherwise, go to step (5.2) -1. **Execute auth flows** - 1. Use 2LO flow to exchange for an auth token - 1. If target audience is provided by the developer, get an [identity token][7]. Go to step(6). - 1. Otherwise, get an access token. Go to step(6). - 1. If client certificate is presented, the exchanged token will be a certificate bind token. Go to step(6). - 1. Use self-signed JWT flow to create an access token locally. - 1. If certificate is presented, embed the certificate into the JWT. - 1. Use the regular [self-signed JWT flow][4] for an access token. Go to step(6). - 1. Use user identity flow to exchange for an access token. Go to step(6). - 1. Use [external account][8] flow to exchange for an access token. Go to step(6). -1. **Post Processing** - 1. Update Quota Project - 1. If a quota project is provided explicitly while initiating ADC, override the quota project in the credential with the explicit value. _[END]_ - 1. Else if the `GOOGLE_CLOUD_QUOTA_PROJECT` environment variable is set, override the quota project in the credential with this value. _[END]_ - -## Changelog - -- **2019-08-13**: Add a link to virtual machine flow (AIP 4115). -- **2019-08-18**: Remove STS support from ADC. -- **2021-01-20**: Add identity token flow (AIP 4116). -- **2021-06-29**: Guidance for GOOGLE_API_KEY temporarily removed until consensus can be established. -- **2021-12-10**: Add external account credentials (AIP 4117). -- **2023-01-23**: Add Quota Project Environment variable. - - - -[0]: https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login -[1]: https://developers.google.com/identity/protocols/oauth2/native-app -[3]: ./4115 -[4]: ./4111 -[5]: ./4113 -[6]: ./4112 -[7]: ./4116 -[8]: ./4117 -[9]: ./4119 - diff --git a/aip/auth/4111.md b/aip/auth/4111.md deleted file mode 100644 index d903f33581..0000000000 --- a/aip/auth/4111.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -id: 4111 -scope: auth -state: approved -created: 2020-07-23 ---- - -# Self-signed JWT - -Self-signed JWT (JSON Web Token) for Google APIs was introduced in 2014 to -provide a more efficient auth stack for Cloud APIs being accessed via service -accounts by bypassing the intermediate step of exchanging client assertions for -OAuth tokens. A self-signed JWT is a spec-conforming JWT that is locally signed -by the service account private key. Since many Cloud APIs accept self-signed JWT -in place of traditional access tokens, it is now considered a standard -authentication method. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -This section describes the general guidance of supporting self-signed -JWT as a means of authentication. - -### Application Default Credentials - -Supporting self-signed JWT is considered a part of [application default -credentials][0]. To understand the overall flow, please read [AIP-4110][0]. - -### Scope vs. Audience - -In the past, the self-signed JWT was only applicable with `audience`. Recently, -the usage of the "scope" claim in self-signed JWTs is now allowed in the Google -Cloud auth ecosystem, which makes the self-signed JWT usable with both audience -and scope. However, caller **must** not specify scope and audience at the same -time to prevent potential conflicts. - -#### Opt-in Strategy - -Currently, this scope support for JWT is gated behind a configurable boolean -option `UseJWTAccessWithScope`(the actual naming may vary depending on the -programming language), as the feature is not supported for all Cloud API service -backends. The default value of this boolean is false, and to use scope with -self-signed JWT, caller **must** specify this option as `true`. Otherwise the -OAuth exchange flow **should** be used instead when scope is provided. The API -clients **should** try to automatically determine this option with the -appropriate value based on the APIs, so this complexity is not exposed to the -upper-layer developer. - -### Default Authentication Method For Service Account Keys - -Considering its better efficiency and reliability comparing with OAuth flow -(bypassing the exchanging step), [ADC][0] **should** use self-signed JWT as the -default authentication flow when service account key is provided as the source -credential. - -In other words, [ADC][0] **should** choose the OAuth flow over the self-signed -JWT flow only if scope is provided and JWT is not enabled via -`UseJWTAccessWithScope`. - -### Expected Behavior - -To support self-signed JWT, the auth libraries **must** follow the steps below: - -1\. Load the [service account ID JSON file][2]. Please note that the self-signed -JWT only supports service account ID credential type. - -2\. Using any standard JWT library, such as one found at [jwt.io][1], create a JWT -with a header and payload like the following examples: - -(1) Example of using audience: - -```json -{ - "alg": "RS256", - "typ": "JWT", - "kid": "abcdef1234567890" -} -{ - "iss": "123456-compute@developer.gserviceaccount.com", - "sub": "123456-compute@developer.gserviceaccount.com", - "aud": "https://pubsub.googleapis.com/", - "iat": 1511900000, - "exp": 1511903600 -} -``` - -(2) Example of using scope: - -```json -{ - "alg": "RS256", - "typ": "JWT", - "kid": "abcdef1234567890" -} -{ - "iss": "123456-compute@developer.gserviceaccount.com", - "sub": "123456-compute@developer.gserviceaccount.com", - "scope": "https://www.googleapis.com/auth/cloud-platform", - "iat": 1511900000, - "exp": 1511903600 -} -``` - -* For the `kid` field in the header, specify the service account's private key -ID. You can find this value in the `private_key_id` field of the service account -JSON file. - -* For the `iss` and `sub` fields, specify the service account's email address. -You can find this value in the `client_email` field of the service account JSON -file. - -* For the `aud` field, specify the audience. The default audience value -**should** be `https://[SERVICE]/`. (e.g. `https://pubsub.googleapis.com/`) - -* For the `scope` field, specify the scope. Please note that `aud` and `scope` -cannot be specified at the same time. - -* For the `iat` field, specify the current Unix time, and for the `exp` field, -the value **must** be exactly 3600 seconds later, when the JWT will expire. - -3\. Sign the JWT with RSA-256 using the private key found in the service -account JSON file. - -## Changelog - -- **2019-08-13**: Add a section for application default credential. -- **2021-06-02**: Update scope support. - - -[0]: https://google.aip.dev/auth/4110 -[1]: https://jwt.io/#libraries-io -[2]: https://google.aip.dev/auth/4112 - diff --git a/aip/auth/4112.md b/aip/auth/4112.md deleted file mode 100644 index 47c9838b29..0000000000 --- a/aip/auth/4112.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -id: 4112 -scope: auth -state: approved -created: 2020-08-13 ---- - -# Service Account Keys - -A service account is a special kind of account used by an application or a -virtual machine (VM) instance, not a person. Applications use service accounts -to make authorized API calls, authorized as either the service account itself, -or as Google Workspace or Cloud Identity users through domain-wide delegation. -Service accounts are associated with private/public RSA key-pairs that are used -for authentication, which is the focus of this AIP. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -This section describes the general guidance of supporting Service Account Key -authentication using traditional OAuth flow. For Service Account Key -authentication using self-signed JWT flow, please refer to the [self-signed -JWT][0] AIP. - -### Service Account Key Authentication Using OAuth - -Under the latest [ADC][1] guidance, when Service Account Key is provided as the -source credential, we prefer to use the [self-signed JWT][0] flow by default, -which does not use the OAuth "scope" argument. Therefore, the client **should** -choose the OAuth flow over self-signed JWT flow only if the OAuth "scope" is -explicitly provided to the client. - -### Expected Behavior - -To support Service Account Key authentication using OAuth flow, the auth -libraries **must** follow the steps below: - -1\. Load the **Service Account ID JSON file** from the file path specified by -**GOOGLE_APPLICATION_CREDENTIALS** environment variable, or an explicit -**credentials** file path specified through client options. The JSON file will -look like below: - -```json -{ - "type": "service_account", - "project_id": "testproject", - "private_key_id": "redacted", - "private_key": "redacted", - "client_email": "testserviceaccount@test.iam.gserviceaccount.com", - "client_id": "113258942105700140798", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/testserviceaccount%40test.iam.gserviceaccount.com" -} -``` - -**Note:** A Service Account ID JSON file can be downloaded from [Google Cloud Console][2]. - -2\. Using any standard JWT library, such as one found at [jwt.io][3], create a -JWT with a header and claims set like the following example: - -```json -{ - "alg": "RS256", - "typ": "JWT", - "kid": "abcdef1234567890" -} -{ - "iss": "123456-compute@developer.gserviceaccount.com", - "sub": "123456-compute@developer.gserviceaccount.com", - "scope": "https://www.googleapis.com/auth/pubsub", -} -``` - -* For the `kid` field in the header, specify the service account's private -key ID. You can find this value in the **private_key_id** field of the -service account JSON file. - -* For the `iss` and `sub` fields, specify the service account's email -address. You can find this value in the **client_email** field of the -service account JSON file. - -* For the `scope` field, specify the **scope** parameter provided by the client. -Multiple scopes can be specified using single space (" ") as delimiter. - -3\. Sign the JWT with RSA-256 using the **private_key** found in the service -account JSON file. The output will be used as the request payload (a.k.a. -assertion) for the 2-legged OAuth flow. - -4\. Define a parameter "grant_type" as -"urn:ietf:params:oauth:grant-type:jwt-bearer". Define a parameter "assertion" as -the payload from step 3. - -5\. Make a POST request to the **token_uri** endpoint with the parameters from -step 4 to obtain an OAuth2 Access Token. - - -[0]: https://google.aip.dev/auth/4111 -[1]: https://google.aip.dev/auth/4110 -[2]: https://console.cloud.google.com/apis/credentials -[3]: https://jwt.io/#libraries-io - diff --git a/aip/auth/4113.md b/aip/auth/4113.md deleted file mode 100644 index ced299ad34..0000000000 --- a/aip/auth/4113.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -id: 4113 -scope: auth -state: approved -created: 2020-07-31 ---- - -# gcloud CLI Integration - -[gcloud][0] is the CLI that manages authentication, local configuration, -developer workflow, and interactions with the Google Cloud Platform (GCP) APIs. -gcloud can generate default credentials by obtaining user access credentials -via 3-legged OAuth (3LO) web flow and saving them to well-known locations in -JSON format. These credentials are intended to be consumed by applications -other than gcloud. [Application Default Credentials (ADC) and Google Unified -Auth Clients (GUAC)][1] **must** support the gcloud default credentials. - -**Note:** Although the sample code is written in Python, this AIP describes -guidance and requirements in a language-neutral way. It uses generic -terminology which may be imprecise or inappropriate in certain languages or -environments. - -## Guidance - -This section describes the general guidance of supporting the gcloud default -credentials. - -### Credentials Generation - -gcloud default credentials can be generated via command ‘[gcloud auth -application-default login][2]’. - -``` -$ gcloud auth application-default login -``` - -The generated credentials are saved to well-known locations which vary as -platforms: - -- **Linux, Mac**: \$HOME/.config/gcloud/application_default_credentials.json -- **Windows**: %APPDATA%/gcloud/application_default_credentials.json - -Below is an example of the gcloud default credentials, - -```json -{ - "client_id": "fake_id.apps.googleusercontent.com", - "client_secret": "fake_secret", - "quota_project_id": "fake_project", - "refresh_token": "fake_token", - "type": "authorized_user" -} -``` - -All the fields are populated by the login response from the Google -authorization backend except for ‘quota_project_id’ which is retrieved from -gcloud’s context. Additionally, the users can override ‘quota_project_id’ with -the ‘--client-id-file’ flag, - -``` -$ gcloud auth application-default login --client-id-file=clientid.json -``` - -### Expected Behaviors - -The auth libraries will use the information in the gcloud default credentials -to exchange access tokens with Google authorization backend. The resulting -access tokens will be further used by applications to call GCP APIs. - -The auth libraries and applications **must** follow the steps below: - -- The auth library loads the gcloud default credentials from the well-known - location (see previous [section](#credentials-generation)) of the platform on - which it runs. - -- The auth library calls Google authorization backend with the refresh token, - client ID and client secret in the gcloud default credentials and procures an - access token. The URL for acquiring access tokens from Google authorization - backend is https://oauth2.googleapis.com/token. Below is an example code with - [google-auth][3] as the auth library and [urllib3][4] as the http transport. - -```python -from google.oauth2 import _client as google_auth_client -import google.auth.transport.urllib3 as google_auth_urllib3 -import urllib3 - -# Create an http transport for communicating with Google authorization backend. -http = urllib3.PoolManager() -request = google_auth_urllib3.Request(http) - -# Build parameters for the access token request. Assume the gcloud default -# credentials are deserialized are into a dictionary ‘gcloud_default’ -# in the previous step. -token_uri = 'https://oauth2.googleapis.com/token' -refresh_token = gcloud_default['refresh_token'] -client_id = gcloud_default['client_id'] -client_secret = gcloud_default['client_secret'] -scopes = ['https://www.googleapis.com/auth/cloud-platform'] - -# Obtain an access token. -access_token, _, _, _ = google_auth_client.refresh_grant( - request, token_uri, refresh_token, client_id, client_secret, scopes) -``` - -- The application calls GCP API with the access token obtained from the - previous step. ‘quota_project_id’ in the gcloud default credentials - **should** be added to the ‘X-Goog-User-Project’ http header so that the - associated account will be charged for billing and quota. - - -[0]: https://cloud.google.com/sdk/gcloud/reference -[1]: https://google.aip.dev/auth/4110 -[2]: https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login -[3]: https://google-auth.readthedocs.io/en/latest/index.html -[4]: https://urllib3.readthedocs.io/en/latest/ - diff --git a/aip/auth/4114.md b/aip/auth/4114.md deleted file mode 100644 index d2979bf5c1..0000000000 --- a/aip/auth/4114.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -id: 4114 -scope: auth -state: approved -created: 2020-07-28 ---- - -# Device Certificate Authentication via Mutual TLS - -Mutual TLS (a.k.a mTLS) authentication enables authentication of both client and -server identities in a TLS handshake and provides the foundation for Device -Certificate Authentication for Context Aware Access for GCP enterprise -customers. With Device Certificate Authentication, the server takes into account -the client certificate in the transport layer when making authorization -decisions. The use of a client certificate provides a stronger indication of the -access originating from a trusted device. This allows enterprise customers to -restrict access from untrusted devices. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -This section describes the general guidance of supporting Device Certificate -Authentication (a.k.a. DCA) via mTLS. - -### Application Default Credentials for DCA - -Users **should** enable DCA through [ADC][0] instead of manual configuration via -client options. - -There are two aspects of ADC for DCA. The first is the automatic procurement of -a device certificate. The second is the automatic switching of the service -endpoint to the mTLS version of the service endpoint. Clients **must** support -both of these aspects when supporting ADC for DCA. - -### Expected Behavior - -Client support for DCA **must** give priority to user overrides specified via -client options. The following decision tree **should** be used: - -1. If user specifies both device certificate and endpoint override via client - options, use them as is. -1. If user does not specify device certificate, attempt to procure and use - a default device certificate. -1. If user does not specify endpoint override, use the default mTLS endpoint if - a device certificate is available and the default regular endpoint otherwise. - -Implications of the above logic: - -1. If user specifies a non-mTLS endpoint override but a device certificate is - available, pass along the certificate anyway and let the server decide what - to do. -1. If user specifies an mTLS endpoint override but device certificate is not - available, do not fail-fast, but let server return error when connecting. - -The above behavior avoids introducing client-side logic that parses whether the -endpoint override is an mTLS url, since the url pattern may change at anytime. - -### Obtaining the Default mTLS Endpoint - -The default mTLS endpoint for a service **should** be read from the Discovery -Document field **"mtlsRootUrl"** instead of generated via regex patterns. - -### Obtaining the Default Device Certificate via SecureConnect - -The default device certificate **should** be procured using the -[EndpointVerification][1] workflow, which fetches the certificate from a -platform-specific credential store (ex. KeyChain in macOS) via a native helper. - -Exporting the certificate via the native helper involves executing a **"cert -provider command"** specified in a well-known gcloud metadata file of the -following format: - -```json -{ - "version": 1 - "min_cloud_sdk_version": "240.0.0" - "has_client_cert": true - "endpoint_verification_error": "" - "cert_provider_command": "[absolute_path_to_provider_command] --fetch_client_cert" -} -``` - -For Linux and macOS platforms, the above metadata file is located at -**"~/.secureConnect/context_aware_metadata.json"**. - -The cert provider command will print the certificate to stdout, which will be in -the form of an X.509 cert followed immediately by the private key: - - -----BEGIN CERTIFICATE----- - Common Name: Google Endpoint Verification - Valid From: November 10, 2019 - Valid To: November 10, 2020 - Serial Number: 4921083229008411918 (0x444b331faf2dbd0e) - ... - -----END CERTIFICATE----- - -----BEGIN PRIVATE KEY----- - ... - -----END PRIVATE KEY----- - -### Obtaining the Default Device Certificate via ECP - -The Enterprise Certificate Proxy (ECP) project is the newly recommended way to -procure device certificates. It has two major advantages compared to the legacy -SecureConnect mechanism: - -1. Allows usage of enterprise certs and private keys stored in native keystores and TPMs - instead of relying on self-signed certs. -1. Delegates signing operations to keystores, so private keys never leave the security realm. - -Please see [ECP Public Documentation][2] for details on ECP configuration. - -### Environment Variables - -There are situations where the ADC for DCA behavior needs to be modified, such -as for integration testing, or for failsafe. To accomodate those scenarios, the -following environment variables **should** be supported. - -**GOOGLE_API_USE_MTLS_ENDPOINT**: If **"always"**, always use mTLS endpoint. If -**"never"**, always use regular endpoint. If **"auto"**, use the default -behavior, which is to use the mTLS endpoint if a device certificate is -available. The default value of this environment variable will be "auto". - -**GOOGLE_API_USE_CLIENT_CERTIFICATE**: If **"true"**, device certificate -authentication will be supported as described in the general guidance. If -**"false"**, the device certificate **must** not be used, even if specified by -the user. The default value **should** be "true" as of May 3, 2024. Users who -wish to disable DCA feature **must** explicitly set this environment variable -to "false". - -### Firewall and IP Address Guidance - -For any given GCP service, its mTLS endpoint has a different IP address compared -to the non-mTLS endpoint but is expected to fall within the same IP range. The -GCP guidance for IP range management is on a service by service basis. See -[Compute Engine IP Range Documentation][3] for example. In the unlikely event -that an end-user has configured firewall rules based on exact IP addresses -instead of an IP range, they may be impacted by the "auto" mTLS endpoint -upgrade behavior. The best-practice recommendation in this case would be to -avoid adding rules that expect exact IP address matches, and instead use -range-based IP rules following public GCP documentation. - -## Changelog - -- **2024-11-25*: GOOGLE_API_USE_CLIENT_CERTIFICATE should default to "true" as of May 3, 2024. -- **2025-02-20*: Add Firewall and IP Address Guidance - - -[0]: https://google.aip.dev/auth/4110 -[1]: https://cloud.google.com/endpoint-verification/docs/overview -[2]: https://cloud.google.com/beyondcorp-enterprise/docs/enable-cba-enterprise-certificates -[3]: https://cloud.google.com/compute/docs/faq#find_ip_range - diff --git a/aip/auth/4115.md b/aip/auth/4115.md deleted file mode 100644 index 98ac553c10..0000000000 --- a/aip/auth/4115.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -id: 4115 -scope: auth -state: approved -created: 2020-08-13 ---- - -# Default Credentials For Google Cloud Virtual Environments - -If the client runs on Google cloud virtual environments such as [Google Compute Engine (GCE)][0], -[Serverless][1], or [Google Kubernetes Engine (GKE)][2], the auth library **may** leverage -Google’s default mutual TLS (mTLS) credentials and obtain bound tokens for the instance. -The auth library **may** use the default mTLS credentials and bound tokens to access Google APIs. - -mTLS authentication enables authentication of both client and server identities in a TLS handshake. -Applications running in Google virtual environments can authenticate to Google APIs using X.509 -SPIFFE Verifiable Identity Documents (SVIDs). These SVIDs are X.509 certificates that contain SPIFFE -IDs specifying the identity of the certificate owner. - -Bound tokens are access tokens that are bound to some property of the credentials used to establish -the mTLS connection. The advantage of bound tokens is that they can be used over secure channels -established via mTLS credentials with the correct binding information, when appropriate access -policies have been put in place. Therefore, using bound tokens is more secure than bearer tokens, -which can be stolen and adversarially replayed. - -This AIP describes the flow of: - -1. Retrieving a configuration through a metadata server (MDS) endpoint. The configuration specifies - how to access Google’s default mTLS credentials. -2. Requesting bound tokens. - -**Note:** Because this AIP describes guidance and requirements in a language-neutral way, it uses -generic terminology which may be imprecise or inappropriate in certain languages or environments. - -## Guidance - -### Access Default mTLS Credentials - -**Note:** Before trying to use Google’s default mTLS credentials, the client **must** first check if the remote -Google API endpoint supports mTLS. If the remote endpoint does NOT support mTLS, the client **should** -connect to the endpoint using TLS. How to check if an endpoint supports mTLS is out of the scope of this -AIP. If the remote endpoint does support mTLS, the client **should** try to connect using mTLS first -before falling back to TLS. How to find the remote API’s mTLS endpoint is out of the scope of this AIP. -If users enabled [Device Certificate Authentication (DCA)](4), the client **should** give priority to DCA -as mTLS credentials. - -To leverage Google’s default mTLS credentials, the client **should** retrieve configurations from -MDS. The MDS in all virtual environments (GCE, Serverless, and GKE) exposes an HTTP endpoint that -serves a configuration that specifies how to access Google's default mTLS credentials. This endpoint -is called the mTLS configuration endpoint. - -The URL of the MDS's mTLS configuration endpoint is: -``` -http://metadata.google.internal/computeMetadata/v1/instance/platform-security/auto-mtls-configuration -``` - -The request to the MDS's mTLS configuration endpoint **should** be an HTTP GET request without any -parameter or payload. - -The response from the MDS's mTLS configuration endpoint **should** contain the following -information: - -* The **Secure Session Agent** address: the client doesn’t have direct access to mTLS credentials. - The Secure Session Agent manages default mTLS credentials. The client can only use mTLS - credentials through the Secure Session Agent. The address can be an IP:port address or a file path - representing a Unix Domain Socket (UDS). - -The client **must** follow the steps below to access Google’s default mTLS credentials. - -1. Check if the remote endpoint supports mTLS. - * If yes, go to step (2). - * If not, go to step (3). -2. Send a request to the MDS's mTLS configuration endpoint. If the request is successful and the - response contains a Secure Session Agent address, use the address to access Google's default mTLS - credentials, and go to step (4). If the request fails or the response contains an empty address, - go to step (3). -3. Fall back to TLS [END]. -4. Configure the TLS library to use the Secure Session Agent ([example][3]) for client authentication - during the mTLS handshake. - -### Request Bound Tokens - -To access Google APIs with bound tokens, the client **should** request tokens from MDS. The MDS in -all virtual environments (GCE, Serverless, and GKE) exposes an HTTP endpoint that serves access tokens. -This endpoint is called the access token endpoint. - -The URL of the MDS's access token endpoint is: -``` -http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token -``` - -The request to the MDS's access token endpoint **should** be an HTTP GET request. The request **may** -have a “scopes” URL parameter with a list of comma-separated scopes. The auth library **should** allow -the caller to optionally specify a list of custom scopes, and add the “scopes” parameter to the request -when needed. Depending on the runtime environment, the request for custom scopes **may** be transparently -ignored or fulfilled by the server. - -The response from the MDS's access token endpoint **should** contain an access token in the following -JSON format: - -```json -{ - "access_token": "YOUR_ACCESS_TOKEN", - "expires_in": 3599, - "token_type": "Bearer" - } -``` - -The client **must** follow the steps below to request new access tokens for Google APIs if existing -tokens expire. - -1. Send an HTTP request to the MDS access token endpoint, retrieve the access token from the response - and go to step (2). -2. Attach the token from step (1) to the request to Google APIs. - -## Changelog - -- **2020-12-14**: Replace note on scopes with more detailed discussion. -- **2021-07-13**: Clarify GCE equivalent runtimes -- **2023-02-16**: Add mTLS configuration endpoint and unify the token binding flow. - - -[0]: https://cloud.google.com/compute -[1]: https://cloud.google.com/serverless -[2]: https://cloud.google.com/kubernetes-engine -[3]: https://github.com/google/s2a-go/tree/main/example -[4]: https://google.aip.dev/auth/4114 - diff --git a/aip/auth/4116.md b/aip/auth/4116.md deleted file mode 100644 index 18361b2f22..0000000000 --- a/aip/auth/4116.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -id: 4116 -scope: auth -state: draft -created: 2021-01-06 ---- - -# Identity Tokens - -Identity Tokens (or ID Tokens) are JSON Web Tokens (JWT) with additional claims pertaining to the identity of the client or end-user (such as "email"). Which additional claims fields are included in the ID token are dependent on the ID -token provider. - -The **fetching** of ID tokens is used to: - - * request a [protected Cloud Run service][0], which requires a valid ID token in the `Authentication` header. - * request an [IAP-protected resource][2], which requires a valid ID token in the `Authentication` header. - -The **validation** of ID tokens should be done by: - - * services receiving an [authenticated PubSub push message][1] sent outside of Google Cloud. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -This section describes the general guidance of ID tokens as a means of -authentication. - -### ID tokens obtained by Application Default Credentials - -When a target audience is provided by the developer, [ADC][3] **should** fetch -an ID token with the credentials provided. For example, if service account keys -are provided, ADC will request an ID token from the OAuth token endpoint. If -[virtual machine credentials][4] are provided, ADC will request an ID token from -the virtual machine server. - -### Expected Behavior for Fetching ID Tokens - -To support fetching ID Tokens, the auth libraries **must** follow the steps -below: - -1\. Accept a target audience parameter when Application Default Credentials -are requested. If a target audience and scope are both provided to the auth library, an exception **must** be thrown. - -2\. Virtual machine credentials return the ID token retrieved from the metadata -server's `instance/service-accounts/default/identity` endpoint, setting the -`audience` querystring parameter to the provided target audience. - -3\. Service account Keys use the [JWT Bearer][5] grant type, and set the -`target_audience` claim to the provided target audience. This will return a JSON -object containing an `id_token` key. - -User Identity flows may be used to issue ID tokens, but are not required to. - -### Expected Behavior for Verifying ID Tokens - -To support verifying ID Tokens, the auth libraries **must** provide a method to -validate a JWT token which can do the following: - -1\. Validate a JWT with an ES256 signature. -2\. Validate JWT `aud` claim against a user-provided audience. -3\. Validate JWT `exp` claim against the current timestamp. - - -[0]: https://cloud.google.com/run/docs/authenticating/service-to-service -[1]: https://cloud.google.com/pubsub/docs/push#setting_up_for_push_authentication -[2]: https://cloud.google.com/iap/docs/signed-headers-howto#securing_iap_headers -[3]: https://google.aip.dev/auth/4110 -[4]: https://google.aip.dev/auth/4115 -[5]: https://tools.ietf.org/html/rfc7523 - diff --git a/aip/auth/4117.md b/aip/auth/4117.md deleted file mode 100644 index b1e8ad96b2..0000000000 --- a/aip/auth/4117.md +++ /dev/null @@ -1,553 +0,0 @@ ---- -id: 4117 -scope: auth -state: approved -created: 2020-12-10 ---- - -# External Account Credentials (Workload Identity Federation) - -Using workload identity federation, your application can access Google Cloud -resources from Amazon Web Services (AWS), Microsoft Azure or any identity -provider that supports OpenID Connect (OIDC) or SAML 2.0. - -Traditionally, applications running outside Google Cloud have used service -account keys to access Google Cloud resources. Using identity federation, -you can allow your workload to impersonate a service account. This lets you -access Google Cloud resources directly, eliminating the maintenance and -security burden associated with service account keys. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -This section describes the general guidance of supporting non-Google external -credentials (AWS, Azure, OIDC and SAML IdPs, etc) as a means of authentication. - -### Prerequisite - -In order to use workload identity federation to access Google cloud resources -from non-Google cloud platforms, the following steps are needed to configure -workload identity pools, providers, service account impersonation and generate -the JSON configuration file to be used by the auth libraries. - -- [Configure Workload Identity Federation from AWS][0] -- [Configure Workload Identity Federation from Microsoft Azure][1] -- [Configure Workload Identity Federation from an OIDC identity provider][2] -- [Configure Workload Identity Federation from a SAML identity provider][3] - -### Configuration File Generation and Usage - -After workload identity federation is configured, the JSON configuration file -should be generated. This sample shows how an AWS configuration file is -generated: - -```bash -$ gcloud iam workload-identity-pools create-cred-config \ - projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \ - --service-account=$SERVICE_ACCOUNT_EMAIL \ - --aws \ - --output-file=$FILEPATH.json -``` - -The following values would need to be replaced: - -- **PROJECT_NUMBER**: Project number of the project that contains the workload - identity pool. -- **POOL_ID**: ID of the workload identity pool. -- **PROVIDER_ID**: ID of the workload identity pool provider. -- **SERVICE_ACCOUNT_EMAIL**: Email address of the service account to - impersonate. -- **FILEPATH**: File to save configuration to. - -If you are using [AWS IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html), -an additional flag `--enable-imdsv2` should be added to the [`gcloud iam workload-identity-pools create-cred-config`](/sdk/gcloud/reference/iam/workload-identity-pools/create-cred-config) command: - -```bash -$ gcloud iam workload-identity-pools create-cred-config \ - projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \ - --service-account=$SERVICE_ACCOUNT_EMAIL \ - --aws \ - --enable-imdsv2 \ - --output-file=$FILEPATH.json -``` - -If you wish to configure the service account access token lifetime, -an additional flag `--service-account-token-lifetime-seconds` should be added to the [`gcloud iam workload-identity-pools create-cred-config`](/sdk/gcloud/reference/iam/workload-identity-pools/create-cred-config) command (this example uses an AWS configuration, but the token lifetime can be configured for all workload identity federation providers): - -```bash -$ gcloud iam workload-identity-pools create-cred-config \ - projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \ - --service-account=$SERVICE_ACCOUNT_EMAIL \ - --aws \ - --service-account-token-lifetime-seconds=$TOKEN_LIFETIME \ - --output-file=$FILEPATH.json -``` - -The service-account-token-lifetime-seconds flag is optional. If not provided, this defaults to one hour. The minimum allowed value is 600 (10 minutes) and the maximum allowed value is 43200 (12 hours). If a lifetime greater than one hour is required, the service account must be added as an allowed value in an Organization Policy that enforces the `constraints/iam.allowServiceAccountCredentialLifetimeExtension` constraint. - -The external identities configuration file can be used with -[Application Default Credentials][6]. In order to use external identities with -Application Default Credentials, the full path to this file should be stored -in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - -```bash -export GOOGLE_APPLICATION_CREDENTIALS=/path/to/config.json -``` - -The library can now automatically choose the right type of client and initialize -credentials from the context provided in the configuration file: - -```python -import google.auth - -credentials, project = google.auth.default() -``` - -External account credentials can also be initialized explicitly using the -generated configuration file. - -```python -# Sample for Azure or OIDC/SAML providers. -import json - -from google.auth import identity_pool - -json_config_info = json.loads(function_to_get_json_config()) -credentials = identity_pool.Credentials.from_info(json_config_info) -scoped_credentials = credentials.with_scopes( - ['https://www.googleapis.com/auth/cloud-platform']) -``` - -```python -# Sample for AWS. -import json - -from google.auth import aws - -json_config_info = json.loads(function_to_get_json_config()) -credentials = aws.Credentials.from_info(json_config_info) -scoped_credentials = credentials.with_scopes( - ['https://www.googleapis.com/auth/cloud-platform']) -``` - -## Expected Behavior - -The auth libraries should use the information in the JSON configuration file to -retrieve the external credentials and exchange them for Google access tokens -using the GCP Security Token Service (via the token exchange endpoint -`https://sts.googleapis.com/v1/token`) and then impersonating a service account -by calling the **IamCredentials** [generateAccessToken][5] API to access GCP -resources. - -All external account JSON files must share the following fields: - -| Field Name | Required | Description | -|-----------------------------------|----------|:------------| -| type | Yes | This identifies the new type of credential object. This must be "external_account" | -| audience | Yes | This is the STS audience which contains the resource name for the workload identity pool and the provider identifier in that pool. | -| subject_token_type | Yes | This is the STS subject token type based on the [OAuth 2.0 token exchange spec][7]. | -| service_account_impersonation_url | No | This is the URL for the service account impersonation request. If this is not available, the STS returned access token should be directly used without impersonation. | -| service_account_impersonation.* | No | This object defines additional service account impersonation options. Only one field is currently supported: “token_lifetime_seconds": This is the requested access token lifetime, e.g. `2800`. | -| token_url | Yes | This is the STS token exchange endpoint. | -| credential_source.* | Yes | This object defines the mechanism used to retrieve the external credential from the local environment so that it can be exchanged for a GCP access token via the STS endpoint. | - -The auth libraries and applications **must** follow the steps below for all -types of external account credentials: - -- Check **credential_source** to determine the necessary logic to retrieve the - external credential which should be used to construct the subject token to - pass to the STS endpoint. This is covered in detail for every credential - configuration below. -- Construct the STS request, based on [rfc8693][4]: - - STS audience should be constructed using the **audience** field. - - **grant_type** must be `urn:ietf:params:oauth:grant-type:token-exchange` - - **requested_token_type** must be - `urn:ietf:params:oauth:token-type:access_token` - - **subject_token_type** is the **subject_token_type** field as described in - the RFC. - - **subject_token** is the retrieved external credentials. Check the - subsequent sections on how this is retrieved in various environments. - - **scope**: the list of space-delimited, case-insensitive OAuth scopes that - specify the desired scopes of the requested security token in the context - of the service or resource where the token should be used. If service - account impersonation is used, the cloud platform or IAM scope should be - passed to STS and then the customer provided scopes should be passed in the - **IamCredentials** call to [generateAccessToken][5]. - - The STS token exchange URL should be the **token_url** (e.g. - `https://sts.googleapis.com/v1/token`). -- Send the STS token exchange request to get the Google access token and its - expiration. -- If the **service_account_impersonation_url** is available, trigger service - account impersonation flow by POSTing to that endpoint with the previously - returned Google access token. - - If this is not available, end the flow and just use the STS access token - for authorization. - - The list of scopes also need to be provided for this endpoint. The customer - provided scopes should be used for this endpoint. - - In order to access this API, the (Cloud platform - `https://www.googleapis.com/auth/cloud-platform` or IAM scope - `https://www.googleapis.com/auth/iam`) are required in the underlying - access token. - - The service account access token lifetime also needs to be provided for this endpoint. The value in - **service_account_impersonation.token_lifetime_seconds** will be used if it - was provided, otherwise it will default to 1 hour. - -### Determining the subject token in AWS - -External account configuration JSON files should contain the following -information in the `credential_source` object to facilitate retrieval of AWS -credentials to be passed as subject tokens to the GCP STS token exchange -endpoint. - -| Field Name | Required | Description | -|--------------------------------------------------|----------|:------------| -| environment_id | Yes | This is the environment identifier, of format `aws${version}`. A version should be specified to indicate to the auth library whether breaking changes were introduced to the underlying AWS implementation. So if aws1 is supported in the current version of the library but a credential file with aws2 is provided, an error should be thrown instructing the developer to upgrade to a newer version of the library. | -| region_url | No | This URL should be used to determine the current AWS region needed for the signed request construction when the region environment variables are not present. | -| url | No | This AWS metadata server URL should be used to retrieve the access key, secret key and security token needed to sign the `GetCallerIdentity` request. The $ROLE_NAME should be retrieved from calling this endpoint without any parameter and then calling again with the returned role name appended to this URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME | -| regional_cred_verification_url | Yes | This defines the regional AWS `GetCallerIdentity` action URL. This URL should be used to determine the AWS account ID and its roles. This should not actually be called by the Auth libraries. It should be called on the STS token server. The region should be substituted by SDK, e.g. `sts.eu-west-1.amazonaws`.com. | -| imdsv2_session_token_url | No | Presence of this URL enforces the auth libraries to fetch a Session Token from AWS. This field is required for EC2 instances using IMDSv2. This Session Token would later be used while making calls to the metadata endpoint. | - -The JSON file for AWS configuration files should have the following form: - -```json -{ - "type": "external_account", - "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", - "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request", - "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken", - "token_url": "https://sts.googleapis.com/v1/token", - "credential_source": { - "environment_id": "aws1", - "region_url": "http://169.254.169.254/latest/meta-data/placement/availability-zone", - "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials", - "regional_cred_verification_url": "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15", - "imdsv2_session_token_url": "http://169.254.169.254/latest/api/token" - } -} -``` - -The auth libraries and applications **must** follow the steps below: - -- Check **credential_source** for environment ID. If the environment ID is - `aws${version}`, this should be an AWS native credential. -- Inspect the version in the environment ID. If this is a newer unexpected - error, trigger an error that the auth library needs to be updated to handle - this type of credentials. -- Validate the host for the **url**, **regional_url** and - **imdsv2_session_token_url** fields if they are provided. The host should - either be **169.254.169.254** or **fd00:ec2::254**. -- If **imdsv2_session_token_url** is available, then fetch session token - from **imdsv2_session_token_url**. Note: only perform this step if you - need to communicate with the metadata server to fetch the region and/or - the security credentials -- Check the environment variables in the following order (`AWS_REGION` and - then the `AWS_DEFAULT_REGION`) to determine the AWS region. If found, skip - using the AWS metadata server to determine this value. -- If the region environment variables are not provided, use the **region_url** - to determine the current AWS region. The API returns the zone name, e.g. - `us-east-1d`. The region should be determined by stripping the last - character, e.g. `us-east-1`. -- Check the environment variables `AWS_ACCESS_KEY_ID`, - `AWS_SECRET_ACCESS_KEY` and the optional `AWS_SESSION_TOKEN` for the AWS - security credentials. If found, skip using the AWS metadata server to - determine these values. -- If **url** is available and the security credentials environment variables - are not provided: - - Call **url** to retrieve the attached AWS IAM role name to the current - instance. - - Call **url/$ROLE_NAME** to get the access key, secret key and security - token needed to sign the `GetCallerIdentity` request. -- Construct the AWS signed request ([AWS Signature Version 4][8]) using the - [GetCallerIdentity][9] **regional_cred_verification_url** (with the region - substituted). This should be serialized by formatting it as a url-encoded - JSON and passed as the **subject_token** to STS endpoint. - Here is a sample of the JSON format used: - - ```json - { - "url": "https://sts.us-east-1.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15", - "headers": [ - { - "value": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", - "key": "x-goog-cloud-target-resource" - }, - { - "value": "20200228T225005Z", - "key": "x-amz-date" - }, - { - "value": "AWS4-HMAC-SHA256 Credential=AKIASOZTBDV4D7ABCDEDF/20200228/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token;x-goog-cloud-target-resource, Signature=abcedefdfedfd", - "key": "Authorization" - }, - { - "value": "sts.us-east-1.amazonaws.com", - "key": "host" - }, - { - "value": "IQoJb3JpZ2luX2VjEIz//////////wEaCXVzLWVh...", - "key": "x-amz-security-token" - } - ], - "method": "POST", - "body": "" - } - ``` - For the AWS token, STS requires a special header `x-goog-cloud-target-resource` to recognize that the token is for a specific workload identity provider. - -### Determining the subject token in Microsoft Azure and URL-sourced credentials - -External account configuration JSON files should contain the following -information in the `credential_source` object to facilitate retrieval of Azure -and other URL-sourced credentials to be passed as subject tokens to the GCP STS -token exchange endpoint. - -| Field Name | Required | Description | -|---------------------------------------------------|----------|:-------------| -| url | Yes | This defines the local metadata server to retrieve the external credentials from. For Azure, this should be the Azure Instance Metadata Service (IMDS) URL used to retrieve the Azure AD access token. | -| headers | No | This defines the headers to append to the GET request to credential_source.url. | -| format.type | No | This indicates the format of the URL response. This can be either "text" or "json". The default should be "text". | -| format.subject_token_field_name | No | Required for JSON URL responses. This indicates the JSON field name where the subject_token should be stored. | - -The JSON file for URL-sourced configuration files (OIDC / SAML) should have the -following form: - -```json -{ - "type": "external_account", - "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", - "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", - "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken", - "token_url": "https://sts.googleapis.com/v1/token", - "credential_source": { - "url": "http://localhost:5000/token", - "format": { - "type": "json", - "subject_token_field_name": "id_token" - } - } -} -``` - -Azure configuration files are a type of OIDC URL-sourced credentials. - -```json -{ - "type": "external_account", - "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", - "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", - "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken", - "token_url": "https://sts.googleapis.com/v1/token", - "credential_source": { - "headers": { - "Metadata": "True" - }, - "url": "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", - "format": { - "type": "json", - "subject_token_field_name": "access_token" - } - } -} -``` - -The auth libraries and applications **must** follow the steps below: - -- Check **credential_source** has a **url** field and no **environment_id**, - otherwise skip the rest of the steps. -- An HTTP GET request should be sent to this local **url** while injecting - the **headers** key/values (if provided in the configuration file) in the - request header. The request should respond with the external credentials - subject token to be passed to STS token endpoint. -- Before parsing the token, check the **format** field. -- If the **format** is not available, assume the external credential returned - by the URL response is provided in plain text format. -- If available, check if the type is **json** - - If json, check the **subject_token_field_name**. - For Azure, this is set to **access_token**. - - Parse the file as JSON and then retrieve the external credential from - the field name based on the value of **subject_token_field_name**. - -### Determining the subject token in file-sourced credentials - -External account configuration JSON files contain the following information -in the `credential_source` object to facilitate retrieval of file-sourced -credentials to be passed as subject tokens to the GCP STS token exchange -endpoint. - -| Field Name | Required | Description | -|---------------------------------------------------|----------|:------------| -| file | Yes | This is the source of the credential. This should be used for a credential locally available. This should take precedence over `url` when both are provided. | -| format.type | No | This indicates the format of the file where the token is stored. This can be either "text" or "json". The default should be "text". | -| format.subject_token_field_name | No | Required for JSON file formats. This indicates the JSON field name where the `subject_token` should be stored. | - -The JSON file for file-sourced configuration files (OIDC / SAML) should have -the following form: - -```json -{ - "type": "external_account", - "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", - "subject_token_type": "urn:ietf:params:oauth:token-type:saml2", - "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken", - "token_url": "https://sts.googleapis.com/v1/token", - "credential_source": { - "file": "/var/run/saml/assertion/token" - } -} -``` - -The auth libraries and applications **must** follow the steps below: - -- Check **credential_source** has a **file** field and no **environment_id**. If not, - this is not a file-sourced credential and the proceeding steps do not apply. -- Get the external credential from the file location specified by the - `credential_source.file` field. -- Before parsing the token, check the **format** field. -- If the **format** is not available, assume the external credential is - provided in plain text format. -- If available, check if the type is **json** - - If json, check the **subject_token_field_name**. - - Parse the file as JSON and then retrieve the external credential from - the field name based on the value of **subject_token_field_name**. - - -### Determining the subject token in executable-sourced credentials - -External account configuration JSON files contain the following information -in the `credential_source` object to facilitate retrieval of executable-sourced -credentials to be passed as subject tokens to the GCP STS token exchange -endpoint. - -| Field Name | Required | Description | -|---------------------------|----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| executable | Yes | Holds the information necessary to run the executable. | -| executable.command | Yes | Specifies the full command to run to retrieve the subject token. This can include arguments. Must be an absolute path for the program. | -| executable.timeout_millis | No | Specifies the timeout duration, in milliseconds. Defaults to 30 seconds when not provided. | -| executable.output_file | No | Specifies the absolute path to the output file where the executable will cache the response. By specifying this path, the auth libraries will first check this location before running the executable. The format of the file should match the JSON format expected by the auth libraries defined below. | - -The JSON file for executable-sourced configuration files (OIDC / SAML) should have -the following form: - -```json -{ - "type": "external_account", - "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", - "subject_token_type": "urn:ietf:params:oauth:token-type:saml2", - "token_url": "https://sts.googleapis.com/v1/token", - "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL@project.iam.gserviceaccount.com:generateAccessToken", - "credential_source": { - "executable": { - "command": "/path/to/executable --arg1=value1 --arg2=value2", - "timeout_millis": 5000, - "output_file": "/path/to/cached/credentials" - } - } -} -``` - -To use executable-sourced credentials, the `GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES` environment variable must be set to `1`. - -Additionally, the executable **must** adhere to the following response format: - -Successful responses: - -| Field Name | Type | Description | -|---------------------------|---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| version | number | The version of the JSON output. Currently only version 1 is supported. | -| success | boolean | The status of the response. True in this case. | -| token_type | string | The 3rd party subject token type. Must be *urn:ietf:params:oauth:token-type:jwt*, *urn:ietf:params:oauth:token-type:id_token*, or *urn:ietf:params:oauth:token-type:saml2*. | -| id_token OR saml_response | string | The 3rd party OIDC token or SAML response. | -| expiration_time | number | The optional 3rd party subject token expiration time in seconds (unix epoch time). Only required in the response when an output file is specified in the credential configuration. | - -A sample successful executable OIDC response: -```json -{ - "version": 1, - "success": true, - "token_type": "urn:ietf:params:oauth:token-type:id_token", - "id_token": "...", - "expiration_time": 1620499962 -} -``` - -A sample successful executable SAML response: -```json -{ - "version": 1, - "success": true, - "token_type": "urn:ietf:params:oauth:token-type:saml2", - "saml_response": "...", - "expiration_time": 1620499962 -} -``` - -Error responses: - -| Field Name | Type | Description | -|------------|---------|:-----------------------------------------------------------------------| -| version | number | The version of the JSON output. Currently only version 1 is supported. | -| success | boolean | The status of the response. False in this case. | | -| code | string | The error code. | -| message | string | The error message. | - -A sample executable error response: -```json -{ - "version": 1, - "success": false, - "code": "401", - "message": "Caller not authorized." -} -``` - -The auth libraries and applications **must** follow the steps below: - -- Check **credential_source** has an **executable** field and no **environment_id**. If not, - this is not a executable-sourced credential and the proceeding steps do not apply. -- Retrieve the external credential's executable information from the - **credential_source.executable** field. -- Check that the `GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES` environment variable is set to **1**. If not, error out. -- Before the next step, check if **credential_source.executable.output_file** was specified in the credential configuration. - - If present, check if there is an executable response at that location. - - If the response is valid and unexpired, or there is no response at that location, continue execution. - - If the response is malformed or invalid, error out. -- Ensure the following environment variables will be available to the executable: - - `GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE`: The audience field from the credential configuration. Must always be present. - - `GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE`: The subject token type. Must always be present. - - `GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL`: The service account email. Only present when service account impersonation is used. - - `GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE`: The output file location from the credential configuration. Only present when specified in the credential configuration. -- Run the command specified at **credential_source.executable.command**. - - Fail in the following scenarios: - - The executable failed to complete in the timeout duration specified. - - The executable's response is invalid, was unsuccessful or expired. - - The executable finished with a non-zero exit code. -- Parse the executable response as JSON and then retrieve the external credential from - the field name based on the value of **token_type**. - - The token_type value must be **urn:ietf:params:oauth:token-type:jwt**, - **urn:ietf:params:oauth:token-type:id_token**, or **urn:ietf:params:oauth:token-type:saml2**. - - If the **token_type** is **urn:ietf:params:oauth:token-type:saml2**, the subject token will be parsed from the **saml_response** field. - - Otherwise it will be parsed from the **id_token** field. - -## Changelog - -- **2025-10-17**: Corrections in specification and examples for External Account Credentials (AIP 4117). -- **2021-12-10**: Add AIP for External Account Credentials (AIP 4117). -- **2022-05-18**: Document executable-sourced credentials (AIP 4117). -- **2022-08-31**: Document configurable token lifetime (AIP 4117). -- **2023-09-12**: Mark region_url as optional (AIP 4117). - - -[0]: https://cloud.google.com/iam/docs/configuring-workload-identity-federation#aws -[1]: https://cloud.google.com/iam/docs/configuring-workload-identity-federation#azure -[2]: https://cloud.google.com/iam/docs/configuring-workload-identity-federation#oidc -[3]: https://cloud.google.com/iam/docs/configuring-workload-identity-federation#saml_1 -[4]: https://tools.ietf.org/html/rfc8693 -[5]: https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateAccessToken -[6]: https://google.aip.dev/auth/4110 -[7]: https://tools.ietf.org/html/rfc8693#section-3 -[8]: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html -[9]: https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html - diff --git a/aip/auth/4118.md b/aip/auth/4118.md deleted file mode 100644 index 27e2e83408..0000000000 --- a/aip/auth/4118.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -id: 4118 -scope: auth -state: draft -created: 2022-09-09 ---- - -# Mutual Authentication Using Workload Credentials - -Mutual TLS (a.k.a mTLS) authentication enables authentication of both client and -server identities in a TLS handshake. With workload credentials, applications -running in Google Cloud can authenticate to Google APIs using [X.509 SPIFFE -Verifiable Identity Documents][0] (SVIDs). These SVIDs are X.509 certificates -that contain [SPIFFE IDs][1] specifying the identity of the certificate owners. -mTLS authentication using X.509 SVIDs occurs when the client uses an X.509 SVID -when performing the TLS handshake. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -If users enable token binding, they **should** do so via [ADC][2]. This section -describes the general guidance of supporting such authentication. - -### Provisioning Workload Credentials in Google Cloud - -On Google Cloud, workload credentials should be provisioned using one of the -following methods: - -- [Set up service security with Envoy][3]. - -- [Set up service security with proxyless gRPC][4]. - -In order for workload credentials to be properly used, the auth libraries -**must** support the automatic switching of the service endpoint to its mTLS -counterpart. - -### Using Workload Credentials - -Users **should** configure [ADC][2] to use workload credentials via the -certificate configuration gcloud metadata file. Workload credentials can be -added as a **"cert_configs"** type as follows: - -```json -{ - "version": 1 - "cert_configs": { - "workload": { - "cert_path": "path/to/cert/file" - "key_path": "path/to/key/file" - "workload_identity_provider": "..." - "authenticate_as_identity_type": "gsa/native" - "service_account_email": "..." - }, - "keychain": { - ... - }, - "pkcs11": { - ... - }, - "windows": { - ... - }, - }, - "libs": { - ... - } -} -``` - -For Linux and macOS platforms, the above metadata file is located in the -well-known gcloud config directory at -**"~/.config/gcloud/certificate_config.json"**. Note that the default location -of this file can be changed using the `GOOGLE_API_CERTIFICATE_CONFIG` -environment variable. - -The following lists the fields of the **"workload"** certificate info type that -are relevant to workload credentials: - -- **"cert_path"**: The specified value will be used as the full path to locate -the workload certificate file. This file **must** contain a PEM-encoded -X.509 certificate chain (ordered from leaf to root) where the leaf -certificate is a valid X.509 SVID. The chain __may__ consist of only the -leaf certificate. - -- **"key_path"**: The specified value will be used as the full path to locate -the workload private key file. This file must contain a PEM-formatted -private key associated with the X.509 certificate specified by -**“cert_path”**. - -The description of the **"workload_identity_provider"**, -**"authenticate_as_identity_type"** and **"service_account_email"** fields can -be found in [mTLS Token Binding][5]. - -To enable mutual authentication to Google APIs using workload credentials, the -**"workload"** section and its **"cert_path"** and **"key_path"** values must be -present in the **"~/.config/gcloud/certificate_config.json"** configuration -file. - -### Expected Behavior - -Support for mTLS authentication to Google APIs using workload credentials -**must** give priority to user mTLS endpoint override via client options. The -auth libraries **must** follow the steps below: - -- Locate the workload certificate and private key files using the above -config file. If one of these files is not present, mTLS using workload -credentials may be disabled. The auth libraries **must** check that the -public and private keys in the certificate and key files match before -passing them to the TLS library. - - - Occasional mismatches may happen, since during certificate rotation the - client library may read the two files while another process is replacing - them. In that case, the library **must** retry reading the certificate - and private key files and checking their match status, up to a maximum - of four attempts. The library **should** wait for 5 seconds between - attempts. - - If the certificate and private key files are loaded in memory (as - opposed to being read from disk for every mTLS connection), the auth - libraries **must** periodically reload them (at least every 10 minutes - or when the certificate expires) to refresh their copies in memory after - the infrastructure rotates them. Refreshing the credentials **must** be - done in a background thread and not upon usage. - -- Configure the TLS library to use the found, and matched, certificate and -key for client authentication during the TLS handshake. - -- If the user specifies the endpoint override via client options, use it as is -and connect to the specified endpoint using mTLS. - -- If the user does not specify the endpoint override, use the default mTLS -endpoint if the certificate and key files exist and the default regular -endpoint otherwise. - -Note that mTLS 1.3 **must** be the only supported version to preserve client -identity and certificate confidentiality. - -One implication of the above logic is that if the user enables mTLS -authentication using workload credentials, provides valid certificate and key -files, and specifies a non-mTLS endpoint override, the client libraries -**should** use the certificate and key anyway and let the server decide what to -do. This avoids introducing client-side logic that parses whether the endpoint -override is an mTLS URL, since the URL pattern may change at any time. - -### Obtaining the Default mTLS Endpoint - -The default mTLS endpoint for a service **should** be read from the Discovery -Document field **"mtlsRootUrl"** instead of generated via regex patterns. - - -[0]: https://github.com/spiffe/spiffe/blob/main/standards/X509-SVID.md -[1]: https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md#2-spiffe-identity -[2]: https://google.aip.dev/auth/4110 -[3]: https://cloud.google.com/traffic-director/docs/security-envoy-setup -[4]: https://cloud.google.com/traffic-director/docs/security-proxyless-setup -[5]: https://google.aip.dev/auth/4119 - diff --git a/aip/auth/4119.md b/aip/auth/4119.md deleted file mode 100644 index ee499325bf..0000000000 --- a/aip/auth/4119.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -id: 4119 -scope: auth -state: draft -created: 2022-09-09 ---- - -# mTLS Token Binding - -Token binding allows issuing Google access tokens that are bound to mTLS -credentials. The advantage of such mTLS bound tokens is that they are meant to -only be used over secure channels established via mTLS credentials they are -bound to. Therefore, using bound tokens is more secure than bearer tokens which -can be stolen and adversarially replayed. - -This AIP describes the flow of (1) obtaining access tokens bound to X.509 -certificate identities, called identity-bound tokens and (2) how to use them to -access Google APIs using the Google auth libraries. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments. - -## Guidance - -If users enable token binding, they **should** do so via [ADC][0]. This section -describes the general guidance of supporting such tokens. - -### Prerequisites - -Identity-bound access tokens require that the clients have -[X.509 SPIFFE Verifiable Identity Documents][1] (SVIDs). [Mutual Authentication -Using Workload Credentials][2] describes how such SVIDs are provisioned in -Google Cloud. - -Additionally, identity-bound access tokens tokens require configuring a workload -identity pool and identity provider with Google Cloud's IAM. The instructions on -how to do this are out of scope of this AIP. - -### Using mTLS Token Binding - -The auth libraries **must** support the following values in the -**"~/.config/gcloud/certificate_config.json"** configuration file. Note that the -default location of this file can be changed using the -`GOOGLE_API_CERTIFICATE_CONFIG` environment variable. - -```json -{ - "version": 1 - "cert_configs": { - "workload": { - "cert_path": "path/to/cert/file" - "key_path": "path/to/key/file" - "workload_identity_provider": "..." - "authenticate_as_identity_type": "gsa/native" - "service_account_email": "..." - }, - "keychain": { - ... - }, - "pkcs11": { - ... - }, - "windows": { - ... - }, - }, - "libs": { - ... - } -} -``` - -The following lists the fields relevant to mTLS token binding configuration: - -- **"workload_identity_provider"**: The specified value will be used to -populate the request to Security Token Service (STS) to request -identity-bound access tokens. This value refers to the fully qualified name -of the workload identity pool and identity provider configured in IAM. The -specified value **must** be of the following format. - -``` -"workload_identity_provider":"//iam.googleapis.com/projects//locations/global/workloadIdentityPools//providers/" -``` - -- **"authenticate_as_identity_type"**: This field specifies what identity is -used to authenticate to Google APIs. The value can be set to `gsa` or -`native`, where `gsa` is the GCP service account of the workload, e.g., the -GCP service account of a GCE VM, and `native` is the native workload -identity, e.g., the GKE pod kubernetes service account. If not specified, -the default value is `gsa`. - -- **"service_account_email"**: If set, the specified value will be used to -populate the request to the IAM Credentials service to request -identity-bound access tokens. This value refers to the service account email -to be used for resource access. If not set, the service account email will -be determined automatically by querying the following Metadata Service -endpoint: -`http://metadata/computeMetadata/v1/instance/service-accounts/default/email`. -The value of this field is only relevant if -**"authenticate_as_identity_type"** is set to `gsa`. - -The description of the **"cert_path"** and **"key_path"** fields can be found in -[Mutual Authentication Using Workload Credentials][2]. - -To enable using token binding when communicating with Google APIs the following -conditions are required: - -- [Mutual Authentication Using Workload Credentials][2] **must** be enabled. - -- The **"workload_identity_provider"** **must** be present, -**"authenticate_as_identity_type"** __may__ be set and -**"service_account_email"** __may__ be set in the **"workload"** -section of the **"~/.config/gcloud/certificate_config.json"** configuration -file. - -### Expected Behavior - -To support the usage of identity-bound access tokens, the auth libraries -**must** follow the steps below when sending requests to Google APIs: - -1. Connect to the mTLS endpoint of the [STS API][3] using the workload -credentials provisioned as described in [Mutual Authentication Using -Workload Credentials][2]. This endpoint **must** be -`sts.mtls.googleapis.com`. - -1. Send an HTTP request to STS’s [ExchangeToken][5] method requesting an -identity-bound token using the information in the -**"workload_identity_provider"** field in the -**"~/.config/gcloud/certificate_config.json"** configuration file. The -scope of the requested token **must** be -`https://www.googleapis.com/auth/iam`. - -1. Connect to the mTLS endpoint of the [IAM Credentials Service API][4] using -the workload credentials provisioned as described in [Mutual Authentication -Using Workload Credentials][2]. This endpoint **must** be -`iamcredentials.mtls.googleapis.com`. - -1. If **"authenticate_as_identity_type"** is set to `gsa`, send an HTTP -request to the IAM Credentials Service’s [GenerateAccessToken][6] method -requesting an identity bound token asserting the service account email in -the **"service_account_email"** field in the -**"~/.config/gcloud/certificate_config.json"** configuration file. The -scope of this token **must** be the same scope defined by the user for -accessing the requested Google API. - -1. Attach the returned token in Step 4 to the request. Note that this request -**must** be sent over an mTLS channel using the same workload credentials -in Step 1. - - -[0]: https://google.aip.dev/auth/4110 -[1]: https://github.com/spiffe/spiffe/blob/main/standards/X509-SVID.md -[2]: https://google.aip.dev/auth/4118 -[3]: https://cloud.google.com/iam/docs/reference/sts/rest -[4]: https://cloud.google.com/iam/docs/reference/credentials/rest -[5]: https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token -[6]: https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateAccessToken - diff --git a/aip/auth/scope.yaml b/aip/auth/scope.yaml deleted file mode 100644 index 3a49e1271c..0000000000 --- a/aip/auth/scope.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Auth -order: 25 diff --git a/aip/client-libraries/4210.md b/aip/client-libraries/4210.md deleted file mode 100644 index a6d238e42e..0000000000 --- a/aip/client-libraries/4210.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -id: 4210 -state: approved -created: 2018-06-22 -js_scripts: - - /assets/js/graphviz/viz.js - - /assets/js/graphviz/lite.render.js - - /assets/js/aip/aip-graphviz.js ---- - -# Client library generators - -API guidelines exist in order to promote simple, intuitive, and consistent -APIs. Users familiar with APIs that generally adhere to AIP guidance are able -to take what they learn in prior APIs and apply it to new ones. - -Client libraries provide a mechanism for users to get started with APIs more -quickly, by simplifying common concerns (such as auth) and by a language-native -way to call API endpoints and receive language-native responses. However, for -these libraries to provide the most value, they also must be simple, intuitive, -and consistent. Code generators provide a means for producing consistent client -libraries at scale. - -Code generators following the standards in these AIPs are known as "generated -API client generators", or _GAPIC generators_ for short. The resulting -libraries are colloquially called _GAPICs_. - -**Note:** Because this AIP describes guidance and requirements in a -language-neutral way, it uses generic terminology which may be imprecise or -inappropriate in certain languages or environments (for example, the use of the -term `class` even though languages such as Go do not have classes). This AIP's -particular use of vocabulary is best understood as an explanation of -principles, and precise adherence to exact vocabulary in this AIP is not an -expectation. - -## Guidance - -The general flow of code generation for client libraries and supporting code in -most supported languages is outlined below. - -**Note:** Exceptions to this pattern are typically due to use of a unique stack -e.g. Node.js use of `protobuf.js` and `grpc-node` which don't have code -generation, or Python using a protobuf wrapper in `proto-plus-python`, but the -general GAPIC flow remains the same. - -```graphviz -digraph { - node [ style="filled,solid" shape=box fontname="Roboto" ]; - splines=ortho; - nodesep=0.3; - center=true; - - proto [ label="API Protobuf\nDescriptors" shape=rectangle fillcolor=aliceblue ]; - - subgraph cluster_code_generators { - rank = same; - style = filled; - fillcolor = lightgrey; - node [ shape=oval ]; - - protobuf [ label="protobuf\ngenerator" fillcolor=deepskyblue3 ]; - grpc [ label="gRPC\ngenerator" fillcolor=gold3 ]; - gapic [ label="GAPIC\ngenerator" fillcolor=darkseagreen ]; - } - - proto -> protobuf; - proto -> grpc; - proto -> gapic; - - subgraph cluster_generated_code { - rank = same; - style = filled; - fillcolor = lightgrey; - node [ shape=rectangle ]; - - protobuf_output [ label="Message & Enum\nCode" fillcolor=deepskyblue3 ]; - grpc_output [ label="Server & Client\nStubs" fillcolor=gold3 ]; - gapic_output [ label="Google API\nClient" fillcolor=darkseagreen ]; - } - - protobuf -> protobuf_output; - grpc -> grpc_output; - gapic -> gapic_output; - - assembly [ label="Package\nassembly" shape=oval fillcolor=aliceblue ]; - - protobuf_output -> assembly - grpc_output -> assembly - gapic_output -> assembly - - assembled_package [ label="Package of\ngenerated code" fillcolor=aliceblue ]; - - assembly -> assembled_package -} -``` - -The following sections focus on the "GAPIC generator" in the above diagram. - -### Protobuf plugins - -The protobuf compiler, `protoc`, supports a [plugin system][0] for code -generation. The plugin system allows plugins to be written _in_ and _for_ any -language. - -Code generators **must** be implemented as `protoc` plugins. The following -rules apply to the implementation of a client library generator as a `protoc` -plugin: - -- The plugin **should** be written in the language being targeted for - generation. -- `protoc` expects plugins to be an executable in `$PATH`, and named - `protoc-gen-{plugin_name}`, corresponding to the `--{plugin_name}_out` option - sent to the `protoc` executable. As such: - - the plugin executable **should** be named `protoc-gen-{lang}_gapic` - - the plugin option **should** follow the convention `--{lang}_gapic_out` -- The plugin **must not** leverage `protoc` "insertion points". Despite the - `protoc` plugin documentation indicating the existence of insertion points, - their use is unsupported and discouraged by the Protobuf team. - -### CLI options - -Code generators **should** be able to run without any options or flags if at -all possible, and be able to generate a valid library from only the protos. If -options are required, `protoc` allows them to be passed as -`--{plugin_name}_opt`, and the string provided here becomes set as the -`parameter` string on the `CodeGeneratorRequest`. - -**Important:** The `CodeGeneratorRequest.parameter` value is a comma-delimited -string of _all_ associated plugin option values that appear at execution time. -This means that commas cannot be used to delimit list-like plugin option values. - -Code generators **must not** rely on environment variables for configuration. - -## Expected behavior - -This section outlines the expected behavioral attributes of the _output of_ the -client library generator (in other words: the libraries that the generators -write). Client libraries **must** implement these concepts in order to be -considered complete. - -### Messages and Enums - -Client library generators **should not** generate code for `message` or `enum` -descriptors which are already generated by the Protobuf-provided code -generators. - -### Services and methods - -Each of the `service` and `rpc` directives in the requested protos **must** be -represented in the client library output, unless the language or transport is -unable to support it. - -**Note:** While how to accomplish this may vary from language to language, in -most classical languages it is probably a class for each service, containing -methods for each RPC. - -- The classes generated for each `service` directive **must** honor the - `google.api.default_host` annotation if it is provided, and use that host as - the default hostname. These classes **should** provide a mechanism for the - end user to override the hostname. - - If the `google.api.default_host` annotation is not present on the `service` - directive, then the generated class **should** require a hostname when it - is instantiated. -- Additionally, if the classes generated for each service support using OAuth - and service credentials, they **must** honor the `google.api.oauth_scopes` - annotation (if it is provided), and use these scopes by default. -- Services that have set the `deprecated` protobuf option to `true` **should** have an - equivalent deprecation tag generated in the generated class. If applicable, this - tag may include a comment that specifies when the service will be removed, which - is typically the next major version update. Similarly, RPCs with this option set - to `true` **should** have their generated language method(s) marked as deprecated. -- Finally, service classes **must** also accept credentials, which are used - appropriately when requests are made. (Accepting a custom gRPC channel - satisfies this requirement.) -- Code generators **must not** generate client _stub_ classes, that would - normally be generated by gRPC, in addition to client library classes. - -### Long-running operations - - - -An RPC is considered to be a "long-running" RPC if (and only if) the RPC's -return type is [`google.longrunning.Operation`][3]. Any API which has one or -more RPCs returning an `Operation` is expected to implement the `Operations` -service. - -Because the `response` and `metadata` fields in [`Operation`][3] are of the -type [`google.protobuf.Any`][4], it is necessary to know what message to use to -deserialize them. This is annotated on the RPC using the -[`google.longrunning.operation_info`][5] annotation. - -**Note:** The values in this struct are _strings_, not message objects; the -code generator uses the string to determine the appropriate message to use. -Strings with no period (`.`) character refer to a message in the same proto -package. - -Code generators **should** fail with an error if a type is provided in the -[`operation_info`][5] annotation which was not imported, or if no response type -or metadata type is provided. Code generators **should** fail with an error if -_either_ the `response_type` or `metadata_type` keys are omitted. - -Client libraries **must** honor the LRO interface; if an RPC has an -[`Operation`][3] as its return type, the generated method **must** intercept it -and return an appropriate idiomatic object for resolving the LRO (such as a -`Future` or `Promise` bound to the underlying [`Operation`][3] object). - -### Streaming - -Client libraries **must** implement streaming to the extent that their -supporting transports allow. An RPC is considered to be streaming if the -`stream` keyword is present on the argument or response type. This is present -in the [`MethodDescriptorProto`][6] message using the `client_streaming` and -`server_streaming` keys. - - -[0]: https://protobuf.dev/reference/other -[1]: https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/plugin.proto -[2]: https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto -[3]: https://github.com/googleapis/googleapis/blob/master/google/longrunning/operations.proto#L122 -[4]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto -[5]: https://github.com/googleapis/googleapis/blob/master/google/longrunning/operations.proto#L222 -[6]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto#L269 - - -## Changelog - -- **2023-06-22**: Added code gen diagram, message/enum guidance, and cleaned up - plugin & option guidance. \ No newline at end of file diff --git a/aip/client-libraries/4221.md b/aip/client-libraries/4221.md deleted file mode 100644 index 2b28b16235..0000000000 --- a/aip/client-libraries/4221.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -id: 4221 -state: approved -created: 2019-06-17 ---- - -# Client-side retry - -Many APIs have error modes that a client should retry. These error modes vary -across APIs, leaving users to hand-write retry logic around client libraries -based on available documentation. Client libraries have the opportunity to help -by implementing automatic client-side retries of well-known error modes. - -## Guidance - -Client libraries **should** provide automatic, client-side retry logic. Client -libraries with automatic client-side retry logic **should** provide a mechanism -for users to specify error codes to be retried and delays for those retries. - -Client libraries for API systems that support remotely-resolved client retry -configuration **should** respect the remotely-resolved configuration. However, -user configuration **must** be honored. - -Client library generators implementing this feature **must** accept a retry -configuration. This retry configuration **may** be supplied via a `protoc` -plugin option. In the absence of a given retry configuration, client library -generators **should not** generate a default retry configuration. - -### Retry implementation - -Client libraries **should** make client-side retry transparent to the user. The -user **should not** have to opt-in to client-side retry explicitly, but the -user **must** have a way to disable client-side retry altogether. - -### Retry configuration mechanisms - -Client libraries **should** surface a mechanism through which users may control -the client-side retry configuration, including disabling client-side retry -altogether. - -For example, Go client libraries for gRPC services can supply an option, -[WithDisableRetry][0], at client initialization to disable the use of the -automatic client-side retry logic. - -```go -opts := []grpc.DialOption{ - grpc.WithDisableRetry(), - grpc.WithTransportCredentials(creds), -} - -cc, err := grpc.Dial("my.api.net:443", opts...) -if err != nil { - // ... -} -``` - -### Remotely-resolved client configuration - -Some API systems have built-in mechanisms for clients to retrieve a -remotely-defined configuration that includes client-side retry configuration. - -For example, gRPC supports the [resolution of client configuration][1] that -includes configuration for [automatic client-side retry][2]. - -Client libraries **should** respect the remotely-resolved configuration, except -when a user overrides it via the aforementioned client library -[retry configuration mechanisms](#retry-configuration-mechanisms). - -### Client library generator retry configuration - -Client library generators that implement client-side retry **must** accept a -retry configuration. This is to enable API producers to supply a retry -configuration that best-suits their service. - -For example, gRPC client-side retry is configured with a [RetryPolicy][3] -within a [gRPC Service Config][4]. Here is a configuration that applies the -`RetryPolicy` to all methods in the `google.example.library.v1.LibraryService` -service, except for those that are explicitly named which get no `RetryPolicy`. - - -```json -{ - "methodConfig": [{ - "name": [{ "service": "google.example.library.v1.LibraryService" }], - "waitForReady": true, - "timeout": "60s", - "retryPolicy": { - "maxAttempts": 3, - "initialBackoff": "1s", - "maxBackoff": "10s", - "backoffMultiplier": 2, - "retryableStatusCodes": ["UNAVAILABLE"] - } - }, - { - "name": [ - { "service": "google.example.library.v1.LibraryService", "method": "CreatePublisher" }, - { "service": "google.example.library.v1.LibraryService", "method": "DeletePublisher" }, - { "service": "google.example.library.v1.LibraryService", "method": "CreateBook" }, - { "service": "google.example.library.v1.LibraryService", "method": "DeleteBook" }, - { "service": "google.example.library.v1.LibraryService", "method": "UpdateBook" }, - { "service": "google.example.library.v1.LibraryService", "method": "MoveBook" } - ], - "waitForReady": true, - "timeout": "10s" - }] -} -``` - - -The retry configuration **may** be a `protoc` plugin option. For example, a -generator could accept the file path of the configuration with an option like: - - --{plugin_name}_opt="retry-config=/path/to/config.file" - -In the absence of a retry configuration, a generator **should not** generate a -"default" retry configuration. This results in a generated client library that -does not retry anything unless configured to do so by the user. - - -[0]: https://godoc.org/google.golang.org/grpc#WithDisableRetry -[1]: https://github.com/grpc/grpc/blob/837a99e1d49a892e6f2c46ee09a1b6b8405571c6/doc/naming.md#resolver-plugins -[2]: https://github.com/grpc/proposal/blob/d4fc009e55f95297374e821d67d679b931753a59/A6-client-retries.md -[3]: https://github.com/grpc/proposal/blob/d4fc009e55f95297374e821d67d679b931753a59/A6-client-retries.md#retry-policy -[4]: https://github.com/grpc/proposal/blob/d4fc009e55f95297374e821d67d679b931753a59/A6-client-retries.md#integration-with-service-config - - -## Further reading - -- For which error codes to retry, see [AIP-194](https://aip.dev/194). - -## Changelog - -- **2020-09-23**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/client-libraries/4222.md b/aip/client-libraries/4222.md deleted file mode 100644 index aa3401ef92..0000000000 --- a/aip/client-libraries/4222.md +++ /dev/null @@ -1,282 +0,0 @@ ---- -id: 4222 -state: approved -created: 2018-06-22 ---- - -# Routing headers - -In some situations, a gRPC API backend is able to route traffic more -efficiently if it knows about some values in the request; however, the request -payload can not be reasonably deconstructed on the wire to perform that -routing. - -## Guidance - -Code generators **must** use the annotations to generate client libraries that, -on a per-RPC basis, extract routing information from the request payload and -add that information to the routing header. - -There are two annotations that specify how to extract routing information from -the request payload: - -* the [`google.api.routing`][routing] annotation that specifies how to construct -routing headers explicitly -* the [`google.api.http`][http] annotation that may specify how to construct -routing headers implicitly. - -For any given RPC, if the explicit routing headers annotation is present, the code -generators **must** use it and ignore any routing headers that might be implicitly -specified in the [`google.api.http`][http] annotation. If the explicit routing -headers annotation is absent, the code generators **must** parse the -[`google.api.http`][http] annotation to see if it specifies routing headers -implicitly, and use that specification. - -## Explicit Routing Headers (`google.api.routing`) - -For an unary or server-streaming RPC the code generator **must** look at the routing -parameters specified in the [`google.api.routing`][routing] annotation, if present. -Any given routing parameter specifies a field name and a pattern with exactly one -named resource ID path segment. For example: - -```proto -rpc CreateTopic(CreateTopicRequest) { - option (google.api.routing) = { - routing_parameters { - field: "parent" - path_template: "{project=projects/*}/**" - } - } -} -``` - -The value of the field `field` **must** be one of the following: - -1. a name of a field in the top-level of the request message -1. a dot-separated path of field names leading to a field in a sub-message of -the request message e.g. `"book.author.name"` where `book` is a message field in -the request message, `author` is a message field in the `book` message, and -`name` is a `string` field in the `author` message - -The _actual field_ specified in the field `field` **must** have the following -characteristics: -- it is type `string` -- it either has a path-like value format resembling a resource name or contains - an unstructured value that would be appropriate as an individual path segment - e.g. a `project_id`. - -**Note:** An empty `google.api.routing` annotation is acceptable. It means that no -routing headers should be generated for the RPC, when they otherwise would be -e.g. implicitly from the `google.api.http` annotation. - -**Note:** It is acceptable to omit the pattern in the resource ID segment, `{parent}` -for example, is equivalent to `{parent=*}` and **must** be parsed, e.g.: -```proto -routing_parameters { - field: "parent" - path_template: "projects/{parent}" -} -``` - -is the same as - -```proto -routing_parameters { - field: "parent" - path_template: "projects/{parent=*}" -} -``` - -**Note:** It is acceptable to omit the `path_template` field altogether. An omitted -`path_template` is equivalent to a `path_template` with the same resource ID name as -the field and the pattern `**`, and **must** be parsed, e.g.: -```proto -routing_parameters { - field: "parent" -} -``` - -is the same as - -```proto -routing_parameters { - field: "parent" - path_template: "{parent=**}" -} -``` - -**Note:** An omitted `path_template` field does not indicate that key-value -pairs with empty values can be sent. It's merely a shorthand. - -When the user supplies an instance of `CreateTopicRequest` to the method, the -client library **must** match all the routing parameters in the order specified -to the fields of that instance. For each routing parameter, the pattern in the -`path_template` **must** be matched to the input message field specified by the -routing parameter's `field` field. In case of a match, the name of the resource ID -path segment must be used as a key, and the value of the resource ID path segment match -must be used as a value of a key-value pair to be appended to the `x-goog-request-params` -header. - -Both the key and the value **must** be URL-encoded per [RFC 6570 §3.2.2][]. -This can be done with standard library URL encoding. For example, adding this header -to a gRPC request in Ruby: - -```ruby -header_params = {} -if (pattern_matches("{project=projects/*}/**", request.parent)) - header_params["project"] = extract_match_value("{project=projects/*}/**", request.parent) -end -request_params_header = URI.encode_www_form header_params -metadata[:"x-goog-request-params"] = request_params_header -``` - -In cases when multiple routing parameters have the same resource ID path segment name, -thus referencing the same header key, the "last one wins" rule is used to determine -which value to send. The "last" here is meant in terms of the order in which they're specified in the annotation. If some of the routing parameters with the same resource ID segment -name have failed to match the field, or if the field was unset, or if the extracted matched value -is an empty string, these parameters are not considered when determining which value -to send. - -Example: - -```proto -option (google.api.routing) = { - routing_parameters { - field: "parent" - path_template: "{project=projects/*}/**" - } - routing_parameters { - field: "parent" - path_template: "{project=projects/*/subprojects/*}/**" - } - routing_parameters { - field: "billing_project" - path_template: "{project=**}" - } -} -``` - -In this case if in a given request the `billing_project` field is set to an non-empty value, -its value will be sent with the `project` key because the routing parameter looking at `billing_project` field is specified last. If the `billing_project` field is not set, the `parent` field will be considered, first trying to send a -project with a subproject specified, and then without. Note that if a given request has a -`parent` field with a value e.g. `projects/100/subprojects/200/foo`, patterns in both first and second `routing_parameters` will match it, but the second one will "win" since it is specified "last". - -If all the routing parameters with the same resource ID segment name have failed -to match the field, the key-value pair corresponding to those routing parameters' -resource ID path segment name **must not** be sent. - -If none of the routing parameters matched their respective fields, the routing header -**must not** be sent. - -Much like URL parameters, if there is more than one key-value pair to be sent, the `&` -character is used as the separator. - -### `path_template` syntax - -As seen in the above examples, the `path_template` can use a variety of symbols -that are interpreted by code generators during conversion to regular expressions -or non-regular expression matcher implementations. The `path_template` consists -of segments delimited by the segment delimiter. The syntax for `path_template` -is as follows: - -- The only acceptable segment delimiter is `/`. - - The last symbol in a `path_template` **may** be a delimiter - it will be - ignored. -- A segment **must** be of one of the following types: - - `*`: A single-segment wildcard. Corresponds to 1 or more non-`/` symbols. - The regex describing it is `[^/]+`. - - A Single-segment wildcard typically represents a resource ID. - - `**`: A multi-segment wildcard. Corresponds to 0 or more segments. - - A multi-segment wildcard **must** only appear as the final segment or - make up the entire `path_template`. - - In a multi-segment `path_template`, a multi-segment wildcard **must** - appear immediately following a segment delimiter. This delimiter is - consumed while matching so a `path_template` like `foo/**` matches all of - the following: `foo`, `foo/`, `foo/bar/baz`. - - In a multi-segment `path_template`, when used as the last segment the - regex describing it is `([:/].*)?`. - - When used as the entire `path_template`, the regex describing it is `.*`. - - Segment delimiters are consumed while matching, including any preceding - delimiter. - - `LITERAL`: A literal segment. A literal segment can contain any - alphanumeric symbol. - - A literal segment **must not** contain a symbol reserved in this syntax. - - Literal segments typically represent a resource collection ID or base - path. - - `{}`: A variable segment. This matches part of the path as specified by its - template. - - A variable segment can be either of the following: - - `{key}`, where `key` is the name to be used in the key-value pair of the - header - - `{key=template}`, where the `template` is the segment(s) (expressed in - this `path_template` syntax) to extract as the value paired with `key` - - A variable segment of just `{key}` defaults to a template of `*` which - matches 1 or more non-`/` symbols. - - While `{key=*}` is technically valid syntax, the simpler syntax of - `{key}` **should** be used. - - A variable segment **must not** contain other variable segments. This - syntax is not recursive. -- A segment **must not** represent a complex resource ID as described in - [AIP-4231][]. A Generator **should** emit an error in this case. - -## Implicit Routing Headers (`google.api.http`) - -**Note:** For an RPC annotated with the [`google.api.routing`][routing] annotation, -the [`google.api.http`][http] annotation must be ignored for the purpose of adding -routing headers. - -If an unary or server-streaming RPC is not annotated with the [`google.api.routing`][routing] -annotation, code generators **must** look at URI-based variables declared in the -[`google.api.http`][http] annotation and transcribe these into the -`x-goog-request-params` header in unary calls. A URI-based variable is a -variable declared as a key in curly braces in the URI string. For example: - -```proto -rpc CreateTopic(CreateTopicRequest) { - option (google.api.http).post = "{parent=projects/*}/topics"; -} -``` - -**Note:** It is acceptable to omit the pattern in the resource ID segment, `{parent}` -for example, is equivalent to `{parent=*}` and **must** be parsed. - -In this case, the applicable variable is `parent`, and it refers to the -`parent` field in `CreateTopicRequest`. When the user provides an instance of -`CreateTopicRequest` to the method (or once the client library has built it, in -the case of method overloads), the client library must extract the key and -value, and append them to the `x-goog-request-params` header. Both the key and -the value **must** be URL-encoded per [RFC 6570 §3.2.2][rfc 6570 §3.2.2]. This can be done -with standard library URL encoding. For example, adding this header to a gRPC -request in Go: - -```go -md := metadata.Pairs("x-goog-request-params", - url.QueryEscape("parent") + "=" + url.QueryEscape(req.GetParent())) -``` - -At runtime, if a field with the same name as the named parameter is unset on the -request message, the key-value pair corresponding to that parameter **must not** -be included in the routing header. If none of the parameters must be included in -the routing header, the routing header **must not** be sent. - -If the [`google.api.http`][http] annotation contains `additional_bindings`, -these patterns **must** be parsed for additional request parameters. Fields -not duplicated in the top-level (or `additional_bindings`) pattern **must** -be included in request parameters, encoded in the same way. - -Much like URL parameters, if there is more than one key-value pair, the `&` -character is used as the separator. - - -[http]: https://github.com/googleapis/googleapis/blob/master/google/api/http.proto -[routing]: https://github.com/googleapis/googleapis/blob/master/google/api/routing.proto -[rfc 6570 §3.2.2]: https://tools.ietf.org/html/rfc6570#section-3.2.2 -[AIP-4231]: ./4231.md#complex-resource-id-path-segments - -## Changelog -- **2023-07-07**: Include `path_template` syntax. -- **2022-07-13**: Updated to include the new `google.api.routing` annotation. -- **2020-04-21**: Explicitly parse path variables missing a trailing segment. -- **2019-11-27**: Include `additional_bindings` as a request parameter source. -- **2019-06-26**: Fix wording and example of key-value pair encoding. -- **2019-06-20**: Specify encoding of header parameters. diff --git a/aip/client-libraries/4223.md b/aip/client-libraries/4223.md deleted file mode 100644 index df3c178027..0000000000 --- a/aip/client-libraries/4223.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: 4223 -state: approved -created: 2022-05-13 ---- - -# Client-side payload validation - -Client-side payload validation is the practice of inspecting the request payload -for any misconfigurations (e.g. missing required fields, attempting to update an -immutable field) prior to executing a network call with the payload. Typically, -documentation communicates the expectations of the service with regards to each -request field, including any requirements on presence or format. The -`google.api.field_behavior` annotation defined in AIP-203 is the -machine-readable format that services use to document behavior in relation to -specific request fields. - -## Guidance - -Client libraries **must not** implement client-side payload validation based -on the `google.api.field_behavior` annotation, except to prevent -[local failures](4223.md#local-failures). - -The reason for this is that the `google.api.field_behavior` annotation is -primarily a machine-readable form of _documentation_, and **not** a -configuration for payload validation. The annotation conveys how the service -_already_ handles the field, and alludes to a service's own payload validation -or expectations. - -Admittedly, depending on services to implement payload validation means clients -will sometimes make network calls that are bound to result in errors. Furthermore, users -then depend on services to provide actionable errors, when the client could have -provided a language-idiomatic, localized error. However, robust server-side -payload validation means that _all types_ of client (first party, third party, -`curl`, etc.) will benefit from the **same** validation, and that there is no -lag between service and clients when the field behavior changes. - -### Local failures - -Client libraries **may** implement client-side payload validation based on the -`google.api.field_behavior` annotation only to the extent that it prevents -local failures, such as crashes within the client library code itself. diff --git a/aip/client-libraries/4231.md b/aip/client-libraries/4231.md deleted file mode 100644 index 5ca6a03d16..0000000000 --- a/aip/client-libraries/4231.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -id: 4231 -state: approved -created: 2018-06-22 ---- - -# Parsing resource names - -In resource-oriented design ([AIP-121][]), _resources_ represent the primary -nouns within APIs, and often have _resource names_ ([AIP-122][]). These -resource names convey information about the structure and hierarchy of the -resource structure in that API. APIs accept these resource names as parameters -when retrieving and modifying resources, and when referencing them in other -objects. However, users may struggle to piece together resource names to send, -and client libraries have the opportunity to make this easier through the use -of helper components. - -## Guidance - -Client libraries **may** provide helper classes or functions to make -constructing resource names more straightforward. However, client libraries -that choose to implement this feature **must** always accept the plain strings -also, for two reasons: - -1. An existing API that adds resource descriptor annotations should be able to - do so without incurring a breaking change. -2. Resource name patterns occasionally evolve, and users need to be able to - send and receive resource names that a statically-compiled client library - may not yet acknowledge. - -### Resource messages - -A resource in an API always has a message that describes the representation of -that resource in that API. Client library generators are able to recognize -these messages when they are annotated with the `google.api.resource` -annotation: - -```proto -// A representation of a Topic in Pub/Sub. -message Topic { - option (google.api.resource) = { - type: "pubsub.googleapis.com/Topic" - pattern: "projects/{project}/topics/{topic}" - }; - - // name and so on... -} -``` - -- The `type` field provides the [unified resource type][aip-123] name. - - Client libraries **should** name their helper component based on this - value. - - The universal resource type usually (but not always) ends with a name that - matches the name of the message. -- The `pattern` field provides the structure of this resource type's names. - - The components in braces represent variable substitutions. Client libraries - implementing this feature **must** accept variables based on these names - when building resource name strings. - - Variable substitution names are usually specified in `snake_case`, but this - is not guaranteed. Client libraries **should** be able to accept any - annotation that uses any coherent case system. - - Patterns are usually slash-separated, but this is not guaranteed. Client - libraries **should** use string interpolation to piece together the - resource name. -- The defining message is expected to contain a field called `name`, which is - the field holding the resource name. - - APIs are able to override the name field's name by setting the `name_field` - property on the `google.api.resource` annotation. - - Code generators **should** fail with an error if a message is annotated as - a resource and has no name field (either the default of `name` or the field - provided in the `name_field` property of the annotation). Code generators - **should** also fail with an error if the field is not a string). - -### Multi-pattern resources - -Occasionally, a resource may have more than one pattern. The common case for -this is when a resource can live under more than one parent type. In this -situation, the `pattern` field on the annotation can be specified more than -once: - -```proto -message LogEntry { - option (google.api.resource) = { - type: "logging.googleapis.com/Log" - pattern: "projects/{project}/logs/{log}" - pattern: "organizations/{organization}/logs/{log}" - pattern: "folders/{folder}/logs/{log}" - pattern: "billingAccounts/{billing_account}/logs/{log}" - }; - - // name and so on... -} -``` - -If necessary, client libraries **may** create a separate helper component for -each pattern, and **may** provide a rollup component. - -### Resources without messages - -Occasionally, a resource may be implicitly defined by an API service, but not -have an explicit message representing that resource. (For example, the -[Firestore API][] defines databases as a common ancestor to its resources, but -does not define a database message.) - -In this situation, APIs annotate the resource on the _file_ instead of on a -_message_, using the `google.api.resource_definition` annotation: - -```proto -option (google.api.resource_definition) = { - type: "firestore.googleapis.com/Database" - pattern: "projects/{project}/databases/{database}" -}; -``` - -Client library generators implementing this feature **must** generate the same -utility components that would be generated when encountering a -[resource message](#resource-messages). - -### Referencing other resources - -APIs often use resource names for referencing fields defined elsewhere. This is -particularly common with the request messages for the standard methods, such as -[Get][aip-131] and [Update][aip-134]; however, resources and other structures -use resource name strings as references also. - -Client libraries implementing this feature **should** also provide their helper -components when resources are being referenced. Client libraries are able to -recognize these fields when they are annotated with the -`google.api.resource_reference` annotation: - -```proto -message GetTopicRequest { - // The name of the topic to retrieve. - string name = 1 [(google.api.resource_reference) = { - type: "pubsub.googleapis.com/Topic" - }]; -} -``` - -The resource reference references the [unified resource type][aip-123] name. - -Some methods also refer to the _parent_ of a type, and in situations where -there are multiple parents, it is repetitive and error-prone to refer to each -individual parent type. In these situations, API producers specify `child_type` -rather than `type`: - -```proto -message ListLogEntriesRequest { - // The collection of log entries to list. - string parent = 1 [(google.api.resource_reference) = { - child_type: "logging.googleapis.com/Log" - }]; -} -``` - -In this situation, client library generators implementing this feature **must** -derive the set of parent resources from the child type. Client library -generators **must** fail with an error if both `type` and `child_type` are -provided. - -### Referencing an arbitrary resource - -Occasionally, a field may reference an arbitrary resource. In this case, APIs -use the special value `*` in their resource reference. - -```proto -message GetIamPolicyRequest { - string resource = 1 [(google.api.resource_reference) = { - type: "*" - }]; -} -``` - -In this situation, client library generators implementing this feature **may** -provide a generic utility class or function to address that resource name. - -### Complex resource ID path segments - -**Warning:** Complex resource ID path segments **should not** generally be used -in new APIs. [AIP-124][] contains advice on handling many-to-many associations. - -Resource patterns **may** contain resource ID path segments which contain -multiple pattern variables separated by a variable separator: - -```proto -message FeedItemTarget { - option (google.api.resource) = { - type: "googleads.googleapis.com/FeedItemTarget" - pattern: "customers/{customer}/feedItemTargets/{feed}~{feed_item}" - }; - - // name and other fields... -} -``` - -This is only used when the resource ID is naturally in multiple parts and it is -useful for the user to be able to manipulate the separate ID parts. - -- A variable separator is one character long, and **must** only one of: `_`, - `-`, `.`, `~` (underscore, hyphen, period, tilde). -- A variable separator **must not** appear before the first pattern variable or - after the last pattern variable. - -### Backwards compatibility - -Client libraries implementing helper components for resources **must** conform -to the following backwards-compatibility expectations: - -- The addition of a `google.api.resource` annotation on an existing message - **must** be a backwards-compatible change. -- An existing resource **must** be able to add new patterns (including the "\*" - wildcard pattern) without breaking changes as long as the following - conditions are met: - - New patterns must always be appended to the list. - - New patterns must use a distinct sequence of collection identifiers (see - [AIP-122][]) compared with all existing patterns within this resource. -- The identifiers within the pattern variables are final - they **must not** be - changed. These identifiers are used in the surface of generated client - libraries. -- The addition of a `google.api.resource_reference` annotation on an existing - field **must** be a backwards-compatible change. -- Changing a `google.api.resource_reference` from `child_type` to `type` - **must** be a backwards-compatible change when the `child_type` referenced - has a single `pattern` and the newly referenced `type` is the matching - parent resource `pattern` (see the - [Referencing other resources](#referencing-other-resources) section for - more info). -- For references that appear in a request, changing from `type` to - `child_type` **must** be a backwards-compatible change when the resource - `pattern` originally referenced via the `type` is included in the set of - possible resource `pattern`s derived through `child_type` resolution (see - the above [Multi-pattern resources](#multi-pattern-resources) and - [Referencing other resources](#referencing-other-resources) sections for - more examples). - -Note: The `ORIGINALLY_SINGLE_PATTERN` and `FUTURE_MULTI_PATTERN` flags are -deprecated, and must not be used. - -## Further reading - -- For more on resource names and patterns, see [AIP-122][]. -- For more on unified resource types, see [AIP-123][]. - -## Changelog - -- **2023-03-25**: Include compatibility guidance for `type` and `child_type`. -- **2022-10-28**: Pattern variables are considered final -- **2020-09-14**: Disallow simultaneous use of both `type` and `child_type`. -- **2020-05-14**: Added complex resource ID path segments. -- **2020-05-07**: Updated backwards compatibility guidance. -- **2019-09-16**: Added guidance for resources without messages. - - -[aip-121]: ../0121.md -[aip-122]: ../0122.md -[aip-123]: ../0123.md -[aip-124]: ../0124.md -[aip-131]: ../0131.md -[aip-134]: ../0134.md -[firestore api]: https://github.com/googleapis/googleapis/tree/master/google/firestore/v1 - diff --git a/aip/client-libraries/4232.md b/aip/client-libraries/4232.md deleted file mode 100644 index 818ebb3fcf..0000000000 --- a/aip/client-libraries/4232.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -id: 4232 -state: approved -created: 2018-06-22 ---- - -# Method signatures - -In protocol buffer RPCs, each RPC takes exactly one argument: a message. -However, sending a full message structure can be cumbersome in the case of -extremely simple requests. - -Many RPCs provide information about which pieces of the request are important -and commonly used. In many languages, functions and methods take multiple -positional or keyword arguments. - -## Guidance - -Some APIs provide annotations to hint how to effectively translate from a -single request object to individual arguments, and client libraries **may** -provide overloads based on these hints. - -However, client libraries implementing this feature **must** retain the default -behavior of accepting the full request object. Put another way, if an API -_adds_ this annotation to an already-published API, the resulting library -change **must** be backwards-compatible. - -Client library generators **may** also choose to provide this functionality in -some cases but not others, as appropriate in the environment. For example, any -of the following strategies would be permissible: - -- Providing overloads iff all arguments in the signature are primitives. -- Providing overloads only for the first of multiple signatures when providing - more than one would produce a conflict. -- Any combination of the above. - -In all of these situations, the requirement that the request object is always -accepted still applies. - -Furthermore, client library generators **may** choose to support this -functionality for a subset of RPC types, those being: - -- Unary -- Server Streaming -- Client Streaming -- Bi-directional Streaming - -### Method Signatures - -An RPC with the [`google.api.method_signature`][method_signature] annotation -indicates that an overload with a flattened method signature is desired where -supported. The string contains comma-separated arguments, in order. If a -field's name contains a period (`.`) character, this indicates a nested field. - -An RPC can provide this annotation more than once to specify multiple -signatures. Order matters here: In some situations, it may not be possible to -generate an overload for every signature provided. In this situation, client -library generators **must** follow a "first match wins" strategy (generate an -overload for the first signature in the conflict set, and drop the rest). - -**Note:** A corollary to this is that it is only guaranteed to be a -backwards-compatible change to _append_ method signature annotations. - -### Required Arguments - -Often, certain fields on the request message are consistently required, as -described in [AIP-203][]. - -While client libraries generally should not perform validation on this (that is -the server's role), client libraries **may** distinguish required arguments in -method signatures from optional ones if appropriate for the language. A field -is considered required for this purpose if annotated with the -`google.api.field_behavior` annotation value of `REQUIRED`: - -```proto -message TranslateTextRequest { - // The text to translate. - string q = 1 [(google.api.field_behavior) = REQUIRED]; -} -``` - -**Note:** The annotation for field behavior is attached to _the field_, not the -method. - -### Restrictions - -If an RPC lists a nested field in -[`google.api.method_signature`][method_signature] (for example, -`"foo.bar.baz"`), none of the individual component fields may be repeated -except for the last one (continuing the example, `baz` could be repeated but -`foo` or `bar` could not be). Code generators implementing this feature -**must** error with a descriptive error message if encountering a non-terminal -repeated field as a field name. - -If any fields are required arguments, all required arguments are expected to -appear before any optional ones. Code generators implementing this feature -**should** error with a descriptive error message if encountering a required -field after an optional one, and **must** do so if the resulting client library -would not be valid. - -### Compatibility - -Removing, reordering or altering an existing `google.api.method_signature` -entry is a breaking change for client libraries. The associated generated -method is either removed entirely or its signature is altered, both of which -break user code. - -## Changelog - -- **2020-07-14**: Added caveat for supporting some RPC types -- **2019-09-27**: Added a Compatibility section. - - -[aip-203]: ../0203.md -[method_signature]: https://github.com/googleapis/googleapis/blob/master/google/api/client.proto#L100 - diff --git a/aip/client-libraries/4233.md b/aip/client-libraries/4233.md deleted file mode 100644 index f522b02023..0000000000 --- a/aip/client-libraries/4233.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: 4233 -state: approved -created: 2018-06-22 ---- - -# Automatic pagination - -Many API responses, particularly to list and search methods, are paginated -([AIP-158][]). Users calling these methods are then required to implement their -own pagination logic, which is common boilerplate. - -## Guidance - -Client libraries **may** provide automatic resolution of pagination (meaning -that it performs requests in the background on an as-needed basis). - -Pagination can be inferred for an RPC when _all_ of the following conditions -are met: - -- The request message contains an `int32 page_size` field. - - For APIs that predate [AIP-158][], a field named `max_results` and/or - typed as `google.protobuf.UInt32Value` or `google.protobuf.Int32Value` - are permissible alternatives. -- The request message contains a `string page_token` field. -- The response message contains a `string next_page_token` field. -- The response message contains one non-primitive `repeated` field. - -Client library generators implementing this feature **must** ensure that it is -a backwards-compatible change to add client-side pagination functionality where -it was previously absent. - -### Implementing pagination - -For the client library to implement pagination (as defined by [AIP-158][]), it -**should** use the `next_page_token` value from the response message to -populate the `page_token` value of an otherwise-identical request message, -continuing indefinitely until the `next_page_token` value is empty. - -**Important:** Client libraries that are implementing automatic resolution of -pagination should only perform requests for future pages on an as-needed basis, -and avoid greedily resolving potentially long and unnecessary result sets. - -Client libraries that are implementing automatic pagination **must** still -provide access to the individual fields on the response message, in the usual -fashion. - -**Note:** If the response message has more than one non-primitive `repeated` -field, the first one (in order of appearance in the file _and_ field number) is -used. If the first field by order of appearance in the message and the first -field by field number do not match, code generators that implement automatic -pagination **should** fail with an error. - -[aip-158]: ../0158.md diff --git a/aip/client-libraries/4234.md b/aip/client-libraries/4234.md deleted file mode 100644 index 1d0b6a2152..0000000000 --- a/aip/client-libraries/4234.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -id: 4234 -state: approved -created: 2021-06-07 ---- - -# Common service client mixins - -Often, APIs can have common features for administering resources that are -separated into utility services. These common, utility services are shared among -the discrete product services. These common services each have a -centrally-defined surface, but individual instances are hosted alongside each -product service. Thus, the surfaces of each common service hosted by the product -service are "mixed in" at runtime. - - -## Guidance - -Client libraries **may** provide client methods for the common services that its -API declares to be mixed-in. Such methods improve the user experience by -presenting the mixin methods from a client configured to communicate with the -product service that hosts the mixin service. - -If client libraries support mixin services, they **must** support the following -common services (and **may** support others): - -- `google.cloud.location.Locations` -- `google.iam.v1.IAMPolicy` -- `google.longrunning.Operations` - -**Note:** The list of supported mixin services and the mixin services -themselves both change infrequently. Any new common service to be supported -**must** be added to the list here and generators **must** be updated. - -To be generated into a client library, a mixin service **must** be declared -under [apis] in a [google.api.Service]. Furthermore, only the RPCs with -[google.api.http] bindings declared in the [http] configuration of the same -[google.api.Service] can be generated (more details on these bindings in -AIP-127). If a mixin service RPC does not have a [google.api.http] rule declared -in the [google.api.Service], it **must not** be generated. - - -## Implementing mixin support - -### Generator configuration - -Client library generators **must** accept the file path of a -[google.api.Service] in YAML form. This file is specified via a flag that -**must** be optional. In other words, the flag **must not** be required for -basic client generation that omits the mixin methods. - -### Mixin API client configuration - -If a mixin API utilizes client library configuration (i.e. annotations, default -retry settings, etc.) such as `google.api.method_signature` or request header -injection, generators **may** support it in the generated mixin methods if the -configuration is accessible. - -Where client library configuration calls for a fully-qualified name, the -_mixin's_ fully-qualified name **must** be used. That is to say, the host -service **must not** refer to a mixin element as if it was in its own package. - -For example, configuring `google.iam.v1.IAMPolicy.GetIAMPolicy` with default -retry and timeout settings would be as follows: - -```json -{ - "name": [{ "service": "google.iam.v1.IAMPolicy", "method": "GetIAMPolicy" }], - "timeout": "60s", - "retryPolicy": { - "initialBackoff": "0.1s", - "maxBackoff": "5s", - "backoffMultiplier": 1.3, - "retryableStatusCodes": ["UNKNOWN"] - } -} -``` - -### Generating mixin methods - -The mixin API RPCs **should** be generated as methods on the surface of the -host API's service client library, alongside the host service's RPCs. This -presents them as top-level methods on the client, but under-the-hood, the -appropriate mixin API stub or request should be invoked. However, generators -**may** choose to present the mixin API RPCs in a different manner if it is more -language idiomatic. - -**Note:** For gRPC clients, the mixin API gRPC stub **must** be used in order -to properly construct the gRPC request. For example, the generated, Go gRPC stub -[LocationsClient] must be used to invoke RPCs for the -`google.cloud.location.Locations` mixin, as opposed to that of the host -service's gRPC stub. - -### Multiple host service clients - -If there are multiple services defined by the host API that would result in -multiple clients being generated, generators **must** include the mixin -methods on all eligible, generated service clients. - -### Overriding a duplicate RPC - -Client library generators **must not** generate a mixin method on any host -service client if a host service already defines an RPC with the same name. For -example, take the following service definition: - -```proto -service LibraryService { - rpc ListBooks(ListBooksRequest) returns (ListBooksResponse); - - // Other host API RPCs... - - // Redefinitions of the google.iam.v1.IAMPolicy mixin service. - rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest) - returns (google.iam.v1.Policy); - - rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest) - returns (google.iam.v1.Policy); - - rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest) - returns (google.iam.v1.TestIamPermissionsResponse); -} -``` - -Should the host API declare the `google.iam.v1.IAMPolicy` as a mixin service, -client library generators **must not** generate the resulting mixin methods that -match the names explicitly declared above for _any_ service client in the host -proto package, but they **must** generate the other methods for this mixin. In -this case, the generator **may** log a warning indicating that a collision was -avoided, or silently skip the mixin methods in question. - -[apis]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto#L96 -[google.api.Service]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto -[google.api.Http]: https://github.com/googleapis/googleapis/blob/master/google/api/http.proto -[http]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto#L124 -[LocationsClient]: https://pkg.go.dev/google.golang.org/genproto@v0.0.0-20210325141258-5636347f2b14/googleapis/cloud/location#LocationsClient diff --git a/aip/client-libraries/4235.md b/aip/client-libraries/4235.md deleted file mode 100644 index 1f52c37855..0000000000 --- a/aip/client-libraries/4235.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: 4235 -state: approved -created: 2024-03-07 ---- - -# Automatically populate fields in the request message - -For APIs that leverage request idempotency as described via [AIP-155], APIs may -choose to have the client libraries automatically populate fields such as -`request_id` if they are not already set by the customer. - -**Note:** This feature is primarily written for `request_id` fields within the -request message. Nonetheless, this feature **must** work for a field of any -name, as long as the conditions below hold true. - -## Guidance - -APIs **may** configure fields in the request message for automatic population. -For a field to be automatically populated, **all** the conditions below -**must** be true: - -- The field **must** be of type `string` -- The field **must** be at the top-level of the request message -- The RPC **must** be a unary RPC (i.e. streaming RPCs are not supported) -- The field **must not** be annotated - with [`google.api.field_behavior = REQUIRED`][required]. -- The field **must** be annotated - with [`google.api.field_info.format = UUID4`][uuid4]. -- The field name **must** be listed - in the [`google.api.MethodSettings.auto_populated_fields`][apf] entry - in [`google.api.Publishing.method_settings`][apf] - for the target method. - -### Expected Generator and Client Library Behavior - -If the aforementioned requirements are met for a given field, client library -generators **must** enable automatic population of said field in the -generated client. - -The field **must** be automatically populated if and only if one of the -following conditions holds: - -- The field supports explicit presence, and has **not** been set by the user -- The field doesn't support explicit presence, and its value is the empty - string (i.e. the default value) - -If a field is specified in the `auto_populated_fields`, but does not meet the -structural requirements, the client library generators **must not** enable -automatic population for that field. Client library generators **may** emit an -error during generation. - -Client libraries **must** reuse automatically populated values for retries of -the same request. In other words, the automatically populated fields -**must not** be regenerated for each RPC attempt with the same request message. - -[AIP-155]: https://google.aip.dev/155 - -[apf]: https://github.com/googleapis/googleapis/blob/master/google/api/client.proto - -[uuid4]: https://google.aip.dev/202#uuid4 - -[required]: https://google.aip.dev/203#required diff --git a/aip/client-libraries/4236.md b/aip/client-libraries/4236.md deleted file mode 100644 index 074290ae20..0000000000 --- a/aip/client-libraries/4236.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -id: 4236 -state: approved -created: 2024-05-16 ---- - -# Version-aware clients - -APIs can annotate [API interfaces][interface def] with -[`google.api.api_version`][annotation]. If `google.api.api_version` is -specified, version-aware clients **must** include the value of -`google.api.api_version` in the request to the API and in the documentation of -the per-API interface clients. - -## Generator and client library behavior - -If an API interface is annotated with `google.api.api_version`, client -library generators **must** include either an HTTP query parameter `$apiVersion` -or HTTP header/gRPC metadata key `X-Goog-Api-Version`, but a request -**must not** contain both. - -### Generated client documentation - -Generated client documentation for a given API interface **must** include the -value of `google.api.api_version`, if it exists in the source protos. The -comment **must** include the original API interface name and the exact contents -of the annotation. - -**Note:** The text does not need to match exactly to the examples below, but it -still needs to fulfill the requirements desribed herein. - -For example, the following API interface definition would produce the following -Go client documentation: - -```proto -service LibraryService { - option (google.api.api_version) = "2026-01-01"; -} -``` - -```go -// The LibraryClient is a client for interacting with the Cloud Library... -// -// This client uses LibraryService version 2026-01-01. -type LibraryClient struct {} -``` - -Any generated documentation for an entire [API service's][service def] client -package **must** include a section that lists the client-interface-version -tuples present in the package. For example, the following API interface -defintions would produce the following client package documentation section: - -```proto -service LibraryService { - option (google.api.api_version) = "2026-01-01"; -} -service BookService { - option (google.api.api_version) = "2026-05-15"; -} -service ShelfService { - option (google.api.api_version) = "2026-02-05"; -} -``` - -```md -## API Versions - -* LibraryClient uses LibraryService version 2026-01-01 -* BookClient uses BookService version 2026-05-15 -* ShelfClient uses ShelfService version 2026-02-05 - -``` - -If all API interfaces share the same API version, this list **should** be -reduced to a single sentence for brevity. For example, if all versions were the -same in the definitions above, the generated client package documentation would -be as follows: - -```md -## API Versions - -All clients use API version 2026-01-01. -``` - -### Version opacity - -Clients and generators **must** treat the value of `google.api.api_version` as -opaque to ensure robust compatibility. This means that the specific format or -structure of the version string **must not** be parsed or interpreted for any -purpose beyond identifying the intended API version. - -## Rationale - -### Necessity for Versioning - -Explicit API versioning using the `google.api.api_version` annotation is -essential for maintaining compatibility between clients and services over time. -As services evolve, their schemas and behaviors may change. By specifying the -API version, a client communicates its expectations to the API service. This -allows the API service to respond in a manner consistent with the client's -intended semantics, preventing errors or unexpected results due to incompatible -changes. - -### Importance of Opaque Treatment - -Treating the `google.api.api_version` value as opaque is important for ensuring -robust compatibility guarantees. By using this identifier opaquely, clients -avoid making assumptions about the underlying versioning scheme, which may -change independently of the API itself. This flexibility allows API service -providers to evolve their versioning strategies without impacting client -compatibility. - -### Mutual Exclusivity of Query and Header - -Both the query parameter and header mechanisms exist to provide flexibility for -different client environments. However, allowing both simultaneously could lead -to ambiguity if the values differ. To ensure consistent version identification -and prevent potential conflicts, only one mechanism should be used at a time. - -### Inclusion in documentation - -The API version identifies the iteration of the API contract being consumed by -the client and thus the end user. The end user needs a means of relating the -API version in use by the client to other API artifacts (such as product -documentation and other client surfaces) and vice versa. - -[annotation]: https://github.com/googleapis/googleapis/blob/master/google/api/client.proto -[interface def]: https://google.aip.dev/9#api-interface -[service def]: https://google.aip.dev/9#api-service - -## Changelog - -- **2025-12-08**: Add documentation generation requirements and reformat. \ No newline at end of file diff --git a/aip/client-libraries/4290.md b/aip/client-libraries/4290.md deleted file mode 100644 index ddec2484ac..0000000000 --- a/aip/client-libraries/4290.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -id: 4290 -state: approved -created: 2018-11-08 ---- - -# Docker interface - -A consequence of using individual generators for API client library generation -is that each generator has its own set of dependencies and requirements in -order to run. - -This is reasonable for a user who wishes to generate many libraries for a -single environment, but presents challenges for a user wishing to generate a -single API for many languages or environments. Users need a way to generate -libraries easily and quickly, with minimal ramp-up per language. - -## Guidance - -Client library generators **should** ship [Docker][] images providing the -generator and exposing a common interface, so that generating the same API in -multiple languages usually only requires substituting in the appropriate Docker -image. Docker images for Google-authored generators will follow a consistent -scheme. - -### CLI usage - -The expected user command to invoke the code generator in a Docker image (from -the proto import root, on a POSIX machine): - -```bash -$ docker run --rm --user $UID \ - --mount type=bind,source=`pwd`/a/b/c/v1/,destination=/in/a/b/c/v1/,readonly \ - --mount type=bind,source=/path/to/dest/,destination=/out/ \ - gcr.io/gapic-images/{GENERATOR} \ - [-- additional options...] -``` - -**Note:** Even though each component of this is standard in the Docker -ecosystem (other than the destination path issue, which is a result of how -protoc handles imports), this is still a rather long command. We can provide a -[shortcut script][] to further simplify this, but such a script would be for -convenience and not a replacement for this interface. - -### Container composition - -Containers **must** include: - -- A current version of protoc, the protocol buffer compiler. -- Common protos permitted to be used by all APIs ([googleapis][]). -- The applicable code generator plugin, as well as any dependencies it - requires. - - The code generator plugin itself **should** be added using an `ADD` or - `COPY` statement from the host machine at build time and installed locally; - it **should not** pull from a package manager. (This leads to catch-22 - situations when cutting releases.) - - Images **may** include either a pre-compiled binary of the plugin, or the - installed source code, depending on the needs of the applicable ecosystem. - - Installation of dependencies **should** use appropriate package managers. - -The common protos and the protoc compiler are supplied by an independent image -(`gcr.io/gapic-images/api-common-protos`). Both `protoc` and the common protos -can be retrieved from this image into a generator's image using the -`COPY --from` syntax (see [multi-stage builds][]). This is the preferred -approach as it follows Docker conventions, and allows the protos to be -versioned independently. - -### Base images - -**TL;DR:** Each language probably wants `language:x.y-alpine` or -`language:x.y-slim`. For example, `ruby:2.5-alpine` or `python:3.7-slim`. -(Alpine images are smaller but idiosyncratic.) - -The following guidelines apply to selecting base images (sorted roughly from -most important to least important): - -- Images **should** generally be based off an official image for the latest - stable version of the language in which the generator is implemented. -- Images **should** be able to install required system dependencies from a - well-understood package manager. -- Images **should** be ultimately based off of Alpine, Debian, or Ubuntu. This - is to ensure we benefit from GCR's [vulnerability scanning][]. -- Images should endeavor to be as small as possible, in line with the general - expectations of the Docker community: - - Use the smallest base image you can. Alpine-based images are great if - possible, but may not always be reasonable. "Slim" Debian images are - usually the next best (and probably significantly more feasible in many - situations). - -### Mount points - -`protoc` must read protos (representing the API to be generated) from disk, and -must write the final output (the client library) to disk. Because the user has -the API protos on the host machine, and will ultimately need the output to go -to said host machine, Docker images **should** use two mount points. This -creates a hole in the abstraction layer: the user must mount the appropriate -locations on the host machine to the appropriate locations in the container. - -The expected locations in the container **must** be constant, and consistent -between all generator container images: - -- `/in/`: The location of the protos to be generated. This **must** be the - import root. - - Example: If generating protos for the Language API, the protos in the - Docker image must live in `/in/google/cloud/language/v1/`. -- `/out/`: The location to which the client library shall be written. - -### Plugin options - -Some micro-generators support configuration provided via protoc plugin options. -In such cases, the options must be routed from the CLI input to the protoc -command. - -The ultimate protoc invocation could look like the following: - -```bash -protoc --proto_path {path/to/common/protos} --proto_path /in/ \ - --{LANG}_gapic_out /out/ \ - --{LANG}_gapic_opt "go-gapic-package=GO_PACKAGE_VALUE" \ - `find /in/ -name *.proto` -``` - -A resulting invocation of the Docker image would be as follows: - -```bash -$ docker run --rm --user $UID \ - --mount type=bind,source=`pwd`/a/b/c/v1/,destination=/in/a/b/c/v1/,readonly \ - --mount type=bind,source=/path/to/dest/,destination=/out/ \ - gcr.io/gapic-images/{GENERATOR} \ - --go-gapic-package GO_PACKAGE_VALUE -``` - -Thus shortcut scripts written to wrap the Docker image invocation **must** pass -all options occurring after `--` to the underlying docker run command. The -internal Docker image **must** provide the conversion from usual shell syntax -to the protoc option syntax. - -Client library generators that make use of plugin options **must** accept those -options as either flags or `key=value` pairs. (If a generator receives a string -without an `=` character, that is a flag, and the implied value is `true`.) If -multiple options are provided, they are comma-separated, to conform with the -protoc behavior if multiple `--opt` flags are specified. - -Additionally, generators **should** prefix all understood option keys with the -target language for that generator (e.g. `go-gapic-package`, -`java-gapic-package`), and **should** use `kebab-case` for keys (in order to -match Docker, since protoc is inconsistent). - -Microgenerators **must not** error on option keys that they do not recognize, -although they **may** issue a warning. - -### Publishing images - -Images for Google-created generators **should** be published in -`gcr.io/gapic-images`, a dedicated project in [Google Container Registry][]. - -Images **should** follow the naming scheme: - - gcr.io/gapic-images/gapic-generator-{lang} - -CI **should** be configured to push a new Docker image to the registry when -releases are made. When a release is tagged in GitHub (with a version number, -such as 1.0.3), the CI service should build an image based on the code at that -tag. - -The resulting image **should** be tagged with each component of the version -number, as well as `latest`, and the resulting tags pushed the registry. (This -is in addition to pushing to a package manager if appropriate, which is outside -the scope of this AIP.) - -This means that a release tag of `1.0.3` in GitHub would result in pushing the -following four tags to GCR: - -- `gcr.io/gapic-images/gapic-generator-{lang}:1` -- `gcr.io/gapic-images/gapic-generator-{lang}:1.0` -- `gcr.io/gapic-images/gapic-generator-{lang}:1.0.3` -- `gcr.io/gapic-images/gapic-generator-{lang}:latest` - -**Note:** These rules assumes that releases have ever-increasing version -numbers; this process will need to be amended slightly if a generator needs to -maintain multiple version streams simultaneously. - - -[googleapis]: https://github.com/googleapis/googleapis -[docker]: https://docker.com/ -[google container registry]: https://cloud.google.com/container-registry/ -[multi-stage builds]: https://docs.docker.com/develop/develop-images/multistage-build/ -[shortcut script]: https://github.com/googleapis/gapic-generator-python/blob/master/gapic.sh -[vulnerability scanning]: https://cloud.google.com/container-registry/docs/container-analysis#vulnerability_source - diff --git a/aip/client-libraries/scope.yaml b/aip/client-libraries/scope.yaml deleted file mode 100644 index 4da24d3032..0000000000 --- a/aip/client-libraries/scope.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Client libraries -order: 30 diff --git a/aip/cloud/2510.md b/aip/cloud/2510.md deleted file mode 100644 index a4cd396856..0000000000 --- a/aip/cloud/2510.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -id: 2510 -state: approved -created: 2018-12-26 -placement: - category: gcp ---- - -# Project identifiers - -Historically, Google had two kinds of projects: API projects and App Engine -projects. API projects used project numbers (e.g. `12345`) as identifiers, and -App Engine projects used project IDs (e.g. `happy-armadillo-789`) as -identifiers. Later, Google converged API projects and App Engine projects, so -now each project has _both_ unique and immutable identifiers. - -The two types of identifiers are used differently in different contexts, and -create a lot of complexity for application development. One critical issue is -that applications cannot reliably join data from different services, because -different services use different project identifiers. - -## Guidance - -**TL;DR:** The project number is the canonical identifier, and the project ID -is an [alias][]; however, unlike normal aliases, it **should** be returned if it -is what the user sent. Additionally, third-party services are unable to -_accept_ project IDs. - -The rationale for this is: - -- Each resource should always have one canonical identifier. -- Because Google's privacy policy restricts the use of project IDs, both - internally and with partners, only the project number can be the canonical - identifier. -- However, even though the project number is the canonical identifier, a policy - of returning it even if the user sent a project ID has proven to be - unfriendly to both humans and declarative tools. - -### Google APIs - -Externally-facing Google APIs **should** accept both project IDs and project -numbers for incoming API requests. - -However, even though the project number is the canonical identifier as -described in AIP-122, services **should** return whichever ID the user sent. -The reason for this is because automatic translation between user-friendly -project IDs and user-unfriendly project numbers has proven to cause real-world -difficulty for users, and also for declarative tools (see AIP-128 for more on -declarative-friendliness). - -Two additional points: - -- Error responses **must** return the originally-provided value without - modification. Error responses **must not** perform any translation between - project IDs and project numbers. -- If a service receives a resource name for a resource that the service does - not own, it **should not** perform any translation between project IDs and - project numbers for those resource names. - -### Internal Google services - -Internal Google services **must** use project numbers for internal data storage -and for output. Project identifiers are widely used as storage keys, which -often appear in logs and metrics. Project IDs are user-settable and thus -considered PII and user data, but project numbers are not. - -Therefore, when an internal service calls an external Google APIs, it -**should** use project numbers for making API requests. - -### Resource References - -Project identifiers also appear in [resource names][]. These resource -names are used both to identify the resource itself and can refer to -other resources ([example][]). - -When project identifiers are provided, the response **should** -include the identifier as it occurred in the request: if the project ID -was provided it should be returned, and if the project number was -provided, that is what should be in the response. - -For example, consider a `Book` resource, - -```proto -message Book { - option (google.api.resource) = { - type: "pubsub.googleapis.com/Book" - pattern: "projects/{project}/books/{book}" - }; - - // The resource name of the Book. - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // A reference to another resource, a Shelf. - string shelf = 2 [(google.api.resource_reference) = { - type: "library.googleapis.com/Shelf" - }]; - - // Other fields... -} -``` - -with the following book submitted from a previous create request (represented as -JSON in this example), - -```json -{ - "name": "projects/my-project/books/les-miserables", - "shelf": "projects/12345/shelves/top-shelf" -} -``` - -and a `GetBookRequest`, - -```proto -message GetBookRequest { - // The name of the Book to retrieve. - // Format: projects/{project}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; -} - -``` - -and if the value of `name` on such a request is, - -``` -projects/my-project/books/les-miserables -``` - -then the value of the field, `name`, returned for the `Book`, **should** match: -the project ID and not the number should be returned. But, the value for the -field, `shelf` should use the project number, as the create request had -submitted a shelf with the project number in the resource name. - -In other words, the following values should be returned: - -``` -book: projects/my-project/books/les-miserables -shelf: projects/12345/shelves/top-shelf -``` - -This guidance is to ensure that there is a minimal difference between user -input and output. - -### Third-party services - -[Third-party services](https://cloud.google.com/marketplace) that are -integrated with Google Cloud Platform **must** only store or provide project -numbers. Google's privacy policy prohibits sharing project IDs with third-party -services, or providing a service for third-party services to translate between -project IDs and project numbers at runtime. - -### Project identifier format - -Services **must** use project resource names as defined by the [Resource -Manager API][] to refer to projects, such as `projects/123456`. This allows the -same API to work with other resources similar to projects, such as -organizations and folders. - -[alias]: ../0122.md#resource-id-aliases -[resource manager api]: https://cloud.google.com/resource-manager/ -[resource names]: ../0122.md -[example]: ../0122.md#fields-representing-another-resource - -## Changelog - -- **2022-10-19**: Clarified guidance for project identifiers in resource - references. -- **2021-07-29**: Reversed previous guidance on returning project IDs; this AIP - now advocates returning what the user sent. -- **2019-08-11**: Add an exception for resources that a service does not own. -- **2019-06-19**: Clarify how error messages should be treated -- **2019-06-10**: Minor language and organization tweaks diff --git a/aip/cloud/2602.md b/aip/cloud/2602.md deleted file mode 100644 index ba4576126f..0000000000 --- a/aip/cloud/2602.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -id: 2602 -state: approved -created: 2019-06-12 -placement: - category: sdk ---- - -# Parameter-dependent arguments - -When designing CLI commands, a common scenario is that a command corresponding -to some conceptual action may take different, largely non-overlapping arguments -depending on the value of a particular parameter. - -For instance, suppose we're designing a new gcloud surface for managing images, -and we need a command that formats an image as JPEG, GIF, or PNG. Regardless of -the image format, the command will need arguments for the source and -destination files, but otherwise depending on the format, an entirely different -set of options will apply. JPEG, for example, might take arguments for -smoothing, subsampling, and DCT method, which are only relevant for JPEG -images. GIF, on the other hand, might take arguments for controlling animated -gifs e.g. whether to loop forever, and a delay time in between frames. Finally, -PNG might take arguments for color type and bits per channel. - -## Guidance - -When the parameter-specific arguments are numerous relative to the other -arguments, create a command group for the action, with separate subcommands -named after each of the parameter values. In the example above, we would thus -create a `gcloud images format` command group, with subcommands called `jpeg`, -`gif`, and `png`. These subcommands can then take their own format-specific -flags. - -Example usage: - -``` -$ gcloud images format jpeg --help - -$ gcloud images format jpeg --source-file=foo --destination-file=bar \ - --dct-method=integer --smoothing=0.1 --subsampling=4:4:4 - -$ gcloud images format png --source-file=foo --destination-file=bar \ - --color-type=0 --bits-per-channel=16 - -$ gcloud images format gif --source-file=foo --destination-file=bar \ - --loop-forever --frame-delay=1ms -``` - -It's possible that over time more and more arguments are added that are common -to all parameters. In that case, it may make sense to instead use a single -command that takes an argument for the parameter. This can be done without -breaking backward compatibility by making the parameter a positional argument. -In the example above, this would involve changing `format` from a command group -to a command, and having it take a positional image format argument which can -be one of: `jpeg`, `gif`, or `png`. Note that all the example commands above -would still function identically (except for the first one, but since it only -affects help text it's not considered a breaking change.) - -## Alternatives considered - -There are several other possibilities for the design of such a command, -outlined below: - -### Single command with an explicit flag corresponding to the parameter - -In the example, this would involve a `--type` flag to specify the image format: - -``` -$ gcloud images format --source-file=source --destination-file=dest \ - --type=JPEG --dct-method=integer --smoothing=0.1 --subsampling=4:4:4 - -$ gcloud images format --source-file=source --destination-file=dest \ - --type=GIF --loop-forever --frame-delay=1ms - -$ gcloud images format --source-file=source --destination-file=dest \ - --type=PNG --color-type=0 --bits-per-channel=16 -``` - -Conceptually it makes the most sense to just have a single format command. -However, this approach has several drawbacks: - -- Unnecessary help text. The user will see all of the format-specific options, - most of which will be irrelevant since they apply to different formats. In - graphical image editing programs such as Photoshop or GIMP, the UI can - selectively show these format-specific options once the user chooses the - desired format from a dropdown. On the CLI, however, we have no such - capability because the help text is statically generated. -- Additional logic needed for validation. Since some arguments will be invalid - depending on the format, the command author needs to ensure specifying - invalid combinations returns an appropriate error. While this can be - accomplished with appropriately nested mutex groups, the nesting has the - potential to become overly deep and complex. - -### Multiple commands named after the action hyphenated with the parameter value - -In the example, this would look like: - -``` -$ gcloud images format-jpeg ... -$ gcloud images format-gif ... -$ gcloud images format-png ... -``` - -This is similar to the recommended design in that each parameter value gets its -own command. However, there are disadvantages: - -- Backward compatibility. If in the future it becomes desirable to make the - parameter value an argument to a single command, this would necessitate a - breaking change. -- It's less elegant from a command tree layout perspective. Grouping the - parameter-specific commands into a command group allows for a natural - decomposition of the command space, in keeping with gcloud's CLI design - philosophy, and allows for - [progressive disclosure](https://en.wikipedia.org/wiki/Progressive_disclosure) - in the help text and in autocompletion. diff --git a/aip/cloud/2603.md b/aip/cloud/2603.md deleted file mode 100644 index 4d0d07971a..0000000000 --- a/aip/cloud/2603.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -id: 2603 -scope: cloud -state: approved -created: 2019-06-13 -placement: - category: sdk ---- - -# List command arguments - -Some list requests take argument(s) for the parent collection in which to list -resources. For example, suppose an API has book resources belonging to publisher -resources, and consider a request to list books belonging to a publisher: - -```proto -message ListBooksRequest { - // The parent, which owns this collection of books. - // Format: publishers/{publisher} - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The maximum number of items to return. - int32 page_size = 2; - - // The next_page_token value returned from a previous List request, if any. - string page_token = 3; -} -``` - -For the corresponding gcloud list command, we have the choice between -`gcloud publishers books list PUBLISHER` (positional) and -`gcloud publishers books list --publisher=PUBLISHER` (flag). - -## Guidance - -All list command arguments should be flags, not positionals. In gcloud's -resource model, command groups generally correspond to resources, and the -positional arguments for commands in a group are reserved for those resources. -In the case of a list command that takes an argument, the argument will refer -to the parent resource and not the command group's resource; therefore, it -should be a flag instead of a positional. - -In the example above, the list command takes an argument for a publisher. Commands -in the `books` command group should reserve positional arguments for book -resources. Thus, the publisher argument for the list command should be a flag: - -``` -gcloud publishers books list --publisher=PUBLISHER -``` - -## Changelog - -- **2020-09-23**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/cloud/2604.md b/aip/cloud/2604.md deleted file mode 100644 index cd632fd3a8..0000000000 --- a/aip/cloud/2604.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -id: 2604 -state: approved -created: 2019-06-13 -placement: - category: sdk ---- - -# Numeric arguments - -Some API fields refer to either a percentage or a fixed number. For example, in -GCE a group can be created with a configurable limit for either the percentage -or number of instances in the group that can undergo maintenance -simultaneously: - -```proto -message ConcurrencyControl { - enum LimitType { - INVALID = 0; - PERCENT = 1; - FIXED = 2; - } - optional int32 concurrency_limit = 1; - optional LimitType limit_type = 2; -} -``` - -## Guidance - -### Flag layout - -In gcloud, such API fields should correspond to a mutually exclusive group -consisting of two flags: one for specifying a number, and the other for -specifying a percentage. The API field in the example above would thus -correspond to the following surface specification in gcloud: - -```yaml -- group: - mutex: true - arguments: - - name: concurrency-limit - help_text: | - Maximum number of instances in the group that can undergo maintenance - simultaneously. - - name: concurrency-limit-percent - help_text: | - Integer from 0 to 100 representing the maximum percentage of instances - in the group that can undergo maintenance simultaneously. -``` - -### Flag naming - -Any flag taking a percentage should end with `-percent` (not `-percentage`). - -### Flag type - -Any flag taking a percentage should take an integer from 0 to 100. If more -precision is required, it is acceptable to take a float from 0 to 100. - -## Alternatives considered - -### One flag, where percentage is specified if the flag value ends with '%', and number is assumed otherwise - -In other words, to specify 10% one would use `--concurrency-limit=10%`, and to -specify 10 instances one would use `--concurrency-limit=10`. - -This would be a cleaner design since it naturally maps a single concept (the -limit) to a single flag (`--concurrency-limit`), avoiding the need for -additional flags that clutter the help text. - -However, the main reason not to prefer this approach is that it significantly -increases the risk of user error. For instance, suppose a group currently -contains 20 instances with a concurrency limit of 10%, and a user wishes to -update the limit to 20%. If the user issues a describe command (or performs a -GET request) to see the existing limit, the API response will contain something -like: - -```yaml -concurrencyControl: - concurrencyLimit: 10 - limitType: PERCENT -``` - -It's easy for the user to gloss over limitType and just assume that -`--concurrency-limit=20` will update the limit to 20%. However, in reality this -would set the limit to 20 instances (100% of the group), potentially leading to -catastrophic consequences. - -The recommend approach avoids this ambiguity at the expense of some elegance, -but we deem this tradeoff necessary. - -### One flag, where percentage is specified if the flag value ends with '%', and number is specified if the flag value ends with 'n' - -In other words, to specify 10% one would use `--concurrency-limit=10%`, and to -specify 10 instances one would use `--concurrency-limit=10n`. It would be an -error to provide a value that doesn't end in '%' or 'n'. - -While this avoids the potential for a user to confuse percentages and numbers, -requiring 'n' at the end of a number is inelegant UX. A number should obviously -resemble a number, and the choice of 'n' is also rather arbitrary. - -## Exceptions - -This CIP does not apply for API fields like timestamps, where we allow the user -to enter either absolute times or durations in the same flag. This is because -absolute times and durations have natural formats that differ, and thus there's -no potential for a user to confuse the two. In general if this is the case, one -flag that accepts both formats should be preferred for the sake of UX -simplicity. diff --git a/aip/cloud/scope.yaml b/aip/cloud/scope.yaml deleted file mode 100644 index 4de940769f..0000000000 --- a/aip/cloud/scope.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Google Cloud Platform -order: 10 -categories: - - code: gcp - title: Google Cloud Platform APIs - - code: sdk - title: Cloud SDK diff --git a/aip/firebase/3201.md b/aip/firebase/3201.md deleted file mode 100644 index 2028b37743..0000000000 --- a/aip/firebase/3201.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: 3201 -scope: firebase -state: draft -created: 2020-06-11 ---- - -# Projects and Apps - -## Guidance - -### Resource Hierarchy - -APIs that utilize an App ID as part of a resource name **must** include a -Project identifier in the parent: - -``` -apps/*/items -``` - -Must instead be: - -``` -projects/*/apps/*/items -``` - -Project identifiers **must** follow [Cloud guidance][aip-2510]. As App IDs are -globally unique, Firebase APIs **should** allow the [unique resource -lookup][aip-159-unique] pattern, allowing a `-` in place of a Project -ID/Number. For example: - -``` -projects/-/apps/1:111222333444:web:abcdef0123456789/things -``` - -### Referencing App IDs - -When referencing an App ID in an SDK or API field, method, or parameter, the -platform-correct initialism of `app_id` **must** be used (as opposed to e.g. -`app`, `application_id`, or `gmp_app_id`). - -[aip-2510]: ../cloud/2510.md -[aip-159-unique]: ../0159.md#unique-resource-lookup diff --git a/aip/firebase/3260.md b/aip/firebase/3260.md deleted file mode 100644 index 646492d008..0000000000 --- a/aip/firebase/3260.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -id: 3260 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# Firebase CLI - -## Guidance - -### Command Naming - -Commands **must** be named in lowercase using colons to separate namespaces. -The final segment of a command **should** be an action verb, for example -`list`, `deploy`, or `clone`. A "get" of a single resource **may** omit the -action for the sake of brevity (e.g. `apps:sdkconfig` instead of -`apps:sdkconfig:get`). - -### Project Selection - -The Firebase CLI works with "project directories" that can be associated with -one or more Firebase projects via the `use` command. This ambient project -selection can be overridden by passing the `-P` or `--project` flag. - -All Firebase CLI commands **must** determine the intended project for a command -based on common project selection, except when a command involves multiple -projects (e.g. a command that clones configuration from one project to -another). - -### JSON Output - -All Firebase CLI commands support machine-readable output via the `--json` -flag. If a command correlates to a single API call, the unmodified response of -that API call should be provided as the JSON response (with wrapped CLI -metadata). - -If a command does not directly correlate to an API call, the output **should** -include all information a user might reasonably need for programmatic -interpretation of the command. Output **must** be formatted in snake-case and -generally conform to all standard Google API guidance (e.g. [field -names][aip-140]). - -### Arguments and Flags - -Required inputs for a command **must** be represented as arguments (e.g. -`database:get /path`) unless doing so would be confusing to the user. For -instance, `appdistribution:distribute` requires as input both a file to -distribute and an App ID, so `--app ` as a required flag is more clear -than two unrelated arguments with no clear hierarchy. - -Flags **must** be named using kebab case (e.g. `--example-flag`) and **may** -provide a single-letter alias that does not conflict with [defined global -flags][global-flags]. - -#### Common Flags - -- `--app ` - used to refer to a specific app within a Firebase project. -- `--force` - used to indicate that a command should proceed without additional - prompting regarding potentially destructive actions. For example, deploying - Cloud Functions with `--force` will automatically delete functions, while - without the user is prompted. -- `-o, --output ` - this flag **may** be used to allow convenient output - of a serialized response to a local file. If the output is JSON, it **must** - output equivalent JSON to `--json` without wrapped CLI metadata. If the - command fetches a deployable resource, it **must** fetch it in a - deploy-compatible format. The string path **may** be optional if a clear - default path exists. If a file already exists at the path, a confirmation - prompt **must** be displayed unless a `--force` flag is also provided. - -### Common Command Types - -#### List Commands - -Commands that return a list of like resources **must** use a `:list` suffix -(e.g. `projects:list`). - -List commands **must not** require manual pagination (e.g. a `--page-token` -flag) and will generally fetch all results (via multiple API calls if -necessary). List commands **may** include a `--limit ` flag when a -natural ordering exists, such as a reverse chronological list of releases. -A `--limit 0` flag indicates that all results should be fetched and -returned. - -The JSON output of a list command **must** be a concatenated array of all -fetched resources in their original wire format. - -#### Clone Commands - -If a command's purpose is to copy information from one resource to another, it -**must** be suffixed with `:clone` and **must** take a `from` and `to` -argument: - - firebase example:clone - -To avoid confusion and accidental misuse, clone commands **must** explicitly -require both arguments and **must not** rely on project selection to populate -either. - -If a clone operation is destructive (replaces existing state), the command -**should** prompt the user for confirmation before proceeding. If a prompt is -added, the command **must** allow a `--force` flag to bypass the prompt. - -### Deployment - -Behavior that takes local state (e.g. a rules file) and applies it to the live -operation of a Firebase project **must** integrate with the `deploy` command. - -#### Scoped Deployments - -If a service has multiple deployable resources, it **may** allow specifying -which resources are deployed through colon namespacing, for example: - - firebase deploy --only functions:func1,functions:func2,hosting:site3 - -Colon namespacing **may** be used to identify one of many like resources (as -with functions above) or to identify specific resource type (e.g. -`firestore:indexes` vs. `firestore:rules`). - -If the service integrates with [deploy targets][deploy-targets], the targets -**must** be addressable via colon namespacing. - - -[global-flags]: https://github.com/firebase/firebase-tools/blob/master/src/index.js -[deploy-targets]: https://firebase.google.com/docs/cli/targets -[aip-140]: ../0140.md - diff --git a/aip/firebase/3270.md b/aip/firebase/3270.md deleted file mode 100644 index 0b696673bd..0000000000 --- a/aip/firebase/3270.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: 3270 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# JavaScript APIs - -## Guidance - -## Changelog diff --git a/aip/firebase/3271.md b/aip/firebase/3271.md deleted file mode 100644 index cba2f6e38c..0000000000 --- a/aip/firebase/3271.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: 3271 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# Android APIs - -## Guidance - -## Changelog diff --git a/aip/firebase/3272.md b/aip/firebase/3272.md deleted file mode 100644 index fa906ffb29..0000000000 --- a/aip/firebase/3272.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: 3272 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# iOS APIs - -## Guidance - -## Changelog diff --git a/aip/firebase/3273.md b/aip/firebase/3273.md deleted file mode 100644 index e36462c040..0000000000 --- a/aip/firebase/3273.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: 3273 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# C++ APIs - -## Guidance - -## Changelog diff --git a/aip/firebase/3274.md b/aip/firebase/3274.md deleted file mode 100644 index ffd845cc72..0000000000 --- a/aip/firebase/3274.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: 3274 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# .NET APIs - -## Guidance - -## Changelog diff --git a/aip/firebase/3275.md b/aip/firebase/3275.md deleted file mode 100644 index 1e64995f17..0000000000 --- a/aip/firebase/3275.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: 3275 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# Python APIs - -## Guidance - -## Changelog diff --git a/aip/firebase/3276.md b/aip/firebase/3276.md deleted file mode 100644 index c65a1cce19..0000000000 --- a/aip/firebase/3276.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: 3276 -scope: firebase -state: draft -created: 2020-06-10 ---- - -# Go APIs - -## Guidance - -## Changelog diff --git a/aip/firebase/scope.yaml b/aip/firebase/scope.yaml deleted file mode 100644 index 6626e53a62..0000000000 --- a/aip/firebase/scope.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Firebase -order: 40 -hidden: true diff --git a/aip/general/0001.md b/aip/general/0001.md deleted file mode 100644 index 8bdaa751ee..0000000000 --- a/aip/general/0001.md +++ /dev/null @@ -1,294 +0,0 @@ ---- -id: 1 -state: approved -created: 2018-08-20 -placement: - category: meta - order: 10 -js_scripts: - - /assets/js/graphviz/viz.js - - /assets/js/graphviz/lite.render.js - - /assets/js/aip/aip-graphviz.js ---- - -# AIP Purpose and Guidelines - -As the corpus of Google APIs has grown and the API Governance team has grown to -meet the demand of supporting them, it is increasingly necessary to have a -corpus of documentation for API producers, reviewers, and other interested -parties to reference. The API style guide and introductory One Platform -documentation are intentionally terse and high-level. The AIP collection -offers a method to provide consistent documentation for API design guidance. - -## What is an AIP? - -AIP stands for **API Improvement Proposal**, which is a design document -providing high-level, concise documentation for API development. They are to -serve as the source of truth for API-related documentation at Google and the -means by which API teams discuss and come to consensus on API guidance. AIPs -are maintained as Markdown files in the [AIP GitHub repository][]. - -## Types of AIPs - -There are several different types of AIPs, described below. The list of AIP -types may evolve over time as necessary. - -### Guidance - -These AIPs describe guidance on API design. These are provided as instruction -for API producers to help write simple, intuitive, and consistent APIs, and are -used by API reviewers as a basis for review comments. - -### Process - -These AIPs describe a process surrounding API design. They often affect the AIP -process itself and are used to enhance the way in which AIPs are handled. - -## Stakeholders - -As with any process there are many different stakeholders when it comes to -reviewing and working with AIPs. Below is a summary of the escalation path -starting with the API producer. - -```graphviz -digraph d_front_back { - rankdir=BT; - ranksep=0.3; - node [ style="filled,solid" shape=box fontname="Roboto" ]; - - producer [ label="API Producer" ]; - editors [ label="AIP Editors" ]; - tl_infra [ label="Infrastructure TL" ]; - tl_design [ label="Design TL" ]; - tl [ label="TL" ]; - - producer -> editors; - editors -> tl_infra -> tl; - editors -> tl_design -> tl; -} -``` - -As noted in the diagram above, the TL is the final decision-maker on the AIP -process and the final point of escalation if necessary. - -### Editors - -The editors are the set of people who make decisions on AIPs. The general goal -is that the AIP process is collaborative and that we largely work on the basis -of consensus. However, a limited number of designated approvers is necessary, -and these Googlers will be approvers for each AIP in the general scope. - -The list of AIP editors is currently: - -- Angie Lin ([@alin04][]) -- Jon Skeet ([@jskeet][]) -- Jose Juan Zavala Iglesias ([@itsStrobe][]) -- Louis Dejardin ([@loudej][]) -- Noah Dietz ([@noahdietz][]) -- Sam Levenick ([@slevenick][]) -- Sam Woodard ([@shwoodard][]) - -The editors are also responsible for the administrative and editorial aspects -of shepherding AIPs and managing the AIP pipeline and workflow. They approve -PRs to AIPs, assign proposal numbers, manage the agenda, set AIP states, and so -forth. They also ensure that AIPs are readable (proper spelling, grammar, -sentence structure, markup, etc.). - -AIP editorship is by invitation of the current editors. - -## Domain-specific AIPs - -Some AIPs may be specific to a particular domain (for example, only to APIs -within a certain PA, or even a certain team). In this situation, the group will -be given a particular block of AIPs to use in accordance with AIP-2, and the -applicable AIPs will clearly indicate their scope. - -## States - -At any given time, AIPs may exist in a variety of states as they work their way -through the process. The following is a summary of each state. - -### Draft - -The initial state for an AIP is the "Draft" state. This means that the AIP is -being discussed and iterated upon, primarily by the original authors. While the -editors _may_ get involved at this stage, it is not necessary. - -**Note:** If significant, high-level iteration is required, it is recommended -to draft AIPs in a Google doc instead of a PR. AIPs that are migrated into the -AIP system from Google Docs **may** skip the draft state and go directly to -reviewing provided there is sufficient approval. - -### Reviewing - -Once discussion on an AIP has generally concluded, but before it is formally -accepted it moves to the "Reviewing" state. This means that the authors have -reached a general consensus on the proposal and the editors are now involved. -At this stage the editors may request changes or suggest alternatives to the -proposal before moving forward. - -**Note:** As a formal matter, one AIP approver (other than the author) **must** -provide formal signoff to advance an AIP to the reviewing state. Additionally, -there **must not** be formal objections ("changes requested" on the GitHub PR) -from other approvers. - -### Approved - -Once an approved AIP has been agreed upon, it enters "approved" state and is -considered "best current practice". - -**Note:** As a formal matter, two AIP approvers (other than the author) -**must** provide formal signoff to advance an AIP to the approved state. -Additionally, there **must not** be formal objections ("changes requested" on -the GitHub PR) from other approvers. - -### Withdrawn - -If an AIP is withdrawn by the author or champion, it enters "withdrawn" state. -AIPs that are withdrawn may be taken up by another champion. - -### Rejected - -If an AIP is rejected by the AIP editors, it enters "rejected" state. AIPs that -are rejected remain, and provide documentation and reference to inform future -discussions. - -### Deferred - -If an AIP has not been acted upon for a significant period of time, the editors -may mark it as "deferred". - -### Replaced - -If an AIP has been replaced by another AIP, it enters "replaced" state. AIP -editors are responsible to provide a notice explaining the replacement and -rationale (the replacement AIP should also clearly explain the rationale). - -In general, API producers should rely primarily on AIPs in the "approved" -state. - -## Workflow - -The following workflow describes the process for proposing an AIP, and moving -an AIP from proposal to implementation to final acceptance. - -### Overview - -```graphviz -digraph d_front_back { - rankdir=LR; - node [ style="filled,solid" shape=box fontname="Roboto" ]; - draft [ label="Draft" fillcolor="orange" ]; - reviewing [ label="Reviewing" fillcolor="lightskyblue" ]; - approved [ label="Approved" fillcolor="palegreen" ]; - withdrawn [ label="Withdrawn" fillcolor="mistyrose" ]; - rejected [ label="Rejected" fillcolor="mistyrose" ]; - deferred [ label="Deferred" fillcolor="lightsteelblue" ]; - replaced [ label="Replaced" fillcolor="lightsteelblue" ]; - - draft -> reviewing; - draft -> withdrawn [ style=dashed, color=mistyrose3 ]; - draft -> rejected [ style=dashed, color=mistyrose3 ]; - reviewing -> approved; - reviewing -> withdrawn [ style=dashed, color=mistyrose3 ]; - reviewing -> rejected [ style=dashed, color=mistyrose3 ]; - draft -> deferred [ style=dashed, color=lightsteelblue3 ]; - reviewing -> deferred [ style=dashed, color=lightsteelblue3 ]; - approved -> replaced [ style=dashed, color=lightsteelblue3 ]; - reviewing -> replaced [ style=dashed, color=lightsteelblue3 ]; -} -``` - -### Proposing an AIP - -In order to propose an AIP, first [open an issue][] to circulate the -fundamental idea for initial feedback. It should generally be possible to -describe the idea in a couple of pages. - -When proposing a new AIP or changes to an existing one, it is best to reference -prior art and/or example use cases that the proposal will impact, so as to -ensure that the proposal is grounded in a realistic problem space. So, proposals -**should** provide concrete references and/or well-defined examples. Appropriate -material includes, but is not limited to, the following: - -- Existing external RFCs or standards -- A corpus of APIs that have aligned on a similar pattern e.g. `Search` methods -- A concrete use case that has yet to be solved that exists or could exist in - one or more APIs e.g. adding an AIP-202 Format for AIP-143 Unicode CLDR - region codes - -Once ready, create a PR with a new file in the AIP directory using a file -titled `aip/new.md`. Ensure that the PR is editable by maintainers. - -In most circumstances, the editors will assign the proposal an AIP number and -submit the PR with the AIP in the "Reviewing" state. The editors may reject an -AIP outright if they have an obvious reason to do so (e.g. the proposal was -already discussed and rejected in another AIP or is fundamentally unsound), in -which case the PR is not merged. - -### Discussing an AIP - -Once the PR is merged, the AIP author is responsible for championing the AIP on -a follow-up approval pull request. This means that the author is responsible -for pushing towards consensus around the proposal. This may involve a -discussion at the regularly scheduled meetings for the API Governance team. - -The AIP author may modify the AIP over the course of discussion by submitting -follow-up commits to the PR. - -### Accepting an AIP - -The editors will work together to ensure that qualified proposals do not linger -in review. - -To gain final approval, an AIP **must** be approved by, at minimum, the TL with -responsibility over the domain covered by the AIP (either design or -infrastructure) and at least one other editor, with no editors actively -requesting changes. - -**Note:** If an AIP editor is the primary author of an AIP, then at least two -_other_ editors must approve it. - -Once the AIP is approved, the editors will update the state of the AIP to -reflect this and submit the PR. - -### Withdrawing or Rejecting an AIP - -The author of an AIP may decide, after further consideration, that an AIP -should not advance. If so, the author may withdraw the AIP by updating the PR -adding a notice of withdrawal with an explanation of the rationale. -Additionally, the author may be unable to get consensus among the group and the -AIP editors may elect to reject the AIP. In this situation, the AIP editors -shall amend the PR adding a notice of rejection with an explanation of the -rationale. In both cases, the AIP editors update the state accordingly and -submit the PR. - -### Replacing an AIP - -In rare cases, it may be necessary to replace an AIP with another one. This is -not general practice: minor edits to approved AIPs are acceptable, and will be -the common way to tweak guidance. However, if new guidance fundamentally alters -the old guidance in some way, then the AIP editors shall create a new AIP that, -once approved, will replace the old one. The old one then enters "Replaced" -state, and will link to the new, current AIP. - -## Changelog - -- **2025-01-09**: Add requirement to include references/examples in proposals. -- **2024-09-04**: Updated names of current editors and remove TLs. -- **2023-05-10**: Updated names of current and editors and TLs. -- **2019-07-30**: Further clarified AIP quorum requirements. -- **2019-05-12**: Collapsed AIP approvers and editors into a single position, - relaxed approval rules from full quorum. -- **2019-05-04**: Updated the AIP to refer to GitHub processes, rather than - internal processes. - -[aip github repository]: https://github.com/googleapis/aip -[open an issue]: https://github.com/googleapis/aip/issues -[@alin04]:https://github.com/alin04 -[@jskeet]: https://github.com/jskeet -[@loudej]: https://github.com/loudej -[@noahdietz]: https://github.com/noahdietz -[@slevenick]: https://github.com/slevenick -[@shwoodard]: https://github.com/shwoodard -[@itsStrobe]: https://github.com/itsStrobe diff --git a/aip/general/0002.md b/aip/general/0002.md deleted file mode 100644 index 7f0b949f42..0000000000 --- a/aip/general/0002.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: 2 -state: approved -created: 2018-08-23 -placement: - category: meta - order: 20 ---- - -# AIP Numbering - -The AIP system provides a mechanism to index and have a single source of truth -for API Improvement Proposals, as well as iterate on them collaboratively and -transparently. - -This document describes the AIP numbering system. - -## Assigning AIP Numbers - -The AIP editors (see [AIP-1](./0001.md)) are responsible for assigning a number -to each AIP when it is accepted as a draft for review. Importantly, _all_ AIPs -have numbers, not just approved ones. The [AIP Index](/) clearly delineates -which AIPs are approved and binding and which are under discussion. - -The editors may decide to reserve a specific block of numbers for groups of -AIPs that are related in some way (for example, that are only scoped to a -specific subset of APIs). - -Beyond this, AIP numbers are assigned arbitrarily. In general, the editors will -take the next AIP number off of the stack to assign to a draft AIP, but -occasionally may use a special/joke number if useful for mnemonic or other -reasons. - -## AIP Blocks - -Currently recognized blocks of AIP numbers are: - -### Generally Applicable - -- **1-99:** Reserved for meta-AIPs (generally process-related). -- **100-999:** General API design guidance - -### Google Product Areas - -- **2700-2799:** Apps (Google Workspace) -- **2500-2599:** Cloud -- **3000-3099:** Actions on Google -- **3200-3299:** Firebase -- **4100-4199:** Auth libraries -- **4200-4299:** Client libraries -- **4600-4699:** Geo - -To request a block for a specific team that is publishing API guidance or -documentation germane to that specific team, reach out to api-editors@. - -## Changelog - -- **2019-10-03:** The 3000-3099 block was assigned to Actions on Google. -- **2019-01-26:** The general API design guidance block was expanded to include - 100-199. -- **2018-10-24:** The 4600-4699 block was assigned to Google Geo. -- **2018-10-02:** The 2500-2599 block was assigned to Google Cloud Platform. -- **2018-10-02:** The 2700-2799 block was assigned to Google Workspace. diff --git a/aip/general/0003.md b/aip/general/0003.md deleted file mode 100644 index 92a4581e74..0000000000 --- a/aip/general/0003.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: 3 -state: approved -created: 2023-03-28 -placement: - category: meta - order: 30 ---- - -# AIP Versioning - -This AIP defines the versioning scheme of the AIPs. - -## Guidance - -- The AIPs **must** be versioned by date, using the [ISO-8601 format of - `YYYY-MM-DD`](https://www.w3.org/TR/NOTE-datetime), that corresponds to the - date the version was added. -- AIPs versions **must** be available as a tag on the source control system used - to store the AIPs, of the format `v{version}`. Example: `v2023-03-28`. -- The AIPs **must** have a new version when there is a significant change to one - or more AIPs. -- Each AIP **must** include a changelog section, with the date the change was - made and a short description. - -## Rationale - -Versions serve as reference points to AIPs at a specific point in time. They are -crucial since guidance on an AIP can be reversed, or include significant changes -such that they are no longer similar to the original design. APIs using AIPs may -need to reference older AIP guidance to justify their design choice. - -### Rationale for date-based versioning - -With date-based versioning, a client can easily find the AIP guidance at the -time an API was authored. - -### Why not individually versioned AIPs - -An alternative to a universal version is to have specific versions attached to -each AIP. - -AIPs often cross-reference one another. If each AIP had a specific version, then -cross-references would also have to specify specific versions of those -referenced AIPs to provide complete guidance. \ No newline at end of file diff --git a/aip/general/0008.md b/aip/general/0008.md deleted file mode 100644 index 5a28bf5c33..0000000000 --- a/aip/general/0008.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -id: 8 -state: approved -created: 2019-05-28 -placement: - category: meta - order: 40 ---- - -# AIP Style and Guidance - -AIP stands for **API Improvement Proposal**, which is a design document -providing high-level, concise documentation for API design and development. The -goal is for these documents to serve as the source of truth for API-related -documentation at Google and the way API teams discuss and come to consensus on -API guidance. - -AIPs are most useful when they are clear and concise, and cover a single topic -or inquiry well. In the same way that AIPs describe consistent patterns and -style for use in APIs, they also _follow_ consistent patterns and style. - -## Guidance - -- AIPs **must** cover a single, discrete topic, and provide clear, actionable - guidance. -- AIPs **must not** duplicate or contradict guidance in another AIP. -- AIPs **may** also cover what _not_ to do, but **should not** cover _only_ - anti-patterns. -- If AIP guidance is conditional (e.g. a design pattern such as Jobs), the - guidance **must** clearly explain under what conditions the guidance should be - followed. - -Guidance contained within an AIP **must** be beneficial to one or more -types of clients or their authors, including but not limited to: - -- Asset inventories which can be used to audit and analyze resources. -- Command line interfaces for exploration and simple automation. -- Custom controllers (e.g. auto-scalers) which poll live state and adjust - resource configuration accordingly. -- [IaC][] clients for orchestration and automation of multiple resources. -- Recommendation tools which provide guidance on which APIs are useful for - specific use cases, and how to use them. -- SDKs to interact with an API from a programming language, often used heavily - for data-plane operations. -- Security orchestration, automation, and remediation tools. -- Simple scripts to automate or orchestrate tasks. -- Test frameworks. -- Tools that operate on resource data at rest. -- Visual User Interfaces for visualization and one-off manual actions. -- Users. - -Examples of improvements include: - -- Requiring new proto annotations that enable more descriptive interfaces on - clients (e.g. requiring `singular` and `plural` on a `google.api.resource` - annotation). - -AIP guidance **must not** be a significant detriment to a client's usability or -implementation difficulty, or maintenance difficulty. - -Examples of detriments include: - -- Introduction of a non-uniform pattern in a standard method such that all - clients must introduce additional code without sufficient benefit (e.g. List - behaves like this *except* for resources that start with the name Foo). -- Renames of well-established fields for minor improvements in readability (e.g. - rename `expire_time` to `lapse_time` since `lapse` is a common term in my - service). - -While the length of AIPs will necessarily vary based on the complexity of the -question, most AIPs **should** be able to cover their content in roughly two -printed pages. - -### File structure - -AIPs **must** be written in Markdown, and **must** be named using their -four-digit number (example: `0008.md`). AIPs that serve a specific scope -**must** be in the subdirectory for that scope. - -AIPs **must** have appropriate front matter. - -```yaml ---- -id: 8 -state: reviewing -created: 2019-05-28 -permalink: /8 -redirect_from: - - /08 - - /008 - - /0008 ---- - -``` - -Front matter for AIPs **must** include: - -- The `aip` key: - - `id`: Required. The ID for the given AIP, as an integer. - - `state`: Required. The current state of the AIP, in all lower-case. The - valid states are listed in [AIP-1][], and common states are `draft`, - `reviewing`, and `approved`. - - `created`: Required. The ISO-8601 date (`yyyy-mm-dd`) when the AIP was - originally drafted, with no quotes. - - `updated`: The ISO-8601 date (`yyyy-mm-dd`) when the AIP was last revised. - - `scope`: The scope for the AIP. This **must** match the directory name for - that scope. Required for AIPs with IDs >= 1000, prohibited otherwise. -- The `permalink` key (required): This **must** be set to - `/{aip.scope}/{aip.id}`. If there is no scope, use `/{aip.id}` instead. -- The `redirect_from` key: This should include a list of any `/{aip.id}` - permutations that a reader would be likely to enter, including: - - `/{aip.id}` (for AIPs where the permalink includes the scope) - - AIP IDs with zero-padding, for each level of zero-padding up to four digits - (for example: `/08`, `/008`, `/0008`). - -### Document structure - -AIPs **must** begin with a top-level heading with the AIP's title (`# Title`). -The title **should** be a noun (not an imperative). For example, "Bad API -precedents" not "Avoid breaking API precedent". - -AIPs **should** then begin with an introduction (with no additional heading), -followed by a `## Guidance` heading. If necessary, the AIP **may** include any -of the following after the guidance, in the following order: - -- "Further reading" is a bulleted list of links to other AIPs that are useful to - fully understand the current AIP. -- "Appendices" covering further explanation in the same AIP. These are - relatively rare but are important in cases where an AIP requires a lot of - justification for the decision. Often this is primarily an explanation of - alternatives considered to help explain the guidance. -- "Changelog" is a bulleted list of changes made to the AIP since the first - writing. - -The guidance section **may** include subsections that elaborate further on -details. Subsections will automatically create an entry in the table of -contents, and an anchor for citations. - -Below is an example AIP shell that uses each major section: - -```md -# AIP title - -The introductory text explains the background and reason why the AIP exists. It -lays out the basic question, but does not tell the reader what to do. - -## Guidance - -The "guidance" section helps the reader know what to do. A common format for -the guidance section is a high-level imperative, followed by an example, -followed by a bulleted list explaining the example. - -### Subsection - -Individual subsections can be cited individually, and further elaborate -details. - -## Rationale - -The "rationale" section is optional, and helps the reader understand the -motivation behind specific guidance within the AIP. - -Deeper explanations of design justification and tradeoffs **must** be in the -rationale instead of other sections, to ensure the rest of the document acts as -an easily actionable reference. - -## History - -The "history" section is optional, and documents events and context around a -significant edit to an AIP. For example, explanation of rewrite would be -included in this section - -While the changelog is a dotted list of one-line summaries of changes to an AIP, -the history section should elaborate on significant events in a descriptive -format. - -The section **must not** be used to exhaustively enumerate all changes. This -is what the changelog provides. - -## Further reading - -A bulleted list of (usually) other AIPs, in the following format: - -- [AIP-1](./0001.md): AIP purpose and guidelines - -## Changelog - -A bulleted list of changes in reverse chronological order, using the following -format: - -- **2020-02-18**: Specified ordering. -- **2019-07-01**: Added a subsection clarifying XYZ. -``` - -AIPs **should** attempt to follow this overall format if possible, but AIPs -**may** deviate from it if necessary (in particular, if the AIP would be more -difficult to understand, even for a reader already accustomed to reading AIPs in -the usual format). - -**Note:** Except for the title, AIPs **must** only use the second heading level -(`##`) and above. AIPs **should** only use the second and third heading levels -(`##`, `###`). - -### Requirement keywords - -AIPs **should** use the following requirement level keywords: "MUST", "MUST -NOT", "SHOULD", "SHOULD NOT", and "MAY", which are to be interpreted as -described in [RFC 2119][]. - -When using these terms in AIPs, they **must** be lower-case and **bold**. These -terms **should not** be used in other ways. - -If "SHOULD" or "SHOULD NOT" are used, they **must** include valid examples of -where other concerns may override the guidance. - -**Important:** If rationale is used, it exists to provide background and a more -complete understanding, but **must not** contain guidance (and RFC-2119 terms -**must not** be used). - -### Code examples - -API design examples in AIPs **should** use [protocol buffers][]. Examples -**should** cover only enough syntax to explain the concept. When using RPCs in -examples, a `google.api.http` annotation **should** be included. - -### Referencing AIPs - -When AIPs reference other AIPs, the prosaic text **must** use the format -`AIP-XXXX` without zero-padding (e.g., `AIP-8`, not `AIP-0008`), and **must** -link to the relevant AIP. AIP links **may** point to a particular section of the -AIP if appropriate. - -**Important:** AIP links **must** use the relative path to the file in the -repository (such as `./0008.md` for core AIPs, or `../0008.md` for AIPs in a -subdirectory); this ensures that the link works both on the AIP site, when -viewing the Markdown file on GitHub, using the local development server, or a -branch. - -## Rationale - -### Designing for a broad set of clients - -API guidance, similar to any software, is most beneficial when there is a clear -purpose and target beneficiary. - -The beneficiaries of improved API design are users. These users interact with -APIs via a variety of clients, depending on their use case as enumerated above. - -API guidance must in turn consider the impact broadly across these clients. - -[aip-1]: ./0001.md -[Infrastructure as Code]: ./0009.md#iac -[IaC]: ./0009.md#iac -[protocol buffers]: https://developers.google.com/protocol-buffers/ -[rfc 2119]: https://www.ietf.org/rfc/rfc2119.txt - -## Changelog - -- **2023-05-20**: Increase API guidance scope to include broad set of clients. -- **2023-03-30**: Removed appendix, added rationale and history to the template. -- **2020-02-18**: Specified reverse chronological ordering for changelog items. -- **2019-08-23**: Added guidance for internal AIP links. \ No newline at end of file diff --git a/aip/general/0009.md b/aip/general/0009.md deleted file mode 100644 index 7a5bed46bc..0000000000 --- a/aip/general/0009.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -id: 9 -state: approved -created: 2019-08-01 -placement: - category: meta - order: 100 ---- - -# Glossary - -In the name of brevity, this AIP defines some common terminology here rather -than in each AIP individually. - -## Guidance - -The following terminology **should** be used consistently throughout AIPs. - -### API - -Application programming interface. This can be a local interface (such as a -client library) or a Network API (defined below). - -### API backend - -A set of servers and related infrastructure that implements the business logic -for an API service. An individual API backend server is often called an API -server. - -### API consumer - -The entity that consumes an API service. For Google APIs, it typically is a -Google project that owns the client application or the server resource. - -### API definition - -The definition of an API, usually defined in a Protocol Buffer service. An API -definition can be implemented by any number of API services. - -### API frontend - -A set of servers plus related infrastructure that provides common functionality -across API services, such as load balancing and authentication. An individual -API frontend server is often called an API proxy. - -**Note:** the API frontend and the API backend may run next to each other or far -away from each other. In some cases, they can be compiled into a single -application binary and run inside a single process. - -### API interface - -The element of an API specification IDL that groups API methods, such as a -Protocol Buffers `service` definition. It is typically mapped to a similar high -level grouping mechanism in most programming languages, like a `class` or -`interface`. - -### API method - -An individual operation within an API. It is typically represented in Protocol -Buffers by an `rpc` definition, and is mapped to a function in the API in most -programming languages. - -### API producer - -The entity that produces an API service. For Google APIs, it typically is a -Google team responsible for the API service. - -### API product - -An API service and its related components, such as Terms of Service, -documentation, client libraries, and service support, are collectively presented -to customers as a API product. For example, Google Calendar API. - -**Note:** people sometimes refer to an API product simply as an API. - -### API service - -A deployed implementation of one or more APIs, exposed on one or more network -addresses, such as the Cloud Pub/Sub API. - -### API service definition - -The combination of API definitions (`.proto` files) and API service -configurations (`.yaml` files) used to define an API service. The schema for -Google API service definition is `google.api.Service`. - -### API service endpoint - -Refers to a network address that an API service uses to handle incoming API -requests. One API service may have multiple API service endpoints, such as -`https://pubsub.googleapis.com` and `https://content-pubsub.googleapis.com`. - -### API service name - -Refers to the logical identifier of an API service. Google APIs use RFC 1035 DNS -compatible names as their API service names, such as `pubsub.googleapis.com`. - -### API title - -Refers to the user-facing product title of an API service, such as "Cloud Pub/Sub -API". - -### API request - -A single invocation of an API method. It is often used as the unit for billing, -logging, monitoring, and rate limiting. - -### API version - -The version of an API or a group of APIs if they are defined together. An API -version is often represented by a string, such as "v1", and presents in API -requests and Protocol Buffers package names. - -### Client - -Clients are programs that perform a specific tasks by calling an API or generic -tools, such as CLIs, that expose the API in a user-accessible fashion or operate -on resource data at rest. - -Examples of clients include the following: - -- Command line interfaces -- Libraries, such as an SDK for a particular programming language -- Scripts that operates on a JSON representation of a resource after reading it - from an API -- Tools, such as a [Declarative clients][] -- Visual UIs, such as a web application - -### Google API - -A Network API exposed by a Google service. Most of these are hosted on the -`googleapis.com` domain. It does not include other types of APIs, such as client -libraries and SDKs. - -### Declarative Clients - -Declarative Clients, also known as Infrastructure as Code (IaC), describes a -category of clients that consumes a markup language or code that represents -resources exposed by an API, and executes the appropriate imperative actions to -drive the resource to that desired state. To determine what changes to make and -if a set of updates was successful a declarative client compares server side -resource attributes with client defined values. The comparison feature ensures -accuracy of a creation or an update but it requires services to treat the client -set fields as read-only and diligently preserve those values. - -Examples of complexities that declarative clients abstract away include: - -- Determining the appropriate imperative action (create / update / delete) to - achieve desired state. -- Ordering of these imperative actions. - -[Terraform][] is an example of such a client. - -### User - -A human being which is using an API directly, such as with cURL. This term is -defined to differentiate usage in the AIPs between a human *user* and a -programmatic *client*. - -### Network API - -An API that operates across a network of computers. Network APIs communicate -using network protocols including HTTP, and are frequently produced by -organizations separate from those that consume them. - -[Declarative clients]: #declarative-clients -[Terraform]: https://www.terraform.io/ - -## Changelog - -- **2025-08-13**: Add API inteface entry -- **2024-12-18**: Downcase headings and terms as per dev docs style -- **2024-10-23**: Add API Title entry -- **2023-07-24**: Rename IaC to Declarative Clients -- **2023-04-01**: Adding definition of IaC -- **2023-03-24**: Reformatting content to include anchor links. diff --git a/aip/general/0100.md b/aip/general/0100.md deleted file mode 100644 index ee03a21bfc..0000000000 --- a/aip/general/0100.md +++ /dev/null @@ -1,349 +0,0 @@ ---- -id: 100 -state: approved -created: 2018-08-27 -placement: - category: process - order: 10 -js_scripts: - - /assets/js/graphviz/viz.js - - /assets/js/graphviz/lite.render.js - - /assets/js/aip/aip-graphviz.js ---- - -# API Design Review FAQ - -API design review exists to ensure a simple, intuitive, and consistent API -experience throughout our API corpus. - -## Do I need API design approval? - -**TL;DR:** You usually need API design approval if you are launching an API -that users can code against (either now or in the future) at the beta or GA -quality level. - -API design review is fundamentally about ensuring we provide a simple and -consistent experience for our users, and therefore is only expected for APIs -that users code directly against. - -The following flowchart illustrates whether or not your API needs to go through -the design review process: - -```graphviz -digraph { - node [ style="filled,solid" shape=box fontname="Roboto" ]; - graph [ splines=ortho, nodesep=0.2 ]; - - audience [ label="Who should code directly\nagainst this API?" - shape=diamond fillcolor=bisque ]; - - subgraph audience_responses { - rank = "same"; - node [ shape=oval fillcolor=orange ]; - - googlers [ label="Googlers\nOnly" fillcolor=lightcoral ]; - public [ label="Anyone" fillcolor=limegreen ]; - partners [ label="Partners\nOnly" fillcolor=deepskyblue ]; - - partners -> public -> googlers [ style=invisible arrowhead=none ]; - } - - - subgraph and_ever { - rank = "same"; - node [ shape=diamond fillcolor=bisque ]; - - forever_partners [ label="Forever?" shape=diamond fillcolor=bisque ]; - forever_googlers [ label="Forever?" shape=diamond fillcolor=bisque ]; - } - - subgraph forever_responses { - rank = "same"; - node [ shape=oval fillcolor=orange ]; - - forever_partners_yes [ label="Yes" fillcolor=deepskyblue ]; - forever_no [ label="No, anyone\neventually" fillcolor=limegreen ]; - forever_googlers_yes [ label="Yes" fillcolor=lightcoral ]; - } - - release_level [ label="What release\nlevel?" shape=diamond fillcolor=bisque ]; - - # Not required is not in the subgraph with the other outcomes because - # it makes the graph much smaller if it can be higher in the image. - - subgraph release_levels { - rank = "same"; - node [ shape=oval ]; - - alpha [ label="Alpha" fillcolor=darkorange ]; - beta [ label="Beta" fillcolor=goldenrod1 ]; - ga [ label="GA" fillcolor=limegreen ]; - - alpha -> beta -> ga [ style=invisible arrowhead=none ]; - } - - changes [ label="Any changes\nfrom beta?" shape=diamond fillcolor=bisque ]; - - subgraph changes_bool { - rank = "same"; - node [ shape=oval ]; - - changes_yes [ label="Yes" fillcolor=goldenrod1 ]; - changes_no [ label="No" fillcolor=limegreen ]; - } - - subgraph outcome { - rank = "same"; - node [ style="rounded,filled" ]; - fyi [ label="FYI" fillcolor=lightblue ]; - recommended [ label="Recommended" fillcolor=limegreen ]; - required [ label="⚠ Required" fillcolor=goldenrod1 ]; - not_required - [ label="Not Required" fillcolor=lightgrey style="rounded,filled" ]; - recommended -> required -> fyi -> not_required - [style=invisible arrowhead=none]; - } - - audience -> googlers [ arrowhead=none style=dashed color=grey ]; - audience -> partners [ arrowhead=none ]; - audience -> public [ arrowhead=none ]; - partners -> forever_partners; - googlers -> forever_googlers [ style=dashed color=grey ]; - public -> release_level; - forever_partners -> forever_partners_yes [ arrowhead=none ]; - forever_googlers -> forever_googlers_yes - [ arrowhead=none style=dashed color=grey ]; - forever_partners -> forever_no [ arrowhead=none ]; - forever_googlers -> forever_no [ arrowhead=none ]; - forever_partners_yes -> recommended; - forever_googlers_yes -> not_required [ style=dashed color=grey ]; - forever_no -> release_level; - release_level -> alpha [ arrowhead=none ]; - release_level -> beta [ arrowhead=none ]; - release_level -> ga [ arrowhead=none ]; - alpha -> recommended; - beta -> required; - ga -> changes; - changes -> changes_yes [ arrowhead=none ]; - changes -> changes_no [ arrowhead=none ]; - changes_yes -> required; - changes_no -> fyi; -} -``` - -### Who should code directly against it? - -One of the more complex questions is, "Who should code directly against this -API?" API design review is primarily concerned about the API's audience. This -means we care about who is permitted to write their own HTTP/gRPC calls against -the service, and who is able to see the documentation. (We do _not_ care about -questions such as whether the service is exposed on the public network.) - -Design review is expected if the general public is intended to read -documentation and write code that interacts with the service. - -The following situations **do not** require design review: - -- An API which will only ever be used by Googlers, or internal tools (for - example, Pantheon). -- An API which will only ever be called by an executable program released by - Google (even if the API could be reverse-engineered from the executable). -- An API which will only ever be called by a single customer or small set of - customers under contract, and which will _never_ be made more widely - available. (Design review is still recommended in this case, but not - required.) - -### Alpha - -For alpha, API design review is optional but recommended. It may often make -sense to endeavor to get initial feedback from customers quickly, and launching -an alpha can be a way of gaining data to determine the best answer to some -usability questions; therefore, bypassing review may be expedient. On the other -hand, launching an alpha requires building an implementation which then takes -engineering effort to update if the API design review at the beta stage raises -concerns. Because API design review can precede implementation work, we -recommend a design review for alpha. - -## Why is design review important? - -**TL;DR:** Product excellence. - -Our design review process exists to ensure that the APIs that we present to -customers are **simple**, **intuitive**, and **consistent**. Your reviewer -approaches your API from the standpoint of a naïve user, thinks through the -resources and actions that your API provides, and attempts to make the surface -as accessible and extensible as possible. - -Your design reviewer is not only evaluating your API, but also checking to -ensure that your API is consistent with Google's existing corpus of APIs. Many -customers use multiple APIs, and therefore it is important that our conventions -and naming choices line up with customer expectations. - -## What should I expect? - -### How long does the review process take? - -Reviewers make an effort to keep up with their assigned reviews and offer -feedback frequently, so as not to cause unnecessary delay, but it's generally -best to begin the review process early in case there are delays. - -The design review process varies based on the size and complexity of the -underlying API surface: - -- Incremental changes to existing APIs generally take a few days. -- Small APIs usually take around a week. -- Entirely new APIs with large surfaces tend to take no less than a week. In - cases with extraordinarily large surfaces (e.g., Cloud AutoML), reviews may - take a month or more to go through design review. - -### How do reviewers approach my API? - -API reviewers seek to approach your API the same way that your users will, by -focusing primarily on the API surface and its user-facing documentation. In an -ideal world, your API reviewer will ask the types of design questions that -users will ask (and nudge the API toward raising fewer of those questions in -the first place). - -### What is precedent? - -In general, we want Google APIs to be as consistent as possible. Once customers -learn their first Google API, it should be easier to learn the second (and then -the third, and so on) because we are using the same patterns consistently. - -We refer to **precedent** to mean decisions that have already been made by -previous APIs, which generally should be binding upon newer APIs in similar -situations. The most common example of this is naming: we have a list of -[standard fields][] that dictate how we use common terms like `name`, -`create_time`, and so forth, and which also dictates that we always attach _the -same_ name to the same concept. - -Precedent also applies to _patterns_. All APIs should implement pagination the -same way. Ditto for long-running operations, import and export, and so on. Once -a pattern has been established, we seek to implement that pattern the same way -wherever it is germane. - -## What should I do? - -### ...if I have a launch on a tight deadline? - -The best thing that you can do is to engage design review as early as possible. -Additionally, make your reviewers aware of your timeline so that they are -aware, and can endeavor to provide you the best possible service. We _want_ you -to make your deadline if at all possible. - -For time-sensitive _alpha_ launches, an API **may** launch without receiving -design review approval. Such launches **must** be limited to a known set of -users. In this case, the reviewers will provide notes for the API team to take -under consideration for subsequent stages. - -**Warning:** Launching an API in alpha with an incomplete design review **does -not** enshrine that API's decisions. Design review will be required to promote -the API to beta, and API reviewers will block your beta launch if there are -issues. - -For launch stages after alpha, the API design review is mandatory due to its -impact on user experience across the board. Your team's inconsistencies affect -more than just your team. - -In some cases, there is a difficult choice to be made between product -excellence and either engineering effort or deadlines. These are difficult -business decisions and we understand that they are sometimes necessary; -however, a director or VP must make an explicit choice to put these other -concerns ahead of product excellence when choosing to bypass design review or -disregard reviewers' feedback. - -### ...to make my review go faster? - -A few tips: - -- Begin API review as early as possible, and follow up frequently. -- Run the [API linter][] beforehand. (If you are disabling the linter at any - point, explain why. Reviewers often find that the linter is disabled because - it did its job.) -- Ensure that every message, RPC, and field is _usefully_ commented. Comments - should be in valid American English and say something meaningful. -- If your API reviewer asks you to explain something, add the explanation _in - the proto comments_, rather than the code review conversation. This will very - often save you a round trip. - -### ...if one of my API reviewers is unresponsive? - -Reach out to the reviewer on Chat. If that fails, reach out to the other -reviewer, who will coordinate accordingly. If that fails also, escalate -according to [AIP-1][]. - -### ...if I have a design question? - -The first places to look at the [API style guide][], the [AIP index][], and -other public APIs within Google. Other public APIs are particularly valuable; -it is common that someone has encountered a situation that is germane to your -question. - -### ...if I have a question not covered there? - -Reach out to api-design@google.com with your question. - -This generally works best when you are seeking guidance on a specific question -related to API design, and when you clearly explain your use case and provide -examples. - -**Note:** The membership of this list comprises almost exclusively volunteers, -who spend the majority of their time doing something else. We do our best to be -responsive, but please be patient with us. - -### ...if a question is complex and languishing in a CL? - -While the code review interface is the best way to resolve questions when -practical, sometimes there are issues that are sufficiently complicated that -working them out in the code review tool is not feasible. In this situation, -reach out to your reviewers and ask to schedule a meeting. In general, most -issues can be discussed in 30 minutes. - -When this happens, make sure that someone documents what is discussed in the -CL, so that the history is preserved. - -### ...if my API needs to violate a standard? - -Clearly document (using an internal comment in the proto) that you are -violating an API design guideline and your rationale for doing so. This comment -**must** be prefixed with `aip.dev/not-precedent`. - -In general, your rationale for the design guideline violation **should** be in -accordance with one of the enumerated reasons listed in [AIP-200][]. If it is -not, work together with your API reviewer to determine the right thing to do. - -### ...if a reviewer is bringing up a previously-settled issue? - -If you have a different reviewer from your API's previous stages, this might -happen. In general, the best approach is simply to reference the code review -where the issue was decided. Reviewers want to avoid causing you churn, and -therefore usually give deference to previous reviews. This is usually -sufficient to resolve the question promptly. - -Occasionally, the reviewer may believe that the previous reviewer made a -significant mistake, and that correcting it is important. In this case, you and -your reviewer should work together to determine the best course of action. - -### ...if the team and the reviewers strongly disagree? - -Escalate according to [AIP-1][]. - -## Does my PA or team have any particular guidelines? - -The Cloud PA has specific guidelines to ensure additional uniformity across -Cloud, and Cloud APIs have their own reviewer pool. Other teams may adopt -similar (but not necessarily identical) rules and systems. Some teams that -produce multiple APIs (for example, machine learning) may also have guidelines -that apply to that group of APIs. - -In all cases, we endeavor to make these guidelines available as AIPs; the -higher AIP numbers are reserved for specific PA and team use (see [AIP-2][]), -and these AIPs are listed in the [AIP index][]. - -[aip-1]: ./0001.md -[aip-2]: ./0002.md -[aip-200]: ./0200.md -[aip index]: / -[api linter]: https://github.com/googleapis/api-linter -[api style guide]: https://cloud.google.com/apis/design/ -[standard fields]: https://cloud.google.com/apis/design/standard_fields diff --git a/aip/general/0111.md b/aip/general/0111.md deleted file mode 100644 index 6494ba6c17..0000000000 --- a/aip/general/0111.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -id: 111 -state: approved -created: 2023-06-17 -placement: - category: api-concepts - order: 50 ---- - -# Planes - -Resources and methods on an API can be divided into the *plane* that they reside -or perform operations upon. For the context of APIs, the following planes are -defined: - -- Management plane: a uniform, resource-oriented API that primarily - configures and allows retrieval of resources. -- Data plane: a heterogenous API (ideally resource-oriented) that reads and - write user data. Often connects to entities provisioned by the management - plane, such as virtual machines. - -The term "plane" was originally used in networking architecture. Although system -and network architecture often defines additional planes (e.g. control plane or -power planes), as the AIPs are focused on the interface, they are not defined in -this AIP. - -## Guidance - -### Management Plane - -Management resources and methods exist primarily to provision, configure, and -audit the resources that the data plane interfaces with. - -As an example, the following are considered management resources for a cloud -provider: - -- virtual machines -- virtual private networks -- virtual disks -- a blob store instance -- a project or account - -### Data Plane - -Methods on the data plane operate on user data in a variety of data formats, and -generally interface with a resource provisioned via a management plane API. -Examples of data plane methods include: - -- writing and reading rows in a table -- pushing to or pulling from a message queue -- uploading blobs to or downloading blobs from a blob store instance - -Data plane APIs **may** be heterogenous across a larger API surface, due to -requirements including high throughput, low latency, or the need to adhere to an -existing interface specification (e.g. ANSI SQL). - -- For convenience, resources and methods that operate on the data plane **may** -expose themselves via resource-oriented management APIs. If so, those resources -and methods **must** adhere to the requirements of the management plane as -specified in the other AIPs ([AIP-131][] through [AIP-135][]). - -### Major distinctions between management and data plane - -- [Declarative clients][] operate on the management plane exclusively. -- Data planes are often on the critical path of user-facing functionality, and - therefore: - - Have higher availability requirements than management planes. - - Are more performance-sensitive than management planes. - - Require higher-throughput than management planes. - - -[AIP-131]: ./0131.md -[AIP-135]: ./0135.md -[Declarative clients]: ./0009.md#declarative-clients - -## Changelog - -- **2023-06-10**: Introduction of this AIP. diff --git a/aip/general/0121.md b/aip/general/0121.md deleted file mode 100644 index f36ff7e182..0000000000 --- a/aip/general/0121.md +++ /dev/null @@ -1,193 +0,0 @@ ---- -id: 121 -state: approved -created: 2019-01-26 -placement: - category: resource-design - order: 10 ---- - -# Resource-oriented design - -Resource-oriented design is a pattern for specifying [RPC][] APIs, based on -several high-level design principles (most of which are common to recent public -HTTP APIs): - -- The fundamental building blocks of an API are individually-named _resources_ - (nouns) and the relationships and hierarchy that exist between them. -- A small number of standard _methods_ (verbs) provide the semantics for most - common operations. However, custom methods are available in situations where - the standard methods do not fit. -- Stateless protocol: Each interaction between the client and the server is - independent, and both the client and server have clear roles. - -Readers might notice similarities between these principles and some principles -of [REST][]; resource-oriented design borrows many principles from REST, while -also defining its own patterns where appropriate. - -## Guidance - -When designing an API, consider the following (roughly in logical order): - -- The resources (nouns) the API will provide -- The relationships and hierarchies between those resources -- The schema of each resource -- The methods (verbs) each resource provides, relying as much as possible on - the standard verbs. - -### Resources - -A resource-oriented API **should** generally be modeled as a resource -hierarchy, where each node is either a simple resource or a collection of -resources. - -A _collection_ contains resources of _the same type_. For example, a publisher -has the collection of books that it publishes. A resource usually has fields, -and resources may have any number of sub-resources (usually collections). - -**Note:** While there is some conceptual alignment between storage systems and -APIs, a service with a resource-oriented API is not necessarily a database, and -has enormous flexibility in how it interprets resources and methods. API -designers **should not** expect that their API will be reflective of their -database schema. In fact, having an API that is identical to the underlying -database schema is actually an anti-pattern, as it tightly couples the surface -to the underlying system. - -### Methods - -Resource-oriented APIs emphasize resources (data model) over the methods -performed on those resources (functionality). A typical resource-oriented API -exposes a large number of resources with a small number of methods on each -resource. The methods can be either the standard methods ([Get][], [List][], -[Create][], [Update][], [Delete][]), or [custom methods][]. - -If the request to or the response from a standard method (or a custom method in -the same *service*) **is** the resource or **contains** the resource, the -resource schema for that resource across all methods **must** be the same. - -| Standard method | Request | Response | -| --------------- | --------------------- | ---------------------- | -| Create | Contains the resource | Is the resource | -| Get | None | Is the resource | -| Update | Contains the resource | Is the resource | -| Delete | None | None | -| List | None | Contains the resources | - -*The table above describes each standard method's relationship to the resource, -where "None" indicates that the resource neither **is** nor **is contained** in -the request or the response* - -A resource **must** support at minimum [Get][]: clients must be -able to validate the state of resources after performing a mutation such -as [Create][], [Update][], or [Delete][]. - -A resource **must** also support [List][], except for [singleton resources][] -where more than one resource is not possible. - -**Note:** A custom method in resource-oriented design does _not_ entail -defining a new or custom HTTP verb. Custom methods use traditional HTTP verbs -(usually `POST`) and define the custom verb in the URI. - -APIs **should** prefer standard methods over custom methods; the purpose of -custom methods is to define functionality that does not cleanly map to any of -the standard methods. Custom methods offer the same design freedom as -traditional RPC APIs, which can be used to implement common programming -patterns, such as database transactions, import and export, or data analysis. - -### Strong Consistency - -For methods that operate on the [management plane][], the completion of those -operations (either successful or with an error, long-running operation, or -synchronous) **must** mean that the state of the resource's existence and all -user-settable values have reached a steady-state. - -[Output only][] values unrelated to the resource [state][] **should** also have -reached a steady-state for values that are related to the resource [state][]. - -Examples include: - -- Following a successful create that is the latest mutation on a resource, a get - request for a resource **must** return the resource. -- Following a successful update that is the latest mutation on a resource, a get - request for a resource **must** return the final values from the update - request. -- Following a successful delete that is the latest mutation on a resource, a get - request for a resource **must** return `NOT_FOUND` (or the resource with the - `DELETED` state value in the case of [soft delete][]) - -Clients of resource-oriented APIs often need to orchestrate multiple operations -in sequence (e.g. create resource A, create resource B which depends on A), and -ensuring that resources immediately reflect steady user state after an operation -is complete ensures clients can rely on method completion as a signal to begin -the next operation. - -[Output only][] fields ideally would follow the same guidelines, but as -these fields can often represent a resource's live state, it's sometimes -necessary for these values to change after a successful mutation operation to -reflect a state change. - -### Stateless protocol - -As with most public APIs available today, resource-oriented APIs **must** -operate over a [stateless protocol][]: The fundamental behavior of any -individual request is independent of other requests made by the caller. -This is to say, each request happens in isolation of other requests made by that -client or another, and resources exposed by an API are directly addressable -without needing to apply a series of specific requests to "reach" the desired -resource. - -In an API with a stateless protocol, the server has the responsibility for -persisting data, which may be shared between multiple clients, while clients -have sole responsibility and authority for maintaining the application state. - -### Cyclic References - -The relationship between resources, such as with [resource references][], -**must** be representable via a [directed acyclic graph][]. The parent-child -relationship also **must** be acyclic, and as per [AIP-124][] a given resource -instance will only have one canonical parent resource. - -A cyclic relationship between resources increases the complexity of managing -resources. Consider resources A and B that refer to -each other. The process to create said resources are: - -1. create resource A without a reference to B. Retrieve id for resource A. -2. create resource B with a reference to A. Retrieve id for resource B. -3. update resource A with the reference to B. - -The delete operation may also become more complex, due to reasoning about which -resource must be dereferenced first for a successful deletion. - -This requirement does not apply to relationships that are expressed via -[output only][] fields, as they do not require the user to specify the values -and in turn do not increase resource management complexity. - -[AIP-124]: ./0124.md -[create]: ./0133.md -[custom methods]: ./0136.md -[delete]: ./0135.md -[directed acyclic graph]: https://en.wikipedia.org/wiki/Directed_acyclic_graph -[get]: ./0131.md -[list]: ./0132.md -[management plane]: ./0111.md#management-plane -[output only]: ./0203.md#output-only -[rest]: https://en.wikipedia.org/wiki/Representational_state_transfer -[resource references]: ./0122.md#fields-representing-another-resource -[rpc]: https://en.wikipedia.org/wiki/Remote_procedure_call -[singleton resources]: ./0156.md -[soft delete]: ./0164.md -[state]: ./0216.md -[stateless protocol]: https://en.wikipedia.org/wiki/Stateless_protocol -[update]: ./0134.md - - -## Changelog - -- **2024-07-08**: Clarify acyclic nature of parent-child relationship. -- **2023-08-24**: Added guidance on consistency guarantees of methods. -- **2023-07-23**: Clarify stateless protocol definition. -- **2023-01-21**: Explicitly require matching schema across standard methods. -- **2022-12-19**: Added a section requiring Get and List. -- **2022-11-02**: Added a section restricting resource references. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0122.md b/aip/general/0122.md deleted file mode 100644 index 06e7e0e590..0000000000 --- a/aip/general/0122.md +++ /dev/null @@ -1,441 +0,0 @@ ---- -id: 122 -state: approved -created: 2019-01-26 -placement: - category: resource-design - order: 20 ---- - -# Resource names - -Most APIs expose _resources_ (their primary nouns) which users are able to -create, retrieve, and manipulate. Additionally, resources are _named_: each -resource has a unique identifier that users use to reference that resource, and -these names are what users should _store_ as the canonical names for the -resources. - -## Guidance - -All resource names defined by an API **must** be unique within that API. (See -the section on [full resource names](#full-resource-names) below for more -information on referring to resources across APIs.) - -Resource names are formatted according to the [URI path schema][], but without -the leading slash: - - publishers/123/books/les-miserables - users/vhugo1802 - -- Resource name components **should** usually alternate between collection - identifiers (example: `publishers`, `books`, `users`) and resource IDs - (example: `123`, `les-miserables`, `vhugo1802`). -- Resource names **must** use the `/` character to separate individual segments - of the resource name. - - Non-terminal segments of a resource name **must not** contain a `/` - character. - - The terminal segment of a resource name **should not** contain a `/` - character. -- Resource names **should** only use characters available in DNS names, as - defined by [RFC-1123](https://tools.ietf.org/html/rfc1123). - - Additionally, resource IDs **should not** use upper-case letters. - - If additional characters are necessary, resource names **should not** use - characters that require URL-escaping, or characters outside of ASCII. - - If Unicode characters can not be avoided, resource names **must** be stored - in Normalization Form C (see [AIP-210][]). -- Resources **must** expose a `name` field that contains its resource name. - - Resources **may** provide the resource ID as a separate field (e.g. - `book_id`). This field **must** apply the - [`OUTPUT_ONLY`](./0203.md#output-only) field behavior classification. - - Resources **may** expose a separate, system-generated unique ID field - [(`uid`)](./0148.md#uid). This field **must** apply the - [`OUTPUT_ONLY`](./0203.md#output-only) field behavior classification. - - Resources **must not** expose tuples, self-links, or other forms of - resource identification. - - All ID fields **should** be strings. - -**Note:** Resource names as described here are used within the scope of a -single API (or else in situations where the owning API is clear from the -context), and are only required to be unique within that scope. For this -reason, they are sometimes called _relative resource names_ to distinguish them -from _full resource names_ (discussed below). - -[aip-210]: ./0210.md -[uri path schema]: https://datatracker.ietf.org/doc/html/rfc3986#appendix-A - -### Collection identifiers - -The collection identifier segments in a resource name **must** be the plural -form of the noun used for the resource. (For example, a collection of -`Publisher` resources is called `publishers` in the resource name.) - -- Collection identifiers **must** be concise American English terms. -- Collection identifiers **must** be in `camelCase`. -- Collection identifiers **must** begin with a lower-cased letter and contain - only ASCII letters and numbers (`/[a-z][a-zA-Z0-9]*/`). -- Collection identifiers **must** be plural. - - In situations where there is no plural word ("info"), or where the singular - and plural terms are the same ("moose"), the non-pluralized (singular) form - is correct. Collection segments **must not** "coin" words by adding "s" in - such cases (e.g, avoid "infos"). -- Within any given single resource name, collection identifiers **must** be - unique. (e.g. `people/xyz/people/abc` is invalid) - - -#### Nested collections - -If a resource name contains multiple levels of a hierarchy, and a parent -collection's name is used as a prefix for the child resource's name, the child -collection's name **may** omit the prefix. For example, given a collection of -`UserEvent` resources that would normally be nested underneath `users`: - -``` -users/vhugo1802/userEvents/birthday-dinner-226 -``` - -An API **should** use the less-redundant form: - -``` -users/vhugo1802/events/birthday-dinner-226 -``` - -In this situation, the _message_ and _resource type_ are still called -`UserEvent`; only the collection and resource identifiers in the pattern(s) are -shortened. Since the _resource type_ is not shortened, the `singular` and -`plural` are similarly _not shortened_. - -``` -message UserEvent { - option (google.api.resource) = { - type: "example.googleapis.com/UserEvent" - // Only the collection & resource identfiers in the `pattern` are shortened. - pattern: "projects/{project}/users/{user}/events/{event}" - singular: "userEvent" - plural: "userEvents" - }; - - string name = 1; -} -``` - -**Note:** APIs wishing to do this **must** follow this format consistently -throughout all of its `pattern` entries defined and anywhere else the -resource is referenced in the API, or else not at all. - -### Resource ID segments - -A resource ID segment identifies the resource within its parent collection. In -the resource name `publishers/123/books/les-miserables`, `123` is the resource -ID for the publisher, and `les-miserables` is the resource ID for the book. - -- If resource IDs are user-specified, the API **must** document allowed - formats. User-specified resource IDs **should** conform to [RFC-1034][]; - which restricts to letters, numbers, and hyphen, with the first character - a letter, the last a letter or a number, and a 63 character maximum. - - Additionally, user-specified resource IDs **should** restrict letters to - lower-case (`^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$`). - - Characters outside of ASCII **should not** be permitted; however, if - Unicode characters are necessary, APIs **must** follow guidance in - [AIP-210][]. -- If resource IDs are not user-settable, the API **should** document the - basic format, and any upper boundaries (for example, "at most 63 - characters"). -- For more information, see the [create][] standard method. - -[create]: ./0133.md#user-specified-ids -[rfc-1034]: https://tools.ietf.org/html/rfc1034 - -### Resource ID aliases - -It is sometimes valuable to provide an alias for common lookup patterns for -resource IDs. For example, an API with `users` at the top of its resource -hierarchy may wish to provide `users/me` as a shortcut for retrieving -information for the authenticated user. - -APIs **may** provide programmatic aliases for common lookup patterns. However, -all data returned from the API **must** use the canonical resource name. - -### Full resource names - -In most cases, resource names are used within a single API only, or else they -are used in contexts where the owning API is clear (for example, -`string pubsub_topic`). - -However, sometimes it is necessary for services to refer to resources in an -arbitrary API. In this situation, the service **should** use the _full resource -name_, a schemeless URI with the owning [API's service name](./0009.md#api-service-name), -followed by the relative resource name: - -``` -//library.googleapis.com/publishers/123/books/les-miserables -//calendar.googleapis.com/users/vhugo1802 -``` - -**Note:** The full resource name **should not** be used for cross-API -references where the owning API is clear; it is only used if a field refers to -resources in multiple APIs where ambiguity is possible. - -### Resource URIs - -The full resource name is a schemeless URI, but slightly distinct from the full -URIs we use to access a resource. The latter includes the protocol -(HTTPS), the API version, and the specific [service endpoint](./0009.md#api-service-endpoint) -to target: - -``` -https://library.googleapis.com/v1/publishers/123/books/les-miserables -https://calendar.googleapis.com/v3/users/vhugo1802 -``` - -The version is not included in the full resource name because the full resource -name is expected to persist from version to version. Even though the API -surface may change between major versions, multiple major versions of the same -API are expected to use the same underlying data. - -**Note:** The correlation between the full resource name and the service's -endpoint is by convention. In particular, one service is able to have multiple -endpoints (example use cases include regionalization, MTLS, and private access), -and the full resource name does not change between these. - -### Fields representing resource names - -When defining a resource, the first field **should** be the resource name, -which **must** be of type `string` and **must** be called `name` for the -resource name. The message **should** include a `google.api.resource` -annotation declaring the type (see [AIP-123][] for more on this). - -```proto -// A representation of a book in the library. -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - // The resource name of the book. - // Format: publishers/{publisher}/books/{book} - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // Other fields... -} -``` - -When defining a method that retrieves or acts on an already-existing resource -(such as `GetBook` or `ArchiveBook`), the first field of the request message -**should** be the resource name, which **must** be of type `string` and -**must** be called `name` for the resource name. The field **should** also be -annotated with the `google.api.resource_reference` annotation, referencing the -resource type ([AIP-123][]). - -```proto -// Request message for ArchiveBook -message ArchiveBookRequest { - // The book to archive. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; - - // Other fields... -} -``` - -**Note:** Fields **must not** be called `name` except for this purpose. For -other use cases, either use a different term or prepend an adjective (for -example: `display_name`). - -[aip-123]: ./0123.md - -### Fields representing a resource's parent - -When defining a method that retrieves resources from a collection or adds a new -resource to a collection (such as `ListBooks` or `CreateBook`), the first field -of the request message **should** be of type `string` and **should** be called -`parent` for the resource name of the collection. The `parent` field **should** -also be annotated with the `google.api.resource_reference` annotation, -referencing the parent's resource type ([AIP-123][]). - -```proto -// Request message for ListBooks. -message ListBooksRequest { - // The publisher to list books from. - // Format: publishers/{publisher_id} - string parent = 1 [(google.api.resource_reference) = { - type: "library.googleapis.com/Publisher" - }]; - - // Other fields (e.g. page_size, page_token, filter, etc.)... -} -``` - -If there is more than one possible parent type, the `parent` field **should** -be annotated with the `child_type` key on `google.api.resource_reference` -instead: - -```proto -// Request message for ListBooks. -message ListBooksRequest { - // The parent to list books from. - // Format: - // - publishers/{publisher_id} - // - authors/{author_id} - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // Other fields (e.g. page_size, page_token, filter, etc.)... -} -``` - -**Note:** Fields **should not** be called `parent` except for this purpose. For -other use cases, use a synonymous term if possible. - -### Fields representing another resource - -When a field represents another resource, the field **should** be of type -`string` and accept the resource name of the other resource. The field name -**should** be equivalent to the corresponding message's name in snake case. - -- Field names **may** include a leading adjective if appropriate (such as - `string dusty_book`). -- Field names **should not** use the `_name` suffix unless the field would be - ambiguous without it (e.g., `crypto_key_name`) -- Fields representing another resource **should** provide the - `google.api.resource_reference` annotation with the resource type being - referenced. -- If using the resource name is not possible and using the ID component alone is -strictly necessary, the field **should** use an `_id` suffix (e.g. `shelf_id`). - -The field **should not** be of type `message` using the `message` that -implements the resource, __except__ for one of following conditions: - -- The API is internal-only, has tight lifecycle relationships, and has a - permission model that enables inherited access to embedded resources. -- The embedding of the resource is done as part of the AIP-162 revisions - pattern. - -Example of a resource reference: - -```proto -// A representation of a book in a library. -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - // Name of the book. - // Format is `publishers/{publisher}/books/{book}` - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The shelf where the book currently sits. - // Format is `shelves/{shelf}`. - string shelf = 2 [(google.api.resource_reference) = { - type: "library.googleapis.com/Shelf" - }]; - - // Other fields... -} -``` - -## Further reading - -- For evolving resource names over time, see - [AIP-180](./0180.md#changing-resource-names). -- For resource types, see [AIP-123][]. - -## Rationale - -### Using names instead of IDs - -For any large system, there are many kinds of resources. To use simple resource -IDs to identify a resource, we'd actually need use a resource-specific tuple to -reliably identify it, such as `(bucket, object)` or `(user, album, photo)`. This -creates several issues: - -* Developers have to understand and remember such anonymous tuples. -* Passing tuples is generally harder than passing strings. -* Centralized infrastructures, such as logging and access control systems, - don't understand specialized tuples. -* Specialized tuples limit API design flexibility, such as providing - reusable API interfaces. For example, - [Long Running Operations][aip-151] can work with many other API interfaces - because they use flexible resource names. - -[aip-151]: ./0151.md - -### Standardizing on `name` - -The concept of resource names is not a new one, and is formalized in Uniform -Resource Names (URN) in conjunction with Uniform Resource Identifiers (URI) and -Uniform Resource Locators (URL). Considering that the term "name" is so heavily -overloaded in general, usage outside of a very well-defined meaning would be -confusing for developers. So, the field name `name` is reserved in the context -of AIP-compliant APIs so as to eliminate any confusion with resource names, and -force other would be "name" fields to use a more specific field name. - -### Disallow embedding of resources - -Using a resource message directly as the type of a field within another resource -is problematic for a number of reasons, which are as follows: - -* Complicates the resource lifecycle: If the dependency resource is - deleted, what happens to the embedded reference in the dependent resource? - Data retention and clean up operations will be significantly complicated. -* Bypasses permissions: If every resource has its own set of permissions, a user - with read permission on the dependent resource that doesn't have the same - permission on the dependency resource suddenly cannot see the full resource. -* Tightly couples resources in all aspects: Changing the requirements in the - schema, permissions, or otherwise for either resource impacts the other, - significantly increasing complexity of roll outs. - -Referencing by name, as is recommended, eliminates all of this complexity by -preventing resource data duplication, and forcing the owning service to be -involved in the resolution of the reference (via Standard Methods), guaranteeing -isolation of logical concerns per-resource. - -## History - -### Disallowing UUIDs in user-specified IDs - -As part of an effort to make APIs more declarative-friendly, APIs were required -to allow user-specified resource ID on creation. As part of this, a supporting -field `string uid` containing a UUID was also encouraged. Guidance was then -added to discourage the _user-specified resource ID_ from being a UUID or -even resembling one. - -Ostensibly, the fact that `uid` contained a service-generated UUID motivated -this restriction on the user-specified resource ID, forcing the user-specified -resource ID to be a more "meaningful" value. However, we no longer saw value in -this requirement, hence its removal. - -## Changelog - -- **2025-03-10**: Drop guidance disallowing UUID in user-specified ID. -- **2024-10-15**: Add some rationale we found for use of `name` as a field and - instead of IDs as an identifier. -- **2024-06-14**: Clarify resource annotation shortening rules for nested - collections. -- **2023-09-19**: Prohibit duplicate collection identifiers. -- **2023-09-01**: Add a clause that allows embedding for revision resource - messages. -- **2023-08-10**: Explicitly disallow embedding resource messages in a resource. -- **2023-03-24**: Correction: full resource name contains the service name rather - than the service endpoint -- **2023-03-17**: Add `OUTPUT_ONLY` guidance for resource ID fields. -- **2020-10-06**: Added declarative-friendly guidance, and tightened character - set restrictions. -- **2020-10-05**: Clarified when full resource names are used. -- **2020-05-19**: Clarified that resource _IDs_ avoid capital characters, not - the entire resource _name_. -- **2020-04-27**: Tighten the restriction on valid characters. -- **2019-12-05**: Added guidance for resource annotations. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. Also changed the final - example from a Pub/Sub example to the usual Book example. -- **2019-07-30**: Changed the nested collection brevity suggestion from "may" - to "should" diff --git a/aip/general/0123.md b/aip/general/0123.md deleted file mode 100644 index 448dd5e19a..0000000000 --- a/aip/general/0123.md +++ /dev/null @@ -1,144 +0,0 @@ ---- -id: 123 -state: approved -created: 2019-05-12 -placement: - category: resource-design - order: 30 ---- - -# Resource types - -Most APIs expose _resources_ (their primary nouns) which users are able to -create, retrieve, and manipulate. APIs are allowed to name their resource types -reasonably freely (within the requirements of this AIP), and are only required -to ensure uniqueness within that API. This means that it is possible (and often -desirable) for different APIs to use the same type name. For example, a Memcache -and Redis API would both want to use `Instance` as a type name. - -When mapping the relationships between APIs and their resources, however, it -becomes important to have a single, globally-unique type name. Additionally, -tools such as Kubernetes or GraphQL interact with APIs from multiple providers. - -## Terminology - -In the guidance below, we use the following terms: - -- **Service Name:** This is the name defined in the [service configuration][]. - This usually (but not necessarily) matches the hostname that users use to - call the service. Example: `pubsub.googleapis.com`. This is equivalent to an - [API Group][] in Kubernetes. -- **Type:** This is the name used for the type within the API e.g. the name of - the Protobuf `message`. This is equivalent to an [Object][] in Kubernetes. - -## Guidance - -APIs **must** define a resource type for each resource in the API, according to -the following pattern: `{Service Name}/{Type}`. The type name **must**: - -- Match the containing API type's name. -- Start with an uppercase letter. -- Only contain alphanumeric characters. -- Be of the singular form of the noun. -- Use PascalCase (UpperCamelCase). - -### Examples - -Examples of resource types include: - -- `pubsub.googleapis.com/Topic` -- `pubsub.googleapis.com/Subscription` -- `spanner.googleapis.com/Database` -- `spanner.googleapis.com/Instance` -- `networking.istio.io/Instance` - -### Annotating resource types - -APIs **should** annotate the resource types for each resource in the API using -the [`google.api.resource`][resource] annotation: - -```proto -// A representation of a Pub/Sub topic. -message Topic { - option (google.api.resource) = { - type: "pubsub.googleapis.com/Topic" - pattern: "projects/{project}/topics/{topic}" - singular: "topic" - plural: "topics" - }; - - // Name and other fields... -} -``` - -- Patterns **must** correspond to the [resource name][aip-122]. -- Pattern variables (the segments within braces) **must** use `snake_case`, and - **must not** use an `_id` suffix. -- Pattern variables **must** conform to the format `[a-z][_a-z0-9]*[a-z0-9]`. -- Pattern variables **must** be unique within any given pattern. (e.g. - `projects/{abc}/topics/{abc}` is invalid; this is usually a natural - corollary of collection identifiers being unique within a pattern.) -- Resources with [multiple patterns][multi-pattern-resources] **must** - preserve ordering: new patterns **must** be added at the end of the list, and - existing patterns **must not** be removed or re-ordered, as this breaks client - library backward compatibility. -- Singular **must** be the lower camel case of the type. - - Pattern variables **must** be the singular form of the resource type e.g. - a pattern variable representing a `Topic` resource ID is named `{topic}`. -- Plural **must** be the lower camel case plural of the singular. - - Pattern collection identifier segments **must** match the plural of the - resources, except in the case of [nested collections][]. - -#### Pattern uniqueness - -When multiple patterns are defined within a resource, these patterns **must** -be mutually unique, where uniqueness is defined as being by-character identical -once all resource ID path segments have been removed, leaving all `/` -separators. - -Therefore the following two patterns **must not** be defined within the same -resource: - -- `user/{user}` -- `user/{user_part_1}~{user_part_2}` - -## Rationale - -### Type and message name alignment - -In addition to simple schema-resource coherence and alignment, a number of -consumers benefit from the `{Type}` and `message` names matching. Consumers have -simpler lookups, client libraries get the same in addition to aligned user -experience where resource-oriented code has naming aligned with the generated -`message` code, generated reference documentation aligns resources with -`message` docs, etc. - -### Singular and Plural - -Well-defined singular and plurals of a resource enable clients to determine the -proper name to use in code and documentation. - -lowerCamelCase can be translated into other common forms of a resource name -such as UpperCamelCase and snake_case. - - -[aip-122]: ./0122.md -[multi-pattern-resources]: https://google.aip.dev/client-libraries/4231#multi-pattern-resources -[API Group]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups -[nested collections]: ./0122.md#collection-identifiers -[Object]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds -[resource]: https://github.com/googleapis/googleapis/blob/master/google/api/resource.proto -[service configuration]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto - - -## Changelog - -- **2025-01-09**: Strongly align resource type and message naming. -- **2024-08-07**: Added multi-pattern ordering compatibility requirements. -- **2023-09-19**: Prohibited duplicate pattern variables. -- **2023-05-06**: Added requirement of singular and plural. -- **2023-01-28**: Clarified guidance for the resource type name. -- **2022-10-28**: Added pattern variable format guidance. -- **2020-05-14**: Added pattern uniqueness. -- **2019-12-05**: Added guidance on patterns. -- **2019-07-17**: Fleshed out the annotation example somewhat. diff --git a/aip/general/0124.md b/aip/general/0124.md deleted file mode 100644 index 75757e5cb7..0000000000 --- a/aip/general/0124.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -id: 124 -state: approved -created: 2020-03-20 -placement: - category: resource-design - order: 40 ---- - -# Resource association - -APIs sometimes have resource hierarchies that can not be cleanly expressed in -the usual tree structure. For example, a resource may have a many-to-one -relationship with two other resource types instead of just one. Alternatively, -a resource may have a many-to-many relationship with another resource type. - -## Guidance - -A resource **must** have at most one canonical parent, and `List` requests -**must not** require two distinct "parents" to work. - -### Multiple many-to-one associations - -If a resource has a many-to-one relationship with multiple resource types, it -**must** choose at most one of them to be the canonical parent. The resource -**may** be associated with other resources through other fields on the -resource. - -```proto -message Book { - // The resource name pattern for Book indicates that Publisher is the - // canonical parent. - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - // The resource name for the book. - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The resource name for the book's author. - string author = 2 [(google.api.resource_reference) = { - type: "library.googleapis.com/Author" - }]; -} -``` - -When listing resources with multiple associations in this way, the RPC **must** -treat the `string parent` field as required as discussed in [AIP-132][], and -**must not** add additional required arguments. The RPC **should** include a -`string filter` field that allows users to filter by other resource -associations as discussed in [AIP-160][]. - -**Note:** Resource reference fields **must** accept the same resource name -format that is used in the `name` field of the referenced resource. - -### Many-to-many associations - -Many-to-many associations are less common in APIs than they are in relational -databases, in part because they are more difficult to model and present over -network interfaces. - -An API **may** contain many-to-many relationships, and **should** use a -repeated field containing a list of resource names, following the principles -described for repeated fields in [AIP-144][]. - -```proto -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The resource names for the book's authors. - repeated string authors = 2 [(google.api.resource_reference) = { - type: "library.googleapis.com/Author" - }]; -} -``` - -**Note:** See [AIP-144][] for more information on repeated fields, including -how to handle common issues such as atomic changes. - -If the use of a repeated field is too restrictive, or if more metadata is -required along with the association, an API **may** model a many-to-many -relationship using a sub-resource with two one-to-many associations. - -```proto -message BookAuthor { - // The resource pattern for BookAuthor indicates that Book is the - // canonical parent. - option (google.api.resource) = { - type: "library.googleapis.com/BookAuthor" - pattern: "publishers/{publisher}/books/{book}/authors/{book_author}" - }; - - // The resource name for the book-author association. - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The resource name for the author. - string author = 2 [(google.api.resource_reference) = { - type: "library.googleapis.com/Author" - }]; - - // Other fields... -} -``` - -**Note:** Using subresources to model an association between resources is only -recommended if additional metadata is required in the relationship, or if the -restrictions around the use of a repeated field preclude the use of that -approach. - -[aip-132]: ./0132.md -[aip-144]: ./0144.md -[aip-160]: ./0160.md - -## Changelog - -- **2021-04-07**: Clarified that resource reference fields accept resource - names with the same format as the `name` field of the resource. diff --git a/aip/general/0126.md b/aip/general/0126.md deleted file mode 100644 index 85f10cda29..0000000000 --- a/aip/general/0126.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: 126 -state: approved -created: 2019-07-24 -placement: - category: resource-design - order: 60 ---- - -# Enumerations - -It is common for a field to only accept or provide a discrete and limited set -of values. In these cases, it can be useful to use enumerations (generally -abbreviated "enums") in order to clearly communicate what the set of allowed -values are. - -## Guidance - -APIs **may** expose enum objects for sets of values that are expected to change -infrequently: - -```proto -// A representation of a book. -message Book { - // Other fields... - - // Possible formats in which the book may be published. - enum Format { - // Default value. This value is unused. - FORMAT_UNSPECIFIED = 0; - - // The printed format, in hardback. - HARDBACK = 1; - - // The printed format, in paperback. - PAPERBACK = 2; - - // An electronic book format. - EBOOK = 3; - - // An audio recording. - AUDIOBOOK = 4; - } - - // The format of the book. - Format format = 99; - - // Other fields... -} -``` - -- All enum values **must** use `UPPER_SNAKE_CASE`. -- The first value of the enum **should** be the name of the enum itself - followed by the suffix `_UNSPECIFIED`. - - An exception to this rule is if there is a clearly useful zero value. In - particular, if an enum needs to present an `UNKNOWN`, it is usually clearer - and more useful for it to be a zero value rather than having both. The - `UNKNOWN` value **may** be prefixed by the enum name as is typical for - avoiding enum value name collisions. -- Enums which will only be used in a single message **should** be nested within that message. - In this case, the enum **should** be declared immediately before it is used. - - The non-zero values of such a nested enum definition **should not** be prefixed by the name - of the enum itself. This generally requires users to write `MyState.MYSTATE_ACTIVE` in their - code, which is unnecessarily verbose. -- Enums which will be used by multiple messages **should** be defined at the package level and - **should** be defined at the bottom of the proto file (see [AIP-191][]). - - Some languages (including C++) hoist enum values into the parent namespace, which can result - in conflicts for enums with the same values in the same proto package. To avoid sharing values, - APIs **should** prefix package-level enum values with the name of the enum. -- Enums **should** document whether the enum is frozen or they expect to add - values in the future. - -### When to use enums - -Enums can be more accessible and readable than strings or booleans in many -cases, but they do add overhead when they change. Therefore, enums **should** -receive new values infrequently. While the definition of "infrequently" may -change based on individual use cases, a good rule of thumb is no more than once -a year. For enums that change frequently, the API **should** use a string and -document the format. - -Additionally, enums **should not** be used when there is a competing, -widely-adopted standard representation (such as with [language codes][bcp-47] -or [media types][]). - -**Note:** If an enumerated value needs to be shared across APIs, an enum -**may** be used, but the assignment between enum values and their corresponding -integers **must** match. - -### Alternatives - -For enumerated values where the set of allowed values changes frequently, APIs -**should** use a `string` field instead, and **must** document the allowed -values. String fields with enumerated values **should** use `kebab-case` for -their values. - -For enumerated values where there is a competing, widely-adopted standard -representation (generally, but not necessarily, a string), that standard -representation **should** be used. This is true even if only a small subset of -values are permitted, because using enums in this situation often leads to -frustrating lookup tables when trying to use multiple APIs together. - -Boolean fields **may** be used in situations where it is clear that no further -flexibility will be needed. The default value **must** be `false`. - -**Note:** When using protocol buffers, it is impossible to distinguish between -`false` and unset. If this is a requirement, an enum **may** be a better design -choice (although `google.protobuf.BoolValue` is also available). - -## Further reading - -- For states, a special type of enum, see [AIP-216][]. - -[aip-191]: ./0191.md -[aip-216]: ./0216.md -[bcp-47]: https://en.wikipedia.org/wiki/IETF_language_tag -[media types]: https://en.wikipedia.org/wiki/Media_type - -## Changelog - -- **2025-10-03**: Added prefixing guidance for `UNKNOWN` value exception. diff --git a/aip/general/0127.md b/aip/general/0127.md deleted file mode 100644 index 5a284b72c0..0000000000 --- a/aip/general/0127.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -id: 127 -state: approved -created: 2019-08-22 -placement: - category: protobuf - order: 10 ---- - -# HTTP and gRPC Transcoding - -APIs that follow [resource-oriented design][aip-121] are defined using -[RPCs][rpc], but the resource-oriented design framework allows them to also be -presented as APIs that largely follow REST/JSON conventions. This is important -in order to help developers use their existing knowledge: over 80% of the -public APIs available follow most REST conventions, and developers are -accustomed to that pattern. - -## Guidance - -APIs **must** provide HTTP definitions for each RPC that they define, except -for bi-directional streaming RPCs, which can not be natively supported using -HTTP/1.1. When providing a bi-directional streaming method, an API **should** -also offer an alternative method that does not rely on bi-directional -streaming. - -### HTTP method and path - -When using protocol buffers, each RPC **must** define the HTTP method and path -using the `google.api.http` annotation: - -```proto -rpc CreateBook(CreateBookRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books" - body: "book" - }; -} - -message CreateBookRequest { - // The publisher who will publish this book. - // When using HTTP/JSON, this field is automatically populated based - // on the URI, because of the `{parent=publishers/*}` syntax. - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The book to create. - // When using HTTP/JSON, this field is populated based on the HTTP body, - // because of the `body: "book"` syntax. - Book book = 2 [(google.api.field_behavior) = REQUIRED]; - - // The user-specified ID for the book. - // When using HTTP/JSON, this field is populated based on a query string - // argument, such as `?bookId=foo`. This is the fallback for fields that - // are not included in either the URI or the body. - // Note that clients use camelCase format to communicate the field names - // to the service. - string book_id = 3; -} -``` - -- The first key (`post` in this example) corresponds to the HTTP method. RPCs - **may** use `get`, `post`, `patch`, or `delete`. - - RPCs **must** use the prescribed HTTP verb for each standard method, as - discussed in [AIP-131][], [AIP-132][], [AIP-133][], [AIP-134][], and - [AIP-135][] - - RPCs **should** use the prescribed HTTP verb for custom methods, as - discussed in [AIP-136][]. - - RPCs **should not** use `put` or `custom`. -- The corresponding value represents the URI. - - URIs **must** use the `{foo=bar/*}` syntax to represent a variable that - should be populated in the request proto. When extracting a [resource - name][aip-122], the variable **must** include the entire resource name, not - just the ID component. - - URIs **may** use nested fields for their variable names. (Additionally, - AIP-134 mandates this for `Update` requests.) - - URIs **must** use the `*` character to represent ID components, which - matches all URI-safe characters except for `/`. URIs **may** use `**` as - the final segment of a URI if matching `/` is required. -- The `body` key defines which single top-level field in the request will be - sent as the HTTP body. If the body is `*`, then this indicates that the - request object itself is the HTTP body. The request body is encoded as JSON - as defined by protocol buffers' canonical [JSON encoding][]. - - RPCs **must not** define a `body` at all for RPCs that use the `GET` or - `DELETE` HTTP verbs. - - RPCs **must** use the prescribed `body` for Create ([AIP-133][]) and Update - ([AIP-134][]) requests. - - RPCs **should** use the prescribed `body` for custom methods ([AIP-136][]). - - The `body` **must not** contain a nested field (or use the `.` character), - - The `body` **must not** be the same as a URI parameter. - - The `body` **must not** be a `repeated` field. - - Fields **should not** use the `json_name` annotation to alter the field - name in JSON, unless doing so for backwards-compatibility reasons. - -**Note:** Bi-directional streaming RPCs should not include a `google.api.http` -annotation at all. If feasible, the service **should** provide non-streaming -equivalent RPCs. - -### Multiple URI bindings - -Occasionally, an RPC needs to correspond to more than one URI: - -```proto -rpc CreateBook(CreateBookRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books" - body: "book" - additional_bindings: { - post: "/v1/{parent=authors/*}/books" - body: "book" - } - additional_bindings: { - post: "/v1/books" - body: "book" - } - }; -} -``` - -- RPCs **may** define any number of additional bindings. The structure is - identical to the `google.api.http` annotation (in fact, it is a recursive - reference). -- RPCs **must not** define an additional binding within an additional binding. -- The `body` clause **must** be identical in the top-level annotation and each - additional binding. - -## Changelog - -- **2022-08-18**: Added the comment that query string parameter names are - in camelCase. -- **2021-01-06**: Added clarification around `body` and nested fields. -- **2019-09-23**: Added a statement about request body encoding, and guidance - discouraging `json_name`. - - -[aip-121]: ./0121.md -[aip-122]: ./0122.md -[aip-131]: ./0131.md -[aip-132]: ./0132.md -[aip-133]: ./0133.md -[aip-134]: ./0134.md -[aip-135]: ./0135.md -[aip-136]: ./0136.md -[json encoding]: https://developers.google.com/protocol-buffers/docs/proto3#json -[rpc]: https://en.wikipedia.org/wiki/Remote_procedure_call - diff --git a/aip/general/0128.md b/aip/general/0128.md deleted file mode 100644 index 14baa48724..0000000000 --- a/aip/general/0128.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -id: 128 -state: approved -created: 2020-10-06 -placement: - category: resource-design - order: 65 ---- - -# Declarative-friendly interfaces - -Many services need to interact with common DevOps tools, particularly those -that create and manage network-addressable resources (such as virtual machines, -load balancers, database instances, and so on). These tools revolve around the -principle of "configuration as code": the user specifies the complete intended -landscape, and tooling is responsible for making whatever changes are necessary -to achieve the user's specification. - -These tools are **declarative**: rather than specifying specific _actions_ to -take, they specify the desired _outcome_, with the actions being derived based -on the differences between the current landscape and the intended one. - -Furthermore, there are numerous popular DevOps tools, with more being -introduced each year. Integrating hundreds of resource types with multiple -tools requires uniformity, so that integration can be automated. - -## Guidance - -### Resources - -Resources that are declarative-friendly **must** use only strongly-consistent -standard methods for managing resource lifecycle, which allows tools to support -these resources generically, as well as conforming to other -declarative-friendly guidance (see [further reading](#further-reading)). - -Declarative-friendly resources **should** designate that they follow the -declarative-friendly style: - -```proto -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - style: DECLARATIVE_FRIENDLY - }; - - // Name and other fields... -} -``` - -### Reconciliation - -If a resource takes time (more than a few seconds) for updates to be realized, -the resource **should** include a `bool reconciling` field to disclose that -changes are in flight. This field **must** be output only. - -A resource **must** set the `reconciling` field to `true` if the current state -of the resource does not match the user's intended state, and the system is -working to reconcile them. This is regardless of whether the root cause of -going into reconciliation was user or system action. - -**Note:** Services responding to a `GET` request **must** return the resource's -current state (not the intended state). - -## Further reading - -A significant amount of guidance is more strict for declarative-friendly -interfaces, due to the focus on automation on top of these resources. This list -is a comprehensive reference to declarative-friendly guidance in other AIPs: - -- Resources **should not** employ custom methods: see AIP-136. -- Resources **must** use the `Update` method for repeated fields: see AIP-144. -- Resources **must** include certain standard fields: see AIP-148. -- Resources **must** have an `etag` field: see AIP-154. -- Resources **should** provide change validation: see AIP-163. -- Resources **should not** implement soft-delete. If the id cannot be re-used, - the resource **must** implement soft-delete and the undelete RPC: see AIP-164 - - -### Annotations - -See [AIP-148 annotations][]. - -## Changelog - -- **2023-07-13**: Move `annotations` from AIP-148. -- **2023-06-17**: Definition of plane was removed and incorporated into AIP-111. -- **2023-05-11**: Removed must on resource_id, which was upstreamed to a general - must. - -[AIP-148 annotations]: ./0148.md#annotations diff --git a/aip/general/0129.md b/aip/general/0129.md deleted file mode 100644 index 47bc8c85f3..0000000000 --- a/aip/general/0129.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -id: 129 -state: approved -created: 2023-09-20 -updated: 2023-10-31 -placement: - category: resource-design - order: 65 ---- - -# Server-Modified Values and Defaults - -Services often provide default values for resource fields, and occasionally -normalize the user input before returning it in the response. The guidance -herein describes how services document such behavior for the benefit of -consumers. - -## Guidance - -### Single Owner Fields - -Fields **must** have a single owner, whether that is the client or the server. -Server owned fields **must** be indicated with the `OUTPUT_ONLY` field_behavior. -All other types of fields **must** be considered to be owned by the client. The -server **must** respect the value (or lack thereof) for all client owned fields -and not modify them. - -### Effective Values - -There are instances where a service will allocate, generate, or calculate a -value if the client chooses not to specify one. For example: a client creates a -virtual machine without specifying a static IP address for the virtual machine -to be available on. Such a scenario is opting into dynamic IP address -allocation. - -Some examples of these types of fields are ones that are: - -* generated (UUID) -* allocated (dynamic IP address) -* assigned (most recent software package version) - -An attribute with an effective value ***must*** be expressed as two fields in -the API: - -* a mutable field that can be optionally set by the user and **must not** be -modified by the service -* an `OUTPUT_ONLY` field that records the effective value decided on by the -service - -Example: -```proto -message VirtualMachine { - … - string ip_address = 4; - string effective_ip_address = 5 [ - (google.api.field_behavior) = OUTPUT_ONLY - ]; -} -``` - -#### Naming - -Effective values **must** be named by prefixing `effective_` to the mutable -field's name. - -### User-Specified Fields - -For user-specified fields, the value in response from the service **must** be -the same as provided by the create or update request. For string fields this -means returning the value unchanged, with one exception: - -* When a string field has a data type annotation, a normalized string that - represents the given value **may** be returned. - -### Normalizations - -A field that is normalized by the service **must** be annotated with the -`google.api.field_info` extension. See ([AIP-202][]) for guidance on using -this extension The allowed set of normalizations includes the following formats: - -* uuid -* ipv4 -* ipv6 -* email - -Normalizations on fields **must** be described using the `google.api.field_info` -annotation. - -## Rationale - -Server-modified and default values often make it harder to implement -[declarative clients][]. These clients are often unable to -tell when their desired state matches the current state for these fields, as the -rules by which a server may modify and return values are complex, not public, -and not repeatable. - -### Rationale for Single Owner Fields - -When fields do not have a single owner they can cause issues for -[declarative clients][]. These clients may attempt to set -values for fields that are overwritten by server set values, leading to the -client entering an infinite loop to correct the change. - -### Rationale for Naming - -Consistent naming is important for identifying standard behavior across APIs -and fields. Programmatic association between user-specified and effective values -depends on consistent naming. - -### Rationale for Normalizations - -Normalizations are important to allow services to store and return values in a -standard way while communicating to clients what changes are semantically -identical. Normalizing a value on the service side allows the service to accept -a wider range of semantically identical inputs without needing to maintain every -value as a raw string. Surfacing the normalization that is being applied to -clients allows for client side comparison of sent and retrieved values to check -for differences. - -For example, in a resource that accepts an email address on a particular field -a client may specify a given email address in a variety of ways. For the email -`ada@example.com` a client may choose to specify `ADA@example.com`, -`aDa@example.com`, or `AdA@example.com`. These are semantically identical and -*should* all be accepted by the service. The service then may choose to -normalize the email address for storage and retrieval through downcasing or -canonicalization. Importantly, the information surfaced to clients on the -normalization of a field will not describe the normalization algorithm itself, -but instead the comparison method used to accurately compute if two values -should be considered equal. - -### Rationale for Field Value Handling - -For fields not using an allowed normalization, -[Declarative clients][] will not be able to identify which changes are -semantically meaningful. When a [Declarative client][Declarative clients] -sends a particular value it will ensure that the value is being returned by the -service to validate it was set correctly. - -## Changelog - -- **2023-10-31:** Update to approved. - -[Declarative clients]: ./0009.md#declarative-clients -[aip-202]: ./0202.md - - -[aip-180]: ./0180.md - diff --git a/aip/general/0130.md b/aip/general/0130.md deleted file mode 100644 index 6f918e259c..0000000000 --- a/aip/general/0130.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -id: 130 -state: approved -created: 2023-03-13 -updated: 2023-09-05 -placement: - category: operations - order: 9 ---- - -# Methods - -An API is composed of one or more methods, which represent a specific operation -that a service can perform on behalf of the consumer. - -## Guidance - -### Categories of Methods - -The following enumerates multiple categories of methods that exist, often -grouped up under some object (e.g. collection or resource) that the method -operates upon. - -| Category Name | Related AIPs | [Declarative client][] integration | CLI / UI integration | SDK integration | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------------------------- | -------------------- | --------------- | -| *Standard Methods* | | | | | -| **Standard collection methods**: operate on a collection of resources (List or Create). | [AIP-121][], [AIP-132][], [AIP-133][] | automatable | automatable | automatable | -| **Standard resource methods**: fetch or mutate a single resource (Get, Update, Delete). | [AIP-121][], [AIP-131][], [AIP-134][], [AIP-135][] | automatable | automatable | automatable | -| **Batch resource methods**: fetch or mutate multiple resources in a collection by name. | [AIP-231][], [AIP-233][], [AIP-234][], [AIP-235][] | may be used to optimize queries | automatable | automatable | -| **Aggregated list methods**: fetch or mutate multiple resources of the same type across multiple collections. | [AIP-159][] | not useful nor automatable | automatable | automatable | -| *Custom Fetch Methods* | | | | | -| **Custom collection fetch methods**: fetch information across a collection that cannot be expressed via a standard method. | [AIP-136][] | handwritten | automatable | automatable | -| **Custom resource fetch methods**: fetch information for a single resource that cannot be expressed via a standard method. | [AIP-136][] | handwritten | automatable | automatable | -| *Custom Mutation Methods* | | | | | -| **Backing up a resource**: storing a copy of a resource at a particular point in time. | [AIP-162][] | unused or handwritten | automatable | automatable | -| **Restoring a resource**: setting a resource to a version from a particular point in time. | [AIP-162][] | unused or handwritten | automatable | automatable | -| **Renaming a resource**: modify the resource's name or id while preserving configuration and data. | [AIP-136][] | unused or handwritten | automatable | automatable | -| **Custom collection mutation methods**: perform an imperative operation referencing a collection that may mutate one or more resources within that collection in fashion that cannot be easily achieved by standard methods (e.g. state transitions). | [AIP-136][] | unused or handwritten | automatable | automatable | -| **Custom resource mutation methods**: perform an imperative operation on a resource that may mutate it in a way a standard method cannot (e.g. state transitions). | [AIP-136][] | unused or handwritten | automatable | automatable | -| *Misc Custom Methods* | | | | -| **Stateless Methods**: a method that has no permanent effect on any data within the API (e.g. translating text) | [AIP-136][] | unused or handwritten | automatable | automatable | -| *None of the above* | | | | | -| **Streaming methods**: methods that communicate via client, server, or bi-directional streams. | | handwritten | handwritten | automatable | - -### Choosing a method category - -While designing a method, API authors should choose from the defined categories -in the following order: - -1. Standard methods (on collections and resources) -1. Standard batch or aggregate methods -1. Custom methods (on collections, resources, or stateless) -1. Streaming methods - -## Rationale - -Resource-oriented standard and custom methods are recommended first, as they can -be expressed in the widest variety of clients (Declarative clients, CLIs, UIs, and so on), and -offer the most uniform experience that allows users to apply their knowledge of -one API to another. - -If a standard method is unsuitable, then custom methods (that are mounted to a -resource or collection) offer a lesser, but still valuable level of consistency, -helping the user reason about the scope of the action and the object whose -configuration is read to inform that action. Although mutative custom methods -are not uniform enough to have a automated integration with exclusively -resource-oriented clients such as [Declarative client][]s, they are still a pattern that -can easily recognized by CLIs, UIs, and SDKs. - -If one cannot express their APIs in a resource-oriented fashion at all, then the -operation falls in a category where the lack of uniformity makes it difficult -for any client aside from SDKs to model the operation. This category is -preferred last due to the fact that a user cannot rely on their knowledge of -similar APIs, as well as the issue that integration with many clients will -likely have to be hand-written. - -[AIP-121]: ./0121.md -[AIP-131]: ./0131.md -[AIP-132]: ./0132.md -[AIP-133]: ./0133.md -[AIP-134]: ./0134.md -[AIP-135]: ./0135.md -[AIP-136]: ./0136.md -[AIP-159]: ./0159.md -[AIP-162]: ./0162.md -[AIP-231]: ./0231.md -[AIP-233]: ./0233.md -[AIP-234]: ./0234.md -[AIP-235]: ./0235.md -[Declarative client]: ./0009.md#declarative-clients - -## Changelog - -- **2023-09-05**: Update to approved. \ No newline at end of file diff --git a/aip/general/0131.md b/aip/general/0131.md deleted file mode 100644 index ebc7c0e90a..0000000000 --- a/aip/general/0131.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -id: 131 -state: approved -created: 2019-01-22 -updated: 2022-06-02 -placement: - category: operations - order: 10 ---- - -# Standard methods: Get - -In REST APIs, it is customary to make a `GET` request to a resource's URI (for -example, `/v1/publishers/{publisher}/books/{book}`) in order to retrieve that -resource. - -Resource-oriented design ([AIP-121][]) honors this pattern through the `Get` -method. These RPCs accept the URI representing that resource and return the -resource. - -## Guidance - -APIs **must** provide a get method for resources. The purpose of the get method -is to return data from a single resource. - -Get methods are specified using the following pattern: - -```proto -rpc GetBook(GetBookRequest) returns (Book) { - option (google.api.http) = { - get: "/v1/{name=publishers/*/books/*}" - }; - option (google.api.method_signature) = "name"; -} -``` - -- The RPC's name **must** begin with the word `Get`. The remainder of the RPC - name **should** be the singular form of the resource's message name. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response message **must** be the resource itself. (There is no - `GetBookResponse`.) - - The response **should** usually include the fully-populated resource unless - there is a reason to return a partial response (see [AIP-157][]). -- The HTTP verb **must** be `GET`. -- The URI **should** contain a single variable field corresponding to the - resource name. - - This field **should** be called `name`. - - The URI **should** have a variable corresponding to this field. - - The `name` field **should** be the only variable in the URI path. All - remaining parameters **should** map to URI query parameters. -- There **must not** be a `body` key in the `google.api.http` annotation. -- There **should** be exactly one `google.api.method_signature` annotation, - with a value of `"name"`. - -### Request message - -Get methods implement a common request message pattern: - -```proto -message GetBookRequest { - // The name of the book to retrieve. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; -} -``` - -- A resource name field **must** be included. It **should** be called `name`. - - The field **should** be [annotated as required][aip-203]. - - The field **must** identify the [resource type][aip-123] that it - references. -- The comment for the `name` field **should** document the resource pattern. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in - another AIP. - -**Note:** The `name` field in the request object corresponds to the `name` -variable in the `google.api.http` annotation on the RPC. This causes the `name` -field in the request to be populated based on the value in the URL when the -REST/JSON interface is used. - - -### Errors - -See [errors][], in particular [when to use PERMISSION_DENIED and -NOT_FOUND errors][permission-denied]. - -[aip-121]: ./0121.md -[aip-123]: ./0123.md -[aip-157]: ./0157.md -[aip-203]: ./0203.md -[errors]: ./0193.md -[permission-denied]: ./0193.md#permission-denied - -## Changelog - -- **2023-03-17**: Align with AIP-122 and make Get a must. -- **2022-11-04**: Aggregated error guidance to AIP-193. -- **2022-06-02**: Changed suffix descriptions to eliminate superfluous "-". -- **2020-06-08**: Added guidance on returning the full resource. -- **2019-10-18**: Added guidance on annotations. -- **2019-08-12**: Added guidance for error cases. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. -- **2019-05-29**: Added an explicit prohibition on arbitrary fields in standard - methods. diff --git a/aip/general/0132.md b/aip/general/0132.md deleted file mode 100644 index 495797501b..0000000000 --- a/aip/general/0132.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -id: 132 -state: approved -created: 2019-01-21 -updated: 2022-06-02 -placement: - category: operations - order: 20 ---- - -# Standard methods: List - -In many APIs, it is customary to make a `GET` request to a collection's URI -(for example, `/v1/publishers/1/books`) in order to retrieve a list of -resources, each of which lives within that collection. - -Resource-oriented design ([AIP-121][]) honors this pattern through the `List` -method. These RPCs accept the parent collection (and potentially some other -parameters), and return a list of responses matching that input. - -## Guidance - -APIs **must** provide a `List` method for resources unless the resource is a -[singleton][]. The purpose of the `List` method is to return data from a finite -collection (generally singular unless the operation supports [reading across -collections][]). - -List methods are specified using the following pattern: - -```proto -rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) { - option (google.api.http) = { - get: "/v1/{parent=publishers/*}/books" - }; - option (google.api.method_signature) = "parent"; -} -``` - -- The RPC's name **must** begin with the word `List`. The remainder of the RPC - name **should** be the plural form of the resource being listed. -- The request and response messages **must** match the RPC name, with - `Request` and `Response` suffixes. -- The HTTP verb **must** be `GET`. -- The collection whose resources are being listed **should** map to the URI - path. - - The collection's parent resource **should** be called `parent`, and - **should** be the only variable in the URI path. All remaining parameters - **should** map to URI query parameters. - - The collection identifier (`books` in the above example) **must** be a - literal string. -- The `body` key in the `google.api.http` annotation **must** be omitted. -- If the resource being listed is not a top-level resource, there **should** - be exactly one `google.api.method_signature` annotation, with a value of - `"parent"`. If the resource being listed is a top-level resource, there - **should** be either no `google.api.method_signature` annotation, or exactly - one `google.api.method_signature` annotation, with a value of `""`. - -### Request message - -List methods implement a common request message pattern: - -```proto -message ListBooksRequest { - // The parent, which owns this collection of books. - // Format: publishers/{publisher} - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The maximum number of books to return. The service may return fewer than - // this value. - // If unspecified, at most 50 books will be returned. - // The maximum value is 1000; values above 1000 will be coerced to 1000. - int32 page_size = 2; - - // A page token, received from a previous `ListBooks` call. - // Provide this to retrieve the subsequent page. - // - // When paginating, all other parameters provided to `ListBooks` must match - // the call that provided the page token. - string page_token = 3; -} -``` - -- A `parent` field **must** be included unless the resource being listed is a - top-level resource. It **should** be called `parent`. - - The field **should** be [annotated as required][aip-203]. - - The field **must** identify the [resource type][aip-123] of the resource - being listed. -- The `page_size` and `page_token` fields, which support pagination, **must** - be specified on all list request messages. For more information, see - [AIP-158][]. - - The comment above the `page_size` field **should** document the maximum - allowed value, as well as the default value if the field is omitted (or set - to `0`). If preferred, the API **may** state that the server will use a - sensible default. This default **may** change over time. - - If a user provides a value greater than the maximum allowed value, the API - **should** coerce the value to the maximum allowed. - - If a user provides a negative or other invalid value, the API **must** send - an `INVALID_ARGUMENT` error. -- The `page_token` field **must** be included on all list request messages. -- The request message **may** include fields for common design patterns - relevant to list methods, such as `string filter` and `string order_by`. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. - -**Note:** List methods **should** return the same results for any user that has -permission to make a successful List request on the collection. Search methods -are more relaxed on this. - -### Response message - -List methods implement a common response message pattern: - -```proto -message ListBooksResponse { - // The books from the specified publisher. - repeated Book books = 1; - - // A token, which can be sent as `page_token` to retrieve the next page. - // If this field is omitted, there are no subsequent pages. - string next_page_token = 2; -} -``` - -- The response message **must** include one repeated field corresponding to the - resources being returned, and **should not** include any other repeated - fields unless described in another AIP (for example, AIP-217). - - The response **should** usually include fully-populated resources unless - there is a reason to return a partial response (see AIP-157). -- The `next_page_token` field, which supports pagination, **must** be included - on all list response messages. It **must** be set if there are subsequent - pages, and **must not** be set if the response represents the final page. For - more information, see AIP-158. -- The message **may** include a `int32 total_size` (or `int64 total_size`) - field with the number of items in the collection. - - The value **may** be an estimate (the field **should** clearly document - this if so). - - If filtering is used, the `total_size` field **should** reflect the size of - the collection _after_ the filter is applied. - -### Ordering - -`List` methods **may** allow clients to specify sorting order; if they do, the -request message **should** contain a `string order_by` field. - -- Values **should** be a comma separated list of fields. For example: - `"foo,bar"`. -- The default sorting order is ascending. To specify descending order for a - field, users append a `" desc"` suffix; for example: `"foo desc, bar"`. -- Redundant space characters in the syntax are insignificant. - `"foo, bar desc"`, `" foo , bar desc "`, and `"foo,bar desc"` are all - equivalent. -- Subfields are specified with a `.` character, such as `foo.bar` or - `address.street`. -- The resulting list order **should** be based on the field type's natural - comparator e.g. numerics ordered numerically, strings ordered - lexicographically, etc. However, APIs **may** choose to use a different - ordering; if so, it **must** be documented in the `order_by` definition. - - Furthermore, [well-known][] types, like `Timestamp` and `Duration` are - compared as their representative type; `Timestamp` is compared as time e.g. - before or after, `Duration` is compared as a quantity e.g. more or less. - - - -**Note:** Only include ordering if there is an established need to do so. It is -always possible to add ordering later, but removing it is a breaking change. - -### Filtering - -List methods **may** allow clients to specify filters; if they do, the request -message **should** contain a `string filter` field. Filtering is described in -more detail in AIP-160. - -**Note:** Only include filtering if there is an established need to do so. It -is always possible to add filtering later, but removing it is a breaking -change. - -### Soft-deleted resources - -Some APIs need to "[soft delete][]" resources, marking them as deleted or -pending deletion (and optionally purging them later). - -APIs that do this **should not** include deleted resources by default in list -requests. APIs with soft deletion of a resource **should** include a -`bool show_deleted` field in the list request that, if set, will cause -soft-deleted resources to be included. - -### Errors - -See [errors][], in particular [when to use PERMISSION_DENIED and -NOT_FOUND errors][permission-denied]. - -## Further reading - -- For details on pagination, see [AIP-158](./0158.md). -- For listing across multiple parent collections, see [AIP-159](./0159.md). - -[aip-121]: ./0121.md -[aip-123]: ./0123.md -[aip-157]: ./0157.md -[aip-158]: ./0158.md -[aip-203]: ./0203.md -[errors]: ./0193.md -[permission-denied]: ./0193.md#permission-denied -[reading across collections]: ./0159.md -[singleton]: ./0156.md -[soft delete]: ./0135.md#soft-delete -[well-known]: https://protobuf.dev/reference/protobuf/google.protobuf - -## Changelog - -- **2025-02-25**: Require documentation for ordering not matching field type - with clarification on ordering of well-known types. -- **2023-03-22**: Fix guidance wording to mention AIP-159. -- **2023-03-17**: Align with AIP-122 and make Get a must. -- **2022-11-04**: Aggregated error guidance to AIP-193. -- **2022-06-02**: Changed suffix descriptions to eliminate superfluous "-". -- **2020-09-02**: Add link to the filtering AIP. -- **2020-08-14**: Added error guidance for permission denied cases. -- **2020-06-08**: Added guidance on returning the full resource. -- **2020-05-19**: Removed requirement to document ordering behavior. -- **2020-04-15**: Added guidance on List permissions. -- **2019-10-18**: Added guidance on annotations. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. -- **2019-07-30**: Added guidance about documenting the ordering behavior. -- **2019-05-29**: Added an explicit prohibition on arbitrary fields in standard - methods. diff --git a/aip/general/0133.md b/aip/general/0133.md deleted file mode 100644 index 07aa21b4ac..0000000000 --- a/aip/general/0133.md +++ /dev/null @@ -1,242 +0,0 @@ ---- -id: 133 -state: approved -created: 2019-01-23 -updated: 2022-06-02 -placement: - category: operations - order: 30 ---- - -# Standard methods: Create - -In REST APIs, it is customary to make a `POST` request to a collection's URI -(for example, `/v1/publishers/{publisher}/books`) in order to create a new -resource within that collection. - -Resource-oriented design ([AIP-121][]) honors this pattern through the `Create` -method. These RPCs accept the parent collection and the resource to create (and -potentially some other parameters), and return the created resource. - -## Guidance - -APIs **should** generally provide a create method for resources unless it is -not valuable for users to do so. The purpose of the create method is to create -a new resource in an already-existing collection. - -Create methods are specified using the following pattern: - -```proto -rpc CreateBook(CreateBookRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books" - body: "book" - }; - option (google.api.method_signature) = "parent,book"; -} -``` - -- The RPC's name **must** begin with the word `Create`. The remainder of the - RPC name **should** be the singular form of the resource being created. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response message **must** be the resource itself. There is no - `CreateBookResponse`. - - The response **should** include the fully-populated resource, and **must** - include any fields that were provided unless they are input only (see - [AIP-203][]) or there is a reason to return a partial response (see - [AIP-157][]). - - If the create RPC is [long-running](#long-running-create), the response - message **must** be a `google.longrunning.Operation` which resolves to the - resource itself. -- The HTTP verb **must** be `POST`. -- The collection where the resource is being added **should** map to the URI - path. - - The collection's parent resource **should** be called `parent`, and - **should** be the only variable in the URI path. - - The collection identifier (`books` in the above example) **must** be - a literal string. -- There **must** be a `body` key in the `google.api.http` annotation, and it - **must** map to the resource field in the request message. - - All remaining fields **should** map to URI query parameters. -- There **should** be exactly one `google.api.method_signature` annotation, - with a value of `"parent,{resource},{resource}_id"`, or "`"parent,{resource}"` - if the resource ID is not required. -- If the API is operating on the [management plane][], the operation should have - [strong consistency][]: the completion of a create operation **must** mean - that all user-settable values and the existence of the resource have reached a - steady-state and reading resource state returns a consistent response. - -### Request message - -Create methods implement a common request message pattern: - -```proto -message CreateBookRequest { - // The parent resource where this book will be created. - // Format: publishers/{publisher} - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The ID to use for the book, which will become the final component of - // the book's resource name. - // - // This value should be 4-63 characters, and valid characters - // are /[a-z][0-9]-/. - string book_id = 2 [(google.api.field_behavior) = REQUIRED]; - - // The book to create. - Book book = 3 [(google.api.field_behavior) = REQUIRED]; -} -``` - -- A `parent` field **must** be included unless the resource being created is a - top-level resource. It **should** be called `parent`. - - The field **should** be [annotated as required][aip-203]. - - The field **must** identify the [resource type][aip-123] of the resource - being created. -- A `{resource}_id` field **must** be included for management plane resources, - and **should** be included for data plane resources. -- The resource field **must** be included and **must** map to the POST body. -- The request message **must not** contain any other required fields and - **should not** contain other optional fields except those described in this - or another AIP. - -### Long-running create - -Some resources take longer to create a resource than is reasonable for a -regular API request. In this situation, the API **should** use a long-running -operation (AIP-151) instead: - -```proto -rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books" - body: "book" - }; - option (google.longrunning.operation_info) = { - response_type: "Book" - metadata_type: "OperationMetadata" - }; -} -``` - -- The response type **must** be set to the resource (what the return type would - be if the RPC was not long-running). -- Both the `response_type` and `metadata_type` fields **must** be specified. - -**Important:** Declarative-friendly resources (AIP-128) **should** use -long-running operations. The service **may** return an LRO that is already set -to done if the request is effectively immediate. - -### User-specified IDs - -An API **must** allow a user to specify the ID component of a resource (the last -segment of the resource name) on creation if the API is operating on the -[management plane][]. - -On the [data plane][], an API **should** allow a user to specify the ID. -Exceptional cases should have the following behavior: - -- The data plane resource allows identical records without a need to - disambiguate between the two (e.g. rows in a table with no primary key). -- The data plane resource will not be exposed in [Declarative clients][]. - -An API -**may** allow the `{resource}_id` field have the [field_behavior][] `OPTIONAL`, -and generate a system-generated ID if one is not specified. - -For example: - -``` -// Using user-specified IDs. -publishers/lacroix/books/les-miserables - -// Using system-generated IDs. -publishers/012345678-abcd-cdef/books/12341234-5678-abcd -``` - -- The `{resource}_id` field **must** exist on the request message, not the - resource itself. - - The field **may** be required or optional. If it is required, it **should** - include the corresponding annotation. -- The `name` field on the resource **must** be ignored. -- There **should** be exactly one `google.api.method_signature` annotation on - the RPC, with a value of `"parent,{resource},{resource}_id"` if the resource - being created is not a top-level resource, or with a value of - `"{resource},{resource}_id"` if the resource being created is a top-level - resource. -- The documentation **should** explain what the acceptable format is, and the - format **should** follow the guidance for resource name formatting in - [AIP-122][]. -- If a user tries to create a resource with an ID that would result in a - duplicate resource name, the service **must** error with `ALREADY_EXISTS`. - - However, if the user making the call does not have permission to see the - duplicate resource, the service **must** error with `PERMISSION_DENIED` - instead. - -**Note:** For REST APIs, the user-specified ID field, `{resource}_id`, -is provided as a query parameters on the request URI. - -### Errors - -See [errors][], in particular [when to use PERMISSION_DENIED and -NOT_FOUND errors][permission-denied]. - -## Further reading - -- For ensuring idempotency in `Create` methods, see [AIP-155][]. -- For naming resources involving Unicode, see [AIP-210][]. - -## Rationale - -### Requiring user-specified ids - -[Declarative clients][] use the resource ID as a way to identify a resource for -applying updates and for conflict resolution. The lack of a user-specified ID -means a client is unable to find the resource unless they store the identifier -locally, and can result in re-creating the resource. This in turn has a -downstream effect on all resources that reference it, forcing them to update to -the ID of the newly-created resource. - -Having a user-specified ID also means the client can precalculate the resource -name and use it in references from other resources. - -[aip-121]: ./0121.md -[aip-122]: ./0122.md -[aip-123]: ./0123.md -[aip-155]: ./0155.md -[aip-157]: ./0157.md -[aip-203]: ./0203.md -[aip-210]: ./0210.md -[data plane]: ./0111.md#data-plane -[management plane]: ./0111.md#management-plane -[errors]: ./0193.md -[field_behavior]: ./0203.md -[Declarative clients]: ./0009.md#declarative-clients -[permission-denied]: ./0193.md#permission-denied -[strong consistency]: ./0121.md#strong-consistency - -## Changelog - -- **2025-10-03**: Allow use of partial responses via AIP-157. -- **2023-10-20**: Clarify that {resource}_id is only required for management plane resources. -- **2023-08-24**: Adding consistency requirement. -- **2023-05-11**: Changing guidance around resource_id to a must. -- **2022-11-04**: Referencing aggregated error guidance in AIP-193, similar to - other CRUDL AIPs. -- **2022-06-02**: Changed suffix descriptions to eliminate superfluous "-". -- **2020-10-06**: Added declarative-friendly guidance. -- **2020-08-14**: Updated error guidance to use permission denied over - forbidden. -- **2020-06-08**: Added guidance on returning the full resource. -- **2019-11-22**: Added clarification on what error to use if a duplicate name - is sent. -- **2019-10-18**: Added guidance on annotations. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. -- **2019-06-10**: Added guidance for long-running create. -- **2019-05-29**: Added an explicit prohibition on arbitrary fields in standard - methods. diff --git a/aip/general/0134.md b/aip/general/0134.md deleted file mode 100644 index 7fa943de78..0000000000 --- a/aip/general/0134.md +++ /dev/null @@ -1,329 +0,0 @@ ---- -id: 134 -state: approved -created: 2019-01-24 -updated: 2022-06-02 -placement: - category: operations - order: 40 ---- - -# Standard methods: Update - -In REST APIs, it is customary to make a `PATCH` or `PUT` request to a -resource's URI (for example, `/v1/publishers/{publisher}/books/{book}`) in -order to update that resource. - -Resource-oriented design ([AIP-121][]) honors this pattern through the `Update` -method (which mirrors the REST `PATCH` behavior). These RPCs accept the URI -representing that resource and return the resource. - -## Guidance - -APIs **should** generally provide an update method for resources unless it is -not valuable for users to do so. The purpose of the update method is to make -changes to the resources without causing side effects. - -Update methods are specified using the following pattern: - -```proto -rpc UpdateBook(UpdateBookRequest) returns (Book) { - option (google.api.http) = { - patch: "/v1/{book.name=publishers/*/books/*}" - body: "book" - }; - option (google.api.method_signature) = "book,update_mask"; -} -``` - -- The RPC's name **must** begin with the word `Update`. The remainder of the - RPC name **should** be the singular form of the resource's message name. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response message **must** be the resource itself. (There is no - `UpdateBookResponse`.) - - The response **should** include the fully-populated resource, and **must** - include any fields that were sent and included in the update mask unless - they are input only (see AIP-203) or there is a reason to return a partial - response (see [AIP-157][]). - - If the update RPC is [long-running](#long-running-update), the response - message **must** be a `google.longrunning.Operation` which resolves to the - resource itself. -- The method **should** support partial resource update, and the HTTP verb - **should** be `PATCH`. - - If the method will only ever support full resource replacement, then the - HTTP verb **may** be `PUT`. However, this is strongly discouraged because - it becomes a backwards-incompatible change to add fields to the resource. -- The resource's `name` field **should** map to the URI path. - - The `{resource}.name` field **should** be the only variable in the URI - path. -- There **must** be a `body` key in the `google.api.http` annotation, and it - **must** map to the resource field in the request message. - - All remaining fields **should** map to URI query parameters. -- There **should** be exactly one `google.api.method_signature` annotation, with - a value of `"{resource},update_mask"`. -- If the API is operating on the [management plane][], the operation should have - [strong consistency][]: the completion of an update operation **must** mean - that all user-settable values and the existence of the resource have reached a - steady-state and reading resource state returns a consistent response. - - - -**Note:** Unlike the other four standard methods, the URI path here references -a nested field (`book.name`) in the example. If the resource field has a word -separator, `snake_case` is used. - -### Request message - -Update methods implement a common request message pattern: - -```proto -message UpdateBookRequest { - // The book to update. - // - // The book's `name` field is used to identify the book to update. - // Format: publishers/{publisher}/books/{book} - Book book = 1 [(google.api.field_behavior) = REQUIRED]; - - // The list of fields to update. - google.protobuf.FieldMask update_mask = 2; -} -``` - -- The request message **must** contain a field for the resource. - - The field **must** map to the `PATCH` body. - - The field **should** be [annotated as required][aip-203]. - - A `name` field **must** be included in the resource message. It **should** - be called `name`. - - The field **must** identify the [resource type][aip-123] of the resource - being updated. -- If partial resource update is supported, a field mask **must** be included. - It **must** be of type `google.protobuf.FieldMask`, and it **must** be - called `update_mask`. - - The fields used in the field mask correspond to the resource being updated - (not the request message). - - The field **must** be optional, and the service **must** treat an omitted - field mask as an implied field mask equivalent to all fields that are - populated (have a non-empty value). - - Update masks **must** support a special value `*`, meaning full replacement - (the equivalent of `PUT`). - - API producers need to be conscious of how adding new, mutable fields to a - resource will be handled when consumers use `*` without knowledge of said - new, mutable fields. Likewise consumers need to use `*` only when the - risks of doing so are acceptable. In general, it is safest to explicitly - specify the fields to update rather than use `*`. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. - -### Side effects - -In general, update methods are intended to update the data within the resource. -Update methods **should not** trigger other side effects. Instead, side effects -**should** be triggered by custom methods. - -In particular, this entails that [state fields][] **must not** be directly -writable in update methods. - -### PATCH and PUT - -**TL;DR:** Google APIs generally use the `PATCH` HTTP verb only, and do not -support `PUT` requests. - -We standardize on `PATCH` because Google updates stable APIs in place with -backwards-compatible improvements. It is often necessary to add a new field to -an existing resource, but this becomes a breaking change when using `PUT`. - -To illustrate this, consider a `PUT` request to a `Book` resource: - - PUT /v1/publishers/123/books/456 - - {"title": "Mary Poppins", "author": "P.L. Travers"} - -Next consider that the resource is later augmented with a new field (here we -add `rating`): - -```proto -message Book { - string title = 1; - string author = 2; - - // Subsequently added to v1 in place... - int32 rating = 3; -} -``` - -If a rating is set on a book and the existing `PUT` request was executed, it -would wipe out the book's rating. In essence, a `PUT` request unintentionally -wiped out data because the previous version did not know about it. - -### Long-running update - -Some resources take longer to update a resource than is reasonable for a -regular API request. In this situation, the API **should** use a long-running -operation ([AIP-151][]) instead: - -```proto -rpc UpdateBook(UpdateBookRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - patch: "/v1/{book.name=publishers/*/books/*}" - body: "book" - }; - option (google.longrunning.operation_info) = { - response_type: "Book" - metadata_type: "OperationMetadata" - }; -} -``` - -- The response type **must** be set to the resource (what the return type would - be if the RPC was not long-running). -- Both the `response_type` and `metadata_type` fields **must** be specified. - -**Note:** Declarative-friendly resources ([AIP-128][]) **should** use long-running -update. - -### Create or update - -If the service uses client-assigned resource names, `Update` methods **may** -expose a `bool allow_missing` field, which will cause the method to succeed in -the event that the user attempts to update a resource that is not present (and -will create the resource in the process): - -```proto -message UpdateBookRequest { - // The book to update. - // - // The book's `name` field is used to identify the book to be updated. - // Format: publishers/{publisher}/books/{book} - Book book = 1 [(google.api.field_behavior) = REQUIRED]; - - // The list of fields to be updated. - google.protobuf.FieldMask update_mask = 2; - - // If set to true, and the book is not found, a new book will be created. - // In this situation, `update_mask` is ignored. - bool allow_missing = 3; -} -``` - -More specifically, the `allow_missing` flag triggers the following behavior: - -- If the method call is on a resource that does not exist, the resource is - created. All fields are applied regardless of any provided field mask. - - However, if any required fields are missing or fields have invalid values, - an `INVALID_ARGUMENT` error is returned. -- If the method call is on a resource that already exists, and all fields - match, the existing resource is returned unchanged. -- If the method call is on a resource that already exists, only fields declared - in the field mask are updated. - -The user **must** have the update permissions to call `Update` even with -`allow_missing` set to `true`. For customers that want to prevent users from -creating resources using the update method, IAM conditions **should** be used. - -### Etags - -An API may sometimes need to allow users to send update requests which are -guaranteed to be made against the most current data (a common use case for this -is to detect and avoid race conditions). Resources which need to enable this do -so by including a `string etag` field, which contains an opaque, -server-computed value representing the content of the resource. - -In this situation, the resource **should** contain a `string etag` field: - -```proto -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - // The resource name of the book. - // Format: publishers/{publisher}/books/{book} - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The title of the book. - // Example: "Mary Poppins" - string title = 2; - - // The author of the book. - // Example: "P.L. Travers" - string author = 3; - - // The etag for this book. - // If this is provided on update, it must match the server's etag. - string etag = 4; -} -``` - -The `etag` field **may** be either [required][] or [optional][]. If it is set, -then the request **must** succeed if and only if the provided etag matches the -server-computed value, and **must** fail with an `ABORTED` error otherwise. The -`update_mask` field in the request does not affect the behavior of the `etag` -field, as it is not a field _being_ updated. - -### Expensive fields - -APIs sometimes encounter situations where some fields on a resource are -expensive or impossible to reliably return. - -This can happen in a few situations: - -- A resource may have some fields that are very expensive to compute, and that - are generally not useful to the customer on update requests. -- A single resource sometimes represents an amalgamation of data from multiple - underlying (and eventually consistent) data sources. In these situations, it - is impossible to return authoritative information on the fields that were not - changed. - -In this situation, an API **may** return back only the fields that were -updated, and omit the rest, and **should** document this behavior if they do -so. - -### Errors - -See [errors][], in particular [when to use PERMISSION_DENIED and -NOT_FOUND errors][permission-denied]. - -In addition, if the user does have proper permission, but the requested resource -does not exist, the service **must** error with `NOT_FOUND` (HTTP 404) unless -`allow_missing` is set to `true`. - -[aip-121]: ./0121.md -[aip-128]: ./0128.md -[aip-151]: ./0151.md -[aip-157]: ./0157.md -[aip-203]: ./0203.md -[errors]: ./0193.md -[management plane]: ./0111.md#management-plane -[permission-denied]: ./0193.md#permission-denied -[state fields]: ./0216.md -[strong consistency]: ./0121.md#strong-consistency -[required]: ./0203.md#required -[optional]: ./0203.md#optional - -## Changelog - -- **2025-10-03**: Allow use of partial responses via AIP-157. -- **2024-12-03**: Add caveats to usage of full replacement `update_mask`. -- **2024-03-14**: Make `update_mask` optional field_behaviour guidance a **must**. -- **2023-08-26**: Adding consistency requirement. -- **2023-07-17**: Make `update_mask` name guidance a **must**. -- **2022-11-04**: Aggregated error guidance to AIP-193. -- **2022-06-02**: Changed suffix descriptions to eliminate superfluous "-". -- **2021-11-04**: Changed the permission check if `allow_missing` is set. -- **2021-07-08**: Added error guidance for resource not found case. -- **2021-03-05**: Changed the etag error from `FAILED_PRECONDITION` (which - becomes HTTP 400) to `ABORTED` (409). -- **2020-10-06**: Added guidance for declarative-friendly resources. -- **2020-10-06**: Added guidance for `allow_missing`. -- **2020-08-14**: Added error guidance for permission denied cases. -- **2020-06-08**: Added guidance on returning the full resource. -- **2019-10-18**: Added guidance on annotations. -- **2019-09-10**: Added a link to the long-running operations AIP - ([AIP-151][]). -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. -- **2019-06-10**: Added guidance for long-running update. -- **2019-05-29**: Added an explicit prohibition on arbitrary fields in standard - methods. diff --git a/aip/general/0135.md b/aip/general/0135.md deleted file mode 100644 index f209831edc..0000000000 --- a/aip/general/0135.md +++ /dev/null @@ -1,264 +0,0 @@ ---- -id: 135 -state: approved -created: 2019-01-24 -updated: 2022-06-02 -placement: - category: operations - order: 50 ---- - -# Standard methods: Delete - -In REST APIs, it is customary to make a `DELETE` request to a resource's URI -(for example, `/v1/publishers/{publisher}/books/{book}`) in order to delete -that resource. - -Resource-oriented design (AIP-121) honors this pattern through the `Delete` -method. These RPCs accept the URI representing that resource and usually return -an empty response. - -## Guidance - -APIs **should** generally provide a delete method for resources unless it is -not valuable for users to do so. - -Delete methods are specified using the following pattern: - -```proto -rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - delete: "/v1/{name=publishers/*/books/*}" - }; - option (google.api.method_signature) = "name"; -} -``` - -- The RPC's name **must** begin with the word `Delete`. The remainder of the - RPC name **should** be the singular form of the resource's message name. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response message **should** be `google.protobuf.Empty`. - - If the resource is [soft deleted](#soft-delete), the response message - **should** be the resource itself. - - If the delete RPC is [long-running](#long-running-delete), the response - message **must** be a `google.longrunning.Operation` which resolves to the - correct response. -- The HTTP verb **must** be `DELETE`. -- The request message field receiving the resource name **should** map to the - URI path. - - This field **should** be called `name`. - - The `name` field **should** be the only variable in the URI path. All - remaining parameters **should** map to URI query parameters. -- There **must not** be a `body` key in the `google.api.http` annotation. -- There **should** be exactly one `google.api.method_signature` annotation, - with a value of `"name"`. If an etag or force field are used, they **may** be - included in the signature. -- If the API is operating on the [Management Plane][], the operation should have - [strong consistency][]: the completion of a delete operation **must** mean - that the existence of the resource has reached a steady-state and reading - resource state returns a consistent response. -- The API **must** fail with a `FAILED_PRECONDITION` error if child resources - are present. See guidance on [Cascading Delete](#cascading-delete) if forcing - deletion of parent and child resources is necessary. - - If the only child resource type is a [Singleton][aip-156], deletion **must** - be allowed, because the lifecycle of a Singleton is tied to that of its - parent resource. This applies even if there are multiple different Singleton - resource types for the same parent resource. - - -The Delete method **should** succeed if and only if a resource was present and -was successfully deleted. If the resource did not exist, the method **should** -send a `NOT_FOUND` error. - -### Request message - -Delete methods implement a common request message pattern: - -```proto -message DeleteBookRequest { - // The name of the book to delete. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; -} -``` - -- A `name` field **must** be included. It **should** be called `name`. - - The field **should** be [annotated as required][aip-203]. - - The field **must** identify the [resource type][aip-123] that it - references. -- The comment for the field **should** document the resource pattern. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. - -### Soft delete - -**Note:** This material was moved into its own document to provide a more -comprehensive treatment: AIP-164. - -### Long-running delete - -Some resources take longer to delete a resource than is reasonable for a -regular API request. In this situation, the API **should** use a long-running -operation instead: - -```proto -rpc DeleteBook(DeleteBookRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - delete: "/v1/{name=publishers/*/books/*}" - }; - option (google.longrunning.operation_info) = { - response_type: "google.protobuf.Empty" - metadata_type: "OperationMetadata" - }; -} -``` - -- The response type **must** be set to the appropriate return type if the RPC - was not long-running: `google.protobuf.Empty` for most Delete RPCs, or the - resource itself for soft delete (AIP-164). -- Both the `response_type` and `metadata_type` fields **must** be specified - (even if they are `google.protobuf.Empty`). - -### Cascading delete - -Sometimes, it may be necessary for users to be able to delete a resource as -well as all applicable child resources. However, since deletion is usually -permanent, it is also important that users not do so accidentally, as -reconstructing wiped-out child resources may be quite difficult. - -If an API allows deletion of a resource that may have child resources, the API -**should** provide a `bool force` field on the request, which the user sets to -explicitly opt in to a cascading delete. - -```proto -message DeletePublisherRequest { - // The name of the publisher to delete. - // Format: publishers/{publisher} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Publisher" - }]; - - // If set to true, any books from this publisher will also be deleted. - // (Otherwise, the request will only work if the publisher has no books.) - bool force = 2; -} -``` - -The API **must** fail with a `FAILED_PRECONDITION` error if the `force` field -is `false` (or unset) and child resources are present. - -### Protected delete - -Sometimes, it may be necessary for users to ensure that no changes have been -made to a resource that is being deleted. If a resource provides an [etag][], -the delete request **may** accept the etag (as either required or optional): - -```proto -message DeleteBookRequest { - // The name of the book to delete. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; - - // Optional. The etag of the book. - // If this is provided, it must match the server's etag. - string etag = 2; -} -``` - -If the etag is provided and does not match the server-computed etag, the -request **must** fail with a `ABORTED` error code. - -**Note:** Declarative-friendly resources (AIP-128) **must** provide the `etag` -field for Delete requests. - -### Delete if existing - -If the service uses client-assigned resource names, `Delete` methods **may** -expose a `bool allow_missing` field, which will cause the method to succeed in -the event that the user attempts to delete a resource that is not present (in -which case the request is a no-op): - -```proto -message DeleteBookRequest { - // The book to delete. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference).type = "library.googleapis.com/Book" - ]; - - // If set to true, and the book is not found, the request will succeed - // but no action will be taken on the server - bool allow_missing = 2; -} -``` - -More specifically, the `allow_missing` flag triggers the following behavior: - -- If the method call is on a resource that does not exist, the request is a - no-op. - - The `etag` field is ignored. -- If the method call is on a resource that already exists, the resource is - deleted (subject to other checks). - -**Note:** Declarative-friendly resources (AIP-128) **should** expose the -`bool allow_missing` field. - -### Errors - -If the user does not have permission to access the resource, regardless of -whether or not it exists, the service **must** error with `PERMISSION_DENIED` -(HTTP 403). Permission **must** be checked prior to checking if the resource -exists. - -If the user does have proper permission, but the requested resource does not -exist, the service **must** error with `NOT_FOUND` (HTTP 404) unless -`allow_missing` is set to `true`. - -[aip-123]: ./0123.md -[aip-131]: ./0131.md -[aip-132]: ./0132.md -[aip-136]: ./0136.md -[aip-154]: ./0154.md -[aip-156]: ./0156.md -[aip-203]: ./0203.md -[aip-214]: ./0214.md -[aip-216]: ./0216.md -[management plane]: ./0111.md#management-plane -[strong consistency]: ./0121.md#strong-consistency -[etag]: ./0134.md#etags - -## Further reading - -- For soft delete and undelete, see AIP-164. -- For bulk deleting large numbers of resources based on a filter, see AIP-165. - -## Changelog - -- **2024-06-11**: Add deletion behavior for parent resource deletion requests without a `force` field. -- **2023-08-24**: Adding consistency requirement. -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2022-02-02**: Changed eTag error from `FAILED_PRECONDITION` to `ABORTED` making it consistent with change to [AIP-154][] & [AIP-134][etag] on 2021-03-05. -- **2020-10-06**: Added guidance for declarative-friendly resources. -- **2020-10-06**: Added guidance for allowing no-op delete for missing - resources. -- **2020-10-06**: Moved soft delete and undelete guidance into a new AIP-164. -- **2020-06-08**: Added guidance for `Get` of soft-deleted resources. -- **2020-02-03**: Added guidance for error cases. -- **2019-10-18**: Added guidance on annotations. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. -- **2019-06-10**: Added guidance for long-running delete. -- **2019-05-29**: Added an explicit prohibition on arbitrary fields in standard - methods. diff --git a/aip/general/0136.md b/aip/general/0136.md deleted file mode 100644 index ef0481343e..0000000000 --- a/aip/general/0136.md +++ /dev/null @@ -1,201 +0,0 @@ ---- -id: 136 -state: approved -created: 2019-01-25 -updated: 2023-03-02 -placement: - category: operations - order: 100 ---- - -# Custom methods - -Resource-oriented design (AIP-121) uses custom methods to provide a means to -express arbitrary actions that are difficult to model using only the standard -methods. Custom methods are important because they provide a means for an API's -vocabulary to adhere to user intent. - -## Guidance - -Custom methods **should** only be used for functionality that can not be easily -expressed via standard methods; prefer standard methods if possible, due to -their consistent semantics. (Of course, this only applies if the functionality -in question actually conforms to the normal semantics; it is _not_ a good idea -to contort things to endeavor to make the standard methods "sort of work".) - -While custom methods vary widely in how they are designed, many principles -apply consistently: - -```proto -// Archives the given book. -rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:archive" - body: "*" - }; -} -``` - -**Note:** The pattern above shows a custom method that operates on a specific -resource. Custom methods can be associated with resources, collections, or -services. The bullets below apply in all three cases. - -- The name of the method **should** be a verb followed by a noun. - - The name **must not** contain prepositions ("for", "with", etc.). - - The verb in the name **should not** contain any of the standard method verbs ([Get][], - [List][], [Create][], [Update][], [Delete][]). - - The name **must not** include the term `Async`. Instead, if the intention is - to differentiate between immediate and long-running RPCs, the suffix `LongRunning` - **may** be used for this purpose. For example, to create a long-running book creation - RPC (if the standard `CreateBook` method was designed before long-running aspects were - considered), a custom `CreateBookLongRunning` method could be introduced. -- The HTTP method **must** be `GET` or `POST`: - - `GET` **must** be used for methods retrieving data or resource state. - - `POST` **must** be used if the method has side effects or mutates resources - or data. -- The HTTP URI **must** use a `:` character followed by the custom verb - (`:archive` in the above example), and the verb in the URI **must** match the - verb in the name of the RPC. - - If word separation is required, `camelCase` **must** be used. -- The `body` clause in the `google.api.http` annotation **should** be `"*"`. - - See [HTTP and gRPC Transcoding][transcoding] for more information. -- Custom methods **should** take a request message matching the RPC - name, with a `Request` suffix. -- Custom methods **should** return a response message matching the RPC - name, with a `Response` suffix. - - When operating on a specific resource, a custom method **may** return the - resource itself. - - -### Resource-based custom methods - -Custom methods **must** operate on a resource if the API can be modeled -as such: - -```proto -// Archives the given book. -rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:archive" - body: "*" - }; -} -``` - -- The parameter for the resource's name **must** be called `name`, and - be the only variable in the URI path. - -### Collection-based custom methods - -While most custom methods operate on a single resource, some custom methods -**may** operate on a collection instead: - -```proto -// Sorts the books from this publisher. -rpc SortBooks(SortBooksRequest) returns (SortBooksResponse) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:sort" - body: "*" - }; -} -``` - -- If the collection's resource has a parent, that resource **must** be called - `parent` and be the only variable in the URI path. -- The collection key (`books` in the above example) **must** be literal. - -### Stateless methods - -Some custom methods are not attached to resources at all. These methods are -generally _stateless_: they accept a request and return a response, and have no -permanent effect on data within the API. - -```proto -// Translates the provided text from one language to another. -rpc TranslateText(TranslateTextRequest) returns (TranslateTextResponse) { - option (google.api.http) = { - post: "/v1/{project=projects/*}:translateText" - body: "*" - }; -} -``` - -- If the method runs in a particular scope (such as a project, as in the above - example), the field name in the request message **should** be the name of the - scope resource. If word separators are necessary, `snake_case` **must** be - used. -- The URI **should** place both the verb and noun after the `:` separator - (avoid a "faux collection key" in the URI in this case, as there is no - collection). For example, `:translateText` is preferable to `text:translate`. -- Stateless methods **must** use `POST` if they involve billing. - -### Declarative-friendly resources - -Declarative-friendly resources usually **should not** employ custom methods -(except specific declarative-friendly custom methods discussed in other AIPs), -because declarative-friendly tools are unable to automatically determine what -to do with them. - -An exception to this is for rarely-used, fundamentally imperative operations, -such as a `Move` or `Rename` operation, for which there would not be an -expectation of declarative support. - -## Rationale - -### HTTP path - -Similar to standard methods, a custom method that operates on a resource or -collection needs a `name` or `parent` parameter to indicate the resource that it -operates on. This convention allows clients to map custom methods to the -appropriate resource. - -### HTTP methods - -Allowing both `GET` and `POST` HTTP verbs allows a clear distinction for -which methods do not mutate data, and which ones do. Methods that only -read data have first-class concepts in some clients (DataSources in -Terraform) and clearly indicate to a user which methods can be called -without risk of runtime impact. - -### Disallowing prepositions - -Generally, method names with prepositions indicate that a new method is being -used where a field should instead be added to an existing method, or the method -should use a distinct verb. For example, if a `CreateBook` message already -exists and you are considering adding `CreateBookFromDictation`, consider a -`TranscribeBook` method instead. Similarly, if there is desire for a -property-specific look-up method, instead of `GetBookByAuthor` consider a -`SearchBooks` with an `author` field as a search dimension. This helps prevent -an explosion of hyper-focused methods that bloat API and client surfaces, and -add complexity to both managing and consuming the API. - -[get]: ./0131.md -[list]: ./0132.md -[create]: ./0133.md -[update]: ./0134.md -[delete]: ./0135.md -[transcoding]: ./0127.md - -### RPC name - -The term "async" is commonly used in programming languages to indicate whether -a specific method call is synchronous or asynchronous, including for making RPCs. -That sync/async aspect is at a different abstraction level to whether the RPC -itself is intended to start a long-running operation. Using "async" within the -RPC name itself causes confusion, and can even cause issues for client libraries -which generate both synchronous and asynchronous methods to call the RPC in some -languages. - -## Changelog - -- **2025-05-12:** Extend disallowing prepositions rationale. -- **2025-01-09:** Add original rationale for disallowing prepositions in names. -- **2023-11-16:** Included link to AIP-127 "HTTP and gRPC Transcoding" for guidance on body definition. -- **2023-05-16:** Added prohibition of the term "async" within RPC names. -- **2023-05-09:** Adding guidance for POST and GET, require parent instead of - the resource singular. -- **2023-03-02:** Explicitly discourage use of standard method verbs. -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-10-06:** Added declarative-friendly guidance. -- **2019-08-01:** Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0140.md b/aip/general/0140.md deleted file mode 100644 index 82a95616d1..0000000000 --- a/aip/general/0140.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -id: 140 -state: approved -created: 2019-07-22 -placement: - category: fields - order: 0 ---- - -# Field names - -Naming fields in a way that is intuitive to users can often be one of the most -challenging aspects of designing an API. This is true for many reasons; often a -field name that seems entirely intuitive to the author can baffle a reader. - -Additionally, users rarely use only one API; they use many APIs together. As a -result, a single company using the same name to mean different things (or -different names to mean the same thing) can often cause unnecessary confusion, -because users can no longer take what they've already learned from one API and -apply that to another. - -In short, APIs are easiest to understand when field names are simple, -intuitive, and consistent with one another. - -## Guidance - -Field names **should** be in correct American English. - -Field names **should** clearly and precisely communicate the concept being -presented and avoid overly general names that are ambiguous. That said, field -names **should** avoid including unnecessary words. In particular, avoid -including adjectives that always apply and add little cognitive value. For -example, a `proxy_settings` field might be as helpful as -`shared_proxy_settings` if there is no unshared variant. - -**Important:** Field names often appear in generated client surfaces. Ensure they -are appropriately descriptive and of suitable length. - -### Case - -Field definitions in protobuf files **must** use `lower_snake_case` names. -These names are mapped to an appropriate naming convention in JSON and in -generated code. - -Additionally, each word in the field **must not** begin with a number, because -it creates ambiguity when converting between snake case and camel case. -Similarly, fields **must not** contain leading, trailing, or adjacent -underscores. - -### Uniformity - -APIs **should** endeavor to use the same name for the same concept and -different names for different concepts wherever possible. This includes names -across multiple APIs, in particular if those APIs are likely to be used -together. - -### Repeated fields - -Repeated fields **must** use the proper plural form, such as `books` or -`authors`. On the other hand, non-repeated fields **should** use the singular -form such as `book` or `author`. This implies that resource names **should** -use the singular form as well, since the field name should follow the resource -name (e.g., use `repeated Book books`, **not** `Books books = 1`). - -### Prepositions - -Field names **should not** include prepositions (such as "with", "for", "at", -"by", etc). For example: - -- `error_reason` (**not** `reason_for_error`) -- `author` (**not** `written_by`) - -It is easier for field names to match more often when following this -convention. Additionally, prepositions in field names may also indicate a -design concern, such as an overly-restrictive field or a sub-optimal data type. -This is particularly true regarding "with": a field named `book_with_publisher` -likely indicates that the book resource may be improperly structured and worth -redesigning. - -**Note:** The word "per" is an exception to this rule. See [AIP-141][] for -guidance in the case where "per" is used as part of a unit (e.g. "miles per hour"). - -### Abbreviations - -For well known name abbreviations among software developers, such as "config" -and "spec", the abbreviations **should** be used in API definitions instead of -the full spelling. This will make the source code easy to read and write. -Examples: - -- `config` (**not** `configuration`) -- `id` (**not** `identifier`) -- `info` (**not** `information`) -- `spec` (**not** `specification`) -- `stats` (**not** `statistics`) - -Furthermore, well known abbreviations for units **should** be used in field names. -See [AIP-141][] for more guidance on fields that represent quantities. Examples: - -- `distance_km` (**not** `distance_kilometers`) -- `width_px` (**not** `width_pixels`) - -### Adjectives - -For uniformity, field names that contain both a noun and an adjective -**should** place the adjective _before_ the noun. For example: - -- `collected_items` (**not** `items_collected`) -- `imported_objects` (**not** `objects_imported`) - -### Verbs - -Field names **must not** be named to reflect an intent or action. They -**must not** be verbs. Rather, because the field defines the *desired -value* for mutations, e.g. Create and Update, and the *current value* -for reads, e.g. Get and List, the name **must** be a noun. It defines -what is so, not what to do. - -- `collected_items` (**not** `collect_items`) -- `disabled` (**not** `disable`) - -In contrast, method names, whether standard or custom, change facets of -resources and are named as verbs. - -### Booleans - -Boolean fields **should** omit the prefix "is". For example: - -- `disabled` (**not** `is_disabled`) -- `required` (**not** `is_required`) - -**Note:** Field names that would otherwise be [reserved words](#reserved-words) -are an exception to this rule. For example, `is_new` (**not** `new`). - -### String vs. bytes - -When using `bytes`, the contents of the field are base64-encoded when using -JSON on the wire. Services **should** use `bytes` when there is a need to send -binary contents over the wire, and **should not** ask the user to manually -base64-encode a field into a `string` field. The one exception is when the -API is designed to handle data that is meant to be base64-encoded at rest and -the double base64-encoding as a result of using `bytes` is undesirable - in -this case, services **may** use a `string`. - -### URIs - -Field names representing arbitrary URIs **should** use `uri`. In particular, -note that URLs are URIs but not all URIs are URLs. - -Field names **may** use a prefix in front of `uri` as appropriate. - -Field names that can only represent a URL **should** use `url`. - -```proto -message Book { - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // A URL pointing to an image of the book. - string image_url = 2; - - // A URI identifying the book. - // This could be an ISBN or a URL. - string uri = 3; -} -``` - -**Note:** APIs that have previously used `uri` for URL fields may continue to -do so to avoid unnecessary API changes and to preserve local consistency. - -### Reserved words - -Field names **should** avoid using names that are likely to conflict with -keywords in common programming languages, such as `new`, `class`, `function`, -`import`, etc. Reserved keywords can cause hardship for developers using the -API in that language. - -### Conflicts - -Messages **should not** include a field with the same name as the enclosing -message (ignoring case transformations). This causes conflicts when generating -code in some languages. - -### Display names - -Many resources have a human-readable name, often used for display in UI. This -field **should** be called `display_name`, and **should not** have a uniqueness -requirement. - -If an entity has an official, formal name (such as a company name or the title -of a book), an API **may** use `title` as the field name instead. The `title` -field **should not** have a uniqueness requirement. - -## Further reading - -- For naming resource fields, see [AIP-122][]. -- For naming fields representing quantities, see [AIP-141][]. -- For naming fields representing time, see [AIP-142][]. - -## Rationale - -### URI vs URL - -The guidance itself mentions that all URLs are URIs, but not all URIs are URLs. -The goal of aligning on URI is to enable a more generalizable field, that can -handle a variety of use cases, as well as drive standardization across APIs, -creating a more coherent surface. At the same time, the requirement being a -**should** allows for more specific terms when it truly merits it. - -## Changelog - -- **2025-10-23**: Call out AIP-141 unit abbreviations as preferred. -- **2025-03-10**: Add rationale for URI guidance. -- **2024-12-20**: Copy over abbreviations guidance from old design site. -- **2024-08-26**: Codify exception to string and base64 guidance -- **2024-05-18**: Documented the effect of field names on client surfaces. -- **2023-04-25**: Field names **must not** be expressed as verbs. -- **2021-07-12**: Normalized display name guidance to "should". -- **2021-04-07**: Added base64 and bytes guidance. -- **2021-03-05**: Added prohibition on leading, trailing, or adjacent - underscores. -- **2020-06-10**: Added prohibition on starting any word with a number. -- **2020-05-29**: Added guidance around URIs. -- **2020-03-24**: Added guidance around conflicting field and message names. -- **2020-01-30**: Added guidance around `display_name` and `title`. - -[aip-122]: ./0122.md -[aip-141]: ./0141.md -[aip-142]: ./0142.md diff --git a/aip/general/0141.md b/aip/general/0141.md deleted file mode 100644 index 51f27a4b57..0000000000 --- a/aip/general/0141.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -id: 141 -state: approved -created: 2019-07-18 -placement: - category: fields - order: 20 ---- - -# Quantities - -Many services need to represent a discrete quantity of items (number of bytes, -number of miles, number of nodes, etc.). - -## Guidance - -Quantities with a clear unit of measurement (such as bytes, miles, and so on) -**must** include the unit of measurement as the suffix. When appropriate, units -**should** use generally accepted abbreviations, and abbreviations **should not** -be pluralized (for example, `distance_km` rather than `distance_kilometers`). - -```proto -// A representation of a non-stop air route. -message Route { - // The airport where the route begins. - string origin = 1; - - // The destination airport. - string destination = 2; - - // The distance between the origin and destination airports. - // This value is also used to determine the credited frequent flyer miles. - int32 distance_miles = 3; -} -``` - -If the quantity is a number of items (for example, the number of nodes in a -cluster), then the field **should** use the suffix `_count` (**not** the prefix -`num_`): - -```proto -// A cluster of individual nodes. -message Cluster { - // The number of nodes in the cluster. - int32 node_count = 1; -} -``` - -**Note:** Fields **must not** use unsigned integer types, because many -programming languages and systems do not support them well. - -### Compound units - -Quantities with compound units of measurement **may** use separating underscores -between units as needed for clarity. Unabbreviated units **must** be separated. -Abbreviated units **should not** be separated unless otherwise ambiguous. -Compound units **should** be in plural form, with all component units in -singular form except for the final component unit, which should be in plural -form unless abbreviated. - -- `energy_kwh` (**not** `energy_kw_h`) -- `energy_kw_fortnights` (**not** `energy_kwfortnight` or `energy_kw_fortnight`) - -**Note:** Metric prefixes **must not** be separated from their base unit. - -### Inverse units - -Quantities with units of measurement that are or include inverse units -**should** indicate all inverse units as a compound unit after a compound -of any non-inverse units, separated by the word "per". -The inverse compound unit **should** be in singular form. - -- `speed_miles_per_hour` (**not** `speed_mph`) -- `speed_meters_per_second` (**not** `speed_meters_per_seconds` or `speed_meter_per_second`) -- `event_count_per_hour` (**not** `events_per_hour`, `event_counts_per_hour`, or `hourly_events`) -- `price_per_kwh` (using [`google.type.Money`][money]) - -**Note:** This guidance does not apply in cases where generally accepted derived -units with special names and symbols exist for inverse quantities. For example, -the derived unit 'hertz' **should** be used when appropriate for reciprocal time. - -### Specialized messages - -It is sometimes useful to create a message that represents a particular -quantity. This is particularly valuable in two situations: - -- Grouping two or more individual quantities together. Example: - [`google.protobuf.Duration`][duration] -- Representing a common concept where the unit of measurement may itself vary. - Example: [`google.type.Money`][money] - -APIs **may** create messages to represent quantities when appropriate. When -using these messages as fields, APIs **should** use the name of the message as -the suffix for the field name if it makes intuitive sense to do so. - -## Changelog - -- **2025-07-09**: Added guidance for compound units. -- **2025-07-09**: Clarified guidance to not pluralize abbreviated units. -- **2025-07-09**: Clarified guidance to use per_ prefix to represent inverse units. -- **2019-09-13**: Added the prohibition on uint and fixed types. - - -[duration]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/duration.proto -[money]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto - diff --git a/aip/general/0142.md b/aip/general/0142.md deleted file mode 100644 index 9370fe1f72..0000000000 --- a/aip/general/0142.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -id: 142 -state: approved -created: 2019-07-16 -placement: - category: fields - order: 30 ---- - -# Time and duration - -Many services need to represent the concepts surrounding time. Representing -time can be challenging due to the intricacies of calendars and time zones, as -well as the fact that common exchange formats (such as JSON) lack a native -concept of time. - -## Guidance - -Fields representing time **should** use the common, generally used components -(such as [`google.protobuf.Timestamp`][timestamp] or -[`google.type.Date`][date]) for representing time or duration types. These -types are [common components][aip-213], and using them consistently allows -infrastructure and tooling to provide a better experience when interacting with -time values. - -### Timestamps - -Fields that represent an absolute point in time (independent of any time zone -or calendar) **should** use the [`google.protobuf.Timestamp`][timestamp] type, -(which uses UNIX timestamps under the hood and hold nanosecond precision). - -These fields **should** have names ending in `_time`, such as `create_time` or -`update_time`. For repeated fields, the names **should** end in `_times` -instead. - -Many timestamp fields refer to an activity (for example, `create_time` refers -to when the applicable resource was created). For these, the field **should** -be named with the `{imperative}_time` form. For example, if a book is being -published, the field storing the time when this happens would use the -imperative form of the verb "to publish" ("publish") resulting in a field -called `publish_time`. Fields **should not** be named using the past tense -(such as `published_time`, `created_time` or `last_updated_time`). - -### Durations - -Fields that represent a span between two points in time (independent of any -time zone or calendar) **should** use the -[`google.protobuf.Duration`][duration] type. - -To illustrate the distinction between timestamps and durations, consider a -flight record: - -```proto -// A representation of a (very incomplete) flight log. -message FlightRecord { - // The absolute point in time when the plane took off. - google.protobuf.Timestamp takeoff_time = 1; - - // The length (duration) of the flight, from takeoff to landing. - google.protobuf.Duration flight_duration = 2; -} -``` - -**Note:** Observant readers may notice that the [timestamp][] and [duration][] -messages have the same structure (`int64 seconds` and `int32 nanos`). However, -the distinction between these is important, because they have different -semantic meaning. Additionally, tooling is able to base behavior off of which -message is used. For example, a Python-based tool could convert timestamps to -[datetime][py_datetime] objects and durations to [timedelta][py_timedelta] -objects. - -### Relative time segments - -In some cases, it may be necessary to represent a time segment inside a stream. -In these cases, the [`google.protobuf.Duration`][duration] type **should** be -used, and the field name **should** end with `_offset`. To ensure that the -meaning is clear, the field **must** have a comment noting the point that the -offset is relative to. - -To illustrate this, consider a resource representing a segment of an audio -stream: - -```proto -message AudioSegment { - // The duration relative to the start of the stream representing the - // beginning of the segment. - google.protobuf.Duration start_offset = 1; - - // The total length of the segment. - google.protobuf.Duration segment_duration = 2; -} -``` - -### Civil dates and times - -Fields that represent a calendar date or wall-clock time **should** use the -appropriate common components: - -- Civil date: [`google.type.Date`][date] -- Wall-clock time: [`google.type.TimeOfDay`][time_of_day] - -Fields representing civil dates **should** have names ending in `_date`, while -fields representing civil times or datetimes **should** have names ending in -`_time`. - -**Note:** Both the `Date` and `TimeOfDay` components are timezone-naïve. Fields -that require timezone-awareness **should** use `DateTime` (see below). - -### Civil timestamps - -Fields that represent a civil timestamp (date and time, optionally with a time -zone) **should** use the [`google.type.DateTime`][datetime] component, and the -field name **should** end in `_time`. - -### Compatibility - -Occasionally, APIs are unable to use the common structures for legacy or -compatibility reasons. For example, an API may conform to a separate -specification that mandates that timestamps be integers or [ISO-8601][] -strings. - -In these situations, fields **may** use other types. If possible, the following -naming conventions apply: - -- For integers, include the meaning (examples: `time`, `duration`, `delay`, - `latency`) **and** the unit of measurement (valid values: `seconds`, - `millis`, `micros`, `nanos`) as a final suffix. For example, - `send_time_millis`. -- For strings, include the meaning (examples: `time`, `duration`, `delay`, - `latency`) but no unit suffix. - -In all cases, clearly document the expected format, and the rationale for its -use. - - -[aip-213]: ./0213.md -[date]: https://github.com/googleapis/googleapis/blob/master/google/type/date.proto -[datetime]: https://github.com/googleapis/googleapis/blob/master/google/type/datetime.proto -[duration]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/duration.proto -[iso-8601]: https://www.iso.org/iso-8601-date-and-time-format.html -[py_datetime]: https://docs.python.org/3/library/datetime.html#datetime.datetime -[py_timedelta]: https://docs.python.org/3/library/datetime.html#datetime.timedelta -[time_of_day]: https://github.com/googleapis/googleapis/blob/master/google/type/timeofday.proto -[timestamp]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto - diff --git a/aip/general/0143.md b/aip/general/0143.md deleted file mode 100644 index b7431c0389..0000000000 --- a/aip/general/0143.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -id: 143 -state: approved -created: 2019-07-24 -placement: - category: fields - order: 40 ---- - -# Standardized codes - -Many common concepts, such as spoken languages, countries, currency, and so on, -have common codes (usually formalized by the [International Organization for -Standardization][iso]) that are used in data communication and processing. -These codes address the issue that there are often different ways to express -the same concept in written language (for example, "United States" and "USA", -or "Español" and "Spanish"). - -## Guidance - -For concepts where a standardized code exists and is in common use, fields -representing these concepts **should** use the standardized code for both input -and output. - -```proto -// A message representing a book. -message Book { - // Other fields... - - // The IETF BCP-47 language code representing the language in which - // the book was originally written. - // https://en.wikipedia.org/wiki/IETF_language_tag - string language_code = 99; -} -``` - -- Fields representing standardized concepts **must** use the appropriate data - type for the standard code (usually `string`). - - Fields representing standardized concepts **should not** use enums, even if - they only allow a small subset of possible values. Using enums in this - situation often leads to frustrating lookup tables when using multiple APIs - together. - - Fields representing standardized concepts **must** indicate which standard - they follow, preferably with a link (either to the standard itself, the - Wikipedia description, or something similar). -- The field name **should** end in `_code` or `_type` unless the concept has an - obviously clearer suffix. -- When accepting values provided by users, validation **should** be - case-insensitive unless this would introduce ambiguity (for example, accept - both `en-gb` and `en-GB`). When providing values to users, APIs **should** - use the canonical case (in the example above, `en-GB`). - -### Content types - -Fields representing a content or media type **must** use [IANA media types][]. -For legacy reasons, the field **should** be called `mime_type`. - -### Countries and regions - -Fields representing individual countries or nations **must** use the [Unicode -CLDR region codes][cldr] ([list][]), such as `US` or `CH`, and the field -**must** be called `region_code`. - -**Important:** Please read the [rationale](#countryregion-field-naming) for this -requirement. - -### Currency - -Fields representing currency **must** use [ISO-4217 currency codes][iso-4217], -such as `USD` or `CHF`, and the field **must** be called `currency_code`. - -**Note:** For representing an amount of money in a particular currency, rather -than the currency code itself, use [`google.type.Money`][money]. - -### Language - -Fields representing spoken languages **must** use [IETF BCP-47 language -codes][bcp-47] ([list][]), such as `en-US` or `de-CH`, and the field **must** -be called `language_code`. - -### Time zones - -Fields representing a time zone **should** use the [IANA TZ][] codes, and the -field **must** be called `time_zone`. - -Fields also **may** represent a UTC offset rather than a time zone (note that -these are subtly different). In this case, the field **must** use the [ISO-8601 -format][] to represent this, and the field **must** be named `utc_offset`. - -## Rationale - -### Country/region field naming - -The use of `region_code` instead of `country_code` is critical to being able to -convey regions that are distinct from any country and to avoid any political -disputes associated with said region regarding their sovereignty or affiliation. -Google and many other companies are supporters of Unicode CLDR and standardize -their product internationalization efforts on Unicode CLDR, and APIs are no -different here. Furthermore, many of the values supported by Unicode CLDR are -not countries on their own, so using a more generic name is actually more -compatible with the specification. - -## Changelog - -- **2024-12-03**: Strengthen rationale of country/region field naming -- **2024-11-12**: Change country/region code list to CLDR list from IANA list -- **2020-05-12**: Replaced `country_code` guidance with `region_code`, - correcting an original error. - - -[bcp-47]: https://en.wikipedia.org/wiki/IETF_language_tag -[cldr]: http://cldr.unicode.org/ -[iana media types]: https://www.iana.org/assignments/media-types/media-types.xhtml -[iana tz]: http://www.iana.org/time-zones -[iso]: https://www.iso.org/ -[iso-4217]: https://en.wikipedia.org/wiki/ISO_4217 -[iso-8601 format]: https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC -[list]: https://www.unicode.org/cldr/charts/46/supplemental/territory_information.html -[money]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto - diff --git a/aip/general/0144.md b/aip/general/0144.md deleted file mode 100644 index 0276c350d7..0000000000 --- a/aip/general/0144.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -id: 144 -state: approved -created: 2020-03-19 -updated: 2022-06-02 -placement: - category: fields - order: 50 ---- - -# Repeated fields - -Representing lists of data in an API is trickier than it often appears. Users -often need to modify lists in place, and longer data series within a single -resource pose a challenge for pagination. - -## Guidance - -Resources **may** use repeated fields where appropriate. - -```proto -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - repeated string authors = 2; -} -``` - -- Repeated fields **must** use a plural field name. - - If the English singular and plural words are identical ("moose", "info"), - the dictionary word **must** be used rather than attempting to coin a new - plural form. -- Repeated fields **should** have an enforced upper bound that will not cause a - single resource payload to become too large. A good rule of thumb is 100 - elements. - - If repeated data has the chance of being too large, the API **should** use - a sub-resource instead. -- Repeated fields **must not** represent the body of another resource inline. - Instead, the message **should** provide the resource names of the associated - resources. - -### Scalars and messages - -Repeated fields **should** use a scalar type (such as `string`) if they are -certain that additional data will not be needed in the future, as using a -message type adds significant cognitive overhead and leads to more complicated -code. - -However, if additional data is likely to be needed in the future, repeated -fields **should** use a message instead of a scalar proactively, to avoid -parallel repeated fields. - -### Update strategies - -A resource **may** use two strategies to enable updating a repeated field: -direct update using the [standard `Update`][aip-134] method, or custom `Add` -and `Remove` methods. - -A standard `Update` method has one key limitation: the user is only able to -update _the entire_ list. Field masks are unable to address individual entries -in a repeated field. This means that the user must read the resource, make -modifications to the repeated field value as needed, and send it back. This is -fine for many situations, particularly when the repeated field is expected to -have a small size (fewer than 10 or so) and race conditions are not an issue, -or can be guarded against with [ETags][aip-154]. - -**Note:** Declarative-friendly resources **must** use the standard `Update` -method, and not introduce `Add` and `Remove` methods. If declarative tools need -to reason about particular relationships while ignoring others, consider using -a subresource instead. - -If atomic modifications are required, the API **should** define custom methods -using the verbs `Add` and `Remove`: - -**Note:** If both of these strategies are too restrictive, consider using a -subresource instead. - -```proto -rpc AddAuthor(AddAuthorRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{book=publishers/*/books/*}:addAuthor" - body: "*" - }; -} - -rpc RemoveAuthor(RemoveAuthorRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{book=publishers/*/books/*}:removeAuthor" - body: "*" - }; -} -``` - -- The data being added or removed **should** be a primitive (usually a - `string`). - - For more complex data structures with a primary key, the API **should** use - a map with the `Update` method instead. -- The RPC's name **must** begin with the word `Add` or `Remove`. The remainder - of the RPC name **should** be the singular form of the field being added. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response message **should** be the resource itself, unless there is useful - context to provide in the response, in which case the response message must - match the RPC name, with a `Response` suffix. - - When the response is the resource itself, it **should** include the - fully-populated resource. -- The HTTP verb **must** be `POST`, as is usual for [custom methods][aip-136]. -- The HTTP URI **must** end with `:add*` or `:remove*`, where `*` is the - snake-case singular name of the field being added or removed. -- The request message field receiving the resource name **should** map to the - URI path. - - The HTTP variable **should** be the name of the resource (such as `book`) - rather than `name` or `parent`. - - That variable **should** be the only variable in the URI path. -- The body clause in the `google.api.http` annotation **should** be `"*"`. -- If the data being added in an `Add` RPC is already present, the method - **must** error with `ALREADY_EXISTS`. -- If the data being removed in a `Remove` RPC is not present, the method - **must** error with `NOT_FOUND`. - -#### Request Message - -```proto -message AddAuthorRequest { - // The name of the book to add an author to. - string book = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference).type = "library.googleapis.com/Book" - ]; - - string author = 2 [(google.api.field_behavior) = REQUIRED]; -} - -message RemoveAuthorRequest { - // The name of the book to remove an author from. - string book = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference).type = "library.googleapis.com/Book" - ]; - - string author = 2 [(google.api.field_behavior) = REQUIRED]; -} -``` - -- A resource field **must** be included. It **should** be the name of the - resource (such as `book`) rather than `name` or `parent`. - - The field **should** be [annotated as required][aip-203]. - - The field **should** identify the [resource type][aip-123] that it - references. -- A field for the value being added or removed **must** be included. It - **should** be the singular name of the field. - - The field **should** be [annotated as required][aip-203]. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. - -## Changelog - -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-10-17**: Recommended returning the resource itself in Add and Remove - RPCs over separate response types. -- **2020-10-17**: Added guidance for Add and Remove RPCs and requests. - -[aip-123]: ./0123.md -[aip-134]: ./0134.md -[aip-136]: ./0136.md -[aip-154]: ./0154.md -[aip-203]: ./0203.md diff --git a/aip/general/0145.md b/aip/general/0145.md deleted file mode 100644 index a03173ae1e..0000000000 --- a/aip/general/0145.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -id: 145 -state: approved -created: 2020-05-28 -placement: - category: fields - order: 60 ---- - -# Ranges - -Services often need to represent ranges of discrete or continuous values. These -have wide differences in meaning, and come in many types: integers, floats, and -timestamps, just to name a few, and the expected meaning of a range can vary in -subtle ways depending on the type of range being discussed. - -## Guidance - -A resource or message representing a range **should** ordinarily use two -separate fields of the same type, with prefixes `start_` and `end_`: - -```proto -// A representation of a chapter in a book. -message Chapter { - string title = 1; - - // The page where this chapter begins. - int32 start_page = 2; - - // The page where the next chapter or section begins. - int32 end_page = 3; -} -``` - -### Inclusive or exclusive ranges - -Fields representing ranges **should** use inclusive start values and exclusive -end values (half-closed intervals) in most situations; in interval notation: -`[start_xxx, end_xxx)`. - -Exclusive end values are preferable for the following reasons: - -- It conforms to user expectations, particularly for continuous values such as - timestamps, and avoids the need to express imprecise "limit values" (e.g. - `2012-04-20T23:59:59`). -- It is consistent with most common programming languages, including C++, Java, - Python, and Go. -- It is easier to reason about abutting ranges: `[0, x), [x, y), [y, z)`, where - values are chainable from one range to the next. - -### Timestamp intervals - -The following section describes the use of the [google.type.Interval][interval] -type, found amongst the common protos that are described in [AIP-213][]. -This type represents a range between two timestamps, with an inclusive start -value and exclusive end value. - -Ranges between two timestamps which conform to the expectations of the -`Interval` message **should** use this rather than having separate start and -end fields. This allows client code to be written against the `Interval` -message (such as checking whether a given timestamp occurs within the interval) -and reused across multiple intervals in the same API, or even across multiple -APIs. - -APIs **may** use start and end timestamp fields instead. In particular, if a -message within an API is inherently describing an interval with extra -information about that interval, the additional level of nesting introduced -by using the `Interval` message may be undesirable. - -### Exceptions - -In some cases, there is significant colloquial precedent for inclusive start -and end values (closed intervals), to the point that using an exclusive end -value would be confusing even for people accustomed to them. - -For example, when discussing dates (not to be confused with timestamps), most -people use inclusive end: a conference with dates "April 21-23" is expected to -run for three days: April 21, April 22, and April 23. This is also true for -days of the week: a business that is open "Monday through Friday" is open, not -closed, on Fridays. - -In this situation, the prefixes `first` and `last` **should** be used instead: - -```proto -// A representation of a chapter in a book. -message Chapter { - string title = 1; - - // The first page of the chapter. - int32 first_page = 2; - - // The last page of the chapter. - int32 last_page = 3; -} -``` - -Fields representing ranges with significant colloquial precedent for inclusive -start and end values **should** use inclusive end values with `first_` and -`last_` prefixes for those ranges only. The service **should** still use -exclusive end values for other ranges where this does not apply, and **must** -clearly document each range as inclusive or exclusive. - -[aip-213]: ./0213.md -[interval]: https://github.com/googleapis/googleapis/blob/master/google/type/interval.proto diff --git a/aip/general/0146.md b/aip/general/0146.md deleted file mode 100644 index 08bd9cc672..0000000000 --- a/aip/general/0146.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -id: 146 -state: approved -created: 2019-05-28 -placement: - category: fields - order: 70 ---- - -# Generic fields - -Most fields in any API, whether in a request, a resource, or a custom response, -have a specific type or schema. This schema is part of the contract that -developers write their code against. - -However, occasionally it is appropriate to have a generic or polymorphic field -of some kind that can conform to multiple schemata, or even be entirely -free-form. - -## Guidance - -While generic fields are generally rare, a service **may** introduce generic -field where necessary. There are several approaches to this depending on how -generic the field needs to be; in general, services **should** attempt to -introduce the "least generic" approach that is able to satisfy the use case. - -### Oneof - -A `oneof` **may** be used to introduce a type union: the user or service is -able to specify one of the fields inside the `oneof`. Additionally, a `oneof` -**may** be used with the same type (usually strings) to represent a semantic -difference between the options. - -Because the individual fields in the `oneof` have different keys, a developer -can programmatically determine which (if any) of the fields is populated. - -A `oneof` preserves the largest degree of type safety and semantic meaning for -each option, and services **should** generally prefer them over other generic -or polymorphic options when feasible. However, the `oneof` construct is -ill-suited when there is a large (or unlimited) number of potential options, or -when there is a large resource structure that would require a long series of -"cascading oneofs". - -**Note:** Adding additional possible fields to an existing `oneof` is a -non-breaking change, but moving existing fields into or out of a `oneof` is -breaking (it creates a backwards-incompatible change in Go protobuf stubs). - -### Maps - -Maps **may** be used in situations where many values _of the -same type_ are needed, but the keys are unknown or user-determined. - -Maps are usually not appropriate for generic fields because the map values all -share a type, but occasionally they are useful. In particular, a map can -sometimes be suited to a situation where many objects of the same type are -needed, with different behavior based on the names of their keys (for example, -using keys as environment names). - -### Struct - -The [`google.protobuf.Struct`][struct] object **may** be used to represent arbitrary -nested JSON. Keys can be strings, and values can be floats, strings, booleans, -arrays, or additional nested structs, allowing for an arbitrarily nested -structure that can be represented as JSON (and is automatically represented as -JSON when using REST/JSON). - -A `Struct` is most useful when the service does not know the schema in advance, -or when a service needs to store and retrieve arbitrary but structured user -data. Using a `Struct` is convenient for users in this case because they can -easily get JSON objects that can be natively manipulated in their environment -of choice. - -If a service needs to reason about the _schema_ of a `Struct`, it **should** -use [JSONSchema][] for this purpose. Because JSONSchema is itself JSON, a valid -JSONSchema document can itself be stored in a `Struct`. - -### Any - -The [`google.protobuf.Any`][any] object can be used to send an arbitrary -serialized protocol buffer and a type definition. - -However, this introduces complexity, because an `Any` becomes useless for any -task other than blind data propagation if the consumer does not have access to -the proto. Additionally, even if the consumer _does_ have the proto, the -consumer has to ensure the type is registered and then deserialize manually, -which is an often-unfamiliar process. - -Because of this, `Any` **should not** be used unless other options are -infeasible. - - -[any]: https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/any.proto -[struct]: https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/struct.proto -[JSONSchema]: https://json-schema.org/ - diff --git a/aip/general/0147.md b/aip/general/0147.md deleted file mode 100644 index a9e4dea5ab..0000000000 --- a/aip/general/0147.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: 147 -state: approved -created: 2020-07-24 -placement: - category: fields - order: 80 ---- - -# Sensitive fields - -Sometimes APIs need to collect sensitive information such as private encryption -keys meant to be _stored_ by the underlying service but not intended to be -_read_ after writing due to the sensitive nature of the data. For this type of -data, extra consideration is required for the representation of the sensitive -data in API requests and responses. - -## Guidance - -If the sensitive information is _required_ for the resource as a whole to -exist, the data **should** be accepted as an [input-only field][input-only] -with no corresponding output field. Because the sensitive data must be present -for the resource to exist, users of the API may assume that existence of the -resource implies storage of the sensitive data. For example: - -```proto -message SelfManagedKeypair { - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The public key data in PEM-encoded form. - bytes public_key = 2; - - // The private key data in PEM-encoded form. - bytes private_key = 3 [ - (google.api.field_behavior) = INPUT_ONLY]; -} -``` - -If the sensitive information is _optional_ within the containing resource, an -[output-only][] boolean field with a postfix of `_set` **should** be used to -indicate whether or not the sensitive information is present. For example: - -```proto -message Integration { - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - string uri = 2; - - // A secret to be passed in the `Authorization` header of the webhook. - string shared_secret = 3 [ - (google.api.field_behavior) = INPUT_ONLY]; - - // True if a `shared_secret` has been set for this Integration. - bool shared_secret_set = 4 [ - (google.api.field_behavior) = OUTPUT_ONLY]; -} -``` - -If it is important to be able to identify the sensitive information without -allowing it to be read back entirely, a field of the same type with an -`obfuscated_` prefix **may** be used instead of the boolean `_set` field to -provide contextual information about the sensitive information. The specific -nature of the obfuscation is outside the scope of this AIP. For example: - -```proto -message AccountRecoverySettings { - // An email to use for account recovery. - string email = 1 [ - (google.api.field_behavior) = INPUT_ONLY]; - - // An obfuscated representation of the recovery email. For example, - // `ada@example.com` might be represented as `a**@e*****e.com`. - string obfuscated_email = 2 [ - (google.api.field_behavior) = OUTPUT_ONLY]; -} -``` - - -[input-only]: ./0203.md#input-only -[output-only]: ./0203.md#output-only - diff --git a/aip/general/0148.md b/aip/general/0148.md deleted file mode 100644 index e75599e831..0000000000 --- a/aip/general/0148.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -id: 148 -state: approved -created: 2020-10-06 -placement: - category: fields - order: 90 ---- - -# Standard fields - -Certain concepts are common throughout any corpus of APIs. In these situations, -it is useful to have a standard field name and behavior that is used -consistently to communicate that concept. - -## Guidance - -Standard fields **should** be used to describe their corresponding concept, and -**should not** be used for any other purpose. - -### Resource names and IDs - -#### name - -Every resource **must** have a `string name` field, used for the resource name -(AIP-122), which **should** be the first field in the resource. - -**Note:** The `_name` suffix **should not** be used to describe other types of -names unless otherwise covered in this AIP. - -#### parent - -The `string parent` field refers to the resource name of the parent of a -collection, and **should** be used in most `List` (AIP-132) and `Create` -(AIP-133) requests. - -### Other names - -#### display_name - -The `string display_name` field **must** be a mutable, user-settable field -where the user can provide a human-readable name to be used in user interfaces. -[Declarative-friendly resources][] **should** include this field. - -Display names **should not** have uniqueness requirements, and **should** be -limited to <= 63 characters. - -#### title - -The `string title` field **should** be the official name of an entity, such as -a company's name. This is a more formal variant of `string display_name`. - -#### given_name - -The `string given_name` field **must** refer to a human or animal's given name. -Resources **must not** use `first_name` for this concept, because the given -name is not placed first in many cultures. - -#### family_name - -The `string family_name` field **must** refer to a human or animal's family -name. Resources **must not** use `last_name` for this concept, because the -family name is not placed last in many cultures. - -### Timestamps - -#### create_time - -The output only `google.protobuf.Timestamp create_time` field **must** -represent the timestamp when the resource was created. This **may** be either -the time creation was initiated or the time it was completed. -[Declarative-friendly resources][] **should** include this field. - -#### update_time - -The output only `google.protobuf.Timestamp update_time` field **must** -represent the timestamp when the resource was most recently updated. Any change -to the resource made by users **must** refresh this value; changes to a -resource made internally by the service **may** refresh this value. -[Declarative-friendly resources][] **should** include this field. - -#### delete_time - -The output only `google.protobuf.Timestamp delete_time` field **must** represent -the timestamp that a resource was soft deleted. This **may** correspond to either -the time when the user requested deletion, or when the service successfully -soft deleted the resource. If a resource is not soft deleted, the `delete_time` -field **must** be empty. - -Resources that support soft delete (AIP-164) **should** provide this field. - -#### expire_time - -The `google.protobuf.Timestamp expire_time` field **should** represent the time -that a given resource or resource attribute is no longer useful or valid (e.g. a -rotating security key). It **may** be used for similar forms of expiration as -described in AIP-214. - -Services **may** provide an `expire_time` value that is inexact, but the -resource **must not** expire before that time. - -#### purge_time - -The `google.protobuf.Timestamp purge_time` field **should** represent the time -when a soft deleted resource will be purged from the system (see AIP-164). -It **may** be used for similar forms of expiration as described in AIP-214. -Resources that support soft delete **should** include this field. - -Services **may** provide a `purge_time` value that is inexact, but the resource -**must not** be purged from the system before that time. - -### Annotations - -To store small amounts of arbitrary data, a `map annotations` -field **may** be added. - -The `annotations` field **must** use the [Kubernetes limits][] to maintain wire -compatibility, and **should** require dot-namespaced annotation keys to prevent -tools from trampling over one another. - -Examples of information that might be valuable to store in annotations include: - -- For CI/CD, an identifier of the pipeline run or version control identifier - used to propagate. - -**Note:** Annotations are distinct from various forms of labels. Labels can be -used by server-side policies, such as IAM conditions. Annotations exist to -allow client tools to store their own state information without requiring a -database. - -### Well known string fields - -#### IP address - -A field that represents an IP address **must** comply with the following: - -* use type `string` -* use the name `ip_address` or end with the suffix `_ip_address` e.g. - `resolved_ip_address` -* specify the IP address version format via one of the supported formats `IPV4`, - `IPV6`, or if it can be either, `IPV4_OR_IPV6` (see [AIP-202][aip-202]) - -#### uid - -The output only `string uid` field refers to a system-assigned unique -identifier for a resource. When provided, this field **must** be a [UUID4][] -and **must** specify this format via the `UUID4` format extension (see -[AIP-202][aip-202]). [Declarative-friendly resources][] **should** include this -field. - -## Further reading - -- For standardized codes, see AIP-143. -- For the `etag` field, see AIP-154. -- For the `request_id` field, see AIP-155. -- For the `filter` field, see AIP-160. -- For fields related to resource revisions, see AIP-162. -- For the `validate_only` field, see AIP-163. -- For fields related to soft delete and undelete, see AIP-164. - -## Rationale - -### Well known string fields - -Some fields represent very well defined concepts or artifacts that sometimes -also have strict governance of their semantics. For such fields, presenting an -equally standardized API surface is important. This enables development of -improved API consumer tools and documentation, as well as a more unified user -experience across the platform. - -## History - -Before 2023-07, `purge_time` for soft-deleted resources was also called -`expire_time`. `purge_time` was introduced to reduce user confusion. - -## Changelog - -- **2023-10-05**: Introduce well known string fields with IP Address and `uid`. -- **2023-08-14**: Introduce the term `annotations` from AIP-128. -- **2023-07-13**: Introduce the term `purge_time`. -- **2021-04-06**: Require output only field behavior for `uid` and `delete_time` - fields. - - -[aip-202]: ./0202.md -[declarative-friendly resources]: ./0128.md#resources -[kubernetes limits]: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/#syntax-and-character-set -[uuid4]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) \ No newline at end of file diff --git a/aip/general/0149.md b/aip/general/0149.md deleted file mode 100644 index 10e7f31ec7..0000000000 --- a/aip/general/0149.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -id: 149 -state: approved -created: 2021-02-12 -placement: - category: fields - order: 100 ---- - -# Unset field values - -In many messages, many fields are optional: the user is not required to provide -them, or for output fields, the service might not populate the field. - -In most cases, there is no meaningful difference between setting it to a -default value (such as `0`) as opposed to not setting it at all; however, -occasionally this distinction is meaningful. - -## Guidance - -Services defined in protocol buffers **should** use the `optional` keyword for -primitives if and only if it is necessary to distinguish setting the field to -its default value (`0`, `false`, or empty string) from not setting it at all: - -```proto -// A representation of a book in a library. -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - // The name of the book. - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The rating for the book, from 0 to 5. - // 0 is distinct from no rating. - optional int32 rating = 2; -} -``` - -**Important:** Services **should not** need to distinguish between the default -value and unset most of the time; if an alternative design does not require -such a distinction, it is usually preferred. In practice, this means `optional` -**should** only ever be used for integers and floats. - -**Important:** Tracking field presence is *not* the same as documenting API -field behavior as defined in [AIP-203][]. For example, a field labeled with -`optional` for presence tracking **may** also be annotated as -`google.api.field_behavior = REQUIRED` if the field must be set. If you only -want to document the server perceived behavior of a field, read [AIP-203][]. - -### Backwards compatibility - -It is a backwards incompatible change to add or remove the `optional` qualifier -to an existing field. This is because the compiled src API is changed (in some -languages). For example, in Golang, adding `optional` changes the field type of -primitives to be the pointer variant of their original type, e.g. a field -formerly of type `string` becomes `*string`, etc. Accordingly, this change -requires that both clients and servers update their usage of the changed field -in unison, which is risky and error prone. Additional information is -[documented by Protobuf][proto docs]. - -## Rationale - -### field behavior and `optional` - -The field behavior annotation and `optional` label are not mutually exclusive, -because they address different problems. The former, -`google.api.field_behavior`, focuses on communicating the server's perception of -a field within the API e.g. if it is required or not, if it is immutable, etc. -The latter, proto3's `optional`, is a wire format and code generation option -that is strictly for toggling field presence tracking. While it might be -confusing for a field to be simultaneously annotated with -`google.api.field_behavior = REQUIRED` and labeled as `optional`, they are -unrelated in practice and can reasonably be used together. - -## Changelog - -- **2024-06-05**: Add backwards compatibility considerations -- **2023-06-20**: Differentiate from field behavior documentation - -[AIP-203]: ./0203.md -[proto docs]: https://protobuf.dev/programming-guides/field_presence/#considerations-for-change-compatibility diff --git a/aip/general/0151.md b/aip/general/0151.md deleted file mode 100644 index 6e9b24b57c..0000000000 --- a/aip/general/0151.md +++ /dev/null @@ -1,184 +0,0 @@ ---- -id: 151 -state: approved -created: 2019-07-25 -placement: - category: operations - order: 110 ---- - -# Long-running operations - -Occasionally, an API may need to expose a method that takes a significant -amount of time to complete. In these situations, it is often a poor user -experience to simply block while the task runs; rather, it is better to return -some kind of promise to the user and allow the user to check back in later. - -The long-running operations pattern is roughly analogous to a [Python -Future][], or a [Node.js Promise][]. Essentially, the user is given a token -that can be used to track progress and retrieve the result. - -## Guidance - -Individual API methods that might take a significant amount of time to complete -**should** return a [`google.longrunning.Operation`][lro] object instead of the -ultimate response message. - -```proto -// Create a book. -rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books" - body: "book" - }; - option (google.longrunning.operation_info) = { - response_type: "Book" - metadata_type: "OperationMetadata" - }; -} -``` - -- The response type **must** be `google.longrunning.Operation`. The `Operation` - proto definition **must not** be copied into individual APIs. - - The response **must not** be a streaming response. -- The method **must** include a `google.longrunning.operation_info` annotation, - which **must** define both response and metadata types. - - The response and metadata types **must** be defined in the file where the - RPC appears, or a file imported by that file. - - If the response and metadata types are defined in another package, the - fully-qualified message name **must** be used. - - The response type **should not** be `google.protobuf.Empty` (except for - [`Delete`][aip-135] methods), unless it is certain that response data will - _never_ be needed. If response data might be added in the future, define an - empty message for the RPC response and use that. - - The metadata type is used to provide information such as progress, partial - failures, and similar information on each `GetOperation` call. The metadata - type **should not** be `google.protobuf.Empty`, unless it is certain that - metadata will _never_ be needed. If metadata might be added in the future, - define an empty message for the RPC metadata and use that. -- APIs with messages that return `Operation` **must** implement the - [`Operations`][lro] service. Individual APIs **must not** define their own - interfaces for long-running operations to avoid non-uniformity. -- If an RPC supports a [validate-only mode][aip-163], the response to a - validation request **must** be one of the following: - - A successful response with an `Operation` which is already complete, with - the `done` field set to `true`, and a valid (but potentially empty) response - message in the `response` field, wrapped in a `google.protobuf.Any` message. - The `name` field **may** be empty, to avoid the service having to maintain - state for successful validation. - - An immediate error response (typically "bad request") - - An `Operation` with the `done` field set to `false`, to indicate - long-running validation. In this case, the `name` field **must** be set, - to allow clients to poll the long-running validation operation until it - has completed. Successful validation **must** eventually be represented by - an operation with `done=true` and a valid (but potentially empty) wrapped - response message in the `response` field. Unsuccessful validation **must** - eventually be represented by an operation with `done=true` and the error - details provided in the `error` field. - -**Note:** User expectations can vary on what is considered "a significant -amount of time" depending on what work is being done. A good rule of thumb is -10 seconds. - -### Standard methods - -APIs **may** return an `Operation` from the [`Create`][aip-133], -[`Update`][aip-134], or [`Delete`][aip-135] standard methods if appropriate. In -this case, the response type in the `operation_info` annotation **must** be the -standard and expected response type for that standard method. - -When creating or deleting a resource with a long-running operation, the -resource **should** be included in [`List`][aip-132] and [`Get`][aip-131] -calls; however, the resource **should** indicate that it is not usable, -generally with a [state enum][aip-216]. - -### Parallel operations - -A resource **may** accept multiple operations that will work on it in parallel, -but is not obligated to do so: - -- Resources that accept multiple parallel operations **may** place them in a - queue rather than work on the operations simultaneously. -- Resources that do not permit multiple operations in parallel (denying any - new operation until the one that is in progress finishes) **must** return - `ABORTED` if a user attempts a parallel operation, and include an error - message explaining the situation. -- Resources with [declarative-friendly APIs][aip-128] **may** allow subsequent - updates to preempt existing operations. In this case, the latest update - begins processing and previous operations are marked as `ABORTED` with an - error message explaining the situation. - -### Expiration - -APIs **may** allow their operation resources to expire after sufficient time -has elapsed after the operation completed. - -**Note:** A good rule of thumb for operation expiry is 30 days. - -### Errors - -Errors that prevent a long-running operation from _starting_ **must** return an -error response ([AIP-193][]), similar to any other method. - -Operations that fail during their execution phase **must** return an -error response ([AIP-193][]), placed in the `Operation.error` [google.rpc.Status][] -field. - -Non-terminal errors that occur over the course of an operation **may** be placed -in the metadata message and the field(s) **must** be [AIP-193][] compliant -[google.rpc.Status][]. - -### Backwards compatibility - -Changing either the `response_type` or `metadata_type` of a long-running operation -is a breaking change. - -## Rationale - -### Validate-only behavior - -The guidance for validate-only responses comes from a tension -between clients, which benefit from "fully formed" operations that can -be treated uniformly, and servers, which don't wish to maintain -additional state for trivial operations. It seems counterintuitive -that just validating a request should generate more state, but a -full operation response that can be fetched later would either -require that or "special" singleton operation IDs. The guidance -provided is a compromise: by returning a "done" operation, clients -can use existing logic to check that the operation has completed -successfully (and therefore doesn't need to be fetched for an -updated status) but server don't need to maintain any additional state. - - -[aip-128]: ./0128.md -[aip-131]: ./0131.md -[aip-132]: ./0132.md -[aip-133]: ./0133.md -[aip-134]: ./0134.md -[aip-135]: ./0135.md -[aip-163]: ./0163.md -[aip-193]: ./0193.md -[aip-216]: ./0216.md -[google.rpc.Status]: https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto -[lro]: https://github.com/googleapis/googleapis/blob/master/google/longrunning/operations.proto -[node.js promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises -[python future]: https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future - - -## Changelog - -- **2025-02-04**: Clarified error propagation behavior for failures - that occur during long-running operations. -- **2024-04-23**: Provided pattern for validation on RPCs returning - long-running operations. -- **2022-05-31**: Added compatibility section. -- **2020-08-24**: Clarified that responses are not streaming responses. -- **2020-06-24**: Added guidance for parallel operations. -- **2020-03-20**: Clarified that both `response_type` and `metadata_type` are - required. -- **2019-11-22**: Added a short explanation of what `metadata_type` is for. -- **2019-09-23**: Added guidance on errors. -- **2019-08-23**: Added guidance about fully-qualified message names when the - message name is in another package. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0152.md b/aip/general/0152.md deleted file mode 100644 index 2363074467..0000000000 --- a/aip/general/0152.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -id: 152 -state: approved -created: 2020-04-27 -updated: 2022-06-02 -placement: - category: design-patterns - order: 10 ---- - -# Jobs - -Occasionally, APIs may need to expose a task that takes significant time to -complete, and where a transient [long-running operation][aip-151] is not -appropriate. For example, a task could need to run repeatedly, or have separate -permissions for configuring the task as opposed to running it. - -## Guidance - -An API **may** define a `Job` resource to represent a particular task with -distinct setup, configuration, and execution: - -```proto -message WriteBookJob { - option (google.api.resource) = { - type: "library.googleapis.com/WriteBookJob" - pattern: "publishers/{publisher}/writeBookJobs/{write_book_job}" - }; - - // Name and other fields... -} -``` - -- The name of the resource **must** end with the word "Job". - - The prefix **should** be a valid RPC name, with a verb and a noun. -- The service **should** define all five of the standard methods (AIP-131, - AIP-132, AIP-133, AIP-134, AIP-135), and use them as the - primary way to configure the job. - -### Run method - -The service **should** define a `Run` custom method that executes the job -immediately: - -```proto -rpc RunWriteBookJob(RunWriteBookJobRequest) - returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/writeBookJobs/*}:run" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "RunWriteBookJobResponse" - metadata_type: "RunWriteBookJobMetadata" - }; -} -``` - -- The RPC's name **must** begin with the word `Run`. The remainder of the - RPC name **should** be the singular form of the job resource being run. -- The request message **must** match the RPC name, with a `Request` suffix. -- The method **should** return a [long-running operation][aip-151], which - **must** resolve to a response message that includes the result of running - the job. - - The response message name must match the RPC name, with a `Response` - suffix. - - The method **may** use any metadata message it wishes. -- The HTTP verb **must** be `POST`, as is usual for [custom methods][aip-136]. -- The body clause in the `google.api.http` annotation **should** be `"*"`. -- The URI path **should** contain a single `name` variable corresponding to the - name of the job resource being run. -- The URI path **must** end with `:run`. -- Errors that prevent execution of the job from _starting_ **must** return an - error response (AIP-193), similar to any other method. Errors that occur - over the course of the job execution **may** be placed in the metadata - message. The errors themselves **must** still be represented with a - [`google.rpc.Status`][status] object. - -### Run request message - -Run methods implement a common request message pattern: - -```proto -message RunWriteBookJobRequest { - // The name of the job to run. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/WriteBookJob" - }]; -} -``` - -- A singular `string name` field **must** be included. - - The field **should** be [annotated as required][aip-203]. - - The field **should** identify the [resource type][aip-123] that it - references. - -### Executions and results - -Ordinarily, the API **should** provide results to the user as the final -response of the `Run` method. However, this is sometimes insufficient; for -example, a job that runs on a recurring schedule in the background can not -deliver results to the user in this way. - -The service **may** store resources representing individual executions along -with their result as a sub-collection of resources under the job, which allows -the user to list *past* job executions. A service that does this **should** -define the `Get`, `List`, and `Delete` methods for the execution resources: - -```proto -message WriteBookJobExecution { - option (google.api.resource) = { - type: "library.googleapis.com/WriteBookJobExecution" - pattern: "publishers/{publisher}/writeBookJobs/{write_book_job}/executions/{execution}" - }; - - // Name and other information about the execution, such as metadata, the - // result, error information, etc. -} -``` - -In this case, the operation returned by job's `Run` method **should** refer to -the child resource. - -## Changelog - -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-11-02**: Expanded guidance on HTTP, field behavior, and resource - reference annotations and request format. - - -[aip-123]: ./0123.md -[aip-136]: ./0136.md -[aip-151]: ./0151.md -[aip-203]: ./0203.md -[status]: https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto - diff --git a/aip/general/0153.md b/aip/general/0153.md deleted file mode 100644 index e2ef132802..0000000000 --- a/aip/general/0153.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -id: 153 -state: approved -created: 2019-12-16 -placement: - category: design-patterns - order: 20 ---- - -# Import and export - -Many users want to be able to load data into an API, or get their existing data -out of an API. This is particularly important for enterprise users, who are -often concerned about vendor lock-in. - -## Guidance - -APIs **may** support import and export operations, which **may** create -multiple new resources, or they **may** populate data into a single resource. - -### Multiple resources - -Services **may** support importing and exporting multiple resources into or out -of an API, and **should** implement a common pattern to do so: - -```proto -rpc ImportBooks(ImportBooksRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:import" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "ImportBooksResponse" - metadata_type: "ImportBooksMetadata" - }; -} - -rpc ExportBooks(ExportBooksRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:export" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "ExportBooksResponse" - metadata_type: "ExportBooksMetadata" - }; -} -``` - -- The method **must** return a long-running operation (see [AIP-151][]) unless - the service can guarantee that it will _never_ need more than a few seconds - to complete. -- The HTTP verb **must** be `POST`, and the `body` **must** be `"*"`. -- A `parent` field **should** be included as part of the URI. - - If importing into or exporting from multiple resources is required, the API - **should** keep the `parent` field and allow the user to use the `-` - character to indicate multiple parents (see [AIP-159][]). - - On import, if the user provides a specific parent, the API **must** reject - any imported resources that would be added to a different parent. -- The URI suffix **should** be `:import` or `:export`. - -### Data for a single resource - -Services **may** support importing and exporting data into or out of a single -resource, and **should** implement a common pattern to do so: - -```proto -rpc ImportPages(ImportPagesRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{book=publishers/*/books/*}:importPages" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "ImportPagesResponse" - metadata_type: "ImportPagesMetadata" - }; -} - -rpc ExportPages(ExportPagesRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{book=publishers/*/books/*}:exportPages" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "ExportPagesResponse" - metadata_type: "ExportPagesMetadata" - }; -} -``` - -- The method **must** return a long-running operation (see [AIP-151][]) unless - the service can guarantee that it will _never_ need more than a few seconds - to complete. -- The HTTP verb **must** be `POST`, and the `body` **must** be `"*"`. -- A field representing the resource that data is being imported into **should** - be included as part of the URI. The field **should** be named after the - resource (and **should not** be called `name`). -- The URI suffix should include both the verb and a noun for the data itself, - such as `:importPages` or `:exportPages`. - -### Request object - -Imports and exports often require two fundamentally different types of -configuration: - -1. Configuration specific to the source or destination. -2. Configuration regarding the imported or exported data itself. - -Source or destination configuration should be grouped into a single message and -placed inside a oneof: - -```proto -message ImportBooksRequest { - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - oneof source { - AuthorSource author_source = 2; - TranslatorSource translator_source = 3; - } - string isbn_prefix = 4; -} - -message ExportBooksRequest { - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - oneof destination { - PrinterDestination printer_destination = 2; - TranslatorDestination translator_destination = 3; - } - string filter = 4; -} -``` - -- The source configuration messages **must** be placed within a `oneof source` - (for import) or `oneof destination` (for export), even if there is only one. - (This maintains flexibility to add more later.) -- Configuration related to the data itself (and therefore common across all - sources) **must** be placed at the top-level of the request message. - -**Note:** The configuration for import and export **may** be different from one -another. (For example, it would be sensible to import from a file but export to -a directory.) - -### Inline sources - -APIs **may** also permit import and export "inline", where the contents to be -imported or exported are provided in the request or response. - -```proto -message InlineSource { - repeated Book books = 1; -} -``` - -- The source or destination **should** be named `InlineSource` or - `InlineDestination`. -- The message **should** include a repeated field representing the resource. - However, if the resource structure is complex, the API **may** use a separate - inline representation. In this situation, the same format **must** be used - for both import and export. - -### Partial failures - -While partial failures are normally discouraged, import and export RPCs -**should** include partial failure information in the metadata object. Each -individual error **should** be a `google.rpc.Status` object describing the -error. For more on errors, see [AIP-193][]. - -[aip-151]: ./0151.md -[aip-159]: ./0159.md -[aip-193]: ./0193.md -[google bigquery]: https://cloud.google.com/bigquery -[google storage]: https://cloud.google.com/storage diff --git a/aip/general/0154.md b/aip/general/0154.md deleted file mode 100644 index 22726c979b..0000000000 --- a/aip/general/0154.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: 154 -state: approved -created: 2019-07-24 -placement: - category: design-patterns - order: 30 ---- - -# Resource freshness validation - -APIs often need to validate that a client and server agree on the current state -of a resource before taking some kind of action on that resource. For example, -two processes updating the same resource in parallel could create a race -condition, where the latter process "stomps over" the effort of the former one. - -ETags provide a way to deal with this, by allowing the server to send a -checksum based on the current content of a resource; when the client sends that -checksum back, the server can ensure that the checksums match before acting on -the request. - -## Guidance - -A resource **may** include an `etag` field on any resource where it is -important to ensure that the client has an up to date resource before acting on -certain requests: - -```proto -// A representation of a book. -message Book { - // Other fields... - - // This checksum is computed by the server based on the value of other - // fields, and may be sent on update and delete requests to ensure the - // client has an up-to-date value before proceeding. - string etag = 99; -} -``` - -- The etag field **must** be a string, and **must** be named `etag`. -- The etag field on the _resource_ **should not** be given any behavior - annotations. -- The etag field **must** be provided by the server on output, and values - **should** conform to [RFC 7232][]. -- If a user sends back an etag which matches the current etag value, the - service **must** permit the request (unless there is some other reason for - failure). -- If a user sends back an etag which does not match the current etag value, the - service **must** send an `ABORTED` error response (unless another error takes - precedence, such as `PERMISSION_DENIED` if the user is not authorized). -- If the user does not send an etag value at all, the service **should** permit - the request. However, services with strong consistency or parallelism - requirements **may** require users to send etags all the time and reject the - request with an `INVALID_ARGUMENT` error in this case. - -**Note:** ETag values **should** include quotes as described in [RFC 7232][]. -For example, a valid etag is `"foo"`, not `foo`. - -### Declarative-friendly resources - -A resource that is declarative-friendly (AIP-128) **must** include an `etag` -field. - -### Etags on request methods - -In some situations, the etag needs to belong on a request message rather than -the resource itself. For example, an `Update` standard method can "piggyback" -off the `etag` field on the resource, but the `Delete` standard method can not: - -```proto -message DeleteBookRequest { - // The name of the book. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; - - // The current etag of the book. - // If an etag is provided and does not match the current etag of the book, - // deletion will be blocked and an ABORTED error will be returned. - string etag = 2 [(google.api.field_behavior) = OPTIONAL]; -} -``` - -On a request message, the `etag` field **should** be given a behavior annotation -- either `REQUIRED` or `OPTIONAL`. See AIP-203 for more information. - -An `etag` field **may** also be used on custom methods, similar to the example -above. - -### Strong and weak etags - -ETags can be either "strongly validated" or "weakly validated": - -- A strongly validated etag means that two resources bearing the same etag are - byte-for-byte identical. -- A weakly validated etag means that two resources bearing the same etag are - equivalent, but may differ in ways that the service does not consider to be - important. - -Resources **may** use either strong or weak etags, as it sees fit, but -**should** document the behavior. Additionally, weak etags **must** have a `W/` -prefix as mandated by [RFC 7232][]. - -[rfc 7232]: https://tools.ietf.org/html/rfc7232#section-2.3 - -## Further reading - -- For how to retry on errors in client libraries, see AIP-194. - -## Changelog -- **2021-04-01**: Updated an additional reference to `FAILED_PRECONDITION` - to `ABORTED`. -- **2021-03-05**: Changed the etag error from `FAILED_PRECONDITION` (which - becomes HTTP 400) to `ABORTED` (409). -- **2020-10-06**: Added declarative-friendly resource requirement. -- **2020-09-02**: Clarified that other errors may take precedence over - `FAILED_PRECONDITION` for etag mismatches. -- **2020-09-02**: Add guidance for etags on request messages. -- **2019-09-23**: Changed the title to "resource freshness validation". diff --git a/aip/general/0155.md b/aip/general/0155.md deleted file mode 100644 index ed253a4ebe..0000000000 --- a/aip/general/0155.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -id: 155 -state: approved -created: 2019-05-06 -placement: - category: design-patterns - order: 40 ---- - -# Request identification - -It is sometimes useful for an API to have a unique, customer-provided -identifier for particular requests. This can be useful for several purposes, -such as de-duplicating requests from parallel processes, ensuring the safety of -retries, or auditing. - -The most important purpose for request IDs is to provide idempotency -guarantees: allowing the same request to be issued more than once without -subsequent calls having any effect. In the event of a network failure, the -client can retry the request, and the server can detect duplication and ensure -that the request is only processed once. - -## Guidance - -APIs **may** add a `string request_id` parameter to request messages (including -those of standard methods) in order to uniquely identify particular requests. - -```proto -message CreateBookRequest { - // The parent resource where this book will be created. - // Format: publishers/{publisher} - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The ID to use for the book, which will become the final component of - // the book's resource name. - // - // This value should be 4-63 characters, and valid characters - // are /[a-z][0-9]-/. - string book_id = 2 [(google.api.field_behavior) = REQUIRED]; - - // The book to create. - Book book = 3 [(google.api.field_behavior) = REQUIRED]; - - // A unique identifier for this request. Restricted to 36 ASCII characters. - // A random UUID is recommended. - // This request is only idempotent if a `request_id` is provided. - string request_id = 4 [(google.api.field_info).format = UUID4]; -} -``` - -- Providing a request ID **must** guarantee idempotency. - - If a duplicate request is detected, the server **should** return the - response for the previously successful request, because the client most - likely did not receive the previous response. - - APIs **may** choose any reasonable timeframe for honoring request IDs. -- The `request_id` field **must** be provided on the request message to which - it applies (and it **must not** be a field on resources themselves). -- Request IDs **should** be optional. -- Request IDs **should** be able to be UUIDs, and **may** allow UUIDs to be the - only valid format. The format restrictions for request IDs **must** be - documented. - - Request IDs that are UUIDs **must** be annotated with the - `google.api.FieldInfo.Format` value `UUID4` using the extension - `(google.api.field_info).format = UUID4`. See [AIP-202](./0202.md) for more. - -### Stale success responses - -In some unusual situations, it may not be possible to return an identical -success response. For example, a duplicate request to create a resource may -arrive after the resource has not only been created, but subsequently updated; -because the service has no other need to retain the historical data, it is no -longer feasible to return an identical success response. - -In this situation, the method **may** return the current state of the resource -instead. In other words, it is permissible to substitute the historical success -response with a similar response that reflects more current data. - -## Further reading - -- For which codes to retry, see [AIP-194](https://aip.dev/194). -- For how to retry errors in client libraries, see - [AIP-4221](https://aip.dev/4221). - -## Rationale - -### Using UUIDs for request identification - -When a value is required to be unique, leaving the format open-ended can lead to -API consumers incorrectly providing a duplicate identifier. As such, -standardizing on a universally unique identifier drastically reduces the chance -for collisions when done correctly. - -## Changelog - -- **2024-01-08**: Add book_id to request message. -- **2023-10-02**: Add UUID format extension guidance. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0156.md b/aip/general/0156.md deleted file mode 100644 index 270b98e1fa..0000000000 --- a/aip/general/0156.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -id: 156 -state: approved -created: 2019-05-12 -placement: - category: resource-design - order: 70 ---- - -# Singleton resources - -APIs sometimes need to represent a resource where exactly one instance of the -resource always exists within any given parent. A common use case for this is -for a config object. - -## Guidance - -An API **may** define _singleton resources_. A singleton resource **must** -always exist by virtue of the existence of its parent, with one and exactly one -per parent. - -For example: - -```proto -message Config { - option (google.api.resource) = { - type: "api.googleapis.com/Config" - pattern: "users/{user}/config" - singular: "config" - plural: "configs" - }; - - // additional fields including name -} -``` - -The `Config` singleton would have the following RPCs: - -```proto -rpc GetConfig(GetConfigRequest) returns (Config) { - option (google.api.http) = { - get: "/v1/{name=users/*/config}" - }; -} - -rpc UpdateConfig(UpdateConfigRequest) returns (Config) { - option (google.api.http) = { - patch: "/v1/{config.name=users/*/config}" - body: "config" - }; -} -``` - -- Singleton resources **must not** have a user-provided or system-generated ID; - their [resource name][aip-122] includes the name of their parent followed by - one static-segment. - - Example: `users/1234/config` -- Singleton resources are always singular. - - Example: `users/1234/thing` -- Singleton resource definitions **must** provide both the `singular` and - `plural` fields (see above example). -- Singleton resources **may** parent other resources. -- Singleton resources **must not** define the [`Create`][aip-133] or - [`Delete`][aip-135] standard methods. The singleton is implicitly created or - deleted when its parent is created or deleted. -- Singleton resources **should** define the [`Get`][aip-131] and - [`Update`][aip-134] methods, and **may** define custom methods as - appropriate. - - However, singleton resources **must not** define the [`Update`][aip-134] - method if all fields on the resource are [output only][aip-203]. -- Singleton resources **may** define the [`List`][aip-132] method, but **must** - implement it according to [AIP-159][aip-159]. See the example below. - - The trailing segment in the path pattern that typically represents the - collection **should** be the `plural` form of the Singleton resource e.g. - `/v1/{parent=users/*}/configs`. - - If a parent resource ID is provided instead of the hyphen `-` as per - AIP-159, then the service **should** return a collection of one Singleton - resource corresponding to the specified parent resource. - -```proto -rpc ListConfigs(ListConfigsRequest) returns (ListConfigsResponse) { - option (google.api.http) = { - get: "/v1/{parent=users/*}/configs" - }; -} - -message ListConfigsRequest { - // To list all configs, use `-` as the user id. - // Formats: - // * `users/-` - // * `users/{user}` - // - // Note: Specifying an actual user id will return a collection of one config. - // Use GetConfig instead. - string parent = 1 [ - (google.api.resource_reference).child_type = "api.googleapis.com/Config"]; - - // other standard pagination fields... -} -``` -## Rationale - -### Support for Standard List - -While Singleton resources are not directly part of a collection themselves, they -can be viewed as part of their parent's collection. The one-to-one relationship -of parent-to-singleton means that for every one parent there is one singleton -instance, naturally enabling some collection-based methods when combined with -the pattern of [Reading Across Collections][aip-159]. The Singleton can present -as a collection to the API consumer as it is indirectly one based on its parent. -Furthermore, presenting the Singleton resource as a pseudo-collection in such -methods enables future expansion to a real collection, should a Singleton be -found lacking. - -### Including `plural` definition - -While a Singleton is by definition singular, there are certain cases where -a Singleton resource may appear in a plural form e.g., if the service supports -Standard List (as defined here). As such, it is better to forward declare the -plural form of the Singleton resource type than to not have it when needed. - -## Changelog - -- **2024-04-15:** Singletons must specify `singular` and `plural` in resource. -- **2023-08-10:** Add Standard `List` support. -- **2023-07-26:** Clarified that read-only singletons should not have `Update`. -- **2021-11-02:** Added an example message and state parent eligibility. -- **2021-01-14:** Changed example from `settings` to `config` for clarity. - -[aip-122]: ./0122.md -[aip-131]: ./0131.md -[aip-132]: ./0132.md -[aip-133]: ./0133.md -[aip-134]: ./0134.md -[aip-135]: ./0135.md -[aip-159]: ./0159.md -[aip-203]: ./0203.md#output-only diff --git a/aip/general/0157.md b/aip/general/0157.md deleted file mode 100644 index 15a65e845e..0000000000 --- a/aip/general/0157.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -id: 157 -state: approved -created: 2019-01-26 -placement: - category: design-patterns - order: 50 ---- - -# Partial responses - -Sometimes, a resource can be either large or expensive to compute, and the API -needs to give the user control over which fields it sends back. - -## Guidance - -APIs **may** support partial responses in one of two ways: - -### Field masks parameter - -Field masks (`google.protobuf.FieldMask`) can be used for granting the user -fine-grained control over what fields are returned. An API **should** support the mask in a side channel. -For example, the parameter can be specified either using an HTTP query -parameter, an HTTP header, or a [gRPC metadata entry][1]. Google Cloud APIs specify field masks as a [system parameter][0]. - -Field masks **should not** be specified in the [request](./0157.md#read-masks-as-a-request-field). - -- The value of the field mask parameter **must** be a `google.protobuf.FieldMask`. -- The field mask parameter **must** be optional: - - An explicit value of `"*"` **should** be supported, and **must** return all - fields. - - If the field mask parameter is omitted, it **must** default to `"*"`, unless otherwise documented. -- An API **may** allow read masks with non-terminal repeated fields (unlike - update masks), but is not obligated to do so. - -**Note:** Changing the default value of the field mask parameter is a [breaking change](../0180.md#semantic-changes). - -### View enumeration - -Alternatively, an API **may** support partial responses with view enums. -View enums are useful for situations where an API only wants to expose a small -number of permutations to the user: - -```proto -enum BookView { - // The default / unset value. - // The API will default to the BASIC view. - BOOK_VIEW_UNSPECIFIED = 0; - - // Include basic metadata about the book, but not the full contents. - // This is the default value (for both ListBooks and GetBook). - BOOK_VIEW_BASIC = 1; - - // Include everything. - BOOK_VIEW_FULL = 2; -} -``` - -- The enum **should** be specified as a `view` field on the request message. -- The enum **should** be named something ending in `-View` -- The enum **should** at minimum have values named `BASIC` and `FULL` (although - it **may** have values other than these). -- The `UNSPECIFIED` value **must** be valid (not an error), and the API - **must** document what the unspecified value will do. - - For List RPCs, the effective default value **should** be `BASIC`. - - For the following RPC types, the effective default value **should** be - either `BASIC` or `FULL`: - - Get - - Create - - Update - - Soft Delete - - Custom Method -- The enum **should** be defined at the top level of the proto file (as it is - likely to be needed in multiple requests, e.g. both `Get` and `List`). See - [AIP-126][] for more guidance on top-level enumerations. -- APIs **may** add fields to a given view over time. APIs **must not** remove a - field from a given view (this is a breaking change). - - **Note:** If a service requires (or might require) multiple views with - overlapping but distinct values, there is a potential for a namespace - conflict. In this situation, the service **should** nest the view enum within - the individual resource. - - **Note:** Having a partial response be the default of standard methods can - degrade the effectiveness of declarative clients. Providing a mechanism to - request the full resource be populated in the response, like this View - pattern, is preferred if partial responses are deemed necessary. - -### Read masks as a request field - -**Warning:** Read mask as a single, explicit field on the request message is -**DEPRECATED** for Google APIs. The [system parameter](#field-masks-parameter) -**must** be used instead. The following guidance is for the benefit of existing -legacy Google and external non-Google usage. - -An API **may** support read masks as a single field on the request message: -`google.protobuf.FieldMask read_mask`. - -- The read mask **must** be a `google.protobuf.FieldMask` and **should** be - named `read_mask`. -- The field mask **should** be optional: - - An explicit value of `"*"` **should** be supported, and **must** return all - fields. - - If the field mask parameter is not provided, all fields **must** be - returned. -- An API **may** allow read masks with non-terminal repeated fields (unlike - update masks), but is not obligated to do so. - -## Rationale - -### Deprecating `read_mask` in request messages - -As mentioned, Google API infrastructure implements a service-wide response -field filtering mechanism, so there is no need for individual API methods to -specify a `read_mask` in their request schema. Doing so is both redundant and a -potential point of conflict for the client or service. - -## Changelog - -- **2025-10-03**: Added default view guidance for other RPC types, and - declarative client warning. -- **2025-06-16**: Reinstate read mask guidance as historical/external reference. -- **2023-05-09**: Fix top-level enum example and link to AIP-126. -- **2022-03-14:** Updated guidance on default value and how to specify a read mask. -- **2021-10-06:** Updated the guidance with system parameters. -- **2021-03-04:** Added guidance for conflicting view enums. - -[0]: https://cloud.google.com/apis/docs/system-parameters -[1]: https://grpc.io/docs/what-is-grpc/core-concepts/#metadata -[AIP-126]: ./0126.md \ No newline at end of file diff --git a/aip/general/0158.md b/aip/general/0158.md deleted file mode 100644 index 6ed881e211..0000000000 --- a/aip/general/0158.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -id: 158 -state: approved -created: 2019-02-18 -placement: - category: design-patterns - order: 60 ---- - -# Pagination - -APIs often need to provide collections of data, most commonly in the [List][] -standard method. However, collections can often be arbitrarily sized, and also -often grow over time, increasing lookup time as well as the size of the -responses being sent over the wire. Therefore, it is important that collections -be paginated. - -## Guidance - -RPCs returning collections of data **must** provide pagination _at the outset_, -as it is a [backwards-incompatible change](#backwards-compatibility) to add -pagination to an existing method. - -```proto -// The request structure for listing books. -message ListBooksRequest { - // The parent, which owns this collection of books. - // Format: publishers/{publisher} - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The maximum number of books to return. The service may return fewer than - // this value. - // If unspecified, at most 50 books will be returned. - // The maximum value is 1000; values above 1000 will be coerced to 1000. - int32 page_size = 2; - - // A page token, received from a previous `ListBooks` call. - // Provide this to retrieve the subsequent page. - // - // When paginating, all other parameters provided to `ListBooks` must match - // the call that provided the page token. - string page_token = 3; -} - -// The response structure from listing books. -message ListBooksResponse { - // The books from the specified publisher. - repeated Book books = 1; - - // A token that can be sent as `page_token` to retrieve the next page. - // If this field is omitted, there are no subsequent pages. - string next_page_token = 2; -} -``` - -- Request messages for collections **should** define an `int32 page_size` - field, allowing users to specify the maximum number of results to return. - - The `page_size` field **must not** be required. - - If the user does not specify `page_size` (or specifies `0`), the API - chooses an appropriate default, which the API **should** document. The API - **must not** return an error. - - If the user specifies `page_size` greater than the maximum permitted by the - API, the API **should** coerce down to the maximum permitted page size. - - If the user specifies a negative value for `page_size`, the API **must** - send an `INVALID_ARGUMENT` error. - - The API **may** return fewer results than the number requested (including - zero results), even if not at the end of the collection. -- Request messages for collections **should** define a `string page_token` - field, allowing users to advance to the next page in the collection. - - The `page_token` field **must not** be required. - - If the user changes the `page_size` in a request for subsequent pages, the - service **must** honor the new page size. - - The user is expected to keep all other arguments to the RPC the same; if - any arguments are different, the API **should** send an `INVALID_ARGUMENT` - error. -- The response **must not** be a streaming response. -- Response messages for collections **should** define a - `string next_page_token` field, providing the user with a page token that may - be used to retrieve the next page. - - The field containing pagination results **should** be the first field in - the message and have a field number of `1`. It **should** be a repeated - field containing a list of resources constituting a single page of results. - - If the end of the collection has been reached, the `next_page_token` field - **must** be empty. This is the _only_ way to communicate - "end-of-collection" to users. - - If the end of the collection has not been reached (or if the API can not - determine in time), the API **must** provide a `next_page_token`. -- Response messages for collections **may** provide an `int32 total_size` - field, providing the user with the total number of items in the list. - - This total **may** be an estimate (but the API **should** explicitly - document that). - -### Skipping results - -The request definition for a paginated operation **may** define an `int32 skip` -field to allow the user to skip results. - -The `skip` value **must** refer to the number of individual resources to skip, -not the number of pages. - -For example: - -- A request with no page token and a `skip` value of `30` returns a single page - of results starting with the 31st result. -- A request with a page token corresponding to the 51st result (because the - first 50 results were returned on the first page) and a `skip` value of `30` - returns a single page of results starting with the 81st result. - -If a `skip` value is provided that cannot be fulfilled e.g. due to latency of -querying a massive data set, the response **must** be `200 OK` with an empty -result set. If it is _known_ to put the cursor beyond the total size of the -collection, the response **must not** include a `next_page_token`. - -### Opacity - -Page tokens provided by APIs **must** be opaque (but URL-safe) strings, and -**must not** be user-parseable. This is because if users are able to -deconstruct these, _they will do so_. This effectively makes the implementation -details of your API's pagination become part of the API surface, and it becomes -impossible to update those details without breaking users. - -**Warning:** Base-64 encoding an otherwise-transparent page token is **not** a -sufficient obfuscation mechanism. - -For page tokens which do not need to be stored in a database, and which do not -contain sensitive data, an API **may** obfuscate the page token by defining an -internal protocol buffer message with any data needed, and send the serialized -proto, base-64 encoded. - -Page tokens **must** be limited to providing an indication of where to continue -the pagination process only. They **must not** provide any form of -authorization to the underlying resources, and authorization **must** be -performed on the request as with any other regardless of the presence of a page -token. - -### Expiring page tokens - -Many APIs store page tokens in a database internally. In this situation, APIs -**may** expire page tokens a reasonable time after they have been sent, in -order not to needlessly store large amounts of data that is unlikely to be -used. It is not necessary to document this behavior. - -**Note:** While a reasonable time may vary between APIs, a good rule of thumb -is three days. - -## Backwards compatibility - -Adding pagination to an existing RPC is a backwards-incompatible change. This -may seem strange; adding fields to proto messages is generally backwards -compatible. However, this change is _behaviorally_ incompatible. - -Consider a user whose collection has 75 resources, and who has already written -and deployed code. If the API later adds pagination fields, and sets the -default to 50, then that user's code breaks; it was getting all resources, and -now is only getting the first 50 (and does not know to advance pagination). -Even if the API set a higher default limit, such as 100, the user's collection -could grow, and _then_ the code would break. - -Additionally, [client libraries implement automatic -pagination](https://google.aip.dev/client-libraries/4233), typically representing paginated -RPCs using different method signatures to unpaginated ones. This means that -adding pagination to a previously-unpaginated method causes a breaking change -in those libraries. - -For this reason, it is important to always add pagination to RPCs returning -collections _up front_; they are consistently important, and they can not be -added later without causing problems for existing users. - -**Warning:** This also entails that, in addition to presenting the pagination -fields, they **must** be _actually implemented_ with a non-infinite default -value. Implementing an in-memory version (which might fetch everything then -paginate) is reasonable for initially-small collections. - -[list]: ./0132.md - -## Rationale - -### Degraded `skip` response - -Large collections, complex queries, and globally distributed data can all -contribute to a paginated method being unable to quickly or confidently fulfill -a given `skip` request. Backend queries can timeout, data collation can take -time, and the end user experience need not suffer as a result. In such cases, -the pagination interface can be leveraged to keep the client engaged by -providing a `next_page_token`, while the service collects an appropriate result. -When the service has definitively determined that the requested `skip` exceeds -the available results, the pagination interface is again applied and -`next_page_token` is omitted to signal the end of results. - -## Changelog - -- **2025-07-08**: Clarify degraded skip response guidance -- **2020-05-24**: Clarified that adding pagination breaks client - libraries. -- **2020-05-13**: Added guidance for skipping results. -- **2020-08-24**: Clarified that responses are not streaming responses. -- **2020-06-24**: Clarified that page size is always optional for users. -- **2019-02-12**: Added guidance on the field being paginated over. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. -- **2019-07-19**: Update the opacity requirement from "should" to "must". diff --git a/aip/general/0159.md b/aip/general/0159.md deleted file mode 100644 index 6357e8f422..0000000000 --- a/aip/general/0159.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -id: 159 -state: approved -created: 2019-07-26 -placement: - category: design-patterns - order: 70 ---- - -# Reading across collections - -Sometimes, it is useful for a user to be able to retrieve resources across -multiple collections, or retrieve a single resource without needing to know -what collection it is in. - -## Guidance - -APIs **may** support reading resources across multiple collections by allowing -users to specify a `-` (the hyphen or dash character) as a wildcard character -in a standard [`List`][aip-132] method: - -``` -GET /v1/publishers/-/books?filter=... -``` - -- The URI pattern **must** still be specified with `*` and permit the - collection to be specified; a URI pattern **must not** hard-code the `-` - character. -- The method **must** explicitly document that this behavior is supported. -- The resources provided in the response **must** use the canonical name of the - resource, with the actual parent collection identifiers (instead of `-`). -- Services **may** support reading across collections on `List` requests - regardless of whether the identifiers of the child resources are guaranteed - to be unique. However, services **must not** support reading across - collections on `Get` requests if the child resources might have a collision. -- Cross-parent requests **should not** support `order_by`. If they do, the - field **must** document that it is best effort. This is because cross-parent - requests introduce ambiguity around ordering, especially if there is - difficulty reaching a parent (see [AIP-217][]). - -**Important:** If listing across multiple collections introduces the -possibility of partial failures due to unreachable parents (such as when -listing across locations), the method **must** indicate this following the -guidance in [AIP-217][]. - -### Unique resource lookup - -Sometimes, a resource within a sub-collection has an identifier that is unique -across parent collections. In this case, it may be useful to allow a -[`Get`][aip-131] method to retrieve that resource without knowing which parent -collection contains it. In such cases, APIs **may** allow users to specify the -wildcard collection ID `-` (the hyphen or dash character) to represent any -parent collection: - -``` -GET https://example.googleapis.com/v1/publishers/-/books/{book} -``` - -- The URI pattern **must** still be specified with `*` and permit the - collection to be specified; a URI pattern **must not** hard-code the `-` - character. -- The method **must** explicitly document that this behavior is supported. -- The resource name in the response **must** use the canonical name of the - resource, with actual parent collection identifiers (instead of `-`). For - example, the request above returns a resource with a name like - `publishers/123/books/456`, _not_ `publishers/-/books/456`. -- The resource ID **must** be unique within parent collections. - -## Further reading - -- For partial failures due to unreachable resources, see [AIP-217][]. - -[aip-131]: ./0131.md -[aip-132]: ./0132.md -[aip-217]: ./0217.md - -## Changelog - -- **2019-08-26**: Added a reference to guidance for unreachable resources. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0160.md b/aip/general/0160.md deleted file mode 100644 index 3a6a7ee18f..0000000000 --- a/aip/general/0160.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -id: 160 -state: approved -created: 2020-02-24 -placement: - category: design-patterns - order: 80 ---- - -# Filtering - -Often, when listing resources (using a list method as defined in [AIP-132][] or -something reasonably similar), it is desirable to filter over the collection -and only return results that the user is interested in. - -It is tempting to define a structure to handle the precise filtering needs for -each API. However, filtering requirements evolve frequently, and therefore it -is prudent to use a string field with a structured syntax accessible to a -non-technical audience. This allows updates to be able to be made -transparently, without waiting for UI or client updates. - -**Note:** Because list filters are intended for a potentially non-technical -audience, they sometimes borrow from patterns of colloquial speech rather than -common patterns found in code. - -## Guidance - -APIs **may** provide filtering to users on `List` methods (or similar methods -to query a collection, such as `Search`). If they choose to do so, they -**should** follow the common specification for filters discussed here. The -syntax is formally defined in the [EBNF grammar][]. - -When employing filtering, a request message **should** have exactly one -filtering field, `string filter`. Filtering of related objects is handled -through [traversal](#traversal-operator) or [functions](#functions). - -**Note:** List Filters have fuzzy matching characteristics with support for -result ranking and scoring. For developers interested in deterministic -evaluation of list filters, see [CEL][]. - -### Literals - -A bare literal value (examples: "42", "Hugo") is a value to be matched against. -Literals appearing alone (with no specified field) **should** usually be -matched anywhere it may appear in an object's field values. - -However, a service **may** choose to only consider certain fields; if so, it -**must** document which fields it considers. A service **may** include new -fields over time, but **should** do so judiciously and consider impact on -existing users. - -**Note:** Literals separated by whitespace are considered to have a fuzzy -variant of `AND`. Therefore, `Victor Hugo` is roughly equivalent to -`Victor AND Hugo`. - -### Logical Operators - -Filtering implementations **should** provide the binary operators: - -| Operator | Example | Meaning | -| -------- | ------------- | -------------------------------------- | -| `AND` | `a AND b` | True if `a` and `b` are true. | -| `OR` | `a OR b OR c` | True if any of `a`, `b`, `c` are true. | - -**Note:** To match common patterns of speech, the `OR` operator has higher -precedence than `AND`, unlike what is found in most programming languages. The -expression `a AND b OR c` evaluates: `a AND (b OR c)`. API documentation and -examples **should** encourage the use of explicit parentheses to avoid -confusion, but **should not** require explicit parentheses. - -### Negation Operators - -Filtering implementations **should** provide the unary operators `NOT` and `-`. -These are used interchangeably, and a service that supports negation **must** -support both formats. - -| Operator | Example | Meaning | -| -------- | ------- | ------------------------ | -| `NOT` | `NOT a` | True if `a` is not true. | -| `-` | `-a` | True if `a` is not true. | - -### Comparison Operators - -Filtering implementations **should** provide the binary comparison operators -`=`, `!=`, `<`, `>`, `<=`, and `>=` for string, numeric, timestamp, and -duration fields (but **should not** provide them for booleans or enums). - -| Operator | Example | Meaning | -| -------- | ------------ | ----------------------------------------------- | -| `=` | `a = true` | True if `a` is true. | -| `!=` | `a != 42` | True unless `a` equals 42. | -| `<` | `a < 42` | True if `a` is a numeric value below 42. | -| `>` | `a > "foo"` | True if `a` is lexically ordered after "foo". | -| `<=` | `a <= "foo"` | True if `a` is "foo" or lexically before it. | -| `>=` | `a >= 42` | True if `a` is a numeric value of 42 or higher. | - -**Note:** Unlike in most programming languages, field names **must** appear on -the left-hand side of a comparison operator; the right-hand side only accepts -literals and logical operators. - -Because filters are accepted as query strings, type conversion takes place to -translate the string to the appropriate strongly-typed value: - -- Enums expect the enum's string representation (case-sensitive). -- Booleans expect `true` and `false` literal values. -- Numbers expect the standard integer or float representations. For floats, - exponents are supported (e.g. `2.997e9`). -- [Durations][] expect a numeric representation followed by an `s` suffix (for - seconds). Examples: `20s`, `1.2s`. -- [Timestamps][] expect an [RFC-3339][] formatted string (e.g. - `2012-04-21T11:30:00-04:00`). UTC offsets are supported. - -**Warning:** The identifiers `true`, `false`, and `null` only carry intrinsic -meaning when used in the context of a typed field reference. - -Additionally, when comparing strings for equality, services **should** support -wildcards using the `*` character; for example, `a = "*.foo"` is true if `a` -_ends with_ ".foo". - -### Traversal operator - -Filtering implementations **should** provide the `.` operator, which indicates -traversal through a message, map, or struct. - -| Example | Meaning | -| --------------- | ----------------------------------------------------- | -| `a.b = true` | True if `a` has a boolean `b` field that is true. | -| `a.b > 42` | True if `a` has a numeric `b` field that is above 42. | -| `a.b.c = "foo"` | True if `a.b` has a string `c` field that is "foo". | - -Traversal **must** be written using the field names from the resource. If a -service wishes to support "implicit fields" of some kind, they **must** do so -through well-documented [functions](#functions). A service **may** specify a -subset of fields that are supported for traversal. - -If a user attempts to traverse to a field that is not defined on the message, -the service **should** return an error with `INVALID_ARGUMENT`. A service -**may** permit traversal to undefined keys on maps and structs, and **should** -document how it behaves in this situation. - -When evaluating an expression involving a traversal, if any non-primitive field -in the chain is not set on the entry being evaluated, the entry **should** be -skipped i.e. not match the filter expression. This applies even when the -comparison is a `!=`, which would imply matching on empty values. In the -examples above, if resource field `a` is not set on the resource instance, that -instance is skipped as a non-match. - -**Important:** The `.` operator **must not** be used to traverse through a -repeated field or list, except for specific use with the `:` operator. - -### Has Operator - -Filtering implementations **must** provide the `:` operator, which means "has". -It is usable with collections (repeated fields or maps) as well as messages, -and behaves slightly differently in each case. - -Repeated fields query to see if the repeated structure contains a matching -element: - -| Example | Meaning | -| ---------- | ----------------------------------------------------------- | -| `r:42` | True if `r` contains 42. | -| `r.foo:42` | True if `r` contains an element `e` such that `e.foo = 42`. | - -**Important:** Filters can not query a _specific_ element on a repeated field -for a value. For example, `e.0.foo = 42` and `e[0].foo = 42` are **not** valid -filters. - -Maps, structs, messages can query either for the presence of a field in the map -or a specific value: - -| Example | Meaning | -| ---------- | ----------------------------------- | -| `m:foo` | True if `m` contains the key "foo". | -| `m.foo:*` | True if `m` contains the key "foo". | -| `m.foo:42` | True if `m.foo` is 42. | - -There are two slight distinctions when parsing messages: - -- When traversing messages, a field is only considered to be present if it has - a non-default value. -- When traversing messages, field names are snake case, although - implementations **may** choose to support automatic conversion between camel - case and snake case. - -For all aforementioned types, simply checking for the presence of a top-level -resource field is possible with the `*` value: - -| Example | Meaning | -| ---------- | ---------------------------------------- | -| `r:*` | True if `repeated` field `r` is present. | -| `p:*` | True if `map` field `p` is present. | -| `m:*` | True if `message` field `m` is present. | - -**Note:** For `map` and `repeated` fields, there is no semantic difference -between an unset field and "set with empty value" - they both resolve to "not -present". - -### Functions - -The filtering language supports a function call syntax in order to support -API-specific extensions. An API **may** define a function using the -`call(arg...)` syntax, and **must** document any specific functions it -supports. - -### Limitations - -A service **may** specify further structure or limitations for filter queries, -above what is defined here. For example, a service may support the logical -operators but only permit a certain number of them (to avoid "queries of death" -or other performance concerns). - -Further structure or limitations **must** be clearly documented, and -**must not** violate requirements set forth in this document. - -### Validation - -If a non-compliant or schematically invalid `filter` string is specified, -the API **should** error with `INVALID_ARGUMENT`. Wherever validation is relaxed -for `filter`, the API **must** document the difference. - -Schematic validation refers, but is not limited to, the following: - -- Fields referenced in the `filter` **must** exist on the filtered schema -- Field values provided in the `filter` **must** align to the type of the field - - For example, for a field `int32 age` a `filter` like `"age=hello"` is - invalid -- Field values for bounded data types e.g. `enum` provided in the `filter` - **must** be a valid value in the set -- Field values for standardized types e.g. `Timestamp` **must** conform to the - documented standard (see [Comparison Operators](#comparison-operators) for a - list of such types) - - -[aip-132]: ./0132.md -[cel]: https://github.com/google/cel-spec -[cel-cpp]: https://github.com/google/cel-cpp -[cel-go]: https://github.com/google/cel-go -[durations]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/duration.proto -[ebnf grammar]: /assets/misc/ebnf-filtering.txt -[rfc-3339]: https://tools.ietf.org/html/rfc3339 -[timestamps]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto - - -## Changelog - -- **2025-10-03**: Clarify top-level field has operator behavior. -- **2025-01-07**: Clarify behavior for unset field in traversal operator chain. -- **2024-12-11**: Move non-compliant filter guidance to Validation section. diff --git a/aip/general/0161.md b/aip/general/0161.md deleted file mode 100644 index dd62537af1..0000000000 --- a/aip/general/0161.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -id: 161 -state: approved -created: 2021-03-01 -placement: - category: design-patterns - order: 85 ---- - -# Field masks - -Often, when updating resources (using an update method as defined in AIP-134 or -something reasonably similar), it is desirable to specify exactly which fields -are being updated, so that the service can ignore the rest, even if the user -sends new values. - -It is tempting to define a mask format to handle the precise needs for each -API. However, masking requirements evolve, and therefore it is prudent to use a -structured syntax. This allows updates to be able to be made transparently, -without waiting for UI or client updates. - -## Guidance - -These masks of field names are called "field masks". Fields representing a field -mask **must** use the `google.protobuf.FieldMask` type. Field masks are most -common on Update requests (AIP-134). - -Field masks **must** always be relative to the resource: - -**Warning:** Read masks as a single field on the request message, for -example: `google.protobuf.FieldMask read_mask` are **DEPRECATED**. Instead, see -AIP-157. - -```proto -message UpdateBookRequest { - // The book to update. - // - // The book's `name` field is used to identify the book to update. - // Format: publishers/{publisher}/books/{book} - Book book = 1 [(google.api.field_behavior) = REQUIRED]; - - // The list of fields to update. - // Fields are specified relative to the book - // (e.g. `title`, `rating`; *not* `book.title` or `book.rating`). - google.protobuf.FieldMask update_mask = 2; -} -``` - -### Read-write consistency - -Read and write behavior for field masks **must** be self-consistent if a mask -is present: - -- If a user updates a resource with a given mask, and then reads the same - resource with the same mask, the exact same data **must** be returned. - - Exception: [Output only fields](#output-only-fields). -- Similarly, reading a resource with a given mask and then updating the - resource with the returned data and the same mask **must** be a no-op. - -**Note:** This implies that any mask that is valid for either read or write -**must** be valid for both. - -### Specifying specific fields - -Field masks **must** permit the specification of specific fields in a defined -struct, using the `.` character for traversal. - -Because field masks are always relative to the resource, direct fields on the -resource require no traversal (examples: `title`, `rating`). Traversal is used -when resources contain messages (example: `author.given_name`). - -**Note:** A user **must** be able to specify either a field as a whole, or one -of its subfields: `author` and `author.given_name` are both valid. - -### Map fields - -Field masks **may** permit the specification of specific fields in a map, if -and only if the map's keys are either strings or integers, using the `.` -character for traversal. - -Field masks **should** support string keys that contain characters that are -problematic for the field mask syntax, using the backtick character. - -```proto -message Book { - // The name of the book. - // Format: publishers/{publisher}/books/{book} - string name = 1; - - // Reviews for the back cover. The key is the author of the review, - // and the value is the text of the review. - // - // Valid field masks: reviews, reviews.smith, reviews.`John Smith` - map reviews = 2; -} -``` - -### Wildcards - -Field masks **may** permit the use of the `*` character on a repeated field or -map to indicate the specification of particular sub-fields in the collection: - -```proto -message Book { - option (google.api.resource) = { - type: "library.googleapis.com/Book" - pattern: "publishers/{publisher}/books/{book}" - }; - - // The name of the book. - // Format: publishers/{publisher}/books/{book} - string name = 1 [(google.api.field_behavior) = IDENTIFIER]; - - // The author or authors of the book. - // Valid field masks: authors, authors.*.given_name, authors.*.family_name - // Invalid field masks: authors.0, authors.0.given_name - repeated Author authors = 2; -} - -message Author { - // The author's given name. - string given_name = 1; - - // The author's family name. - string family_name = 2; -} -``` - -**Note:** Field masks **must not** permit accessing a particular element of a -repeated field by index, and **must** return an `INVALID_ARGUMENT` error if -this is attempted. - -### Output only fields - -If a user includes an output only field in an update mask indirectly (by using -a wildcard or specifying an overall message that includes an output-only -subfield), the service **must** ignore any output only fields provided as -input, even if they are cleared or modified. - -If a user directly specifies an output only field in an update mask, the -service **must** ignore the output only fields provided as input, even if -they are cleared or modified, to permit the same field mask to be used for -input and output. - -### Invalid field mask entries - -When reading data, field masks **may** ignore entries that point to a value -that can not exist (either a field that does not exist, or a map key that the -service considers invalid). - -When writing data, field masks **should** return an `INVALID_ARGUMENT` error if -an entry points to a value that can not exist; however, the service **may** -permit deletions. - -## Changelog - -- **2023-10-18**: Update guidance for presence of output only fields in update - mask. -- **2023-07-17**: Move `update_mask` guidance to AIP-134. diff --git a/aip/general/0162.md b/aip/general/0162.md deleted file mode 100644 index eda027d511..0000000000 --- a/aip/general/0162.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -id: 162 -state: draft -created: 2019-09-17 -updated: 2023-09-01 -placement: - category: design-patterns - order: 88 ---- - -# Resource Revisions - -Some APIs need to have resources with a revision history, where users can -reason about the state of the resource over time. There are several reasons for -this: - -- Users may want to be able to roll back to a previous revision, or diff - against a previous revision. -- An API may create data which is derived in some way from a resource at a - given point in time. In these cases, it may be desirable to snapshot the - resource for reference later. - -**Note:** We use the word _revision_ to refer to a historical reference for a -particular resource, and intentionally avoid the term _version_, which refers -to the version of an API as a whole. - -## Guidance - -APIs **may** store a revision history for a resource. Examples of when it is -useful include: - -- When it is valuable to expose older versions of a resource via an API. This - can avoid the overhead of the customers having to write their own API to store - and enable retrieval of revisions. -- Other resources depend on different revisions of a resource. -- There is a need to represent the change of a resource over time. - -APIs implementing resources with a revision history **should** abstract resource -revisions as nested collection of the resource. Sometimes, the revisions -collection can be a top level collection, exceptions include: - -- If resource revisions are meant to have longer lifespan than the parent -resource. In other words, resource revisions exist after resource deletion. - - -```proto -message BookRevision { - // The name of the book revision. - string name = 1; - - // The snapshot of the book - Book snapshot = 2 - [(google.api.field_behavior) = OUTPUT_ONLY]; - - // The timestamp that the revision was created. - google.protobuf.Timestamp create_time = 3 - [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Other revision IDs that share the same snapshot. - repeated string alternate_ids = 4 - [(google.api.field_behavior) = OUTPUT_ONLY]; -} -``` - -- The `message` **must** be annotated as a resource (AIP-123). -- The `message` name **must** be named `{ResourceType}Revision`. -- The resource revision **must** contain a field with a message type of the - parent resource, with a field name of `snapshot`. - - The value of `snapshot` **must** be the configuration of the parent - at the point in time the revision was created. -- The resource revision **must** contain a `create_time` field (see [AIP-142][]). -- The resource revision **may** contain a repeated field `alternate_ids`, which would - contain a list of resource IDs that the revision is also known by (e.g. `latest`) - -### Creating Revisions - -Depending on the resource, different APIs may have different strategies for - -- Create a new revision any time that there is a change to the parent resource -- Create a new revision when important system state changes -- Create a new revision when specifically requested - -APIs **may** use any of these strategies. APIs **must** -document their revision creation strategy. - -### Resource names for revisions - -When referring to specific revision of a resource, the subcollection name -**must** be named `revisions`. Resource revisions have names with the format -`{resource_name}/revisions/{revision_id}`. For example: -``` -publishers/123/books/les-miserables/revisions/c7cfa2a8 -``` - -### Server-specified Aliases - -Services **may** reserve specific IDs to be [aliases][alias] (e.g. -`latest`). These are read-only and managed by the service. - -``` -GET /v1/publishers/{publisher}/books/{book}/revisions/{revision_id} -``` - -- If a `latest` ID exists, it **must** represent the most recently created -revision. The content of `publishers/{publisher}/books/{book}/revisions/latest` -and `publishers/{publisher}/books/{book}` can differ, as the latest revision may -be different from the current state of the resource. - -### User-Specified Aliases - -APIs **may** provide a mechanism for users to assign an [alias][] ID to an -existing revision with a custom method "alias": - -```proto -rpc AliasBookRevision(AliasBookRevisionRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*/revisions/*}:alias" - body: "*" - }; -} -``` - -```proto -message AliasBookRevisionRequest { - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/BookRevision" - }]; - - // The ID of the revision to alias to, e.g. `CURRENT` or a semantic - // version. - string alias_id = 2 [(google.api.field_behavior) = REQUIRED]; -} -``` - -- The request message **must** have a `name` field: - - The field **must** be [annotated as required][aip-203]. - - The field **must** identify the [resource type][aip-123] that it - references. -- The request message **must** have a `alias_id` field: - - The field **must** be [annotated as required][aip-203]. -- If the user calls the method with an existing `alias_id`, the request **must** - succeed and the alias will be updated to refer to the provided revision. This - allows users to write code against a specific alias (e.g. `published`) and the - revision can change with no code change. - -### Rollback - -A common use case for a resource with a revision history is the ability to roll -back to a given revision. APIs **should** handle this with a `Rollback` custom -method: - -```proto -rpc RollbackBook(RollbackBookRequest) returns (BookRevision) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*/revisions/*}:rollback" - body: "*" - }; -} -``` - -- The method **must** use the `POST` HTTP verb. -- The method **should** return a resource revision. - -```proto -message RollbackBookRequest { - // The revision that the book should be rolled back to. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/BookRevision" - }]; -} -``` - -- The request message **must** have a `name` field, referring to the resource - revision whose configuration the resource should be rolled back to. - - The field **must** be [annotated as required][aip-203]. - - The field **must** identify the [resource type][aip-123] that it - references. - -### Child resources - -Resources with a revision history **may** have child resources. If they do, -there are two potential variants: - -- Child resources where each child resource is a child of the parent resource - as a whole. -- Child resources where each child resource is a child of _a single revision - of_ the parent resource. - -APIs **should not** include multiple levels of resources with revisions, as -this quickly becomes difficult to reason about. - -### Standard methods - -Any standard methods **must** implement the corresponding AIPs (AIP-131, -AIP-132, AIP-133, AIP-134, AIP-135), with the following additional behaviors: - -- List methods: By default, revisions in the list response **must** be ordered - in reverse chronological order. User can supply `order_by` to override the - default behavior. -- If the revision supports aliasing, a delete method with the resource name - of the alias (e.g. `revisions/1.0.2`) **must** remove the alias instead of - deleting the resource. - -As revisions are nested under the resource, also see [cascading delete][]. - -## Rationale - -### Abstract revisions as nested collection - -Revisions being resources under nested collection make revisions a first class -citizen. - -- Revisions can offer standard get, list, and delete methods. -- It retains the flexibility of extending new fields to revision in addition to - the resource message. - -### Tagging to Aliases - -Previously, a concept of `tag` existed. This concept was redundant with that of -an [alias][], and the terms were consolidated to reduce complexity in the AIPs. - -### Output only resource configuration - -Although it was an option to have the revision take in the resource -configuration as part of the create method, doing so would have allowed users to -submit resource configuration for a revision that the resource was never in. - -`OUTPUT_ONLY` and requiring that a created revision represents the resource at -current point in time eliminates that issue. - -## History - -### Switching from a collection extension to a subcollection - -In 2023-09, revisions are abstracted as a nested resource collection. Prior to -this, revisions are more like extension of an existing resource by using `@` -symbol. List and delete revisions were custom methods on the resource -collection. A single Get method was used to retrieve either the resource -revision, or the resource. - -Its primary advantage was allowing a resource reference to seamlessly refer to -a resource, or its revision. - -It also had several disadvantages: - -- List revisions is a custom method (:listRevisions) on the resource collection -- Delete revision is a custom method on the resource collection -- Not visible in API discovery doc -- Resource ID cannot use `@` - -The guidance was modified ultimately to enable revisions to behave like a -resource, which reduces the users cognitive load and allows resource-oriented -clients to easily list, get, create, and update revisions. - -### Using resource ID instead of tag - -In the previous design, revisions had a separate identifer for a revision known -as a `tag`, that would live in a revision. - -Tags were effectively a shadow resource ID, requiring methods to create, get and -filter revisions based on the value of the tag. - -By consolidating the concept of a tag into the revision ID, the user no longer -needs to be familiar with a second set of retrieval and identifier methods. - -## Changelog - -- **2023-09-01**: AIP was updated to be a sub-collection. -- **2021-04-27**: Added guidance on returning the resource from Delete Revision. - -[aip-142]: ./0142.md -[alias]: ./0122.md#resource-id-aliases -[cascading delete]: ./0135.md#cascading-delete -[UUID4]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) diff --git a/aip/general/0163.md b/aip/general/0163.md deleted file mode 100644 index a69473983c..0000000000 --- a/aip/general/0163.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -id: 163 -state: approved -created: 2019-12-16 -placement: - category: design-patterns - order: 90 ---- - -# Change validation - -Occasionally, a user wants to validate an intended change to see what the -result will be before actually making the change. For example, a request to -provision new servers in a fleet will have an impact on the overall fleet size -and cost, and could potentially have unexpected downstream effects. - -## Guidance - -APIs **may** provide an option to validate, but not actually execute, a -request, and provide the same response (status code, headers, and response -body) that it would have provided if the request was actually executed. - -To provide this option, the method **should** include a `bool validate_only` -field in the request message: - -```proto -message ReviewBookRequest { - string name = 1 [(google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; - int32 rating = 2; - string comment = 3; - - // If set, validate the request and preview the review, but do not actually - // post it. - bool validate_only = 4; -} -``` - -The API **must** perform permission checks and any other validation that would -be performed on a "live" request; a request using `validate_only` **must** fail -if it determines that the actual request would fail. - -**Note:** It may occasionally be infeasible to provide the full output. For -example, if creating a resource would create an auto-generated ID, it does not -make sense to do this on validation. APIs **should** omit such fields on -validation requests in this situation. - -### Declarative-friendly resources - -A resource that is declarative-friendly (AIP-128) **must** include a -`validate_only` field on methods that mutate the resource. - -## Changelog - -- **2020-10-06:** Added declarative-friendly resource requirement. diff --git a/aip/general/0164.md b/aip/general/0164.md deleted file mode 100644 index d0f0eed26c..0000000000 --- a/aip/general/0164.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -id: 164 -state: approved -created: 2020-10-06 -placement: - category: design-patterns - order: 95 ---- - -# Soft delete - -There are several reasons why a client could desire soft delete and undelete -functionality, but one over-arching reason stands out: recovery from mistakes. -A service that supports undelete makes it possible for users to recover -resources that were deleted by accident. - -## Guidance - -APIs **may** support the ability to "undelete", to allow for situations where -users mistakenly delete resources and need the ability to recover. - -If a resource needs to support undelete, the `Delete` method **must** simply -mark the resource as having been deleted, but not completely remove it from the -system. If the method behaves this way, it **should** return the updated -resource instead of `google.protobuf.Empty`. - -Resources that support soft delete **should** have both a `delete_time` and -`purge_time` field as described in AIP-148. Additionally, resources **should** -include a `DELETED` state value if the resource includes a `state` field -(AIP-216). - -### Undelete - -A resource that supports soft delete **should** provide an `Undelete` method: - -```proto -rpc UndeleteBook(UndeleteBookRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:undelete" - body: "*" - }; -} -``` - -- The HTTP verb **must** be `POST`. -- The `body` clause **must** be `"*"`. -- The response message **must** be the resource itself. There is no - `UndeleteBookResponse`. - - The response **should** include the fully-populated resource unless it is - infeasible to do so. - - If the undelete RPC is [long-running](#long-running-undelete), the response - message **must** be a `google.longrunning.Operation` which resolves to the - resource itself. - -### Undelete request message - -Undelete methods implement a common request message pattern: - -```proto -message UndeleteBookRequest { - // The name of the deleted book. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference).type = "library.googleapis.com/Book"]; -} -``` - -- A `name` field **must** be included. It **should** be called `name`. - - The field **should** be [annotated as required][aip-203]. - - The field **should** identify the [resource type][aip-123] that it - references. - - The comment for the field **should** document the resource pattern. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. - -### Long-running undelete - -Some resources take longer to undelete a resource than is reasonable for a -regular API request. In this situation, the API **should** use a long-running -operation (AIP-151) instead: - -```proto -rpc UndeleteBook(UndeleteBookRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:undelete" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "Book" - metadata_type: "OperationMetadata" - }; -} -``` - -- The response type **must** be set to the resource (what the return type would - be if the RPC was not long-running). -- Both the `response_type` and `metadata_type` fields **must** be specified. - -### Expunge - -Resources that support soft delete **may** provide an `Expunge` custom method to -allow users to trigger immediate permanent deletion of a resource. This method can -operate on resources that are currently in a `CREATING`, `READY` or `SOFT_DELETED` -state (e.g., `delete_time` is set). - -```proto -// Permanently deletes a soft-deleted Book. -rpc ExpungeBook(ExpungeBookRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:expunge" - body: "*" - }; - option (google.api.method_signature) = "name"; -} -``` - -- The URI must use a custom method with the :expunge suffix. -- The HTTP verb must be POST and the body clause must be "*". -- The response message must be `google.protobuf.Empty` or a `google.longrunning.Operation`. - -### Long-running expunge - -If the expunge process takes significant time, the method **may** be a -`google.longrunning.Operation` (AIP-151) instead: - -```proto -// Permanently deletes a soft-deleted Book. -rpc ExpungeBook(ExpungeBookRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:expunge" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "google.protobuf.Empty" - metadata_type: "OperationMetadata" - }; - option (google.api.method_signature) = "name"; -} -``` - -### Expunge request message - -Expunge methods implement a common request message pattern: - -```proto -message ExpungeBookRequest { - // The name of the soft-deleted book to expunge. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference).type = "library.googleapis.com/Book" - ]; -} -``` - -- The request message **must** refer to the resource to be expunged by name. -- There **should not** be any other request fields. - -### List and Get - -Soft-deleted resources **should not** be returned in `List` (AIP-132) responses -by default (unless `bool show_deleted` is true). `Get` (AIP-131) requests for -soft-deleted resources **should** return the resource (rather than a -`NOT_FOUND` error). - -APIs that soft delete resources **may** choose a reasonable strategy for -purging those resources, including automatic purging after a reasonable time -(such as 30 days), allowing users to set an expiry time (AIP-214), or retaining -the resources indefinitely. Regardless of what strategy is selected, the API -**should** document when soft deleted resources will be completely removed. - -### Declarative-friendly resources - -Soft-deletable resources have a poorer experience than hard-deleted resources in -declarative clients: since an ID on a soft-deleted resource is not re-usable -unless a custom method (undelete) is called, an imperative client must be -introduced or hand-written code is required to incorporate the usage of the -custom method. - -### Errors - -If the user does not have permission to access the resource, regardless of -whether or not it exists, the service **must** error with `PERMISSION_DENIED` -(HTTP 403). Permission **must** be checked prior to checking if the resource -exists. - -If the user does have proper permission, but the requested resource does not -exist (either it was never created or already expunged), the service **must** -error with `NOT_FOUND` (HTTP 404). - -If the user calling a soft `Delete` has proper permission, but the requested -resource is already deleted, the service **must** succeed if `allow_missing` is -`true`, and **should** error with `NOT_FOUND` (HTTP 404) if `allow_missing` is -`false`. - -If the user calling `Undelete` has proper permission, but the requested -resource is not deleted, the service **must** respond with `ALREADY_EXISTS` -(HTTP 409). - -If the user calling `Expunge` requests a resource that does not exist (was never -created or already expunged), the method **must** return `NOT_FOUND` (HTTP 404). - -If the resource exists but is not in a ready or soft-deleted state, the method -**must** return `FAILED_PRECONDITION` (HTTP 400). - -Standard permission errors (`PERMISSION_DENIED`) apply. Services **must** require -an explicit expunge permission that is separate from standard delete permissions -(e.g., `..expunge`). - -## Further reading - -- For the `Delete` standard method, see AIP-135. -- For long-running operations, see AIP-151. -- For resource freshness validation (`etag`), see AIP-154. -- For change validation (`validate_only`), see AIP-163. - -## Changelog - -- **2026-04-28**: Added guidance for the `Expunge` custom method. -- **2024-09-24**: Included missing requirement for `delete_time`. -- **2023-07-13**: Renamed overloaded `expire_time` to `purge_time`. -- **2021-07-12**: Added error behavior when soft deleting a deleted resource. -- **2021-07-12**: Clarified that `ALREADY_EXISTS` errors apply to `Undelete`. -- **2021-07-12**: Changed the `expire_time` field to "should" for consistency - with AIP-148. -- **2020-09-23**: Soft delete material in AIP-135 migrated to this AIP. - -[aip-123]: ./0123.md -[aip-203]: ./0203.md diff --git a/aip/general/0165.md b/aip/general/0165.md deleted file mode 100644 index 04a0565ec7..0000000000 --- a/aip/general/0165.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -id: 165 -state: approved -created: 2019-12-18 -updated: 2022-06-02 -placement: - category: design-patterns - order: 100 ---- - -# Criteria-based delete - -Occasionally, an API may need to provide a mechanism to delete a large number -of resources based on some set of filter parameters, rather than requiring the -individual resource name of the resources to be deleted. - -This is a rare case, reserved for situations where users need to delete -thousands or more resources at once, in which case the normal Batch Delete -pattern ([AIP-235][]) becomes unwieldy and inconvenient. - -## Guidance - -**Important:** Most APIs **should** use only Delete ([AIP-135][]) or Batch -Delete ([AIP-235][]) for deleting resources, and **should not** implement -deleting based on criteria. This is because deleting is generally irreversible -and this type of operation makes it easy for a user to accidentally lose -significant amounts of data. - -An API **may** implement a Purge method to permit deleting a large number of -resources based on a filter string; however, this **should** only be done if -the Batch Delete ([AIP-235][]) pattern is insufficient to accomplish the -desired goal: - -```proto -rpc PurgeBooks(PurgeBooksRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:purge" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "PurgeBooksResponse" - metadata_type: "PurgeBooksMetadata" - }; -} -``` - -- The RPC's name **must** begin with the word `Purge`. The remainder of the - RPC name **should** be the plural form of the resource being purged. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response type **must** be a `google.longrunning.Operation` (see - AIP-151) that resolves to a message whose name matches the RPC name, with - a `Response` suffix. -- The HTTP verb **must** be `POST`, and the `body` **must** be `"*"`. -- The URI path **should** represent the collection for the resource. -- The `parent` field **should** be included in the URI. If the API wishes to - support deletion across multiple parents, it **should** accept the `-` - character consistent with [AIP-159][]. - -### Request message - -Purge methods implement a common request message pattern: - -```proto -message PurgeBooksRequest { - // The publisher to purge books from. - // To purge books across publishers, send "publishers/-". - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // A filter matching the books to be purged. - string filter = 2 [(google.api.field_behavior) = REQUIRED]; - - // Actually perform the purge. - // If `force` is set to false, the method will return a sample of - // resource names that would be deleted. - bool force = 3; -} -``` - -- A singular `string parent` field **should** be included, unless the resource - is top-level. - - The field **should** be [annotated as required][aip-203]. - - The field **should** identify the [resource type][aip-123] that it - references. -- A singular `string filter` field **must** be included and **must** follow the - same semantics as in List methods (AIP-160). - - It **should** be [annotated as required][aip-203]. - - A wildcard value of `"*"` **may** be supported for deleting everything. -- A singular `bool force` field **must** be included. If it is not set, the API - **must** return a count of the resources that would be deleted as well as a - sample of those resources, without actually performing the deletion. - -### Response message - -Purge methods implement a common response message pattern: - -```proto -message PurgeBooksResponse { - // The number of books that this request deleted (or, if `force` is false, - // the number of books that will be deleted). - int32 purge_count = 1; - - // A sample of the resource names of books that will be deleted. - // Only populated if `force` is set to false. - repeated string purge_sample = 2 [(google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; -} -``` - -- A singular `int32 purge_count` field **should** be included, and provide the - number of resources that were deleted (or would be deleted). This count - **may** be an estimate similar to `total_size` in AIP-158 (but the service - **should** document this if so). -- A `repeated string purge_sample` field **should** be included: If `force` is - `false`, it **should** provide a sample of resource names that will be - deleted. If `force` is true, this field **should not** be populated. - - The sample **should** be a sufficient size to catch clearly obvious - mistakes: A good rule of thumb is 100. The API **should** document the - size, and **should** document that it is a maximum (it is possible to send - fewer). - - The sample **may** be random or **may** be deterministic (such as the first - matched resource names). The API **should** document which approach is - used. - - The field **should** identify the [resource type][aip-123] that it - references. - -**Note:** Even if `purge_count` and `purge_sample` are not included, the -`force` field **must** still be included in the request. - -## Changelog - -- **2025-07-23:** Explicitly state filter wildcard may be supported. -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-10-29**: Expanded guidance on HTTP, field behavior, and resource - reference annotations. - -[aip-123]: ./0123.md -[aip-135]: ./0135.md -[aip-159]: ./0159.md -[aip-203]: ./0203.md -[aip-235]: ./0235.md diff --git a/aip/general/0180.md b/aip/general/0180.md deleted file mode 100644 index 62fe33bf84..0000000000 --- a/aip/general/0180.md +++ /dev/null @@ -1,312 +0,0 @@ ---- -id: 180 -state: approved -created: 2019-07-23 -placement: - category: compatibility - order: 10 ---- - -# Backwards compatibility - -APIs are fundamentally contracts with users, and users often write code against -APIs that is then launched into a production service with the expectation that -it continues to work (unless the API has a [stability level][aip-181] that -indicates otherwise). Therefore, it is important to understand what constitutes -a backwards compatible change and what constitutes a backwards incompatible -change. - -## Guidance - -Existing client code **must not** be broken by a service updating to a new -minor or patch release. Old clients **must** be able to work against newer -servers (with the same major version number). - -**Important:** It is not always clear whether a change is compatible or not. -The guidance here **should** be treated as indicative, rather than as a -comprehensive list of every possible change. - -There are three distinct types of compatibility to consider: - -1. Source compatibility: Code written against a previous version **must** - compile against a newer version, and successfully run with a newer version - of the client library. -2. Wire compatibility: Code written against a previous version **must** be able - to communicate correctly with a newer server. In other words, not only are - inputs and outputs compatible, but the serialization and deserialization - expectations continue to match. -3. Semantic compatibility: Code written against a previous version **must** - continue to receive what most reasonable developers would expect. (This can - be tricky in practice, however, and sometimes determining what users will - expect can involve a judgment call.) - -**Note:** In general, the specific guidance here assumes use of protocol -buffers and JSON as transport formats. Other transport formats may have -slightly different rules. - -**Note:** This guidance assumes that APIs are intended to be called from a -range of consumers, written in multiple languages and with no control over -how and when consumers update. Any API which has a more limited scope (for -example, an API which is only called by client code written by the same team -as the API producer, or deployed in a way which can enforce updates) should -carefully consider its own compatibility requirements. - -### Adding components - -In general, new components (interfaces, methods, messages, fields, enums, or -enum values) **may** be added to existing APIs in the same major version. - -However, keep the following guidelines in mind when doing this: - -- Code written against the previous surface (and thus is unaware of the new - components) **must** continue to be treated the same way as before. - - New required fields **must not** be added to existing request messages or - resources. - - Any field being populated by clients **must** have a default behavior - matching the behavior before the field was introduced. - - This can be tricky to do in some cases. For example, adding pagination - after the fact where previously all items were returned (i.e. `page_size` - is infinite, which is not advised). If the default for the new `page_size` - field is _less_ than what was previously returned, older clients will - incorrectly assume all results were returned. - - Any field previously populated by the server **must** continue to be - populated, even if it introduces redundancy. -- For enum values specifically, be aware that it is possible that user code - does not handle new values gracefully. - - Enum values **may** be freely added to enums which are only used in request - messages. - - Enums that are used in response messages or resources and which are - expected to receive new values **should** document this. Enum values still - **may** be added in this situation; however, appropriate caution **should** - be used. - -**Note:** It is possible when adding a component closely related to an existing -component (for example, `string foo_value` when `string foo` already exists) to -enter a situation where generated code will conflict. Service owners **should** -be aware of subtleties in the tooling they or their users are likely to use -(and tool authors **should** endeavor to avoid such subtleties if possible). - -### Removing or renaming components - -Existing components (interfaces, methods, messages, fields, enums, or enum -values) **must not** be removed from existing APIs in the same major version. -Removing a component is a backwards incompatible change. - -**Important:** Renaming a component is semantically equivalent to "remove and -add". In cases where these sorts of changes are desirable, a service **may** -add the new component, but **must not** remove the existing one. In situations -where this can allow users to specify conflicting values for the same semantic -idea, the behavior **must** be clearly specified. - -### Moving components between files - -Existing components **must not** be moved between files. - -Moving a component from one proto file to another within the same package is -wire compatible, however, the code generated for languages like C++ or Python -will result in breaking change since `import` and `#include` will no longer -point to the correct code location. - -### Moving into oneofs - -Existing fields **must not** be moved into or out of a oneof. This is a -backwards-incompatible change in the Go protobuf stubs. - -### Changing the type of fields - -Existing fields and messages **must not** have their type changed, even if the -new type is wire-compatible, because type changes alter generated code in a -breaking way. - -### Changing string length - -APIs **should** avoid increasing the upper bound for the size or limit (if -accepted as input) of `string` fields. APIs **should** treat expected size upper -bound increases as incompatible changes (see [Changing resource -names](#changing-resource-names) as an example). APIs **may** pad out values with -filler characters if reserving a consistent size is necessary, but this **must** -be documented if done. - -### Changing resource names - -A resource **must not** change its [name][aip-122]. - -Unlike most breaking changes, this affects major versions as well: in order for -a client to expect to use v2.0 access a resource that was created in v1.0 or -vice versa, the same resource name **must** be used in both versions. - -More subtly, the set of valid resource names **should not** change either, for -the following reasons: - -- If resource name formats become more restrictive, a request that would - previously have succeeded will now fail. -- If resource name formats become less restrictive than previously documented, - then code making assumptions based on the previous documentation could break. - Users are very likely to store resource names elsewhere, in ways that may be - sensitive to the set of permitted characters and the length of the name. - Alternatively, users might perform their own resource name validation to - follow the documentation. - - For example, Amazon gave customers [a lot of warning][ec2] and had a - migration period when they started allowing longer EC2 resource IDs. - -### Semantic changes - -Code will often depend on API behavior and semantics, _even when such behavior -is not explicitly supported or documented_. Therefore, APIs **must not** change -visible behavior or semantics in ways that are likely to break reasonable user -code, as such changes will be seen as breaking by those users. - -**Note:** This does involve some level of judgment; it is not always clear -whether a proposed change is likely to break users, and an expansive reading of -this guidance could ostensibly prevent _any_ change (which is not the intent). - -#### Changing value format or construction - -APIs **must not** change the expected format or algorithm used to construct the -value of an existing field - even if the field is `OUTPUT_ONLY` and populated by -the API service - within an API version. Doing so requires a new API version. - -For example, changing the format of a field `ip_address` conforming to IPv4 -format to instead contain IPv6 values is a breaking change. - -#### Default values must not change - -Default values are the values set by servers for resources when they are not -specified by the client. This section only applies to static default values within -fields on resources and does not apply to dynamic defaults such as the default IP -address of a resource. - -Changing the default value is considered breaking and **must not** be done. The -default behavior for a resource is determined by its default values, and this -**must not** change across minor versions. - -For example: - -```proto -message Book { - // google.api.resource and other annotations and fields - - // The genre of the book - // If this is not set when the book is created, the field will be given a value of FICTION. - enum Genre { - UNSPECIFIED = 0; - FICTION = 1; - NONFICTION = 2; - } -} -``` - -Changing to: - -```proto -message Book { - // google.api.resource and other annotations and fields - - // The genre of the book - // If this is not set when the book is created, the field will be given a value of NONFICTION. - enum Genre { - UNSPECIFIED = 0; - FICTION = 1; - NONFICTION = 2; - } -} -``` - -would constitute a breaking change. - -#### Serializing defaults - -APIs **must not** change the way a field with a default value is serialized. For -example if a field does not appear in the response if the value is equal to the -default, the serialization **must not** change to include the field with the -default. Clients may depend on the presence or absence of a field in a resource -as semantically meaningful, so a change to how serialization is done for absent -values **must not** occur in a minor version. - -Consider the following proto, where the default value of `wheels` is `2`: - -```proto -// A representation of an automobile -message Automobile { - // google.api.resource and other annotations and fields - - // The number of wheels on the automobile. - // The default value is 2, when no value is sent by the client. - int wheels = 2; -} -``` - -First the proto serializes to JSON when the value of `wheels` is `2` as follows: - -```json -{ - "name": "my-car" -} -``` - -Then, the API service changes the serialization to include `wheel` even if the -value is equal to the default value, `2` as follows: - -```json -{ - "name": "my-car", - "wheels": 2 -} -``` - -This constitutes a change that is not backwards compatible within a major -version. - -## Further reading - -- For compatibility around field behavior, see [AIP-203][]. -- For compatibility around pagination, see [AIP-158][]. -- For compatibility around long-running operations, see [AIP-151][]. -- For understanding stability levels and expectations, see [AIP-181][]. -- For compatibility with client library resource name parsing, see [AIP-4231][] -- For compatibility with client library method signatures, see [AIP-4232][] -- For compatibility around field presence changes, see [AIP-149][]. -- For compatibility around resource types, see [AIP-123][]. - -## Rationale - -### Risk of string length changes - -End users may store resource properties, like the `name`, in a dedicated -database column with a limited length. If the service starts returning values -for the `name` that are twice the originally documented/observed length, this -may unexpectedly break the customer's database. Furthermore, string properties -that appear in URLs (including query parameters) are especially likely to have -client-side limits, making them more sensitive to length changes. - -### Risk of changing value format or construction - -Customers often depend on the format or algorithmic construction of a field for -client-side parsing, hashing, or database table construction. Changing it in -an existing field could break that client-side consumption. - -## Changelog - -- **2025-10-21**: Added guidance for string length changes, changing formats, - and an example for carefully adding components. -- **2024-08-07**: Added reference to resource type compatibility. -- **2024-06-05**: Added reference to field presence compatibility. -- **2023-07-26**: Added reference to field behavior compatibility. -- **2023-07-26**: Added note on APIs which have limited clients. -- **2022-08-11**: Added "Moving components between files" section. -- **2022-06-01**: Added more links to other AIPs with compatibility concerns -- **2019-12-16**: Clarified that moving existing fields into oneofs is - breaking. - - -[aip-122]: ./0122.md -[aip-123]: ./0123.md -[aip-149]: ./0149.md -[aip-151]: ./0151.md -[aip-158]: ./0158.md -[aip-181]: ./0181.md -[aip-203]: ./0203.md -[aip-4231]: https://google.aip.dev/client-libraries/4231 -[aip-4232]: https://google.aip.dev/client-libraries/4232 -[ec2]: https://aws.amazon.com/blogs/aws/theyre-here-longer-ec2-resource-ids-now-available/ - diff --git a/aip/general/0181.md b/aip/general/0181.md deleted file mode 100644 index b1a9b5afb4..0000000000 --- a/aip/general/0181.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -id: 181 -state: approved -created: 2019-02-18 -placement: - category: compatibility - order: 20 ---- - -# Stability levels - -While different organizations (both inside Google and outside) have different -product life cycles, AIPs refer to the _stability_ of an API component using -the following terms. - -**Note:** These stability levels roughly correspond to the product launch -stages (alpha, beta, GA) in Google Cloud, but are not identical. GCP imposes -its own additional expectations and commitments on top of what is outlined -here. - -## Alpha - -An _alpha_ component undergoes rapid iteration with a known set of users who -**must** be tolerant of change. The number of users **should** be a -curated, manageable set, such that it is feasible to communicate with all -of them individually. - -Breaking changes **must** be both allowed and expected in alpha components, and -users **must** have no expectation of stability. - -## Beta - -A _beta_ component **must** be considered complete and ready to be declared -stable, subject to public testing. Beta components **should** be exposed to an -unknown and potentially large set of users. In other words, beta components -**should not** be behind an allowlist; instead, they **should** be available to -the public. - -Because users of beta components tend to have a lower tolerance of change, beta -components **should** be as stable as possible; however, the beta component -**must** be permitted to change over time. These changes **should** be minimal -but **may** include backwards-incompatible changes to beta components. -Backwards-incompatible changes **must** be made only after a reasonable -deprecation period to provide users with an opportunity to migrate their code. -This deprecation period **must** be defined at the time of being marked beta. - -Beta components **should** be time-boxed and promoted to stable if no issues -are found in the specified timeframe, which **should** be specified at the time -of being marked beta. A reasonable time period **may** vary, but a good rule of -thumb is 90 days. - -## Stable - -A _stable_ component **must** be fully-supported over the lifetime of the major -API version. Because users expect such stability from components marked stable, -there **must** be no breaking changes to these components, subject to the -caveats described below. - -### Major versions - -When breaking changes become necessary, the API producer **should** create the -next major version of the API, and start a deprecation clock on the existing -version. - -Turn-down of any version containing stable components **must** have a formal -process defined at the time of being marked stable. This process **must** -specify a deprecation period for users which provides them with reasonable -advance warning. - -### Isolated changes - -On very rare occasions, it could be preferable to make a small, isolated -breaking change, if this will only cause inconvenience to a small subset of -users. (Creating a new major version is an inconvenience to all users.) In this -case, the API producer **may** deprecate the component, but **must** continue -to support the component for the normal turndown period for a stable component. - -**Important:** Making an in-place breaking change in a stable API is considered -an extreme course of action, and should be treated with equal or greater -gravity as creating a new major version. For example, at Google, this requires -the approval of the API Governance team. - -### Emergency changes - -In certain exceptional cases, such as security concerns or regulatory -requirements, any API component **may** be changed in a breaking manner -regardless of its stability level, and a deprecation is not promised in these -situations. diff --git a/aip/general/0182.md b/aip/general/0182.md deleted file mode 100644 index f31fd0ed52..0000000000 --- a/aip/general/0182.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -id: 182 -state: reviewing -created: 2021-08-13 -placement: - category: compatibility - order: 30 ---- - -# External software dependencies - -Some services have a particular type of dependency on external software: they -allow users to create resources that run on or expose the external software in -some way. For example: - -- A database admin service can allow users to create databases running on a - particular version of a particular database engine (for example, PostgreSQL - 13.4). -- A virtual machine service can allow users to create VMs running a particular - operating system (for example, Ubuntu 20.04). -- An application or function platform service can allow users to write code - that runs against a particular version of a programming language (for - example, Node.js 16.6). - -Services that provide external software to users in this way will eventually -need to address the fact that all of these types of software have release -lifecycles, and the versions they currently expose will eventually reach -end-of-life. - -## Guidance - -Services that expose external software dependencies **should** allow users to -create resources using any currently-supported LTS (long-term support) version -of the supported software, and **may** allow users to create resources using -non-LTS versions. - -Services **should not** indefinitely allow users to create new resources using -versions that have reached end-of-life, although they **may** have a transition -period between when the software version reaches end-of-life and when support -for creating new resources with that version is removed. - -**Note:** Restricting or removing the ability to create resources using -end-of-life versions of software is **not** considered a breaking change for -the service for the purpose of AIP-181, even though it actually is one. -However, because the change can break existing users' workflows, services -**must** notify users who are using resources approaching end-of-life. - -If possible, services **should** allow previously-created resources to remain, -and **may** warn users of the risks associated with continuing to use -end-of-life software. Services **should not** proactively remove resources -using end-of-life software, or impose other restrictions on existing resources, -unless critical security concerns require the service to do so. - -### Continued support - -If supporting a version that has reached end-of-life is necessary for business -reasons (usually because the end-of-life software still has significant -adoption), the service **may** choose to officially support the end-of-life -version, but **must** take on the responsibility of patching and maintaining -the software if it does so. diff --git a/aip/general/0185.md b/aip/general/0185.md deleted file mode 100644 index 4e7b70a34b..0000000000 --- a/aip/general/0185.md +++ /dev/null @@ -1,184 +0,0 @@ ---- -id: 185 -state: approved -created: 2024-10-22 -placement: - category: compatibility - order: 40 ---- - -# API Versioning - -This topic describes the versioning strategies used by Google APIs. In -general, these strategies apply to all Google-managed services. - -## Guidance - -All Google API interfaces **must** provide a _major version number_, which is -encoded at the end of the protobuf package, and included as the first part of -the URI path for REST APIs. In the event an API needs to make an incompatible -change, consult [AIP-180][] and [AIP-181][] for necessary steps based on the -stability level of the surface in question. - -Note: The use of the term "major version number" above is taken from -[semantic versioning][]. However, unlike in traditional semantic versioning, -Google APIs **must not** expose minor or patch version numbers. For -example, Google APIs use `v1`, not `v1.0`, `v1.1`, or `v1.4.2`. From a user's -perspective, major versions are updated in place with minor/patch equivalent -changes, and users receive new functionality without migration. - -A new major version of an API **must not** depend on a previous major version of -the same API. An API surface **must not** depend on other APIs, except for in -the cases outlined in [AIP-213][] and [AIP-215][]. - -Different versions of the same API **must** be able to work at the same time -within a single client application for a reasonable transition period. This time -period allows the client to transition smoothly to the newer version. An older -version **must** go through a reasonable, well-communicated deprecation period -before being shut down. - -For releases which have [alpha or beta stability][AIP-181], APIs **must** append -the stability level after the major version number in the protobuf package and -URI path using one of these strategies: - -- Channel-based versioning (recommended) -- Release-based versioning -- Visibility-based versioning - -### Channel-based versioning - -A *stability channel* is a long-lived release at a given stability level that -receives in-place updates. There is no more than one channel per stability level -for a major version. Under this strategy, there are up to three channels -available: alpha, beta, and stable. - -The alpha and beta channel **must** have their stability level appended to the -version, but the stable channel **must not** have the stability level appended. -For example, `v1` is an acceptable version for the stable channel, but `v1beta` -or `v1alpha` are not. Similarly, `v1beta` or `v1alpha` are acceptable versions -for the respective beta and alpha channel, but `v1` is not acceptable for -either. Each of these channels receives new features and updates "in-place". - -The beta channel's functionality **must** be a superset of the stable channel's -functionality, and the alpha channel's functionality **must** be a superset of -the beta channel's functionality. - -#### Deprecating API functionality - -API elements (fields, messages, RPCs) **may** be marked deprecated in any -channel to indicate that they should no longer be used: - -```proto -// Represents a scroll. Books are preferred over scrolls. -message Scroll { - option deprecated = true; - - // ... -} -``` - -Deprecated API functionality **must not** graduate from alpha to beta, nor beta -to stable. In other words, functionality **must not** arrive "pre-deprecated" -in any channel. - -The beta channel's functionality **may** be removed after it has been deprecated -for a sufficient period; we recommend 180 days. For functionality that exists -only in the alpha channel, deprecation is optional, and functionality **may** be -removed without notice. If functionality is deprecated in an API's -alpha channel before removal, the API **should** apply the same annotation, and -**may** use any timeframe it wishes. - -### Release-based versioning - -**Important:** This pattern is not commonly used for new services. There are -existing services that follow it, but Channel-based Versioning is the preferred -mechanism. - -An *individual release* is an alpha or beta release that is expected to be -available for a limited time period before its functionality is incorporated -into the stable channel, after which the individual release will be shut down. -When using release-based versioning strategy, an API may have any number of -individual releases at each stability level. - -Note: Both the channel-based and release-based strategies update the _stable_ -version in-place. There is a single stable channel, rather than individual -stable releases, even when using the release-based strategy. - -Alpha and beta releases **must** have their stability level appended to the -version, followed by an incrementing release number. For example, `v1beta1` or -`v1alpha5`. APIs **should** document the chronological order of these versions -in their documentation (such as comments). - -Each alpha or beta release **may** be updated in place with backwards-compatible -changes. For beta releases, backwards-incompatible updates **should** be made by -incrementing the release number and publishing a new release with the change. -For example, if the current version is `v1beta1`, then `v1beta2` is released -next. - -Alpha and beta releases **should** be shut down after their functionality -reaches the stable channel. An alpha release **may** be shut down at any time, -while a beta release **should** allow users a reasonable transition period; we -recommend 180 days. - -### Visibility-based versioning - -[API visibility][] is an advanced feature provided by Google API infrastructure. -It allows API producers to expose multiple external API views from one internal -API surface, and each view is associated with an API _visibility label_, such -as: - -```proto -import "google/api/visibility.proto"; - -message Resource { - string name = 1; - - // Preview. Do not use this feature for production. - string display_name = 2 - [(google.api.field_visibility).restriction = "PREVIEW"]; -} -``` - -A visibility label is a case-sensitive string that can be used to tag any API -element. By convention, visibility labels should always use UPPER case. -An implicit `PUBLIC` label is applied to all API elements unless an explicit -visibility label is applied as in the example above. - -Each visibility label is an allow-list. API producers need to grant visibility -labels to API consumers for them to use API features associated with the labels. -In other words, an API visibility label is like an ACL'ed API version. - -Multiple visibility labels **may** be applied to an element by using a -comma-separated string (e.g. `"PREVIEW,TRUSTED_TESTER"`). When multiple -visibility labels are used, then the client needs only _one_ of the visibility -labels (logical `OR`). - -By default, the visibility labels granted to the API consumer are used to verify -incoming requests. However, a client can send requests with an explicit -visibility label as follows: - -``` -GET /v1/projects/my-project/topics HTTP/1.1 -Host: pubsub.googleapis.com -Authorization: Bearer y29.... -X-Goog-Visibilities: PREVIEW -``` - -A single API request can specify at most one visibility label. - -API producers can use API visibility for API versioning, such as -`INTERNAL` and `PREVIEW`. A new API feature starts with the `INTERNAL` label, -then moves to the `PREVIEW` label. When the feature is stable and becomes -generally available, all API visibility labels are removed from the API -definition. - -In general, API visibility is easier to implement than API versioning for -incremental changes, but it depends on sophisticated API infrastructure support. -Google Cloud APIs often use API visibility for Preview features. - -[AIP-180]: https://aip.dev/180 -[AIP-181]: https://aip.dev/181 -[AIP-213]: https://aip.dev/213 -[AIP-215]: https://aip.dev/215 -[api visibility]: https://github.com/googleapis/googleapis/blob/master/google/api/visibility.proto -[semantic versioning]: https://semver.org/ diff --git a/aip/general/0190.md b/aip/general/0190.md deleted file mode 100644 index 96883a9665..0000000000 --- a/aip/general/0190.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -id: 190 -state: approved -created: 2025-06-10 -placement: - category: polish - order: 0 ---- - -# Naming conventions - -This topic describes the naming conventions used in Google APIs. In -general, these conventions apply to all Google-managed services. - -## Guidance - -In order to provide consistent developer experience across many APIs and -over a long period of time, all names used by an API **should** be: - -- straightforward -- intuitive -- consistent - -This includes names of interfaces, resources, collections, methods, and -messages. - -Since English is a second language for many developers, one goal of these -naming conventions is to make every API name understandable to the majority of -developers. It does this by encouraging the use of a simple, consistent, and -small vocabulary when naming methods and resources. - -- Names used in APIs **should** be in correct American English. For - example, license (instead of licence), color (instead of colour). -- Commonly accepted short forms or abbreviations of long words **may** - be used for brevity. For example, API is preferred over Application - Programming Interface. -- Unless otherwise specified, definitions **must** use UpperCamelCase names, - as defined by - [Google Java Style](https://google.github.io/styleguide/javaguide.html#s5.3-camel-case). -- Use intuitive, familiar terminology where possible. For example, - when describing removing (and destroying) a resource, delete is - preferred over erase. -- Use the same name or term for the same concept, including for - concepts shared across APIs. -- Avoid name overloading. Use different names for different concepts. -- Avoid overly general names that are ambiguous within the context of - the API and the larger ecosystem of Google APIs. They can lead to - misunderstanding of API concepts. Rather, choose specific names that - accurately describe the API concept. This is particularly important - for names that define first-order API elements, such as resources. - There is no definitive list of names to avoid, as every name must be - evaluated in the context of other names. Instance, info, and service - are examples of names that have been problematic in the past. Names - chosen should describe the API concept clearly (for example: - instance of what?) and distinguish it from other relevant concepts - (for example: does "alert" mean the rule, the signal, or the - notification?). -- Carefully consider use of names that may conflict with keywords in - common programming languages. Such names **may** be used but will - likely trigger additional scrutiny during API review. Use them - judiciously and sparingly. - -### Interface names - -To avoid confusion with [Service Names](./0009.md#api-service-name) such as -`pubsub.googleapis.com`, the term *interface name* refers to the name -used when defining a `service` in a .proto file: - -```proto -// Library is the interface name. -service Library { - rpc ListBooks(...) returns (...); - rpc ... -} -``` - -You can think of the *service name* as a reference to the actual -implementation of a set of APIs, while the *interface name* refers to -the abstract definition of an API. - -An interface name **should** use an intuitive noun such as Calendar or -BlobStore. The name **should not** conflict with any well-established -concepts in programming languages and their runtime libraries (for -example, File). - -In the rare case where an *interface name* would conflict with another -name within the API, a suffix (for example `Api` or `Service`) -**should** be used to disambiguate. - -### Method names - -A service **may**, in its IDL specification, define one or more API -methods that correspond to methods on collections and resources. The -method names **should** follow the naming convention of `VerbNoun` in -UpperCamelCase, where the noun is typically the resource type. - -Standard methods, and their Batch variants, define their naming guidance in -the following documents: - -Method | Standard | Batch ------- | -------- | ----- -`Get` | [AIP-131][] | [AIP-231][] -`List` | [AIP-132][] | N/A -`Create` | [AIP-133][] | [AIP-233][] -`Update` | [AIP-134][] | [AIP-234][] -`Delete` | [AIP-135][] | [AIP-235][] - -All other methods are considered Custom Methods and adhere to AIP-136 naming -guidance. - -### Message names - -Message names **should** be short and concise. Avoid unnecessary or redundant -words. Adjectives can often be omitted if there is no corresponding message -without the adjective. For example, the `Shared` in `SharedProxySettings` is -unnecessary if there are no _unshared_ proxy settings. - -Message names **should not** include prepositions (e.g. "With", "For"). -Generally, message names with prepositions are better represented with -optional fields on the message. - -#### Request and response messages - -For request and response message names, see AIP-136 for custom methods and the -appropriate AIP for -[standard methods](https://google.aip.dev/general#operations). - -## Further reading - -- For proto and language package naming, see AIP-191. -- For collection ID naming conventions, see - [AIP-122](./0122.md#collection-identifiers). -- For Enum names, see AIP-126. -- For field names, see AIP-140. -- For repeated field names, see [AIP-140](./0140#repeated-fields). -- For fields representing times and durations, see AIP-142. -- For fields representing dates and times of day, see - [AIP-142](./0142#civil-dates-and-times). -- For fields representing a quantity, see AIP-141. -- For the canonical `List` method `filter` field, see - [AIP-132](./0132#filtering). -- For the canonical `List` response message, see - [AIP-132](./0132#response-message). -- For well known abbreviations, see [AIP-140](./0140#abbreviations). - - -[AIP-131]: ./0131.md -[AIP-132]: ./0132.md -[AIP-133]: ./0133.md -[AIP-134]: ./0134.md -[AIP-135]: ./0135.md -[AIP-231]: ./0231.md -[AIP-233]: ./0233.md -[AIP-234]: ./0234.md -[AIP-235]: ./0235.md diff --git a/aip/general/0191.md b/aip/general/0191.md deleted file mode 100644 index f2e0d1d004..0000000000 --- a/aip/general/0191.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -id: 191 -state: approved -created: 2019-07-25 -placement: - category: polish - order: 10 ---- - -# File and directory structure - -A consistent file and directory structure, while making minimal difference -technically, makes API surface definitions easier for users and reviewers to -read. - -## Guidance - -**Note:** The following guidance applies to APIs defined in protocol buffers, -such as those used throughout Google. While the spirit of this guidance applies -to APIs defined using other specification languages or formats, some of the -particular recommendations might be irrelevant. - -### Syntax - -APIs defined in protocol buffers **must** use `proto3` syntax. - -### Single package - -APIs defined in protocol buffers **must** define each individual API in a -single package, which **must** end in a version component. For example: - -```proto -syntax = "proto3"; - -package google.cloud.translation.v3; -``` - -Google APIs **must** reside in a directory that matches the protocol buffer -`package` directive. For example, the package above dictates that the directory -be `google/cloud/translation/v3`. - -### File names - -It is often useful to divide API definitions into multiple files. File names -**must** use `snake_case`. - -APIs **should** have an obvious "entry" file, generally named after the API -itself. An API with a small number of discrete services (Google Cloud Pub/Sub's -`Publisher` and `Subscriber` is a good example) **may** have a separate entry -file per service. - -APIs with only one file **should** use a filename corresponding to the name of -the API. - -API `service` definitions and associated RPC request and response `message` -definitions **should** be defined in the same file. - -Bear in mind that the file names often become module names in client libraries, -and customers use them in `import` or `use` statements. Therefore, choosing a -descriptive and language keyword-free filename does matter. For example, a file -called `import.proto` may be problematic in Python. - -**Note:** The version **must not** be used as a filename, because this creates -bizarre imports in client libraries. Filenames such as `v3.proto` or -`v1beta1.proto` are prohibited. - -### File layout - -Individual files **should** place higher level and more important definitions -before lower level and less important definitions. - -In a proto file, components **should** be in the following order, and each of -these **should** be separated by a blank line: - -- Copyright and license notice (if applicable). -- The proto `syntax` statement. -- The proto `package` statement. -- Any `import` statements, in alphabetical order. -- Any file-level `option` statements. -- Any `service` definitions. - - Methods **should** be grouped by the resource they impact, and standard - methods **should** precede custom methods. -- Resource `message` definitions. A parent resource **must** be defined before - its child resources. -- The RPC request and response `message` definitions, in the same order of the - corresponding methods. Each request message **must** precede its - corresponding response message (if any). -- Any remaining `message` definitions. -- Any top-level `enum` definitions. - -### Packaging annotations - -Protocol buffers ships with annotations to declare the package or namespace -(depending on the vocabulary of the target language) of the generated files. -For example, setting `go_package` or `csharp_namespace` will override the -inferred package name. - -When defining APIs, the following rules apply: - -- Java - - The `java_package` annotation **must** be set. The correct value is usually - the proto package with the appropriate TLD prefixed. Example: - `com.google.example.v1`. - - The `java_multiple_files` annotation **must** be set to `true`. - - The `java_outer_classname` annotation **must** be set, and **should** be - set to the name of the proto filename, in `PascalCase`, with `Proto` - appended. Example: `LibraryProto`. -- Other languages - - Package or namespace directives for other languages **must** be set either - in every file in the proto package, or none of them. If they are set, the - values **must** be identical in every file. - - If any part of the protobuf package is a compound name (such as - accessapproval), C#, Ruby and PHP options **must** be specified in order - to take account of the word breaks using PascalCase (UpperCamelCase). - Example: - ```proto - option csharp_namespace = "Google.Cloud.AccessApproval.V1"; - option php_namespace = "Google\\Cloud\\AccessApproval\\V1"; - option ruby_package = "Google::Cloud::AccessApproval::V1"; - ``` - - The `go_package` value depends directly on how the Go code is managed i.e. - if the module name is based on the VCS provider or using a remote import - path, but often has a consistent structure. - - The module **may** differ based on product area e.g. - `google.cloud.accessapproval.v1` would be in module - `cloud.google.com/go/accessapproval`. - - The package import path **should** be derived from the proto package. - - An API version in the proto package **should** be prefixed with `api` e.g. - the proto package segment `v1` becomes `apiv1`. - - The terminal import path segment **should** be based on the product name - found within the proto package and **must** be suffixed with `pb` e.g. - `accessapproval` becomes `accessapprovalpb`. - - This value **should** be left to the team owning the generated code to - decide on. - -All packaging annotations **should** be specified in alphabetical order of -name. Refer to the [Protobuf documentation][package docs] for more about -language package options. - -**Important:** While languages other than Java have sensible defaults for APIs -which don't include compound names, be aware that _adding_ this annotation -(with a value not equivalent to the default) constitutes a breaking change in -that language. When releasing protos, be sure that omissions are intentional. - -## Rationale - -### Java packaging options - -Set the option, `java_multiple_files`, to true to get a cleaner file structure. -Doing so instructs `protoc` to create one output file per Protobuf type, which -allows for more fine-grained imports. The option, `java_outer_classname`, is -required in combination with `java_multiple_files`. It instructs `protoc` to -wrap each compiled Protobuf type in a Java class whose name is the value of the -option. This prevents potential naming collisions between generated types. - - -### Go packaging option - -The Go packaging option needs to be decided by the team that owns the generated -code, because it is directly tied to the source code management practices of the -team. Allowing every proto package to decide on their own Go package creates -inconsistencies and friction in management of the code. Within that owning team, -having a consistent structure in the Go package naming is critical to a -consistent end user experience. - -## Changelog - -- **2024-06-13**: Added guidance for Go packaging annotation. -- **2024-06-05**: Added rationale for Java packaging options. -- **2023-02-24**: Added guidance on protobuf syntax. -- **2022-10-18**: Added guidance on Ruby/PHP/C# options. -- **2019-11-18**: Added guidance on the packaging annotations. - -[package docs]: https://protobuf.dev/programming-guides/proto3/#packages diff --git a/aip/general/0192.md b/aip/general/0192.md deleted file mode 100644 index 86cc2356fc..0000000000 --- a/aip/general/0192.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -id: 192 -state: approved -created: 2019-07-25 -placement: - category: polish - order: 20 ---- - -# Documentation - -Documentation is one of the most critical aspects of API design. Users of your -API are unable to dig into the implementation to understand the API better; -often, the API surface definition and its corresponding documentation will be -the only things a user has. Therefore, it is important that documentation be as -clear, complete, and unambiguous as possible. - -## Guidance - -In APIs defined in protocol buffers, public comments **must** be included over -every component (service, method, message, field, enum, and enum value) using -the protocol buffers comment format. This is important even in cases where the -comment is terse and uninteresting, as numerous tools read these comments and -use them. - -Services, in particular, **should** have descriptive comments that explain what -the service is and what users are able to do with it. - -**Note:** Many readers will not be native English speakers. Comments **should** -avoid jargon, slang, complex metaphors, pop culture references, or anything -else that will not easily translate. Additionally, many readers will have -different backgrounds and viewpoints; if writing examples involving people, -comments **should** use people who are non-controversial and no longer alive. - -### Style - -Comments **should** be in grammatically correct American English. However, the -first sentence of each comment **should** omit the subject and be in the -third-person present tense: - -```proto -// Creates a book under the given publisher. -rpc CreateBook(CreateBookRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books" - body: "book" - }; -} -``` - -### Descriptions - -Descriptions of messages and fields **should** be brief but complete. Sometimes -comments are necessarily perfunctory because there is little to be said; -however, before jumping to that conclusion, consider whether some of the -following questions are relevant: - -- What is it? -- How do you use it? -- What does it do if it succeeds? What does it do if it fails? -- Is it idempotent? -- What are the units? (Examples: meters, degrees, pixels) -- What are the side effects? -- What are common errors that may break it? - - What is the expected input format? - - What range of values does it accept? (Examples: `[0.0, 1.0)`, `[1, 10]`) - - Is the range inclusive or exclusive? - - For strings, what is the minimum and maximum length, and what characters - are allowed? - - If a value is above the maximum length, do you truncate or send an error? -- Is it always present? (Example: "Container for voting information. Present - only when voting information is recorded.") -- Does it have a default setting? (Example: "If `page_size` is omitted, the - default is 50.") - -### Formatting - -Any formatting in comments **must** be in [CommonMark][]. Headings and tables -**must not** be used, as these cause problems for several tools, and are -unsuitable for client library reference documentation. - -Comments **should** use `code font` for field or method names and for literals -(such as `true`). - -Raw HTML **must not** be used. - -"ASCII art" attempts to present a diagram within the protos **must not** be -used. The Markdown within the protos is consumed by a large number of renderers, -and any ASCII art is very unlikely to be well-presented by all of them. If -a diagram is useful in order to understand the API, include a link to a -documentation page containing the diagram as an image. - -### Cross-references - -A comment can "link" to another component (service, method, message, field, -enum, or enum value) as a Markdown reference link. The reference **must** be one -of the following forms: - -- The fully-qualified name of the element e.g. `[Book][google.example.v1.Book]` -- A scope-relative reference qualified e.g. `[Sci-Fi genre][Genre.GENRE_SCI_FI]` -- An implied reference e.g. `[Book][]` which equates to `[Book][Book]` - -These references are resolved as per [name resolution][] rules. - -Containing fields names **must not** be used in references. They will not -resolve. The original definition **must** be referenced instead. For example, -`[author][Book.author.family_name]` where `author` is a field of `Book`, will -not resolve, but `[author][Author.family_name]` will. - -[name resolution]: https://protobuf.dev/programming-guides/proto3/#name-resolution - -### External links - -Comments **may** link to external pages to provide background information -beyond what is described in the public comments themselves. External links -**must** use absolute (rather than relative) URLs, including the protocol -(usually `https`), and **should not** assume the documentation is located on -any particular host. For example: -`[Spanner Documentation](https://cloud.google.com/spanner/docs)` - -### Trademarked names - -When referring to the proper, trademarked names of companies or products in -comments, acronyms **should not** be used, unless the acronym is such dominant -colloquial use that avoiding it would obscure the reference (example: [IBM][]). - -Comments **should** spell and capitalize trademarked names consistent with the -trademark owner's current branding. - -### Deprecations - -To deprecate a component (service, method, message, field, enum, or enum value), -the `deprecated` [option](https://developers.google.com/protocol-buffers/docs/proto#options) -**must** be set to `true`, and the first line of the respective comment -**must** start with `"Deprecated: "` and provide alternative solutions for -developers. If there is no alternative solution, a deprecation reason **must** -be given. - -### Internal comments - - - -Comments **may** be explicitly marked as internal by wrapping internal content -in `(--` and `--)`. - -Non-public links, internal implementation notes (such as `TODO` and `FIXME` -directives), and other such material **must** be marked as internal. - -**Note:** Comments **should** use only leading comments (not trailing comments -or detached comments). In particular, comments **must not** use both a leading -and trailing comment to describe any component, because this is a common source -of inadvertent omissions of the internal content annotation. - -[commonmark]: https://commonmark.org/ -[ibm]: https://en.wikipedia.org/wiki/IBM - -## Changelog - -- **2024-10-29**: Include cross-reference resolution rules. -- **2023-08-11**: Expand deprecated comment requirement to all components. -- **2021-04-20**: Added guidance for deprecated services and RPCs. -- **2020-04-01**: Added guidance requiring absolute URLs for external links. -- **2020-02-14**: Added guidance around the use of trademarked names. -- **2019-09-23**: Added guidance about not using both leading and trailing - comments. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0193.md b/aip/general/0193.md deleted file mode 100644 index 317cfb7beb..0000000000 --- a/aip/general/0193.md +++ /dev/null @@ -1,477 +0,0 @@ ---- -id: 193 -state: approved -created: 2019-07-26 -placement: - category: polish - order: 30 ---- - -# Errors - -Effective error communication is an important part of designing simple -and intuitive APIs. Services returning standardized error responses -enable API clients to construct centralized common error handling logic. -This common logic simplifies API client applications and eliminates the -need for cumbersome custom error handling code. - -## Guidance - -Services **must** return a [`google.rpc.Status`][Status] message when an -API error occurs, and **must** use the canonical error codes defined in -[`google.rpc.Code`][Code]. More information about the particular codes -is available in the [gRPC status code documentation][]. - -Error messages **should** help a reasonably technical user *understand* -and *resolve* the issue, and **should not** assume that the user is an -expert in your particular API. Additionally, error messages **must not** -assume that the user will know anything about its underlying -implementation. - -Error messages **should** be brief but actionable. Any extra information -**should** be provided in the `details` field. If even more information -is necessary, you **should** provide a link where a reader can get more -information or ask questions to help resolve the issue. It is also -important to [set the right tone][writing-tone] when writing messages. - -The following sections describe the fields of `google.rpc.Status`. - -### Status.message - -The `message` field is a developer-facing, human-readable "debug message" -which **should** be in English. (Localized messages are expressed using -a `LocalizedMessage` within the `details` field. See -[`LocalizedMessage`](#localizedmessage) for more details.) Any dynamic aspects of -the message **must** be included as metadata within the `ErrorInfo` that appears -in [`details`](#status-details). - -The message is considered a problem description. It is intended for -developers to understand the problem and is more detailed than -[`ErrorInfo.reason`][ErrorInfo-reason], discussed [later](#errorinfo). - -Messages **should** use simple descriptive language that is easy to understand -(without technical jargon) to clearly state the problem that results in an -error, and offer an actionable resolution to it. - -For pre-existing (brownfield) APIs which have previously returned errors -without machine-readable identifiers, the value of `message` **must** -remain the same for any given error. For more information, see -[Changing Error Messages](#changing-error-messages). - -### Status.code - -The `code` field is the status code, which **must** be the numeric value of -one of the elements of the [`google.rpc.Code`][Code] enum. - -For example, the value `5` is the numeric value of the `NOT_FOUND` -enum element. - -### Status.details - -The `details` field allows messages with additional error information to -be included in the error response, each packed in a `google.protobuf.Any` -message. - -Google defines a set of [standard detail payloads][details] for error -details, which cover most common needs for API errors. -Services **should** use these standard detail payloads when feasible. - -Each type of detail payload **must** be included at most once. For -example, there **must not** be more than one [`BadRequest`][BadRequest] -message in the `details`, but there **may** be a `BadRequest` and a -[`PreconditionFailure`][PreconditionFailure]. - -All error responses **must** include an `ErrorInfo` within `details`. This -provides machine-readable identifiers so that users can write code against -specific aspects of the error. - -The following sections describe the most common standard detail payloads. - -#### ErrorInfo - -The [`ErrorInfo`][ErrorInfo] message is the primary way to send a -machine-readable identifier. Contextual information **should** be -included in `metadata` in `ErrorInfo` and **must** be included if it -appears within an error message. - -The `reason` field is a short snake_case description of the cause of the -error. Error reasons are unique within a particular domain of errors. -The reason **must** be at most 63 characters and match a regular expression of -`[A-Z][A-Z0-9_]+[A-Z0-9]`. (This is UPPER_SNAKE_CASE, without leading -or trailing underscores, and without leading digits.) - -The reason **should** be terse, but meaningful enough for a human reader to -understand what the reason refers to. - -Good examples: - -- `CPU_AVAILABILITY` -- `NO_STOCK` -- `CHECKED_OUT` -- `AVAILABILITY_ERROR` - -Bad examples: - -- `THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE` (overly verbose) -- `ERROR` (too general) - -The `domain` field is the logical grouping to which the `reason` belongs. -The domain **must** be a globally unique value, and is typically the name of the service -that generated the error, e.g. `pubsub.googleapis.com`. - -The (reason, domain) pair form a machine-readable way of identifying a particular error. -Services **must** use the same (reason, domain) pair for the same error, and -**must not** use the same (reason, domain) pair for logically different errors. -The decision about whether two errors are "the same" or not is not always clear, but -**should** generally be considered in terms of the expected action a client might take -to resolve them. - -The `metadata` field is a map of key/value pairs providing additional -dynamic information as context. Each key within `metadata` **must** be at most -64 characters long, and conform to the regular expression `[a-z][a-zA-Z0-9-_]+`. - -Any request-specific information which contributes to the `Status.message` or -`LocalizedMessage.message` messages **must** be represented within `metadata`. -This practice is critical so that machine actors do not need to parse error -messages to extract information. - -For example consider the following message: - -> An <e2-medium> VM instance with <local-ssd=3,nvidia-t4=2> is currently unavailable -> in the <us-east1-a> zone. Consider trying your request in the <us-central1-f,us-central1-c> -> zone(s), which currently has/have capacity to accommodate your request. Alternatively, -> you can try your request again with a different VM hardware configuration -> or at a later time. For more information, see the troubleshooting documentation. - -The `ErrorInfo.metadata` map for the same error could be: - -- `"zone": "us-east1-a"` -- `"vmType": "e2-medium"` -- `"attachment": "local-ssd=3,nvidia-t4=2"` -- `"zonesWithCapacity": "us-central1-f,us-central1-c"` - -Additional contextual information that does not appear in an error message -**may** also be included in `metadata` to allow programmatic use by the client. - -The metadata included for any given (reason,domain) pair can evolve over time: - -- New keys **may** be included -- All keys that have been included **must** continue to be included (but may have empty values) - -In other words, once a user has observed a given key for a (reason, domain) pair, the -service **must** allow them to rely on it continuing to be present in the future. - -The set of keys provided in each (reason, domain) pair is independent from other pairs, -but services **should** aim for consistent key naming. For example, two error reasons -within the same domain should not use metadata keys of `vmType` and `virtualMachineType`. - -#### LocalizedMessage - -[`google.rpc.LocalizedMessage`][LocalizedMessage] is used to provide an error -message which **should** be localized to a user-specified locale where -possible. - -If the [`Status.message`](#status-message) field has a sub-optimal value -which cannot be changed due to the constraints in the -[Changing Error Messages](#changing-error-messages) section, `LocalizedMessage` -**may** be used to provide a better error message even when no user-specified -locale is available. - -Regardless of how the locale for the message was determined, both the `locale` -and `message` fields **must** be populated. - -The `locale` field specifies the locale of the message, -following [IETF bcp47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) (Tags for -Identifying Languages). Example values: `"en-US"`, `"fr-CH"`, `"es-MX"`. - -The `message` field contains the localized text itself. This -**should** include a brief description of the error and a call to action -to resolve the error. The message **should** include contextual information -to make the message as specific as possible. Any contextual information -in the message **must** be included in `ErrorInfo.metadata`. See -[`ErrorInfo`](#errorinfo) for more details of how contextual information -may be included in a message and the corresponding metadata. - -The `LocalizedMessage` payload **should** contain the complete resolution -to the error. If more information is needed than can reasonably fit in this -payload, then additional resolution information **must** be provided in -a `Help` payload. See the [Help](#help) section for guidance. - -#### Help - -When other textual error messages (in `Status.message` or -`LocalizedMessage.message`) don't provide the user sufficient -context or actionable next steps, or if there are multiple points of -failure that need to be considered in troubleshooting, a link to -supplemental troubleshooting documentation **must** be provided in the -`Help` payload. - -Provide this information in addition to a clear problem definition and -actionable resolution, not as an alternative to them. The linked -documentation **must** clearly relate to the error. If a single page -contains information about multiple errors, the -[`ErrorInfo.reason`](#errorinfo) value **must** be used to narrow down -the relevant information. - -The `description` field is a textual description of the linked information. -This **must** be suitable to display to a user as text for a hyperlink. -This **must** be plain text (not HTML, Markdown etc). - -Example `description` value: `"Troubleshooting documentation for STOCKOUT errors"` - -The `url` field is the URL to link to. This **must** be an absolute URL, -including scheme. - -Example `url` value: -`"https://cloud.google.com/compute/docs/resource-error"` - -For publicly-documented services, even those with access controls on actual -usage, the linked content **must** be accessible without authentication. - -For privately-documented services, the linked content **may** require -authentication. - -### Error messages - -Textual error messages can be present in both `Status.message` and -`LocalizedMessage.message` fields. Messages **should** be succinct but -actionable, with request-specific information (such as a resource name -or region) providing precise details where appropriate. Any request-specific -details **must** be present in [`ErrorInfo.metadata`](#errorinfo). - -#### Changing error messages - -Changing the content of `Status.message` over time must be done carefully, -to avoid breaking clients who have previously had to rely on the message -for all information. See [the rationale section](#updating-statusmessage) -for more details. - -For a given RPC: - -- If the RPC has *always* returned `ErrorInfo` with machine-readable - information, the content of `Status.message` **may** change over time. - (For example, the API producer may provide a clearer explanation, - or more request-specific information.) -- Otherwise, the content of `Status.message` **must** be stable, - providing the same text with the same request-specific information. - Instead of changing `Status.message`, the API **should** include a - [`LocalizedMessage`](#localizedmessage) within `Status.details`. - - -Even if an RPC has always returned `ErrorInfo`, the API **may** keep -the existing `Status.message` stable and add a -[`LocalizedMessage`](#localizedmessage) within `Status.details`. - -The content of `LocalizedMessage.details` **may** change over time. - -### Partial errors - -APIs **should not** support partial errors. Partial errors add -significant complexity for users, because they usually sidestep the use -of error codes, or move those error codes into the response message, -where the user **must** write specialized error handling logic to -address the problem. - -However, occasionally partial errors are necessary, particularly in bulk -operations where it would be hostile to users to fail an entire large -request because of a problem with a single entry. - -Methods that require partial errors **should** use [long-running -operations][], and the method **should** put partial failure information -in the metadata message. The errors themselves **must** still be -represented with a [`google.rpc.Status`][Status] object. - -### Permission Denied - -If the user does not have permission to access the resource or parent, -regardless of whether or not it exists, the service **must** error with -`PERMISSION_DENIED` (HTTP 403). Permission **must** be checked prior to -checking if the resource or parent exists. - -If the user does have proper permission, but the requested resource or -parent does not exist, the service **must** error with `NOT_FOUND` (HTTP -404). - -## HTTP/1.1+JSON representation - -When clients use HTTP/1.1 as per [AIP-127](./0127.md), the error information -is returned in the body of the response, as a JSON object. For backward -compatibility reasons, this does not map precisely to `google.rpc.Status`, -but contains the same core information. The schema is defined in the following proto: - -```proto -message Error { - message Status { - // The HTTP status code that corresponds to `google.rpc.Status.code`. - int32 code = 1; - // This corresponds to `google.rpc.Status.message`. - string message = 2; - // This is the enum version for `google.rpc.Status.code`. - google.rpc.Code status = 4; - // This corresponds to `google.rpc.Status.details`. - repeated google.protobuf.Any details = 5; - } - - Status error = 1; -} -``` - -The most important difference is that the `code` field in the JSON is an HTTP status code, -*not* the direct value of `google.rpc.Status.code`. For example, a `google.rpc.Status` -message with a `code` value of 5 would be mapped to an object including the following -code-related fields (as well as the message, details etc): - -```json -{ - "error": { - "code": 404, // The HTTP status code for "not found" - "status": "NOT_FOUND" // The name in google.rpc.Code for value 5 - } -} -``` - -The following JSON shows a fully populated HTTP/1.1+JSON representation of an error response. - - -```json -{ - "error": { - "code": 429, - "message": "The zone 'us-east1-a' does not have enough resources available to fulfill the request. Try a different zone, or try again later.", - "status": "RESOURCE_EXHAUSTED", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.ErrorInfo", - "reason": "RESOURCE_AVAILABILITY", - "domain": "compute.googleapis.com", - "metadata": { - "zone": "us-east1-a", - "vmType": "e2-medium", - "attachment": "local-ssd=3,nvidia-t4=2", - "zonesWithCapacity": "us-central1-f,us-central1-c" - } - }, - { - "@type": "type.googleapis.com/google.rpc.LocalizedMessage", - "locale": "en-US", - "message": "An VM instance with is currently unavailable in the zone. Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation." - }, - { - "@type": "type.googleapis.com/google.rpc.Help", - "links": [ - { - "description": "Additional information on this error", - "url": "https://cloud.google.com/compute/docs/resource-error" - } - ] - } - ] - } -} -``` - - -## Rationale - -### Requiring ErrorInfo - -`ErrorInfo` is required because it further identifies an error. With -only approximately twenty [available values][Code] for `Status.status`, -it is difficult to disambiguate one error from another across an entire -[API Service][API Service]. - -Also, error messages often contain dynamic segments that express -variable information, so there needs to be machine-readable component of -*every* error response that enables clients to use such information -programmatically. - -### Including LocalizedMessage - -`LocalizedMessage` was selected as the location to present alternate -error messages. While `LocalizedMessage` **may** use a locale specified -in the request, a service **may** provide a `LocalizedMessage` even without -a user-specified locale, typically to provide a better error message in -[situations where `Status.message` cannot be changed](#updating-statusmessage). -Where the locale is not specified by the user, it **should** be `en-US` -(US English). - -A service **may** include `LocalizedMessage` even when the same message is -provided in `Status.message` and when localization into a user-specified locale -is not supported. Reasons for this include: - -- An intention to support user-specified localization in the near future, allowing - clients to consistently use `LocalizedMessage` and not change their error-reporting - code when the functionality is introduced. -- Consistency across all RPCs within a service: if some RPCs include - `LocalizedMessage` and some only use `Status.message` for error messages, clients - have to be aware of which RPCs will do what, or implement a fall-back mechanism. - Providing `LocalizedMessage` on all RPCs allows simple and consistent client code - to be written. - -### Updating Status.message - -If a client has ever observed an error with `Status.message` populated -(which it always will be) but without `ErrorInfo`, the developer of that client -may well have had to resort to parsing `Status.message` in order to find out -information beyond just what `Status.code` conveys. That information may be -found by matching specific text (e.g. "Connection closed with unknown cause") -or by parsing the message to find out metadata values (e.g. a region with -insufficient resources). At that point, `Status.message` is implicitly part -of the API contract, so **must not** be updated - that would be a breaking -change. This is one reason for introducing `LocalizedMessage` into the -`Status.details`. - -RPCs which have **always** included `ErrorInfo` are in a better position: -the contract is then more about the stability of `ErrorInfo` for any given -error. The reason and domain need to be consistent over time, and the -metadata provided for any given (reason,domain) can only be expanded. -It's still possible that clients could be parsing `Status.message` instead of -using `ErrorInfo`, but they will always have had a more robust option -available to them. - -## Further reading - -- For which error codes to retry, see [AIP-194][aip-194]. -- For how to retry errors in client libraries, see - [AIP-4221][aip-4221]. - -## Changelog - -- **2024-10-18**: Rewrite/restructure for clarity. -- **2024-01-10**: Incorporate guidance for writing effective messages. -- **2023-05-17**: Change the recommended language for `Status.message` to be - the service's native language rather than English. -- **2023-05-17**: Specify requirements for changing error messages. -- **2023-05-10**: Require [`ErrorInfo`][ErrorInfo] for all error responses. -- **2023-05-04**: Require uniqueness by message type for error details. -- **2022-11-04**: Added guidance around PERMISSION_DENIED errors previously - found in other AIPs. -- **2022-08-12**: Reworded/Simplified intro to add clarity to the intent. -- **2020-01-22**: Added a reference to the [`ErrorInfo`][ErrorInfo] message. -- **2019-10-14**: Added guidance restricting error message mutability to if - there is a machine-readable identifier present. -- **2019-09-23**: Added guidance about error message strings being able to - change. - - - -[aip-4221]: https://google.aip.dev/client-libraries/4221 -[details]: https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto -[ErrorInfo]: https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76 -[ErrorInfo-reason]: https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L57 -[PreconditionFailure]: https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L139-L166 -[BadRequest]: https://github.com/googleapis/googleapis/blob/477a59d764428136ba1d857a9633c0d231de6efa/google/rpc/error_details.proto#L168-L218 -[LocalizedMessage]: https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285 -[grpc status code documentation]: https://github.com/grpc/grpc/blob/master/doc/statuscodes.md -[Code]: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto -[Status]: https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto -[Status details]: https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48 -[long-running operations]: ./0151.md -[API Service]: https://cloud.google.com/apis/design/glossary#api_service -[writing-tone]: https://developers.google.com/tech-writing/error-messages/set-tone -[Error model]: https://cloud.google.com/apis/design/errors#error_model -[Help]: https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256 -[resource-error]: https://cloud.google.com/compute/docs/resource-error -[InvalidArgument]: https://github.com/googleapis/googleapis/blob/d4acb64370d333024a167551e7da854506109ba2/google/rpc/code.proto#L52-L58 - - diff --git a/aip/general/0194.md b/aip/general/0194.md deleted file mode 100644 index a5aba5c1ec..0000000000 --- a/aip/general/0194.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -id: 194 -state: approved -created: 2019-08-16 -placement: - category: polish - order: 40 ---- - -# Automatic retry configuration - -RPCs sometimes fail. When one does, the client performing the RPC needs to know -whether it is safe to retry the operation. When status codes are used -consistently across multiple APIs, clients can respond to failures -appropriately. - -## Guidance - -Clients **should** automatically retry requests for which repeated runs would -not cause unintended state changes, which are non-transactional, and which are -[unary](https://grpc.io/docs/guides/concepts/). - -Clients **should not** automatically retry transactional requests; instead -these requests **should** have application-level retry logic that retries the -entire transaction block from the start. - -Clients **should not** automatically retry requests in which repeated runs -would cause unintended state changes. - -**Note:** This AIP does not cover client streaming or bi-directional streaming. - -**Note:** For client side retry behavior in the client libraries: see -[AIP-4221](https://aip.dev/4221). - -### Retryable codes - -For methods listed as retryable above, clients **should** retry the following -error codes: - -- `UNAVAILABLE`: This code generally results from network hiccups, and is - generally transient. It is retryable under the expectation that the - connection will become available (soon). - -### Non-retryable codes - -The following codes **should not** be automatically retried for any request: - -- `OK`: The request succeeded. -- `CANCELLED`: An application can cancel a request, which **must** be honored. -- `DEADLINE_EXCEEDED`: An application can set a deadline, which **must** be - honored. -- `INVALID_ARGUMENT`: Retrying a request with an invalid argument will never - succeed. -- `DATA_LOSS`: This is an unrecoverable error and **must** immediately be - surfaced to the application. - -### Generally non-retryable codes: - -The following codes generally **should not** be automatically retried for any -request: - -- `RESOURCE_EXHAUSTED`: This code may be a signal that quota is exhausted. - Retries therefore may not be expected to work for several hours; meanwhile - the retries may have billing implications. If `RESOURCE_EXHAUSTED` is used - for other reasons than quota and the expected time for the resource to become - available is much shorter, it may be retryable. -- `INTERNAL`: This code generally means that some internal part of the system - has failed, and usually means a bug should be filed against the system. These - **should** immediately be surfaced to the application. -- `UNKNOWN`: Unlike `INTERNAL`, this code is reserved for truly - unknown-to-the-system errors, and therefore may not be safe to retry. These - **should** immediately be surfaced to the application. -- `ABORTED`: This code typically means that the request failed due to a - sequencer check failure or transaction abort. These **should not** be retried - for an individual request; they **should** be retried at a level higher (the - entire transaction, for example). - -Some codes **may** be automatically retried if a system is designed without -synchronization or signaling between various components. For example, client -might retry `NOT_FOUND` on a read operation, which is designed to hang forever -until the resource is created. However, these types of systems are generally -discouraged. - -Therefore, the following codes **should not** be automatically retried for any -request: - -- `NOT_FOUND`: A client **should not** retry until a resource is created. -- `ALREADY_EXISTS`: A client **should not** retry until a resource is deleted. -- `PERMISSION_DENIED`: A client **should not** retry until it has permission. -- `UNAUTHORIZED`: A client **should not** retry until it is authorized. -- `UNAUTHENTICATED`: A client **should not** retry until it is authenticated. -- `FAILED_PRECONDITION`: A client **should not** retry until system state - changes. -- `OUT_OF_RANGE`: A client **should not** retry until the range is extended. -- `UNIMPLEMENTED`: A client **should not** retry until the RPC is implemented. - -## Further reading - -- For parallel or retried request disambiguation, see [AIP-154](./0154.md). diff --git a/aip/general/0200.md b/aip/general/0200.md deleted file mode 100644 index 7591842af0..0000000000 --- a/aip/general/0200.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -id: 200 -state: approved -created: 2018-06-28 -placement: - category: meta - order: 30 -redirect_from: /not-precedent ---- - -# Precedent - -Many times, APIs are written in ways that do not match new guidance that is -added to these standards after those APIs have already been released. -Additionally, sometimes it can make sense to intentionally violate standards -for particular reasons, such as maintaining consistency with established -systems, meeting stringent performance requirements, or other practical -concerns. Finally, as carefully as everyone reviews APIs before they are -released, sometimes mistakes can slip through. - -Since it often is not feasible to fix past mistakes or make the standards serve -every use case, APIs may be stuck with these exceptions for quite some time. -Further, since new APIs often base their designs (names, types, structures, -etc) on existing APIs, it is possible that a standards violation in one API -could spill over into other APIs, even if original reason for the exception is -not applicable to the other APIs. - -As a result of this problem, it is important to "stop the bleeding" of these -standards exceptions into new APIs, and additionally document the reasons for -each exception so that historical wisdom is not lost. - -## Guidance - -If an API violates the AIP standards for any reason, there **must** be an -internal comment linking to this document using its descriptive link -([aip.dev/not-precedent]()) to ensure others do not copy the violations or cite -the errors as precedent of a "previously approved API". - -The comment should also include an explanation of what violates standards and -why it is necessary. For example: - -```proto -message DailyMaintenanceWindow { - // Time within the maintenance window to start the maintenance operations. - // It must use the format "HH MM", where HH : [00-23] and MM : [00-59] GMT. - // (-- aip.dev/not-precedent: This was designed for consistency with crontab, - // and preceded the AIP standards. - // Ordinarily, this type should be `google.type.TimeOfDay`. --) - string start_time = 2; - - // Output only. Duration of the time window, automatically chosen to be - // smallest possible in the given scenario. - // (-- aip.dev/not-precedent: This preceded the AIP standards. - // Ordinarily, this type should be `google.protobuf.Duration`. --) - string duration = 3; -} -``` - -**Important:** APIs should only be considered to be precedent-setting if they -are in beta or GA. - -### Local consistency - -If an API violates a standard throughout, it would be jarring and frustrating -to users to break the existing pattern only for the sake of adhering to the -global standard. - -For example, if all of an API's resources use `creation_time` (instead of the -standard field `create_time` described in [AIP-142][]), a new resource in that -API should continue to follow the local pattern. - -However, others who might otherwise copy that API should be made aware that -this is contra-standard and not something to cite as precedent when launching -new APIs. - -```proto -// ... -message Book { - // (-- aip.dev/not-precedent: This field was present before there was a - // standard field. - // Ordinarily, it should be spelled `create_time`. --) - google.protobuf.Timestamp creation_time = 1; -} - -// ... -message Author { - // (-- aip.dev/not-precedent: `Book` had `creation_time` before there was - // a standard field, so we match that here for consistency. Ordinarily, - // this would be spelled `create_time`. --) - google.protobuf.Timestamp creation_time = 1; -} -``` - -### Pre-existing functionality - -Standards violations are sometimes overlooked before launching, resulting in -APIs that become stable and therefore can not easily be modified. Additionally, -a stable API may pre-date a standards requirement. - -In these scenarios, it is difficult to make the API fit the standard. However, -the API should still cite that the functionality is contra-standard so that -other APIs do not copy the mistake and cite the existing API as a reason why -their design should be approved. - -### Adherence to external spec - -Occasionally, APIs must violate standards because specific requests are -implementations of an external specification (for example, OAuth), and their -specification may be at odds with AIP guidelines. In this case, it is likely to -be appropriate to follow the external specification. - -### Adherence to existing systems - -Similar to the example of an external specification above, it may be proper for -an API to violate AIP guidelines to fit in with an existing system in some way. -This is a fundamentally similar case where it is wise to meet the customer -where they are. A potential example of this might be integration with or -similarity to a partner API. - -### Expediency - -Sometimes there are users who need an API surface by a very hard deadline or -money walks away. Since most APIs serve a business purpose, there will be times -when an API could be better but cannot get it that way and into users' hands -before the deadline. In those cases, API review councils **may** grant -exceptions to ship APIs that violate guidelines due to time and business -constraints. - -### Technical concerns - -Internal systems sometimes have very specific implementation needs (e.g., they -rely on operation transforms that speak UTF-16, not UTF-8) and adhering to AIP -guidelines would require extra work that does not add significant value to API -consumers. Future systems which are likely to expose an API at some point -should bear this in mind to avoid building underlying infrastructure which -makes it difficult to follow AIP guidelines. - -## Changelog - -- **2020-03-27**: Reworded much of this AIP to follow [AIP-8][], and remove - first and second person. No semantic changes. -- **2019-05-04**: Changed to a public link ([aip.dev/not-precedent]()), and - changed references to "the style guide" to use the more generic term - "standards" (to account for a general shift to AIPs). - -[aip-8]: ./0008.md -[aip-142]: ./0142.md diff --git a/aip/general/0202.md b/aip/general/0202.md deleted file mode 100644 index 1f5b6ff67e..0000000000 --- a/aip/general/0202.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: 202 -state: approved -created: 2023-09-22 -placement: - category: fields - order: 0 ---- - -# Fields - -The [`google.api.FieldInfo`][field info proto] type, through its accompanying -extension `google.api.field_info`, enriches a field's schema beyond the basic -name and type information. - -## Guidance - -Decorating a field with `google.api.field_info` is only necessary when -explicitly stated in this AIP or another that leverages `google.api.FieldInfo` -information. As such, the guidance herein applies to those scenarios as well. - -### Format - -Fields with a primitive type can still have a specific format. To convey that -type format, the `FieldInfo.Format` enumeration is used via the -`(google.api.field_info).format` extension field. The following guidance conveys -the meaning of and requirements for use of each `FieldInfo.Format` value. - -#### UUID4 - -The `UUID4` format represents a UUID version 4 value as governed by -[RFC 4122][]. It **must** only be used on a field of type `string`. - -Such a value **may** be normalized by the service to entirely lowercase letters. -For example, the value `F47AC10B-58CC-0372-8567-0E02B2C3D479` would be -normalized to `f47ac10b-58cc-0372-8567-0e02b2c3d479`. - -As such, equivalence comparison **must not** be done via primitive text -comparison. Instead, an [RFC 4122][] compliant implementation **must** be used. - -#### IPv4 - -The `IPV4` format represents an IP v4 address as governed by [RFC 791][]. It -**must** only be used on a field of type `string`. - -Such a value **may** be condensed by the service, with leading zeros in each -octet stripped. For example, `001.022.233.040` would be condensed to -`1.22.233.40`. - -As such, equivalence comparison **must not** be done via primitive text -comparison. Instead, an [RFC 791][] compliant implementation **must** be used. - -#### IPv6 - -The `IPV6` format represents an IP v6 address as governed by [RFC 4291][]. It -**must** only be used on a field of type `string`. - -Such a value **may** be normalized by the service to entirely lowercase letters -with zeros compressed, following [RFC 5952][]. For example, the value -`2001:0DB8:0::0` would be normalized to `2001:db8::`. - -As such, equivalence comparison **must not** be done via primitive text -comparison. Instead, an [RFC 4291][] compliant implementation **must** be used. - -#### IPv4 or IPv6 - -The `IPV4_OR_IPV6` value indicates that the field can be either an IP v4 or v6 -address, as described in the [IPv4](#ipv4) and [IPv6](#ipv6) sections. - -#### Format Compatibility - -Adding a format specifier to an existing, unspecified field **is not** backwards -compatible, *unless* the field in question has always conformed to the format -being specified. - -Changing an existing format specifier to a different one in all cases **is not** -backwards compatible. - -#### Extending Format - -Any new `FieldInfo.Format` value **must** be governed by an -[IETF-approved RFC][ietf rfc] or a [Google-approved AIP](./0001.md). - -## Rationale - -#### Why add a format specifier? - -The format of a primitive-typed field can be critical to its usability. Some -programming languages may convey a specific type format as a standalone type, -as Java does with [UUID][java uuid]. Most have specific structural requirements -that are validated by the service, so conveying the format to the user ahead of -time is critical to their experience. - -#### Why discourage primitive equality comparisons? - -The text representations of the supported formats have many nuances and -transforming the value into a canonical representation is non-trivial. As such, -aligning implementations between each consumer and each service without any -issue is infeasible. - -#### Why document value normalizations? - -While primitive comparison is not recommended for any of the supported formats, -uniform normalization of values is important to set consumer expectations, and -create a user-friendly surface. - -#### Why require an RFC or AIP for new formats? - -Those formats which are sufficiently standardized to merit an RFC or AIP are -stable enough and widely enough known to be incorporated as a supported value -and see usage in Google APIs. Requiring such extra guidance means that governing -the format specification is not the responsibility of the `FieldInfo.Format` -enumeration itself. - -[field info proto]: https://github.com/googleapis/googleapis/blob/master/google/api/field_info.proto -[rfc 4122]: https://datatracker.ietf.org/doc/html/rfc4122 -[rfc 791]: https://datatracker.ietf.org/doc/html/rfc791 -[rfc 4291]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.2 -[rfc 5952]: https://datatracker.ietf.org/doc/html/rfc5952 -[ietf rfc]: https://www.ietf.org/standards/rfcs -[java uuid]: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html diff --git a/aip/general/0203.md b/aip/general/0203.md deleted file mode 100644 index 55ffcac4b0..0000000000 --- a/aip/general/0203.md +++ /dev/null @@ -1,302 +0,0 @@ ---- -id: 203 -state: approved -created: 2018-07-17 -placement: - category: fields - order: 15 ---- - -# Field behavior documentation - -When defining fields in protocol buffers, it is customary to explain to users -certain aspects of the field's behavior (such as whether it is required or -optional). Additionally, it can be useful for other tools to understand this -behavior (for example, to optimize client library signatures). - -## Guidance - -APIs use the `google.api.field_behavior` annotation to describe well-understood -field behavior, such as a field being required or immutable. - -```proto -// The audio data to be recognized. -RecognitionAudio audio = 2 [(google.api.field_behavior) = REQUIRED]; -``` - -- APIs **must** apply the `google.api.field_behavior` annotation on every field - on a message or sub-message used in a request. - - An exception to this is the AIP-154 `etag` field on a resource message, - which **should not** have any `google.api.field_behavior` assigned. -- The annotation **must** include any [google.api.FieldBehavior][] values that - accurately describe the behavior of the field. - - `FIELD_BEHAVIOR_UNSPECIFIED` **must not** be used. -- APIs **must** at minimum use one of `REQUIRED`, `OPTIONAL`, or `OUTPUT_ONLY`. - -**Warning:** Although `field_behavior` does not impact proto-level behavior, -many clients (e.g. CLIs and SDKs) rely on them to generate code. Thoroughly -review and consider which values are relevant when adding a new field. - -Fields with no annotation are interpreted as `OPTIONAL` for -backwards-compatility. Nontheless, this annotation **must not** be omitted. - -**Note:** The vocabulary given in this document is for _descriptive_ purposes -only, and does not itself add any validation. The purpose is to consistently -document this behavior for clients. - -### field behavior of nested messages - -`google.api.field_behavior` annotations on a nested message are independent of -the annotations of the parent. - -For example, a nested message can have a field behavior of `REQUIRED` while the -parent field can be `OPTIONAL`: - -```proto -message Title { - string text = 1 [(google.api.field_behavior) = REQUIRED]; -} - -message Slide { - Title title = 1 [(google.api.field_behavior) = OPTIONAL]; -} -``` - -In the case above, if a `title` is specified, the `text` field is required. - -## Vocabulary - -### Identifier - -The use of `IDENTIFIER` indicates that a field within a resource message is used -to identify the resource. It **must** be attached to the `name` field and **must -not** be attached to any other field (see [fields representing resource names]). - -The `IDENTIFIER` value conveys that the field is not accepted as input (i.e. -`OUTPUT_ONLY`) in the context of a create method, while also being considered -`IMMUTABLE` and accepted as input for mutation methods that accept the -resource as the primary input e.g. [Standard Update][aip-134]. - -This annotation **must not** be applied to references to other resources within -a message. - -### Immutable - -The use of `IMMUTABLE` indicates that a field on a resource cannot be changed -after its creation. This can apply to either fields that are input or outputs, -required or optional. - -When a service receives an immutable field in an update request (or similar), -even if included in the update mask, the service **should** ignore the field if -the value matches, but **should** error with `INVALID_ARGUMENT` if a change is -requested. - -Potential use cases for immutable fields (this is not an exhaustive list) are: - -- Attributes of resources that are not modifiable for the lifetime of the - application (e.g. a disk type). - -**Note:** Fields which are "conditionally immutable" **must not** be given the -immutable annotation. - -### Input only - -The use of `INPUT_ONLY` indicates that the field is provided in requests and -that the corresponding field will not be included in output. - -Additionally, a field **should** only be described as input only if it is a -field in a resource message or a field of a message included within a resource -message. Notably, fields in request messages (a message which only ever acts as -an argument to an RPC, with a name usually ending in `Request`) **should not** -be described as input only because this is already implied. - -Potential use cases for input only fields (this is not an exhaustive list) are: - -- The `ttl` field as described in AIP-214. - -**Warning:** Input only fields are rare and should be considered carefully -before use. - -### Optional - -The use of `OPTIONAL` indicates that a field is not required. - -A field **may** be described as optional if it is a field on a request message -(a message that is an argument to an RPC, usually ending in `Request`), or a -field on a submessage. - -### Output only - -The use of `OUTPUT_ONLY` indicates that the field is provided in responses, but -that including the field in a message in a request does nothing (the server -**must** clear out any value in this field and **must not** throw an error as a -result of the presence of a value in this field on input). Similarly, services -**must** ignore the presence of output only fields in update field masks (see: -AIP-161). - -Additionally, a field **should** only be described as output only if it is a -field in a resource message, or a field of a message farther down the tree. -Notably, fields in response messages (a message which only ever acts as a -return value to an RPC, usually ending in `Response`) **should not** be -described as output only because this is already implied. - -Output only fields **may** be set to empty values if appropriate to the API. - -Potential use cases for output only fields (this is not an exhaustive list) -are: - -- Create or update timestamps. -- Derived or structured information based on original user input. -- Properties of a resource assigned by the service which can not be altered. - -### Required - -The use of `REQUIRED` indicates that the field **must** be present (and set to -a non-empty value) on the request or resource. - -A field **should** only be described as required if _either_: - -- It is a field on a resource that a user provides somewhere as input. In this - case, the resource is only valid if a "truthy" value is _stored_. - - When [creating][aip-133] the resource, a value **must** be provided for the - field on the create request. - - When [updating][aip-134] the resource, the user **may** omit the field - provided that the field is also absent from the field mask, indicating no - change to the field (otherwise it **must** be provided). -- It is a field on a request message (a message that is an argument to an RPC, - with a name usually ending in `Request`). In this case, a value **must** be - provided as part of the request, and failure to do so **must** cause an error - (usually `INVALID_ARGUMENT`). - -We define the term "truthy" above as follows: - -- For primitives, values other than `0`, `0.0`, empty string/bytes, and `false` -- For repeated fields maps, values with at least one entry -- For messages, any message with at least one "truthy" field. - -Fields **should not** be described as required in order to signify: - -- A field which will always be present in a response. -- A field which is conditionally required in some situations. -- A field on any message (including messages that are resources) which is never - used as user input. - -**Note:** In most cases, empty values (such as `false` for booleans, `0` for -integers, or the unspecified value for enums) are indistinguishable from unset -values, and therefore setting a required field to a falsy value yields an -error. A corollary to this is that a required boolean must be set to `true`. - -### Unordered List - -The use of `UNORDERED_LIST` on a repeated field of a resource indicates that -the service does not guarantee the order of the items in the list. - -A field **should** be described as an unordered list if the service does not -guarantee that the order of the elements in the list will match the order that -the user sent, including a situation where the service will sort the list on -the user's behalf. - -A resource with an unordered list **may** return the list in a stable order, or -**may** return the list in a randomized, unstable order. - -## Backwards compatibility - -Adding or changing `google.api.field_behavior` values can represent a semantic -change in the API that is perceived as incompatible for existing clients. The -following are examples of backwards incompatible changes with -`google.api.field_behavior`: - -* Adding `REQUIRED` to an existing field previously considered `OPTIONAL` -(implicitly or otherwise) -* Adding a new field annotated as `REQUIRED` to an existing request message -* Adding `OUTPUT_ONLY` to an existing field previously accepted as input -* Adding `INPUT_ONLY` to an existing field previously emitted as output -* Adding `IMMUTABLE` to an existing field previously considered mutable -* Removing `OUTPUT_ONLY` from an existing field previously ignored as input -* Removing `IDENTIFIER` from an existing field. - -There are some changes that *are* backwards compatible, which are as follows: - -* Adding `OPTIONAL` to an existing field -* Adding `IDENTIFIER` to an existing `name` field -* Changing from `REQUIRED` to `OPTIONAL` on an existing field -* Changing from `OUTPUT_ONLY` and/or `IMMUTABLE` to `IDENTIFIER` on an existing - field -* Removing `REQUIRED` from an existing field -* Removing `INPUT_ONLY` from an existing field previously excluded in responses -* Removing `IMMUTABLE` from an existing field previously considered immutable - -## Rationale - -### Identifier field behavior - -Resource names, the primary identifiers for any compliant resource, are never -fully constructed by the user on create. Such fields are typically assigned -`OUTPUT_ONLY` field behavior. They are, however, also often consumed as -the primary identifier in scenarios where the resource itself is the primary -request payload. Such fields could *not* be considered `OUTPUT_ONLY`. -Furthermore, in mutation requests, like Standard Update, the resource name as -the primary identifier cannot be changed in place. Such fields are typically -assigned `IMMUTABLE` field behavior. These conflicting and context-dependent -field behaviors meant that a new value was necessary to single out and convey -the behavior of the resource name field. - -### Required set of annotations - -A field used in a request message must be either an input or an output. - -In the case of an output, the `OUTPUT_ONLY` annotation is sufficient. - -In the case of an input, a field is either required or optional, and therefore -should have at least the `REQUIRED` or `OPTIONAL` annotation, respectively. -Only providing `INPUT_ONLY` does not convey the necessity of the field, so -specifying either `REQUIRED` or `OPTIONAL` is still necessary. - -### Requiring field behavior - -By including the field behavior annotation for each field, the overall behavior -that the resource exhibits is more clearly defined. Clearly defined field -behavior improves programmatic clients and user understanding. - -Requiring the annotation also forces the API author to explicitly consider the -behavior when initially authoring of the API. - -Modifying field behavior after initial authoring can result in -backwards-incompatible changes in clients. For example, making an optional field -required results in backwards-incompatible changes in the method signature of an -RPC or a resource in a [Declarative client][]. See the -[Backwards compatibility](#backwards-compatibility) section for more detailed -compatibility guidance. - -## History - -In 2023-05 field_behavior was made mandatory. Prior to this change, the -annotation was often omitted. Its values are relied upon to produce high quality -clients. Furthermore, adding or changing some of the field_behavior values after -the fact within a major version can be backwards-incompatible. See the -[Backwards compatibility](#backwards-compatibility) section for more detailed -compatibility guidance. - -The benefits of requiring field_behavior at the time that the API is authored -surpass the costs to clients and API users of not doing so. - -[aip-133]: ./0133.md -[aip-134]: ./0134.md -[aip-180]: ./0180.md -[google.api.FieldBehavior]: https://github.com/googleapis/googleapis/blob/master/google/api/field_behavior.proto#L49 -[Declarative client]: ./0009.md#declarative-clients -[fields representing resource names]: ./0122.md#fields-representing-resource-names - -## Changelog - -- **2023-09-14**: Clarify that nested behavior and parent behavior are - independent. -- **2023-08-25**: Add guidance on `IDENTIFIER`. -- **2023-07-20**: Describe compatibility guidance with new section. -- **2023-05-24**: Clarify that `IMMUTABLE` does not imply input nor required. -- **2023-05-10**: Added guidance to require the annotation. -- **2020-12-15**: Added guidance for `UNORDERED_LIST`. -- **2020-05-27**: Clarify behavior when receiving an immutable field in an - update. -- **2019-12-05**: Added guidance on output only fields in field masks. -- **2019-06-18**: Use the machine-readable annotation, not comments. diff --git a/aip/general/0205.md b/aip/general/0205.md deleted file mode 100644 index c345a519fc..0000000000 --- a/aip/general/0205.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: 205 -state: approved -created: 2019-02-18 -placement: - category: process - order: 20 -redirect_from: /beta-blocker ---- - -# Beta-blocking changes - -APIs often release an Alpha version of their API in order to get early feedback -from customers. This API is provisional and can change many times before the -important feedback is incorporated and the API is made stable for Beta. - -Since the purpose of Alpha is to gather feedback, the API does not need to be -perfect yet, and it's not strictly necessary for API authors to address every -usability concern or address every point in the API standards. Often, API -authors and API reviewers will not agree on the best design, and the best way -to find out is by having users try out the API. - -However, once the feedback has been collected and the API is going to be -promoted to Beta, usability concerns and style issues do need to be addressed. -In order to ensure that these issues are not forgotten, they should be -explicitly documented in the API. - -## Guidance - -If an API has usability concerns or violates API standards, and the present -design should receive additional scrutiny before being carried through to the -Beta version, there **must** be an internal comment linking to this document -using its descriptive link ([aip.dev/beta-blocker]()) to ensure that the design -is corrected before the API is released to Beta. - -The comment **must** also indicate what kind of change should be made for Beta. -For example: - -```proto -message InputConfig { - // Parameters for input. - // (-- aip.dev/beta-blocker: Convert well-known parameters into explicit - // fields before the Beta launch. --) - map parameters = 1; -} -``` - -If an exception to API standards _does_ need to be carried through to Beta and -GA, see [AIP-200][]. - -[aip-200]: ./0200.md diff --git a/aip/general/0210.md b/aip/general/0210.md deleted file mode 100644 index e65b3fab35..0000000000 --- a/aip/general/0210.md +++ /dev/null @@ -1,171 +0,0 @@ ---- -id: 210 -state: approved -created: 2018-08-20 -placement: - category: design-patterns - order: 110 ---- - -# Unicode - -APIs should be consistent on how they explain, limit, and bill for string -values and their encodings. This ranges from little ambiguities (like fields -"limited to 1024 characters") all the way to billing confusion (are names and -values of properties in Datastore billed based on characters or bytes?). - -In general, if we talk about limits measured in bytes, we are discriminating -against non-ASCII text since it takes up more space. On the other hand, if we -talk about "characters", we are ambiguous about whether those are Unicode "code -points", "code units" for a particular encoding (e.g. UTF-8 or UTF-16), -"graphemes", or "grapheme clusters". - -## Unicode primer - -Character encoding tends to be an area we often gloss over, so a quick primer: - -- Strings are just bytes that represent numbers according to some encoding - format. -- When we talk about **characters**, we sometimes mean Unicode **code points**, - which are numbers in the Unicode spec (up to 21 bits). -- Other times we might mean **graphemes** or **grapheme clusters**, which may - have multiple numeric representations and may be represented by more than one - code point. For example, `á` may be represented as a composition of - `U+0061 + U+0301` (the `a` + the accent combining mark) or as a single code - point, `U+00E1`. -- Protocol buffers uses **UTF-8** ("Unicode Transformation Format") which is a - variable-length encoding scheme using up to 4 **code units** (8-bit bytes) - per code point. - -## Guidance - -### Character definition - -**TL;DR:** In our APIs, "characters" means "Unicode code points". - -In API documentation (e.g., API reference documents, blog posts, marketing -documentation, billing explanations, etc), "character" **must** be defined as a -Unicode code point. - -### Length units - -**TL;DR:** Set size limits in "characters" (as defined above). - -All string field length limits defined in API comments **must** be measured and -enforced in characters as defined above. This means that there is an underlying -maximum limit of (`4 * characters`) bytes, though this limit will only be hit -when using exclusively characters that consist of 4 UTF-8 code units (32 bits). - -If you use a database system (e.g. Spanner) which allows you to define a limit -in characters, it is safe to assume that this byte-defined requirement is -handled by the underlying storage system. - -### Billing units - -APIs **may** use either code points or bytes (using the UTF-8 encoding) as the -unit for billing or quota measurement (e.g., Cloud Translation chooses to use -characters). If an API does not define this, the assumption is that the unit of -billing is characters (e.g., $0.01 _per character_, not $0.01 _per byte_). - -### Unique identifiers - -**TL;DR:** Unique identifiers **should** limit to ASCII, generally only -letters, numbers, hyphens, and underscores, and **should not** start with a -number. - -Strings used as unique identifiers **should** limit inputs to ASCII characters, -typically letters, numbers, hyphens, and underscores -(`[a-zA-Z][a-zA-Z0-9_-]*`). This ensures that there are never accidental -collisions due to normalization. If an API decides to allow all valid Unicode -characters in unique identifiers, the API **must** reject any inputs that are -not in Normalization Form C. Generally, unique identifiers **should not** start -with a number as that prefix is reserved for Google-generated identifiers and -gives us an easy way to check whether we generated a unique numeric ID for or -whether the ID was chosen by a user. - -Unique identifiers **should** use a maximum length of 64 characters, though -this limit may be expanded as necessary. 64 characters should be sufficient for -most purposes as even UUIDs only require 36 characters. - -**Note:** See AIP-122 for recommendations about resource ID segments. - -### Normalization - -**TL;DR:** Unicode values **should** be stored in [Normalization Form C][]. - -Values **should** always be normalized into Normalization Form C. Unique -identifiers **must** always be stored in Normalization Form C (see the next -section). - -Imagine we're dealing with Spanish input "estaré" (the accented part -will be bolded throughout). This text has what we might visualize as 6 -"characters" (in this case, they are grapheme clusters). It has two possible -Unicode representations: - -- Using 6 code points: `U+0065` `U+0073` `U+0074` `U+0061` `U+0072` - **`U+00E9`** -- Using 7 code points: `U+0065` `U+0073` `U+0074` `U+0061` `U+0072` **`U+0065` - `U+0301`** - -Further, when encoding to UTF-8, these code points have two different -serialized representations: - -- Using 7 code-units (7 bytes): `0x65` `0x73` `0x74` `0x61` `0x72` **`0xC3` - `0xA9`** -- Using 8 code-units (8 bytes): `0x65` `0x73` `0x74` `0x61` `0x72` **`0x65` - `0xCC` `0x81`** - -To avoid this discrepancy in size (both code units and code points), use -[Normalization Form C][] which provides a canonical representation for strings. - -[normalization form c]: https://unicode.org/reports/tr15/ - -### Uniqueness - -**TL;DR:** Unicode values **must** be normalized to [Normalization Form C][] -before checking uniqueness. - -For the purposes of unique identification (e.g., `name`, `id`, or `parent`), -the value **must** be normalized into [Normalization Form C][] (which happens -to be the most compact). Otherwise we may have what is essentially "the same -string" used to identify two entirely different resources. - -In our example above, there are two ways of representing what is essentially -the same text. This raises the question about whether the two representations -should be treated as equivalent or not. In other words, if someone were to use -both of those byte sequences in a string field that acts as a unique -identifier, would it violate a uniqueness constraint? - -The W3C recommends using Normalization Form C for all content moving across the -internet. It is the most compact normalized form on Unicode text, and avoids -most interoperability problems. If we were to treat two Unicode byte sequences -as different when they have the same representation in NFC, we'd be required to -reply to possible "Get" requests with content that is **not** in normalized -form. Since that is definitely unacceptable, we **must** treat the two as -identical by transforming any incoming string data into Normalized Form C or -rejecting identifiers not in the normalized form. - -There is some debate about whether we should view strings as sequences of code -points represented as bytes (leading to uniqueness determined based on the -byte-representation of said string) or to interpret strings as a higher level -abstraction having many different possible byte-representations. The stance -taken here is that we already have a field type for handling that: `bytes`. -Fields of type `string` already express an opinion of the validity of an input -(it must be valid UTF-8). As a result, treating two inputs that have identical -normalized forms as different due to their underlying byte representation seems -to go against the original intent of the `string` type. This distinction -typically doesn't matter for strings that are opaque to our services (e.g., -`description` or `display_name`), however when we rely on strings to uniquely -identify resources, we are forced to take a stance. - -Put differently, our goal is to allow someone with text in any encoding (ASCII, -UTF-16, UTF-32, etc) to interact with our APIs without a lot of "gotchas". - -## References - -- [Unicode normalization forms](https://unicode.org/reports/tr15/) -- [Datastore pricing "name and value of each property"](https://cloud.google.com/datastore/pricing) - doesn't clarify this. -- [Natural Language pricing](https://cloud.google.com/natural-language/pricing) - uses charges based on UTF-8 code points rather than code units. -- [Text matching and normalization](https://sites.google.com/a/google.com/intl-eng/apis/matching?pli=1) diff --git a/aip/general/0211.md b/aip/general/0211.md deleted file mode 100644 index 3eee873a5e..0000000000 --- a/aip/general/0211.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: 211 -state: approved -created: 2021-02-24 -placement: - category: design-patterns - order: 115 ---- - -# Authorization checks - -The majority of operations, whether reads or writes, require authorization: -permission to do the thing the user is asking to do. Additionally, it is -important to be careful how much information is provided to _unauthorized_ -users, since leaking information can be a security concern. - -## Guidance - -Services **must** check authorization before validating any request, to ensure -both a secure API surface and a consistent user experience. An operation -**may** require multiple permissions or preconditions in order to grant -authorization. - -If a request can not pass the authorization check for any reason, the service -**must** error with `PERMISSION_DENIED`, and the corresponding error message -**should** look like: "Permission '`{p}`' denied on resource '`{r}`' (or it -might not exist)." This avoids leaking resource existence. - -If it is not possible to determine authorization for a resource because the -resource does not exist, the service **should** check authorization to read -children on the parent resource, and return `NOT_FOUND` if the authorization -check passes. - -### Multiple operations - -A service could encounter a situation where it has two different operations -with two different permissions, either of which would reveal the existence of a -resource if called, but a user only has permission to call one of them. - -In this situation, the service **should** still only check for authorization -applicable to the operation being called, and **should not** try to "help out" -by checking for related authorization that would provide permission to reveal -existence, because such algorithms are complicated to implement correctly and -prone to accidental leaks. - -For example, posit a scenario where: - -- A resource exists within a given collection that a user is unable to read. -- The user _does_ have the ability to create other resources, and the - collection uses user-specified IDs (meaning that a failure because of a - duplicate ID would reveal existence). - -In this situation, the get or create methods **should** still only check -_their_ permissions when determining what error to return, and not one -another's. - -## Rationale - -[RFC 7231 §6.5.3][] states that services are permitted to use `404 Not Found` -in lieu of `403 Forbidden` in situations where the service does not want to -divulge existence, whereas this AIP argues for the use of `PERMISSION_DENIED` -(which corresponds to `403 Forbidden` in HTTP) instead. We take this position -for the following reasons: - -- The practice of "getting `404 Not Found` until you have enough permission to - get `403 Forbidden`" is counter-intuitive and increases the difficulty of - troubleshooting. - - A service _could_ ameliorate this by sending information about missing - permissions while still using the `404 Not Found` status code, but this - constitutes a mixed message. -- While `403 Forbidden` is essentially always an error requiring manual action, - `404 Not Found` is often a valid response that the application can handle - (e.g. "get or create"); overloading it for permission errors deprives - applications of this benefit. -- RFC 7231 §6.5.4 states that `404 Not Found` results are cacheable, but - permission errors are not generally cacheable. Sending explicit cache - controls on a conditional basis could ameliorate this, but would defeat the - purpose. -- The guidance here is more consistent with most other real-world authorization - systems. - -[rfc 7231 §6.5.3]: https://tools.ietf.org/html/rfc7231#section-6.5.3 - -## Changelog - -- **2021-05-11:** Added a more detailed "Rationale" section. diff --git a/aip/general/0213.md b/aip/general/0213.md deleted file mode 100644 index bbbb4bfa2e..0000000000 --- a/aip/general/0213.md +++ /dev/null @@ -1,222 +0,0 @@ ---- -id: 213 -state: approved -created: 2018-08-17 -placement: - category: protobuf - order: 20 ---- - -# Common components - -As specified in [AIP-215][], APIs must be self-contained except for the use -of "common component" packages which are intended for use by multiple APIs. - -There are two kinds of common component packages: - -- Organization-specific common components, covering organization-specific - concepts such as a "viewport" in Maps. -- Global common components which are generic (i.e. not domain-specific), - such as "timestamp" or "postal address". - -Where it is safe to share a single representation across multiple APIs, -common components can make it easier for clients to interact with those APIs. -Concept-specific client code can be written once, and messages can be used from -the response of one API in the request of another without clunky copying, for -example. - -This benefit comes with significant restrictions and limitations, however, -and should not be attempted lightly. - -Note that even if the *domain* of a component is common, the requirements of -a component may be organization-specific. For example, some organizations may -have particular requirements of how financial values are represented, leading -to multiple finance-oriented organization-specific common components - because -any global common component would either not meet the organization-specific -requirements, or be too complex for general use. - -## Guidance - -- Organization-wide common component packages **must** end with `.type`, e.g. - `google.geo.type` or `google.shopping.type`. -- Organizations **must** consult the API design team before creating a new - organization-wide common component package. -- Organization-wide common component packages **must** be published in [the - `googleapis` repository](https://github.com/googleapis/googleapis). -- Organizations creating and publishing a new organization-wide common component - package **must** update this AIP to include it in the - [list below](#existing-organization-specific-common-component-packages). -- Organizations **must not** define generic components in organization-specific - common component packages, instead preferring global common components. -- Common components **must not** be "moved" (that is, deleted from one common - component package and added to a different one) from an organization-specific - common component package to a global common component package or vice versa. - - A common component **may** be copied from an organization-specific common - component package to a global common component package (without deleting the - original component) if it is found to be more widely-applicable than - originally expected. -- Fields **should not** be added to existing messages. -- Values **should not** be added to existing enums. -- Fields **must not** be removed from existing messages. -- Values **must not** be removed from existing enums. -- While documentation **may** be clarified, it **should not** change the - meanings of existing values, including the validity of any given message - or set of messages. -- New proto messages and enums **may** be added to common component packages. - - API teams **should** allow sufficient time for propagation to clients - before using the new messages and enums in their APIs. Fields may take some - time for any changes to propagate through publication to client libraries - and other surfaces. - - API teams **should** consult widely within their organization, and ideally - with the API design team, before adding a new message or enum, due to the - limitations listed above. - -## Existing global common components - -The global common components, which public-facing protos for an API **may** safely -import, are as follows: - -- [`google.api.*`](https://github.com/googleapis/googleapis/blob/master/google/api) (but *not* subpackages of `google.api`) -- [`google.longrunning.Operation`](https://github.com/googleapis/googleapis/blob/master/google/longrunning/operations.proto) -- [`google.protobuf.*`](https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf) -- [`google.rpc.*`](https://github.com/googleapis/googleapis/blob/master/google/rpc/) -- [`google.type.*`][type] - -Note that some common components may have internal-only fields. APIs **should** -generally only rely on fields which have been -[released into open source](https://github.com/googleapis/googleapis). - -Google APIs **may** also import [`google.iam.v1.*`][iam], which provides the -IAM messages used throughout Google. - - -[iam]: https://github.com/googleapis/googleapis/tree/master/google/iam/v1 - -**Note:** Many APIs also import components from other packages for internal-only -use (e.g. to apply visibility labels or provide instructions to internal -infrastructure). This is acceptable provided that the _public_ components do not -contain such references. - -### Protobuf types - -The `google.protobuf` package is somewhat special in that it is shipped with -protocol buffers itself, rather than with API tooling. (For most API designers, -this should be an implementation detail). - -This package includes a small library of types useful for representing common -programming language constructs: - -- [`google.protobuf.Duration`][duration]: Durations, with nanosecond-level - precision. The protobuf runtime provides helper functions to convert to and - from language-native duration objects where applicable (such as Python's - [`timedelta`][timedelta]). -- [`google.protobuf.Struct`][struct]: JSON-like structures (a dictionary of - primitives, lists, and other dictionaries). The protobuf runtime provides - helper functions in most languages to convert struct objects to and from - JSON. -- [`google.protobuf.Timestamp`][timestamp]: Timestamps, with nanosecond-level - precision. The protobuf runtime provides helper functions in most languages - to convert to and from language-native timestamp objects (such as Python's - [`datetime`][datetime]). - - -[datetime]: https://docs.python.org/3/library/datetime.html#datetime.datetime -[duration]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/duration.proto -[struct]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto -[timedelta]: https://docs.python.org/3/library/datetime.html#datetime.timedelta -[timestamp]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto - - -### API Types - -The `google.type` package provides a "standard library" of types useful for -representing common concepts in APIs. While types are added from time to time -and the definitive list is always [the code][type], several types deserve note: - -- [`google.type.Color`][color]: RGB or RGBA colors. -- [`google.type.Date`][date]: Calendar dates, with no time or time zone - component. -- [`google.type.DayOfWeek`][day_of_week]: The day of the week, with no other - date, time, or time zone component. -- [`google.type.LatLng`][lat_lng]: Geographic coordinates. -- [`google.type.Money`][money]: Currency. -- [`google.type.PostalAddress`][postal_address]: Postal addresses in most - countries. -- [`google.type.TimeOfDay`][time_of_day]: Wall-clock time, with no date or time - zone component. - - -[type]: https://github.com/googleapis/googleapis/tree/master/google/type -[color]: https://github.com/googleapis/googleapis/blob/master/google/type/color.proto -[date]: https://github.com/googleapis/googleapis/blob/master/google/type/date.proto -[day_of_week]: https://github.com/googleapis/googleapis/blob/master/google/type/dayofweek.proto -[lat_lng]: https://github.com/googleapis/googleapis/blob/master/google/type/latlng.proto -[money]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto -[postal_address]: https://github.com/googleapis/googleapis/blob/master/google/type/postal_address.proto -[time_of_day]: https://github.com/googleapis/googleapis/blob/master/google/type/timeofday.proto - - -### Adding to common protos - -Occasionally, it may be useful to add protos to these packages or to add to the -list of commonly-available protos. In order to do this, [open an issue][] on -the AIP repository in GitHub, noting the guidelines above. - -## Existing organization-specific common component packages - -The following organization-specific common component packages exist and conform with the above guidance: - -- [`google.apps.script.type`](https://github.com/googleapis/googleapis/tree/master/google/apps/script/type) - Common component package for Google Apps Script. -- [`google.geo.type`](https://github.com/googleapis/googleapis/tree/master/google/geo/type) - Common component package for Google Maps and the Geo organization. -- [`google.actions.type`](https://github.com/googleapis/googleapis/tree/master/google/actions/type) - Common component package for Actions on Google APIs. - -## Non-conformant common component packages - -The following common component packages exist, but do not conform with the above guidance, -and do not form a precedent for further such packages. - -- [`google.cloud.common`](https://github.com/googleapis/googleapis/tree/master/google/cloud/common): - This does not conform to the requirement for the package name to end in `.type`. (This would otherwise - be acceptable, and this package should be considered as the Cloud common component package.) -- [`google.logging.type`](https://github.com/googleapis/googleapis/tree/master/google/logging/type): - This appears to be API-specific, although it's used from multiple APIs; some aspects should probably - be global or in a Cloud common component package. -- [`google.cloud.workflows.type`](https://github.com/googleapis/googleapis/tree/master/google/cloud/workflows/type): - API-specific types. -- [`google.cloud.oslogin.common`](https://github.com/googleapis/googleapis/tree/master/google/cloud/oslogin/common): - API-specific types, and a non-conformant name. -- [`google.identity.accesscontextmanager.type`](https://github.com/googleapis/googleapis/tree/master/google/identity/accesscontextmanager/type): - API-specific types. -- [`google.networking.trafficdirector.type`](https://github.com/googleapis/googleapis/tree/master/google/networking/trafficdirector/type): - API-specific types. - -## Rationale - -Common components are effectively unversioned: APIs evolve independently of -each other, both in terms of definition and implementation. A change such as -adding a field is backward-compatible and predictable in specific APIs, and the -API team can ensure that the server implementation is available before the API -definition is published. By contrast, a change in a common component would -effectively be universally available even if most API implementations did not -take it into account. - -Adding a new message or enum is backward-compatible, as it does not affect -existing APIs that may import other messages or enums from the same common -component package. - -Consultation with the API design team is required for global common components -and suggested for organization-specific common components as the border between -"generic" and "organization-specific" is a gray area; some generic *concepts* -have organization-specific use cases which surface through the components. - -## Changelog - -- **2023-06-27**: Restructured AIPs 215 and 213 for clarity, and introduced the - concept of organization-wide common protos more formally. -- **2018-08-17**: Initial AIP written. - -[open an issue]: https://github.com/googleapis/aip/issues -[aip-215]: ./0215.md diff --git a/aip/general/0214.md b/aip/general/0214.md deleted file mode 100644 index 9e678b3a96..0000000000 --- a/aip/general/0214.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -id: 214 -state: approved -created: 2018-06-19 -placement: - category: design-patterns - order: 120 ---- - -# Resource expiration - -Customers often want to provide the time that a given resource or resource -attribute is no longer useful or valid (e.g. a rotating security key). Currently -we recommend that customers do this by specifying an exact "expiration time" -into a `google.protobuf.Timestamp expire_time` field; however, this adds -additional strain on the user when they want to specify a relative time offset -until expiration rather than a specific time until expiration. - -Furthermore, the world understands the concept of a "time-to-live", often -abbreviated to TTL, but the typical format of this field (an integer, measured -in seconds) results in a sub-par experience when using an auto-generated client -library. - -## Guidance - -1. APIs wishing to convey an expiration **must** rely on a - [`google.protobuf.Timestamp`][timestamp] field called `expire_time`. -2. APIs wishing to allow a relative expiration time **must** define a `oneof` - called `expiration` (or `{something}_expiration`) containing both the - `expire_time` field and a separate [`google.protobuf.Duration`][duration] - field called `ttl`, the latter marked as input only. -3. APIs **must** always return the expiration time in the `expire_time` field - and leave the `ttl` field blank when retrieving the resource. -4. APIs that rely on the specific semantics of a "time to live" (e.g., DNS - which must represent the TTL as an integer) **may** use an `int64 ttl` - field (and **should** provide an [aip.dev/not-precedent](./0200.md) comment - in this case). - -### Example - -```proto -message ExpiringResource { - // google.api.resource and other annotations and fields - - oneof expiration { - // Timestamp in UTC of when this resource is considered expired. - // This is *always* provided on output, and is calculated using - // the value of [ttl][] if set when created. - google.protobuf.Timestamp expire_time = 2; - - // Input only. The TTL for this resource. - google.protobuf.Duration ttl = 3 [(google.api.field_behavior) = INPUT_ONLY]; - } -} -``` - -## Rationale - -### Alternatives considered - -#### A new standard field called `ttl` - -We considered allowing a standard field called `ttl` as an alternative way of -defining the expiration, however doing so would require that API services -continually update the field, like a clock counting down. This could -potentially cause problems with the read-modify-write lifecycle where a -resource is being processed for some time, and effectively has its life -extended as a result of that processing time. - -#### Always use `expire_time` - -This is the current state of the world with a few exceptions. In this scenario, -we could potentially push the computation of `now + ttl = expire_time` into -client libraries; however, this leads to a somewhat frustrating experience in -the command-line and using REST/JSON. Leaving things as they are is typically -the default, but it seems many customers want the ability to define relative -expiration times as it is quite a bit easier and removes questions of time -zones, stale clocks, and other silly mistakes. - - -[duration]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/duration.proto -[timestamp]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto - diff --git a/aip/general/0215.md b/aip/general/0215.md deleted file mode 100644 index c8780cadae..0000000000 --- a/aip/general/0215.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: 215 -state: approved -created: 2018-10-01 -placement: - category: protobuf - order: 30 ---- - -# API-specific protos - -APIs are mostly defined in terms of protos which are API-specific, with -occasional dependencies on common components. Keeping APIs isolated from each -other avoids versioning problems and client library packaging problems. - -## Guidance - -- All protos specific to an API **must** be within a package with a major version - (e.g., `google.library.v1`). -- References to resources in other APIs **must** be expressed in terms of - resource names ([AIP-122][]), rather than using the resource messages. -- When two versions of an API use effectively the same (API-specific) proto - that proto **must** be duplicated in each version. (In other words, APIs - **must not** create their own "API-specific common component" packages.) -- Organization-specific common components **may** be placed in a common package, - as described in [AIP-213][], but **must not** be used by any API outside - that organization. -- Global common components (also described in AIP-213) **may** be freely used by any API. - -## Rationale - -When one API depends on protos defined by another API, this introduces uncertainty -in terms of customer-expected behavior and client library dependency management. -Suppose `google.cloud.library.v1` depends on the protos (rather than abstract resources) -in `google.cloud.movies.v2`. Any change to `google.cloud.movies.v2` can cause problems. - -For example: - -- If a field is added to a message in `google.cloud.movies.v2`, should customers using - `google.cloud.library.v1` expect to see it? If so, how soon after the field has - been added? What about other API changes? -- If the whole major version `google.cloud.movies.v2` is deprecated - (typically after v3 has been released), does that mean `google.cloud.library.v1` has - to change to use `google.cloud.movies.v3`, and if so, does that require a new major version - for the library API as well? -- How should client library versioning reflect changes to dependent APIs? - -Keeping APIs isolated from each other, with a limited set of common components which are -maintained in a highly disciplined way, reduces a lot of the issues with dependencies. - -API-specific common components shared across versions add complexity for client -library generation and packaging, and are inflexible in terms of versioning. -When protos are duplicated because they *start* off the same in multiple versions, -they can still diverge over time as they are isolated from each other. - -## Changelog - -- **2023-06-27**: Restructured AIPs 215 and 213 for clarity. -- **2023-05-11**: Changed "PA" to "organization". -- **2018-10-01**: Initial AIP written. - -[aip-213]: ./0213.md -[aip-122]: ./0122.md diff --git a/aip/general/0216.md b/aip/general/0216.md deleted file mode 100644 index 5233dfcacc..0000000000 --- a/aip/general/0216.md +++ /dev/null @@ -1,242 +0,0 @@ ---- -id: 216 -state: approved -created: 2018-10-01 -updated: 2022-06-02 -placement: - category: fields - order: 110 ---- - -# States - -Many API resources carry a concept of "state": ordinarily, the resource's place -in its life cycle. For example, a virtual machine may be being provisioned, -available for use, being spun down, or potentially be in one of several other -situations. A job or query may be preparing to run, be actively running, have -completed, and so on. - -## Guidance - -Resources needing to communicate their state **should** use an enum, which -**should** be called `State` (or, if more specificity is required, end in the -word `State`). This enum **should** be nested within the message it describes -when only used as a field within that message. - -**Important:** We use the term `State`, and _not_ `Status` (which is reserved -for the HTTP and gRPC statuses). - -### Enum values - -Ideally, Google APIs use the same terminology throughout when expressing the -same semantic concepts. There are usually many words available to express a -given state, but our customers often use multiple APIs together, and it is -easier for them when our terms are consistent. - -At a high level: - -- Resources that are available for use are `ACTIVE` (preferred over terms such - as "ready" or "available"). -- Resources that have completed a (usually terminal) requested action use past - participles (usually ending in `-ED`), such as `SUCCEEDED` (not - "successful"), `FAILED` (not "failure"), `DELETED`, `SUSPENDED`, and so on. -- Resources that are currently undergoing a state change use present - participles (usually ending in `-ING`), such as `RUNNING`, `CREATING`, - `DELETING`, and so on. In this case, it is expected that the state is - temporary and will resolve to another state on its own, with no further user - action. - -**Note:** Remember to only add states that are useful to customers. Exposing a -large number of states simply because they exist in your internal system is -unnecessary and adds confusion for customers. Each state must come with a use -case for why it is necessary. - -### Output only - -The field referencing the `State` enum in a resource **should** behave and be -documented as "Output only", in accordance with [AIP-203](./0203.md). - -APIs **should not** allow a `State` enum to be directly updated through an -"update" method (or directly set through the "create" method), and **should** -instead use custom state transition methods. - -This is because update methods are generally not expected to have side effects, -and also because updating state directly implies that it is possible to set the -state to any available value, whereas states generally reflect a resource's -progression through a lifecycle. - -### State transition methods - -State transition methods are a special type of custom method that are -responsible for transitioning a state field from one enum value to another. As -part of the transition, other fields may also change, e.g. an `update_time` -field. The method definition should look like the following: - -```proto -// Publishes a book. -// The `state` of the book after publishing is `PUBLISHED`. -// `PublishBook` can be called on Books in the state `DRAFT`; Books in a -// different state (including `PUBLISHED`) returns an error. -rpc PublishBook(PublishBookRequest) returns (Book) { - option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:publish" - body: "*" - }; -} -``` - -- The name of the method **should** be a verb followed by the singular form of - the resource's message name. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response message **should** be the resource itself. - - If the RPC is [long-running][], the response message **should** be a - `google.longrunning.Operation` which resolves to the resource itself. -- The HTTP verb **must** be `POST`. -- The HTTP URI **must** use a `:` character followed by the custom verb - (`:publish` in the above example), and the verb in the URI **must** match the - verb in the name of the RPC. - - If word separation is required, `camelCase` **must** be used. -- The `body` clause in the `google.api.http` annotation **must** be `"*"`. -- The request message field receiving the resource name **should** map to the - URI path. - - This field **should** be called `name`. - - The `name` field **should** be the only variable in the URI path. All - remaining parameters **should** map to URI query parameters. -- If the state transition is not allowed, the service **must** error with - `FAILED_PRECONDITION` (HTTP 400). - -The request message should look like this: - -```proto -message PublishBookRequest { - // The name of the book to publish. - // Format: publishers/{publisher}/books/{book} - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; -} -``` - -- A resource name field **must** be included. It **should** be called `name`. -- The comment for the field **should** document the resource pattern. -- Other fields **may** be included. - -## Additional Guidance - -### Default value - -The zero value of each state enum **should** adhere to the following -convention: - -```proto -enum State { - // The default value. This value is used if the state is omitted. - STATE_UNSPECIFIED = 0; - - // Other values... -} -``` - -Resources **should not** provide an unspecified state to users, and this value -**should not** actually be used. - -### Value uniqueness - -Multiple top-level enums within the same package **must** not share the same -values. This is because the C++ protoc code generator flattens top-level enum -values into a single namespace. - -State enums **should** live inside the resource definition. - -### Prefixes - -Using a `STATE_` prefix on every enum value is unnecessary. State enum values -**should not** be prefixed with the enum name, except for the default value -`STATE_UNSPECIFIED`. - -### Breaking changes - -**TL;DR:** Clearly communicate to users that state enums may receive new values -in the future, and be conscientious about adding states to an existing enum. - -Even though adding states to an existing states enum _can_ break existing user -code, adding states is not considered a breaking change. Consider a state with -only two values: `ACTIVE` and `DELETED`. A user may add code that checks -`if state == ACTIVE`, and in the else cases simply assumes the resource is -deleted. If the API later adds a new state for another purpose, that code will -break. - -We ultimately can not control this behavior, but API documentation **should** -actively encourage users to code against state enums with the expectation that -they may receive new values in the future. - -APIs **may** add new states to an existing State enum when appropriate, and -adding a new state is _not_ considered a breaking change. - -### When to avoid states - -Sometimes, a `State` enum may not be what is best for your API, particularly in -situations where a state has a very small number of potential values, or when -states are not mutually exclusive. - -Consider the example of a state with only `ACTIVE` and `DELETED`, as discussed -above. In this situation, the API may be better off exposing a -`google.protobuf.Timestamp delete_time`, and instructing users to rely on -whether it is set to determine deletion. - -### Common states - -The following is a list of states in common use. APIs **should** consider prior -art when determining state names, and **should** value local consistency above -global consistency in the case of conflicting precedent. - -#### Resting states - -"Resting states" are lifecycle states that, absent user action, are expected to -remain indefinitely. However, the user can initiate an action to move a -resource in a resting state into certain other states (resting or active). - -- `ACCEPTED` -- `ACTIVE` -- `CANCELLED` -- `DELETED` -- `FAILED` -- `SUCCEEDED` -- `SUSPENDED` -- `VERIFIED` - -#### Active states - -"Active states" are lifecycle states that typically resolve on their own into a -single expected resting state. - -**Note:** Remember only to expose states that are useful to customers. Active -states are valuable only if the resource will be in that state for a sufficient -period of time. If state changes are immediate, active states are not -necessary. - -- `CREATING` (usually becomes `ACTIVE`) -- `DELETING` (usually becomes `DELETED`) -- `PENDING` (usually becomes `RUNNING`) -- `REPAIRING` (usually becomes `ACTIVE`) -- `RUNNING` (usually becomes `SUCCEEDED`) -- `SUSPENDING` (usually becomes `SUSPENDED`) - -## Further reading - -- For information on enums generally, see [AIP-126][]. - -## Changelog - -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-10-20**: Added guidance on prefixing enum values with enum name. -- **2020-09-02**: Clarified that states are not directly set on create either. -- **2019-12-05**: Changed guidance on state transition methods, downgrading - **must** to **should** on the response type. -- **2019-08-16**: Added guidance for state transition methods. -- **2019-07-18**: Added explicit guidance on the unspecified value. - -[aip-126]: ./0126.md -[long-running]: ./0151.md diff --git a/aip/general/0217.md b/aip/general/0217.md deleted file mode 100644 index aca145aa81..0000000000 --- a/aip/general/0217.md +++ /dev/null @@ -1,288 +0,0 @@ ---- -id: 217 -state: approved -created: 2019-08-26 -placement: - category: design-patterns - order: 130 ---- - -# Unreachable resources - -Occasionally, a user may ask for a list of resources, and some set of resources -in the list are temporarily unavailable. The most typical use case is while -supporting [Reading Across Collections][aip-159]. For example, a user may ask to -list resources across multiple parent locations, but one of those locations is -temporarily unreachable. In this situation, it is still desirable to provide -the user with all the available resources, while indicating that something is -missing. - -## Guidance - -If a method to retrieve data is capable of partially failing due to one or more -resources being temporarily unreachable, the response message **must** include -a field to indicate this: - -```proto -message ListBooksResponse { - // The books matching the request. - repeated Book books = 1; - - // The next page token, if there are more books matching the - // request. - string next_page_token = 2; - - // Unreachable resources. - repeated string unreachable = 3 [ - (google.api.field_behavior) = UNORDERED_LIST - ]; -} -``` - -- The field **must** be a repeated string, and **should** be named - `unreachable`. -- The field **must** contain the resource names of the resources that are - unreachable or those that impede reaching the requested collection, such as - the parent resource of the collection that could not be reached. - - For example, if an entire location is unreachable, preventing access to the - localized collection of resources requested, the location resource is - included. -- The field **must** contain _service-relative_ resource names, and **must not** - contain full resource names, resource URIs, or simple resource IDs. See - [AIP-122][aip-122] for definitions. - - For example, if a `Book` resource is unreachable, the _service-relative_ - resource name `"shelves/scifi1/books/starwars4"` is included in - `unreachable`, as opposed to the _full_ resource name - `"//library.googleapis.com/shelves/scifi1/books/starwars4"`, the - _parent-relative_ resource `"books/starwars4"`, the resource ID - `"starwars4"`, or the resource URI. -- The response **must not** provide any other information about the issue(s) - that made the listed resources unreachable. - - For example, the response cannot contain an extra field with error reasons - for each `unreachable` entry. -- The service **must** provide a way for the user to make a more specific - request and receive an error with additional information e.g. via a Standard - Get or a Standard List targeted at the unreachable collection parent. - - The service **must** also allow the user to repeat the original call with - more restrictive parameters. -- The resource names that appear in `unreachable` **may** be heterogeneous. - - The `unreachable` field definition **should** document what potential - resources could be provided in this field, and note that it might expand - later. - - For example, if both an entire location and a specific resource in a - different location are unreachable, the unreachable location's name - e.g. `"projects/example123/locations/us-east1"` and the unreachable - resource's name e.g. - `"projects/example123/locations/europe-west2/instances/example456"` will - both appear in `unreachable`. -- The `unreachable` field **must not** have semantically meaningful ordering or - structure within the list. Put differently, `unreachable` **must** be an - unordered list. - - As such, the `unreachable` field **must** be annotated with `UNORDERED_LIST` - field behavior (see [AIP-203][unordered]). - -[aip-122]: ./0122.md -[aip-160]: ./0160.md -[unordered]: ./0203.md#unordered-list - -**Important:** If a single unreachable location or resource prevents returning -any data by definition (for example, a list request for a single publisher -where that publisher is unreachable), the service **must** fail the entire -request with an error. - -### Pagination - -While preparing a page of results to fulfill a page fetch RPC e.g. an -[AIP-132][aip-132] Standard List call, if the service encounters any unreachable -resources or collections they **must** do the following: - -- Include the resource name for the unreachable resource in the `unreachable` - response field. - - The resource name **must** be the most appropriately scoped for the - unreachable resource or collection. - - For example, if a specific zone within a region is unreachable, the - unreachable resource name would be a zonal Location e.g. - `projects/example/locations/us-west1-a`, but if an entire region is - unreachable, the resource name would be a regional Location e.g. - `projects/example/locations/us-west1`. - - The resource name **must** be included, regardless of restrictive paging - parameters e.g. `order_by`, when it is identified as unreachable. -- Populate results that were previously considered unreachable on a following - page if their availability is restored and the paging parameters allow for - their inclusion. - - Determining inclusion eligibility based on paging parameters also includes - any documented default ordering behavior in the absence of user-specified - ordering in the request. - - For example, if region `projects/example/locations/us-west1` was unavailable - in the first page of an ordered paging call, and including its resources - would violate the ordering, those out-of-order resources are not included in - the following page. - - Similarly, if the same exact request is made, and resources previously - considered unreachable are available again, they **must** be populated, - within the constraints of the paging parameters. -- Limit the number of unreachable resource names returned in a given response - if, even after up-scoping the unreachable resource name, the number of - unreachable resource names exceeds a documented maximum. - - This maximum **must** be documented in the `unreachable` field comments - directly. - - This is independent of the `page_size` set by the caller. - -#### Retaining previous behavior - -Services **may** continue with previously implemented `unreachable` pagination -behavior where changing it would induce an incompatible change as per -[AIP-180][aip-180], but **must** document said behavior on the `unreachable` -field(s) directly. - -[aip-180]: ./0180.md - -### Adopting partial success - -In order for an existing API that has a default behavior *differing* from the -aforementioned guidance i.e. the API call returns an error status instead of a -partial result, to adopt the `unreachable` pattern the API **must** do the -following: - -- The default behavior **must** be retained to avoid incompatible behavioral - changes - - For example, if the default behavior is to return an error if any location - is unreachable, that default behavior **must** be retained. -- The request message **must** have a `bool return_partial_success` field -- The response message **must** have the standard - `repeated string unreachable` field -- The two aforementioned fields **must** be added simultaneously - -When the `bool return_partial_success` field is set to `true` in a request, the -API **must** behave as described in the aforementioned guidance with regards to -populating the `repeated string unreachable` response field. - -```proto -message ListBooksRequest { - // Standard List request fields... - - // Setting this field to `true` will opt the request into returning the - // resources that are reachable, and into including the names of those that - // were unreachable in the [ListBooksResponse.unreachable] field. This can - // only be `true` when reading across collections e.g. when `parent` is set to - // `"projects/example/locations/-"`. - bool return_partial_success = 4; -} - -message ListBooksResponse { - // Standard List Response fields... - - // Unreachable resources. Populated when the request opts into - // `return_partial_success` and reading across collections e.g. when - // attempting to list all resources across all supported locations. - repeated string unreachable = 3 [ - (google.api.field_behavior) = UNORDERED_LIST - ]; -} -``` - -#### Partial success granularity - -If the `bool return_partial_success` field is set to `true` in a request that is -scoped beyond the supported granualirty of the API's ability to reasonably -report unreachable resources, the API **should** return an `INVALID_ARGUMENT` -error with details explaining the issue. For example, if the API only supports -`return_partial_success` when [Reading Across Collections][aip-159], it returns -an `INVALID_ARGUMENT` error when given a request scoped to a specific parent -resource collection. The supported granularity **must** be documented on the -`return_partial_success` field. - -## Rationale - -### Using service-relative resource names - -In general, relative resource names, as defined in AIP-122, are the best -practice for referring to resources by name _within_ a service and in other -services when that other service is obvious. The full resource name format is -strictly less consumable (e.g., requires extra parsing client side), and -over-specified for the uses of `unreachable`. Resource URIs are not transport -agnostic, as they are unusable in standard methods for gRPC users, and simple -resource IDs do not provide enough information about exactly which resource -was unreachable in a heterogenous list of resources. - -### Minimizing extra error details in response - -The context in which an unreachable resource is discovered may be sensitive and -the state of the system fluid between calls. As such, it is preferred to defer -to the service by making a more specific RPC to get more details about a -specific resource or parent. This allows the parent to handle all necessary RPC -checks and system state resolution on at time of request, rather than by -shoehorning potentially privileged or stale information into the broader list -call it was unreachable for. - -### Unordered `unreachable` contents - -It is important for broad API consistency that the contents of `unreachable` not -have a specific or order semantic structure. If each API baked a specific -ordering into a standard field, no single implementation, client or server side, -would be correct. - -### Per page `unreachable` resources - -Populating `unreachable` resources on a per page basis allows end users to -identify immediately when a page is incomplete, rather than _after_ paging -through all results. Paging to completion is not guaranteed, so it is important -to communicate as soon as possible when there are unreachable resource missing -from a given page. Furthermore, it allows users to identify when there is a -potential issue that they need to account for in subsequent calls. Finally, -retaining unreachable resources until the end of paging results requires -services to retain the state for what should be indepedent and fully isolated -API calls. - -### Using request field to opt-in - -Introducing a new request field as means of opting into the partial success -behavior is the best way to communicate user intent while keeping the -default behavior backwards compatible. The alternative, changing the default -behavior with the introduction of the `unreachable` response field, presents -a backwards incompatible change. Users that previously expected failure when any -resource was unreachable, assume the successful response means all resources -are accounted for in the response. - -### Introducing fields simultaneously - -Introducing the request and response fields simultaneously is to prevent an -invalid intermediate state that is presented by only adding one or the other. If -only `unreachable` is added, then it could be assumed that it being empty means -all resources were returned when that may not be true. If only -`return_partial_success` is added, then the user wouldn't have a means of -knowing which resources were unreachable. - -### Partial success granularity limitations - -At a certain level of request scope granularity, an API is simply unable to -enumerate the resources that are unreachable. For example, global-only APIs may -be unable to provide granularity at a localized collection level. In such a -case, preemptively returning an error when `return_partial_success=true` -protects the user from the risks of the alternative - expecting unreachable -resources if there was an issue, but not getting any, thus falsely assuming -everything was retrieved. This aligns with guidance herein that suggests failing -requests that cannot be fulfilled preemptively. - -## History - -### Pagination guidance - -The original guidance for how to populate the `unreachable` field revolved -around consuming the contents as if they were the paged results. This meant that -paged resources and unreachable resources couldn't be returned in the same -response i.e. page, and users needed to completely page through all results -in order to see if any were unreachable. See the Rationale section for the -reasoning around the changes. - -## Further reading - -- For listing across collections, see [AIP-159][]. - -## Changelog - -- **2024-07-29**: Reformat guidance, add explicit resource name format -- **2024-07-26**: Change pagination guidance. - requirement. -- **2024-07-19**: Add guidance for brownfield adoption of partial success. - -[aip-159]: ./0159.md diff --git a/aip/general/0231.md b/aip/general/0231.md deleted file mode 100644 index dab4c519d3..0000000000 --- a/aip/general/0231.md +++ /dev/null @@ -1,191 +0,0 @@ ---- -id: 231 -state: approved -created: 2019-06-18 -updated: 2022-06-02 -placement: - category: operations - order: 200 ---- - -# Batch methods: Get - -Some APIs need to allow users to get a specific set of resources at a -consistent time point (e.g. using a read transaction). A batch get method -provides this functionality. - -## Guidance - -APIs **may** support Batch Get using the following pattern: - -```proto -rpc BatchGetBooks(BatchGetBooksRequest) returns (BatchGetBooksResponse) { - option (google.api.http) = { - get: "/v1/{parent=publishers/*}/books:batchGet" - }; -} -``` - -- The RPC's name **must** begin with `BatchGet`. The remainder of the RPC name - **should** be the plural form of the resource being retrieved. -- The request and response messages **must** match the RPC name, with - `Request` and `Response` suffixes. -- The HTTP verb **must** be `GET`. -- The HTTP URI **must** end with `:batchGet`. -- The URI path **should** represent the collection for the resource, matching - the collection used for simple CRUD operations. If the operation spans - parents, a dash (`-`) **may** be accepted as a wildcard. -- There **must not** be a body key in the `google.api.http` annotation. -- The operation **must** be atomic: it **must** fail for all resources or - succeed for all resources (no partial success). For situations requiring - partial failures, `List` ([AIP-132][]) methods **should** be used. - - If the operation covers multiple locations and at least one location is - down, the operation **must** fail. - -### Request message - -The request for a batch get method **should** be specified with the following -pattern: - -```proto -message BatchGetBooksRequest { - // The parent resource shared by all books being retrieved. - // Format: publishers/{publisher} - // If this is set, the parent of all of the books specified in `names` - // must match this field. - string parent = 1 [ - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The names of the books to retrieve. - // A maximum of 1000 books can be retrieved in a batch. - // Format: publishers/{publisher}/books/{book} - repeated string names = 2 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; -} -``` - -- A `parent` field **should** be included, unless the resource being retrieved - is a top-level resource, to facilitate inclusion in the URI as - well to permit a single permissions check. If a caller sets this field, and - the parent collection in the name of any resource being retrieved does not - match, the request **must** fail. - - This field **should** be required if only 1 parent per request is allowed. - - The field **should** identify the [resource type][aip-122-parent] that it - references. - - The comment for the field **should** document the resource pattern. -- The request message **must** include a repeated field which accepts the - resource names specifying the resources to retrieve. The field **should** be - named `names`. - - If no resource names are provided, the API **should** error with - `INVALID_ARGUMENT`. - - The field **should** be required. - - The field **should** identify the [resource type][aip-122-names] that it - references. - - The comment for the field **should** document the resource pattern. -- Other fields besides `name` **may** be "hoisted" from the [standard Get - request][request-message]. There is no way to allow for these fields to - accept different values for different resources; if this is needed, use the - [alternative request message form](#nested-request-objects). -- Batch get **should not** support pagination because transactionality across - API calls would be extremely difficult to implement or enforce, and the - request defines the exact scope of the response anyway. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. -- The comment above the `names` field **should** document the maximum number of - requests allowed. - -### Response message - -The response for a batch get method **should** be specified with the following -pattern: - -```proto -message BatchGetBooksResponse { - // Books requested. - repeated Book books = 1; -} -``` - -- The response message **must** include one repeated field corresponding to the - resources being retrieved. -- The order of books in the response **must** be the same as the names in the - request. - -[aip-122-names]: ./0122.md#fields-representing-resource-names -[aip-122-parent]: ./0122.md#fields-representing-a-resources-parent -[request-message]: ./0131.md#request-message - -### Nested request objects - -If the [standard Get request message][request-message] contains a field besides -the resource name that needs to be different between different resources being -requested, the batch message **may** alternatively hold a `repeated` field of -the [standard Get request message][request-message]. This is generally -discouraged unless your use case really requires it. - -The request for a batch get method using this approach **should** be specified -with the following pattern: - -```proto -message BatchGetBooksRequest { - // The parent resource shared by all books being retrieved. - // Format: publishers/{publisher} - // If this is set, the parent field in the GetBookRequest messages - // must either be empty or match this field. - string parent = 1 [ - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The requests specifying the books to retrieve. - // A maximum of 1000 books can be retrieved in a batch. - repeated GetBookRequest requests = 2 - [(google.api.field_behavior) = REQUIRED]; -} -``` - -- A `parent` field **should** be included. If a caller sets this field, and the - parent collection in the name of any resource being retrieved does not match, - the request **must** fail. - - This field **should** be required if only 1 parent per request is allowed. - - The field **should** identify the [resource type][aip-122-parent] that it - references. - - The comment for the field **should** document the resource pattern. -- The request message **must** include a repeated field which accepts the - request messages specifying the resources to retrieve, as specified for - [standard Get methods][request-message]. The field **should** be named - `requests`. - - The field **should** be required. -- Other fields **may** be "hoisted" from the [standard Get - request][request-message], which means that the field can be set at either - the batch level or child request level. Similar to `parent`, if both the - batch level and child request level are set for the same field, the values - **must** match. -- Batch get **should not** support pagination because transactionality across - API calls would be extremely difficult to implement or enforce, and the - request defines the exact scope of the response anyway. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. -- The comment above the `requests` field **should** document the maximum number - of requests allowed. - -[aip-132]: https://aip.dev/132 - -## Changelog - -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-09-16**: Suggested annotating `parent`, `names`, and `requests` fields. -- **2020-08-27**: Removed parent recommendations for top-level resources. -- **2020-03-24**: Clarified behavior if no resource names are sent. -- **2019-09-11**: Changed the primary recommendation to specify a repeated - string instead of a repeated standard Get request message. Moved the original - recommendation into its own section. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0233.md b/aip/general/0233.md deleted file mode 100644 index 1b9144eaca..0000000000 --- a/aip/general/0233.md +++ /dev/null @@ -1,237 +0,0 @@ ---- -id: 233 -state: approved -created: 2019-06-18 -updated: 2022-06-02 -placement: - category: operations - order: 210 ---- - -# Batch methods: Create - -Some APIs need to allow users to create multiple resources in a single -transaction. A batch create method provides this functionality. - -## Guidance - -APIs **may** support Batch Create using the following two patterns: - -Returning the response synchronously - -```proto -rpc BatchCreateBooks(BatchCreateBooksRequest) returns (BatchCreateBooksResponse) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:batchCreate" - body: "*" - }; -} -``` - -Returning an Operation which resolves to the response asynchronously - -```proto -rpc BatchCreateBooks(BatchCreateBooksRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:batchCreate" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "BatchCreateBooksResponse" - metadata_type: "BatchCreateBooksOperationMetadata" - }; -} -``` - -- The RPC's name **must** begin with `BatchCreate`. The remainder of the RPC - name **should** be the plural form of the resource being created. -- The request and response messages **must** match the RPC name, with - `Request` and `Response` suffixes. -- If the batch method returns an `google.longrunning.Operation`, both the - `response_type` and `metadata_type` fields **must** be specified. -- The HTTP verb **must** be `POST`. -- The HTTP URI **must** end with `:batchCreate`. -- The URI path **should** represent the collection for the resource, matching - the collection used for simple CRUD operations. If the operation spans - parents, a dash (`-`) **may** be accepted as a wildcard. -- The body clause in the `google.api.http` annotation **should** be `"*"`. - -### Atomic vs. Partial Success - -- The batch create method **may** support atomic (all resources created or none - are) or partial success behavior. To make a choice, consider the following - factors: - - **Complexity of Ensuring Atomicity:** Operations that are simple - passthrough database transactions **should** use an atomic operation, - while operations that manage complex resources **should** use partial - success operations. - - **End-User Experience:** Consider the perspective of the API consumer. - Would atomic behavior be preferable for the given use case, even if it - means that a large batch could fail due to issues with a single or a few - entries? -- Synchronous batch create **must** be atomic. -- Asynchronous batch create **may** support atomic or partial success. - - If supporting partial success, see - [Operation metadata message](#operation-metadata-message) requirements. - -### Request message - -The request for a batch create method **should** be specified with the -following pattern: - -```proto -message BatchCreateBooksRequest { - // The parent resource shared by all books being created. - // Format: publishers/{publisher} - // If this is set, the parent field in the CreateBookRequest messages - // must either be empty or match this field. - string parent = 1 [ - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The request message specifying the resources to create. - // A maximum of 1000 books can be created in a batch. - repeated CreateBookRequest requests = 2 - [(google.api.field_behavior) = REQUIRED]; -} -``` - -- A `parent` field **should** be included, unless the resource being created is - a top-level resource. If a caller sets this field, and the - `parent` field of any child request message does not match, the request - **must** fail. The `parent` field of child request messages can be omitted if - the `parent` field in this request is set. - - This field **should** be required if only 1 parent per request is allowed. - - The field **should** identify the [resource type][aip-122-parent] that it - references. - - The comment for the field **should** document the resource pattern. -- The request message **must** include a repeated field which accepts the - request messages specifying the resources to create, as specified for - [standard Create methods][request-message]. The field **should** be named - `requests`. - - The field **should** be required. -- Other fields **may** be "hoisted" from the [standard Create - request][request-message], which means that the field can be set at either - the batch level or child request level. Similar to `parent`, if both the - batch level and child request level are set for the same field, the values - **must** match. - - Fields which must be unique cannot be hoisted (e.g. Customer-provided id - fields). -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. -- The comment above the `requests` field **should** document the maximum number - of requests allowed. - -### Response message - -The response for a batch create method **should** be specified with the -following pattern: - -```proto -message BatchCreateBooksResponse { - // Books created. - repeated Book books = 1; -} -``` - -- The response message **must** include one repeated field corresponding to the - resources that were created. - -### Operation metadata message - -- The `metadata_type` message **must** either match the RPC name with - `OperationMetadata` suffix, or be named with `Batch` prefix and - `OperationMetadata` suffix if the type is shared by multiple Batch methods. -- If batch create method supports partial success, the metadata message **must** - include a `map failed_requests` field to communicate - the partial failures. - - The key in this map is the index of the request in the `requests` field in - the batch request. - - The value in each map entry **must** mirror the error(s) that would normally - be returned by the singular Standard Create method. - - If a failed request can eventually succeed due to server side retries, such - transient errors **must not** be communicated using `failed_requests`. - - When all requests in the batch fail, `Operation.error` **must** be set with - `code = google.rpc.Code.Aborted` and `message = "None of the requests - succeeded, refer to the BatchCreateBooksOperationMetadata.failed_requests - for individual error details"` -- The metadata message **may** include other fields to communicate the - operation progress. - -### Adopting Partial Success - -In order for an existing Batch API to adopt the partial success pattern, the API -must do the following: - -- The default behavior must be retained to avoid incompatible behavioral - changes. -- If the API returns an Operation: - - The request message **must** have a `bool return_partial_success` field. - - The Operation `metadata_type` **must** include a - `map failed_requests` field. - - When the `bool return_partial_success` field is set to true in a request, - the API should allow partial success behavior, otherwise it should continue - with atomic behavior as default. -- If the API returns a direct response synchronously: - - Since the existing clients will treat a success response as an atomic - operation, the existing version of the API **must not** adopt the partial - success pattern. - - A new version **must** be created instead that returns an Operation and - follows the partial success pattern described in this AIP. - -## Rationale - -### Restricting synchronous batch methods to be atomic - -The restriction that synchronous batch methods must be atomic is a result of -the following considerations. - -The previous iteration of this AIP recommended batch methods must be atomic. -There is no clear way to convey partial failure in a sync response status code -because an OK implies it all worked. Therefore, adding a new field to the -response to indicate partial failure would be a breaking change because the -existing clients would interpret an OK response as all resources created. - -On the other hand, as described in [AIP-193](https://aip.dev/193), Operations -are more capable of presenting partial states. The response status code for an -Operation does not convey anything about the outcome of the underlying operation -and a client has to check the response body to determine if the operation was -successful. - -### Communicating partial failures - -The AIP recommends using a `map failed_requests` field -to communicate partial failures, where the key is the index of the failed -request in the original batch request. The other options considered were: - -- A `repeated google.rpc.Status` field. This was rejected because it is not - clear which entry corresponds to which request. -- A `map` field, where the key is the request id of - the failed request. This was rejected because: - - Client will need to maintain a map of request_id -> request in order to use - the partial success response. - - Populating a request id for the purpose of communicating errors could - conflict with [AIP-155](https://aip.dev/155) if the service can not - guarantee idempotency for an individual request across multiple batch - requests. -- A `repeated FailedRequest` field, where FailedRequest contains the individual - create request and the `google.rpc.Status`. This was rejected because echoing - the request payload back in response is discouraged due to additional - challenges around user data sensitivity. - -[aip-122-parent]: ./0122.md#fields-representing-a-resources-parent -[request-message]: ./0133.md#request-message - -## Changelog - -- **2025-03-06**: Added detailed guidance for partial success behavior, and - decision framework for choosing between atomic and partial success -- **2023-04-18**: Changed the recommendation to allow returning partial - successes. -- **2022-06-02**: Changed suffix descriptions to eliminate superfluous "-". -- **2020-09-16**: Suggested annotating `parent` and `requests` fields. -- **2020-08-27**: Removed parent recommendations for top-level resources. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0234.md b/aip/general/0234.md deleted file mode 100644 index 7a4410844b..0000000000 --- a/aip/general/0234.md +++ /dev/null @@ -1,235 +0,0 @@ ---- -id: 234 -state: approved -created: 2019-06-18 -updated: 2022-06-02 -placement: - category: operations - order: 220 ---- - -# Batch methods: Update - -Some APIs need to allow users to modify a set of resources in a single -transaction. A batch update method provides this functionality. - -## Guidance - -APIs **may** support Batch Update using the following two patterns: - -Returning the response synchronously - -```proto -rpc BatchUpdateBooks(BatchUpdateBooksRequest) returns (BatchUpdateBooksResponse) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:batchUpdate" - body: "*" - }; -} -``` - -Returning an Operation which resolves to the response asynchronously - -```proto -rpc BatchUpdateBooks(BatchUpdateBooksRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:batchUpdate" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "BatchUpdateBooksResponse" - metadata_type: "BatchUpdateBooksOperationMetadata" - }; -} -``` - -- The RPC's name **must** begin with `BatchUpdate`. The remainder of the RPC - name **should** be the plural form of the resource being updated. -- The request and response messages **must** match the RPC name, with - `Request` and `Response` suffixes. -- If the batch method returns an `google.longrunning.Operation`, both the - `response_type` and `metadata_type` fields **must** be specified. -- The HTTP verb **must** be `POST`. -- The HTTP URI **must** end with `:batchUpdate`. -- The URI path **should** represent the collection for the resource, matching - the collection used for simple CRUD operations. If the operation spans - parents, a dash (`-`) **may** be accepted as a wildcard. -- The body clause in the `google.api.http` annotation **should** be `"*"`. - -### Atomic vs. Partial Success - -- The batch update method **may** support atomic (all resources updated or none - are) or partial success behavior. To make a choice, consider the following - factors: - - **Complexity of Ensuring Atomicity:** Operations that are simple - passthrough database transactions **should** use an atomic operation, - while operations that manage complex resources **should** use partial - success operations. - - **End-User Experience:** Consider the perspective of the API consumer. - Would atomic behavior be preferable for the given use case, even if it - means that a large batch could fail due to issues with a single or a few - entries? -- Synchronous batch update **must** be atomic. -- Asynchronous batch update **may** support atomic or partial success. - - If supporting partial success, see - [Operation metadata message](#operation-metadata-message) requirements. - -### Request message - -The request for a batch update method **should** be specified with the -following pattern: - -```proto -message BatchUpdateBooksRequest { - // The parent resource shared by all books being updated. - // Format: publishers/{publisher} - // If this is set, the parent field in the UpdateBookRequest messages - // must either be empty or match this field. - string parent = 1 [ - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The request message specifying the resources to update. - // A maximum of 1000 books can be modified in a batch. - repeated UpdateBookRequest requests = 2 - [(google.api.field_behavior) = REQUIRED]; -} -``` - -- A `parent` field **should** be included, unless the resource being updated is - a top-level resource. If a caller sets this field, and the - parent collection in the name of any resource being updated does not match, - the request **must** fail. - - This field **should** be required if only 1 parent per request is allowed. - - The field **should** identify the [resource type][aip-122-parent] that it - references. - - The comment for the field **should** document the resource pattern. -- The request message **must** include a repeated field which accepts the - request messages specifying the resources to update, as specified for - [standard Update methods][request-message]. The field **should** be named - `requests`. - - The field **should** be required. -- Other fields **may** be "hoisted" from the [standard Update - request][request-message], which means that the field can be set at either - the batch level or child request level. Similar to `parent`, if both the - batch level and child request level are set for the same field, the values - **must** match. - - The `update_mask` field is a good candidate for hoisting. -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. -- The comment above the `requests` field **should** document the maximum number of - requests allowed. - -### Response message - -The response for a batch update method **should** be specified with the -following pattern: - -```proto -message BatchUpdateBooksResponse { - // Books updated. - repeated Book books = 1; -} -``` - -- The response message **must** include one repeated field corresponding to the - resources that were updated. - -### Operation metadata message - -- The `metadata_type` message **must** either match the RPC name with - `OperationMetadata` suffix, or be named with `Batch` prefix and - `OperationMetadata` suffix if the type is shared by multiple Batch methods. -- If batch update method supports partial success, the metadata message **must** - include a `map failed_requests` field to communicate - the partial failures. - - The key in this map is the index of the request in the `requests` field - in the batch request. - - The value in each map entry **must** mirror the error(s) that would normally - be returned by the singular Standard Update method. - - If a failed request can eventually succeed due to server side retries, such - transient errors **must not** be communicated using `failed_requests`. - - When all requests in the batch fail, `Operation.error` **must** be set with - `code = google.rpc.Code.Aborted` and `message = "None of the requests - succeeded, refer to the BatchUpdateBooksOperationMetadata.failed_requests - for individual error details"` -- The metadata message **may** include other fields to communicate the - operation progress. - -### Adopting Partial Success - -In order for an existing Batch API to adopt the partial success pattern, the API -must do the following: - -- The default behavior must be retained to avoid incompatible behavioral - changes. -- If the API returns an Operation: - - The request message **must** have a `bool return_partial_success` field. - - The Operation `metadata_type` **must** include a - `map failed_requests` field. - - When the `bool return_partial_success` field is set to true in a request, - the API should allow partial success behavior, otherwise it should continue - with atomic behavior as default. -- If the API returns a direct response synchronously: - - Since the existing clients will treat a success response as an atomic - operation, the existing version of the API **must not** adopt the partial - success pattern. - - A new version **must** be created instead that returns an Operation and - follows the partial success pattern described in this AIP. - -## Rationale - -### Restricting synchronous batch methods to be atomic - -The restriction that synchronous batch methods must be atomic is a result of -the following considerations. - -The previous iteration of this AIP recommended batch methods must be atomic. -There is no clear way to convey partial failure in a sync response status code -because an OK implies it all worked. Therefore, adding a new field to the -response to indicate partial failure would be a breaking change because the -existing clients would interpret an OK response as all resources updated. - -On the other hand, as described in [AIP-193](https://aip.dev/193), Operations -are more capable of presenting partial states. The response status code for an -Operation does not convey anything about the outcome of the underlying operation -and a client has to check the response body to determine if the operation was -successful. - -### Communicating partial failures - -The AIP recommends using a `map failed_requests` field -to communicate partial failures, where the key is the index of the failed -request in the original batch request. The other options considered were: - -- A `repeated google.rpc.Status` field. This was rejected because it is not - clear which entry corresponds to which request. -- A `map` field, where the key is the request id of - the failed request. This was rejected because: - - Client will need to maintain a map of request_id -> request in order to use - the partial success response. - - Populating a request id for the purpose of communicating errors could - conflict with [AIP-155](https://aip.dev/155) if the service can not - guarantee idempotency for an individual request across multiple batch - requests. -- A `repeated FailedRequest` field, where FailedRequest contains the individual - update request and the `google.rpc.Status`. This was rejected because echoing - the request payload back in response is discouraged due to additional - challenges around user data sensitivity. - -[aip-122-parent]: ./0122.md#fields-representing-a-resources-parent -[request-message]: ./0134.md#request-message - -## Changelog - -- **2025-03-06**: Changed recommendation to allow partial success, along with - detailed guidance -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-09-16**: Suggested annotating `parent` and `requests` fields. -- **2020-08-27**: Removed parent recommendations for top-level resources. -- **2019-09-11**: Fixed the wording about which child field the `parent` field - should match. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0235.md b/aip/general/0235.md deleted file mode 100644 index e38609443b..0000000000 --- a/aip/general/0235.md +++ /dev/null @@ -1,307 +0,0 @@ ---- -id: 235 -state: approved -created: 2019-06-18 -updated: 2022-06-02 -placement: - category: operations - order: 230 ---- - -# Batch methods: Delete - -Some APIs need to allow users to delete a set of resources in a single -transaction. A batch delete method provides this functionality. - -## Guidance - -APIs **may** support Batch Delete using the following two patterns: - -Returning the response synchronously - -```proto -rpc BatchDeleteBooks(BatchDeleteBooksRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:batchDelete" - body: "*" - }; -} -``` - -Returning an Operation which resolves to the response asynchronously - -```proto -rpc BatchDeleteBooks(BatchDeleteBooksRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=publishers/*}/books:batchDelete" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "google.protobuf.Empty" - metadata_type: "BatchDeleteBooksOperationMetadata" - }; -} -``` - -- The RPC's name **must** begin with `BatchDelete`. The remainder of the RPC - name **should** be the plural form of the resource being deleted. -- The request message **must** match the RPC name, with a `Request` suffix. -- The response message **should** be `google.protobuf.Empty`. - - If the resource is [soft deleted][soft-delete], the response message - **should** be a response message containing the updated resources. -- If the batch method returns an `google.longrunning.Operation`, both the - `response_type` and `metadata_type` fields **must** be specified. - - If the resource is [soft deleted][soft-delete], the `response_type` - **should** be a response message containing the updated resources. -- The HTTP verb **must** be `POST` (not `DELETE`). -- The HTTP URI **must** end with `:batchDelete`. -- The URI path **should** represent the collection for the resource, matching - the collection used for simple CRUD operations. If the operation spans - parents, a dash (`-`) **may** be accepted as a wildcard. -- The body clause in the `google.api.http` annotation **should** be `"*"`. - -### Atomic vs. Partial Success - -- The batch delete method **may** support atomic (all resources deleted or none - are) or partial success behavior. To make a choice, consider the following - factors: - - **Complexity of Ensuring Atomicity:** Operations that are simple - passthrough database transactions **should** use an atomic operation, - while operations that manage complex resources **should** use partial - success operations. - - **End-User Experience:** Consider the perspective of the API consumer. - Would atomic behavior be preferable for the given use case, even if it - means that a large batch could fail due to issues with a single or a few - entries? -- Synchronous batch delete **must** be atomic. -- Asynchronous batch delete **may** support atomic or partial success. - - If supporting partial success, see - [Operation metadata message](#operation-metadata-message) requirements. - -### Request message - -The request for a batch delete method **should** be specified with the -following pattern: - -```proto -message BatchDeleteBooksRequest { - // The parent resource shared by all books being deleted. - // Format: publishers/{publisher} - // If this is set, the parent of all of the books specified in `names` - // must match this field. - string parent = 1 [ - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The names of the books to delete. - // A maximum of 1000 books can be deleted in a batch. - // format: publishers/{publisher}/books/{book} - repeated string names = 2 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "library.googleapis.com/Book" - }]; -} -``` - -- A `parent` field **should** be included, unless the resource being deleted is - a top-level resource. If a caller sets this field, and the - parent collection in the name of any resource being deleted does not match, - the request **must** fail. - - This field **should** be required if only 1 parent per request is allowed. - - The field **should** identify the [resource type][aip-122-parent] that it - references. - - The comment for the field **should** document the resource pattern. -- The request message **must** include a repeated field which accepts the - resource names specifying the resources to delete. The field **should** be - named `names`. - - The field **should** be required. - - The field **should** identify the [resource type][aip-122-names] that it - references. - - The comment for the field **should** document the resource pattern. -- Other fields besides `name` **may** be "hoisted" from the [standard Delete - request][request-message]. There is no way to allow for these fields to - accept different values for different resources; if this is needed, use the - [alternative request message form](#request-message-containing-standard-delete-request-messages). -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. -- The comment above the `names` field **should** document the maximum number of - requests allowed. -- Filter-based matching **must not** be supported. - -### Request message containing standard delete request messages - -If the [standard Delete request message][request-message] contains a field -besides the resource name that needs to be different between different -resources being requested, the batch message **may** alternatively hold a -`repeated` field of the [standard Delete request message][request-message]. -This is generally discouraged unless your use case really requires it. - -The request for a batch delete method **should** be specified with the -following pattern: - -```proto -message BatchDeleteBooksRequest { - // The parent resource shared by all books being deleted. - // Format: publishers/{publisher} - // If this is set, the parent of all of the books specified in the - // DeleteBookRequest messages must match this field. - string parent = 1 [ - (google.api.resource_reference) = { - child_type: "library.googleapis.com/Book" - }]; - - // The requests specifying the books to delete. - // A maximum of 1000 books can be deleted in a batch. - repeated DeleteBookRequest requests = 2 - [(google.api.field_behavior) = REQUIRED]; -} -``` - -- A `parent` field **should** be included. If a caller sets this field, and the - parent collection in the name of any resource being deleted does not match, - the request **must** fail. - - This field **should** be required if only 1 parent per request is allowed. - - The field **should** identify the [resource type][aip-122-parent] that it - references. - - The comment for the field **should** document the resource pattern. -- The request message **must** include a repeated field which accepts the - request messages specifying the resources to delete, as specified for - [standard Delete methods][request-message]. The field **should** be named - `requests`. - - The field **should** be required. -- Other fields **may** be "hoisted" from the [standard Delete - request][request-message], which means that the field can be set at either - the batch level or child request level. Similar to `parent`, if both the - batch level and child request level are set for the same field, the values - **must** match. - - Fields which must be unique cannot be hoisted (e.g. `etag`). -- The request message **must not** contain any other required fields, and - **should not** contain other optional fields except those described in this - or another AIP. -- The comment above the `requests` field **should** document the maximum number - of requests allowed. -- Filter-based matching **must not** be supported unless it is infeasible to - support critical use cases without it, because it makes it too easy for users - to accidentally delete important data. If it is unavoidable, see [AIP-165][]. - -### Response message (soft-delete only) - -In the case where a response message is necessary because the resource is -soft-deleted, the response **should** be specified with the following pattern: - -```proto -message BatchDeleteBooksResponse { - // Books deleted. - repeated Book books = 1; -} -``` - -- The response message **must** include one repeated field corresponding to the - resources that were soft-deleted. - -### Operation metadata message - -- The `metadata_type` message **must** either match the RPC name with - `OperationMetadata` suffix, or be named with `Batch` prefix and - `OperationMetadata` suffix if the type is shared by multiple Batch methods. -- If batch delete method supports partial success, the metadata message **must** - include a `map failed_requests` field to communicate - the partial failures. - - The key in this map is the index of the request in the `requests` field in - the batch request. - - The value in each map entry **must** mirror the error(s) that would normally - be returned by the singular Standard Delete method. - - If a failed request can eventually succeed due to server side retries, such - transient errors **must not** be communicated using `failed_requests`. - - When all requests in the batch fail, `Operation.error` **must** be set with - `code = google.rpc.Code.Aborted` and `message = "None of the requests - succeeded, refer to the BatchDeleteBooksOperationMetadata.failed_requests - for individual error details"` -- The metadata message **may** include other fields to communicate the - operation progress. - -### Adopting Partial Success - -In order for an existing Batch API to adopt the partial success pattern, the API -must do the following: - -- The default behavior must be retained to avoid incompatible behavioral - changes. -- If the API returns an Operation: - - The request message **must** have a `bool return_partial_success` field. - - The Operation `metadata_type` **must** include a - `map failed_requests` field. - - When the `bool return_partial_success` field is set to true in a request, - the API should allow partial success behavior, otherwise it should continue - with atomic behavior as default. -- If the API returns a direct response synchronously: - - Since the existing clients will treat a success response as an atomic - operation, the existing version of the API **must not** adopt the partial - success pattern. - - A new version **must** be created instead that returns an Operation and - follows the partial success pattern described in this AIP. - -## Rationale - -### Restricting synchronous batch methods to be atomic - -The restriction that synchronous batch methods must be atomic is a result of -the following considerations. - -The previous iteration of this AIP recommended batch methods must be atomic. -There is no clear way to convey partial failure in a sync response status code -because an OK implies it all worked. Therefore, adding a new field to the -response to indicate partial failure would be a breaking change because the -existing clients would interpret an OK response as all resources created. - -On the other hand, as described in [AIP-193](https://aip.dev/193), Operations -are more capable of presenting partial states. The response status code for an -Operation does not convey anything about the outcome of the underlying operation -and a client has to check the response body to determine if the operation was -successful. - -### Communicating partial failures - -The AIP recommends using a `map failed_requests` field -to communicate partial failures, where the key is the index of the failed -request in the original batch request. The other options considered were: - -- A `repeated google.rpc.Status` field. This was rejected because it is not - clear which entry corresponds to which request. -- A `map` field, where the key is the request id of - the failed request. This was rejected because: - - Client will need to maintain a map of request_id -> request in order to use - the partial success response. - - Populating a request id for the purpose of communicating errors could - conflict with [AIP-155](https://aip.dev/155) if the service can not - guarantee idempotency for an individual request across multiple batch - requests. -- A `repeated FailedRequest` field, where FailedRequest contains the individual - create request and the `google.rpc.Status`. This was rejected because echoing - the request payload back in response is discouraged due to additional - challenges around user data sensitivity. - -[aip-122-names]: ./0122.md#fields-representing-resource-names -[aip-122-parent]: ./0122.md#fields-representing-a-resources-parent -[aip-165]: ./0165.md -[request-message]: ./0135.md#request-message -[soft-delete]: ./0135.md#soft-delete - -## Changelog - -- **2025-03-06**: Changed recommendation to allow partial success, along with - detailed guidance -- **2022-06-02:** Changed suffix descriptions to eliminate superfluous "-". -- **2020-09-16**: Suggested annotating `parent`, `names`, and `requests` fields. -- **2020-08-27**: Removed parent recommendations for top-level resources. -- **2020-03-27**: Added reference to AIP-165 for criteria-based deletion. -- **2019-10-11**: Changed the primary recommendation to specify a repeated - string instead of a repeated standard Delete message. Moved the original - recommendation into its own section. -- **2019-09-11**: Fixed the wording about which child field the `parent` field - should match. -- **2019-08-01**: Changed the examples from "shelves" to "publishers", to - present a better example of resource ownership. diff --git a/aip/general/0236.md b/aip/general/0236.md deleted file mode 100644 index b94a925b2a..0000000000 --- a/aip/general/0236.md +++ /dev/null @@ -1,399 +0,0 @@ ---- -id: 236 -state: approved -created: 2023-03-30 -updated: 2023-03-30 -placement: - category: resource-design - order: 240 ---- - -# Policy preview - -A policy is a resource that provides rules that admit or deny access to other -resources. Generally, the outcome of a policy can be evaluated to a specific set -of outcomes. - -Changes to policies without proper validation may have unintended consequences -that can severely impact a customer’s overall infrastructure setup. To safely -update resources, it is beneficial to test these changes via policy rollout -APIs. - -Preview is a rollout safety mechanism for policy resources, which gives the -customer the ability to validate the effect of their proposed changes against -production traffic prior to the changes going live. The result of the policy -evaluation against traffic is logged in order to give the customer the data -required to test the correctness of the change. - -Firewall policies exemplify a case that is suitable for previewing. A new -configuration can be evaluated against traffic to observe which IPs would be -allowed or denied. This gives the customer the data to guide a decision on -whether to promote the proposed changes to live. - -The expected flow for previewing a policy is as follows: - -1. The user creates an experiment containing a new policy configuration - intended to replace the live policy. -2. The user uses the "startPreview" method to start generating logs which compare - the live and experiment policy evaluations against live traffic. -3. The user inspects the logs to determine whether the experiment has the - intended result. -4. The user uses the "commit" method to promote the experiment to live. - -## Guidance - -### Non-goals - -This proposal is for a safety mechanism for policy rollouts only. Safe rollouts -for non-policy resources are not in scope. - -### Experiments - -A new configuration of a policy to be previewed is stored as a nested collection -under the policy. These nested collections are known as experiments. - -A hypothetical policy resource called, `Policy`, is used throughout. It has the -following resource name pattern: - -`projects/{project}/locations/{location}/policies/{policy}` - -The experimental versions of the resource used for previewing or other safe -rollout practices are represented as a nested collection under `Policy` using a -new resource type. The resource type **must** follow the naming convention -*RegularResourceType*`Experiment`. - -The following pattern is used for the experiment collection: - -`projects/{project}/locations/{location}/policies/{policy}/experiments/{experiment}` - -A proto used to represent an experiment **must** contain the following: - - 1. The required top-level fields for a resource, like `name` and `etag` - 2. The policy message that is being tested itself - 3. The field, `preview_metadata`, which contains metadata specific to - previewing the experiment of a specific resource type. - -```proto -message PolicyExperiment { - - // google.api.resource, name, and other annotations and fields - - // The policy experiment. This Policy will be used to preview the effects of - // the change but will not affect live traffic. - Policy policy = 2; - - // The metadata associated with this policy experiment. - PolicyPreviewMetadata preview_metadata = 3 - [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Allows clients to store small amounts of arbitrary data. - map annotations = 4; -} -``` - -- The experiment proto **must** have a top-level field with the same type as the - live policy. - - It **must** be named as the live resource type. For example, if the - experiment is for FirewallPolicy, then this field **must** be named - `firewall_policy`. - - The name inside the embedded `policy` message **must** be the name of the - live policy. -- When the user is ready to promote an experiment, they **must** copy the - `policy` message into the live policy and delete the experiment. This can be - done manually or via a "commit" custom method. -- A product **may** support multiple experiments concurrently being previewed - for a single live policy. - - Each experiment must generate logs having each entry preceded by log_prefix - so that the user can compare the results of the experiment with the behavior - of the live policy. - - The number of experimental configurations for a given live policy **may** be - capped at a certain number and the cap **must** be documented. -- Cascading deletes **must** occur: if the live policy is deleted, all - experiments **must** also be deleted. -- `map` [annotations][aip-128-annotations] **must** allow clients - to store small amounts of arbitrary data. - -### Metadata - -`preview_metadata` tracks all metadata of previewing the experiment. The -messages **must** follow the convention: *RegularResourceType*`PreviewMetadata`. -This is so the proto can be defined uniquely for each resource type in the -same service with experiments. - -```proto -message PolicyPreviewMetadata { - // Possible values of the state of previewing the experiment. - enum State { - // Default value. This value is unused. - STATE_UNDEFINED = 0; - - // The experiment is actively previewing. - ACTIVE = 1; - - // The previewing of the experiment has been stopped. - SUSPENDED = 2; - } - - // The state of previewing the experiment. - State state = 1; - - // An identifying string common to all logs generated when previewing the - // experiment. Searching all logs for this string will isolate the results. - string log_prefix = 2; - - // The most recent time at which this experiment started previewing. - google.protobuf.Timestamp start_time = 3; - - // The most recent time at which this experiment stopped previewing. - google.protobuf.Timestamp stop_time = 4; -} -``` - -- `PolicyPreviewMetadata` **must** have the fields defined in the proto above. - - It **may** have additional fields if the service or resource requires it. -- When an experiment is first previewed, `preview_metadata` **must** be - absent. - - It is present on the experiment once the "startPreview" method is used. -- All `preview_metadata` fields **must** be output only. -- `state` changes between `ACTIVE` and `SUSPENDED` when previewing is started - or stopped. This happens when the "startPreview" or "stopPreview custom methods - are invoked, respectively. -- The first time the "startPreview" custom method is used, the system **must** - create `preview_metadata` and do the following: - - It **must** set the `state` to `ACTIVE` - - It **must** populate `start_time` with the current time. - - `start_time` **must** be updated every time `state` is changed to - `ACTIVE`. - - It **must** set a system generated `log_prefix` string, which is a - predefined constant hard coded by the system developers. - - The same value is used for previewing experiments for the given resource - type. For example, "FirewallPolicyPreviewLog" for FirewallPolicy. -- When the "stopPreview" custom method is used, the system **must** do the - following: - - It **must** set the `state` to `SUSPENDED` - - It **must** populate the `stop_time` with the current time. - -### Methods - -#### create - -- The resource **must** be created using long-running - [Create][aip-133-long-running] and - `google.longrunning.operation_info.response_type` **must** be - `PolicyExperiment`. -- Creating a new experiment to preview **must** support the following use -cases: - - Preview a new policy. - - Preview an update to an already live policy. - - Preview a deletion of a current policy. -- For the update and delete use cases, the `policy` field in the experiment - **must** have the full payload of the live policy copied into it, including - the name. - - The user **must** set the rules to the new intended state to preview an - update. - - The user **must** set set the rules to represent a no-op to preview a - delete. -- To preview a new policy, the system must do the following: - - If the system does not support a nested collection without a live policy, - the user **must** create a live policy and set the rules to represent a - no-op. For example, the rules of a no-op policy **may** be empty. - - An experiment is created as a child of the no-op policy. -- If the system supports previewing multiple experiments for a live policy, - calling "create" more than once **must** create multiple experiments. - -#### update - -- The resource **must** be updated using long-running - [Update][aip-134-long-running] and - `google.longrunning.operation_info.response_type` **must** be - `PolicyExperiment`. -- The name inside `policy` **must not** change but the other fields can in - order to change the experiment being previewed because this `policy` is - intended to replace the live policy, and the name of the live policy - **must not** change. -- The system **must** set the `state` to `SUSPENDED` if the `state` was `ACTIVE` - at the time of an update. - - This is so the user can easily distinguish between different versions of - the experiment being previewed. - -#### get -- The standard method, [Get][aip-131], **must** be included for - `PolicyExperiment` resource types. - -#### list - -- The standard method, [List][aip-132], **must** be included for - `PolicyExperiment` resource types. -- Filtering on `PolicyPreviewMetadata` indicates which experiments are actively - previewed. - - For example, the following filter string returns a List response with - experiments being previewed: preview_metadata.state = ACTIVE. - -#### delete - -- The resource **must** be deleted using long-running - [Delete][aip-135-long-running] and - `google.longrunning.operation_info.response_type` **must** be - `PolicyExperiment`. - -#### startPreview - -```proto -// Starts previewing a PolicyExperiment. This triggers the system to start -// generating logs to evaluate the PolicyExperiment. -rpc StartPreviewPolicyExperiment(StartPreviewPolicyExperimentRequest) - returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=policies/*/experiments/*}:startPreview" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "PolicyExperiment" - metadata_type: "StartPreviewPolicyExperimentMetadata" - }; -} - -// The request message for the startPreview custom method. -message StartPreviewPolicyExperimentRequest { - // The name of the PolicyExperiment. - string name = 1; -} -``` - -- This custom method is required. -- `google.longrunning.Operation.metadata_type` **must** follow guidance on - [Long-running operations][aip-151] -- This method **must** trigger the system to start generating logs to preview - the experiment. -- Whenever the method is called successfully, the system **must** set the - following values in the `PolicyPreviewMetadata`: - - `log_prefix` to the predefined constant. - - `start_time` to the current time - - `state` to `ACTIVE`. -- If the method is called on an experiment with the rules representing a no-op, - then the system **must** preview the deletion of the live policy. - -#### stopPreview - -```proto -// Stops previewing a PolicyExperiment. This triggers the system to stop -// generating logs to evaluate the PolicyExperiment. -rpc StopPreviewPolicyExperiment(StopPreviewPolicyExperimentRequest) - returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=policies/*/experiments/*}:stopPreview" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "PolicyExperiment" - metadata_type: "StopPreviewPolicyExperimentMetadata" - }; -} - -// The request message for the stopPreview custom method. -message StopPreviewPolicyExperimentRequest { - // The name of the PolicyExperiment. - string name = 1; -} -``` - -- This custom method is required. -- `google.longrunning.Operation.metadata_type` **must** follow guidance on - [Long-running operations][aip-151] -- This method **must** trigger the system to stop generating logs to preview the - experiment. -- Whenever the method is called successfully, the system **must** set the - following values in the `PolicyPreviewMetadata`: - - `stop_time` to the current time - - `state` to `SUSPENDED` - -#### commit - -The resource **may** expose a new custom method called "commit" to promote an -experiment. The system copies `policy` from the experiment into the live policy -and then deletes the experiment. - -Declarative clients **may** manually copy fields from an experiment into the -live policy and then delete the experiment rather than calling "commit" if -preferable. - -```proto -// Commits a PolicyExperiment. This copies the PolicyExperiment's policy message -// to the live policy then deletes the PolicyExperiment. -rpc CommitPolicyExperiment(CommitPolicyExperimentRequest) - returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=policies/*/experiments/*}:commit" - body: "*" - }; - option (google.longrunning.operation_info) = { - response_type: "google.protobuf.Empty" - metadata_type: "CommitPolicyExperimentMetadata" - }; -} - -// The request message for the commit custom method. -message CommitPolicyExperimentRequest { - string name = 1; - string etag = 2; - string parent_etag = 3; -} -``` - -- `google.longrunning.Operation.metadata_type` **must** follow guidance on - [Long-running operations][aip-151] -- The method **must** atomically copy `policy` from the experiment into the live - policy, and then delete the experiment. -- If any experiment fails "commit", previewing it **must not** stop, and the - live policy **must not** be updated. -- The method can be called on an experiment in any state. -- The `etag` **must** match that of the experiment in order for commit to be - successful. This is so the user does not commit an unintended version of the - experiment. - - If no `etag` is provided, the API **must not** succeed to prevent the user - from unintentionally committing a different version of the experiment as - intended. - - A `parent_etag` **may** be provided to guarantee that the experiment - overwrites a specific version of the live policy. -- The method is not idempotent and calling it twice on the same experiment - **must** return a 404 NOT_FOUND as the experiment is deleted as part of the - first call. - -### Changes to live policy API methods - -#### delete - -- A delete of the live policy **must** delete all experiments. -- To maintain the experiments while negating the effect of the live policy, the - live policy **must** be changed to a no-op policy instead of using this - method. - -### Logging - -Logging is crucial for the user to evaluate whether an experiment should be -promoted to live. - -Logs **must** contain the results of the evaluated experiment, the `etag` -associated with that experiment alongside that of the live policy, and be -preceded by the value of `log_prefix`. - - The `etag` fields help the user identify which - configurations of the live and experiment are evaluated in the log. - - `log_prefix` helps the user separate logs specifically generated for - previewing the experiment from other use cases. - -Overall, these logs help the user make a decision about whether to promote the -experiment to live. - -## Changelog - -- **2023-04-27:** Methods for start and stop renamed. State to enum. Annotations - added. -- **2023-03-30:** Initial AIP written. - -[aip-128-annotations]: https://aip.dev/128#annotations -[aip-131]: https://aip.dev/131 -[aip-132]: https://aip.dev/132 -[aip-133-long-running]: https://aip.dev/133#long-running-create -[aip-134-long-running]: https://aip.dev/134#long-running-update -[aip-135-long-running]: https://aip.dev/135#long-running-delete -[aip-151]: https://google.aip.dev/151 diff --git a/aip/general/scope.yaml b/aip/general/scope.yaml deleted file mode 100644 index e90fb3e4f0..0000000000 --- a/aip/general/scope.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: General -order: 0 -categories: - - code: meta - - code: process - - code: api-concepts - title: API Concepts - - code: resource-design - title: Resource Design - - code: operations - - code: fields - - code: design-patterns - title: Design Patterns - - code: compatibility - title: Compatibility and Versioning - - code: polish - - code: protobuf - title: Protocol buffers - - code: misc - title: Miscellaneous - default: true diff --git a/aog.html b/aog.html new file mode 100644 index 0000000000..804ed13628 --- /dev/null +++ b/aog.html @@ -0,0 +1,325 @@ + + + + Actions on Google AIPs + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + + +
+
+ +
+

Actions on Google

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NumberTitle
3001 + Actions on Google AIP Process +
3010 + Actions on Google Vertical Integration Webhook Format +
3020 + BII Schema Principles +
3021 + Type protos in Actions on Google APIs +
3022 + Built-in intent arguments and fulfillment APIs +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/aog/3001.html b/aog/3001.html new file mode 100644 index 0000000000..11cbd7e8c7 --- /dev/null +++ b/aog/3001.html @@ -0,0 +1,352 @@ + + + + AIP-3001: Actions on Google AIP Process + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-3001

+

Actions on Google AIP Process

+

This AIP extends AIP-1 with details specific to Actions on Google AIPs. Any +details of AIP-1 not modified or contradicted by this AIP also apply to +Actions on Google AIPs.

+

Stakeholders

+

As with any process there are many different stakeholders when it comes to +reviewing and working with AIPs. Below is a summary of the escalation path +starting with the API producer.

+
digraph d_front_back {
+  rankdir=BT;
+  ranksep=0.3;
+  node [ style="filled,solid" shape=box fontname="Roboto" ];
+
+  producer [ label="API Producer" ];
+  editors [ label="AIP Editors" ];
+  aog_editors [ label="Actions on Google AIP Editors" ];
+  tl_infra [ label="Infrastructure TL" ];
+  tl_design [ label="Design TL" ];
+  tl [ label="TL" ];
+
+  producer -> aog_editors;
+  aog_editors -> editors;
+  editors -> tl_infra -> tl;
+  editors -> tl_design -> tl;
+}
+
+

Actions on Google Editors

+

The Actions on Google editors are the set of people who make decisions on +Actions on Google AIPs before escalation to the general editors defined in +AIP-1.

+

The list of Actions on Google AIP editors is currently:

+ +

The Actions on Google editors have the same responsibilities as the general +editors. They also have the additional responsibility of establishing +correctness of, and leadership support for, the contents of Actions on Google +AIPs.

+

Actions on Google AIP editorship is by invitation of the current Actions on +Google editors.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/aog/3010.html b/aog/3010.html new file mode 100644 index 0000000000..421af9599a --- /dev/null +++ b/aog/3010.html @@ -0,0 +1,354 @@ + + + + AIP-3010: Actions on Google Vertical Integration Webhook Format + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-3010

+

Actions on Google Vertical Integration Webhook Format

+

If an action is part of a vertical program that requires a webhook for Google +to integrate with the action, the webhook format must follow this AIP.

+

Guidance

+

Custom method name

+

Custom methods in a vertical program are defined by Google and implemented by +third-party actions. Guidelines related to names of custom methods in +AIP-136 should be applied.

+
    +
  • The name of the method should be a verb followed by a noun.
  • +
  • The name must not contain prepositions (“for”, “with”, etc.).
  • +
  • If word separation is required for the method name, lowerCamelCase + should be used.
  • +
+

Examples:

+
    +
  • getAccountBalance
  • +
  • completeTransaction
  • +
+

Base URL in Action Package

+

The base URL configured in Action Package defines the common part of the actual +execution URL of the webhook.

+
    +
  • The base URL may include a trailing slash, but must work if + :customMethodName is appended directly.
      +
    • Google Cloud Functions base URLs without a trailing slash do not work, + because the first segment of the path is used to identify the webhook.
    • +
    +
  • +
  • The endpoint must be HTTPS and must have a valid certificate.
  • +
+

Examples:

+
    +
  • https://us-central1.cloudfunctions.net/myWebhook/ (not + https://us-central1.cloudfunctions.net/myWebhook)
  • +
  • https://test.com/assistant/api
  • +
+

Actual execution URL

+

The vertical program must compute the actual execution URL by appending +baseUrl with :customMethodName.

+

Examples:

+
    +
  • https://us-central1.cloudfunctions.net/myWebhook/:completeTransaction
  • +
  • https://test.com/assistant/api:completeTransaction
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/aog/3020.html b/aog/3020.html new file mode 100644 index 0000000000..4312778a56 --- /dev/null +++ b/aog/3020.html @@ -0,0 +1,493 @@ + + + + AIP-3020: BII Schema Principles + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-3020

+

BII Schema Principles

+

Built-in intents (BIIs) allow third party developers to declare what their +Actions can do. When a developer registers an Action for a BII, Google can then +invoke that action to fulfill user requests matching that built-in intent.

+

Terminology

+

In the general principles below, we use the following terms:

+
    +
  • +

    Built-in intents (BII): Fulfillment schemas that are used to call + compatible APIs to perform Actions in response to a user query. Built-in + intents allow your service to express its fulfillment capabilities to Google. + By registering for built-in intents and mapping intent parameters to the + fulfillment, it becomes possible for the Google Assistant to invoke the + service to perform a task in response to natural language queries.

    +

    A BII comprises an operation (full list below) and a Schema.org entity, +otherwise known as a type. For example, CREATE_RESERVATION would be a BII +for initiating a new reservation; this intent applies to various domains such +as airline, hotel, restaurant, and other reservations.

    +
  • +
  • +

    Operation: An Action which acts as a wrapper around a type.

    +
  • +
  • Type: The object on which the operation is acting upon.
  • +
+

General principles

+

Each BII should be treated like an API. While BIIs are technically +fulfillment schemas, they fill the same role as an API, in that they tell third +party developers about the structure of the request that their Action handles.

+

This AIP details principles for schema creation, with operation-specific and +type-specific information, followed by a list of operations for BIIs.

+

Schema creation

+
    +
  • Existing Schema.org types and properties should be reused whenever the + semantics needed already exist.
  • +
  • The formula for naming a BII must be:
      +
    • Operation + Type := VERB ["Operation" from list below] + '_' + + NOUN ["Type" from Schema.org].
    • +
    • Types can be compound nouns which have more than one token. Types with more + than one token have tokens separated by '_'.
        +
      • Example: CREATE + '_' + MONEY_TRANSFER = CREATE_MONEY_TRANSFER
      • +
      +
    • +
    +
  • +
  • BII names must be in CAPITAL_SNAKE_CASE (e.g. VERB_NOUN_NOUN).
  • +
  • For more detail, see here.
  • +
+

Operations

+
    +
  • Operations comprise a small catalog of simple, generalizable verbs. These can + be found at the bottom of the AIP under "List of BII Operations."
  • +
  • There must not be overlap between the scope covered by any operations + (mutual exclusivity).
      +
    • Example: GET and CREATE do not overlap in scope; while both involve + presenting an object, GET is for retrieving an existing object, while + CREATE assumes no object yet exists and creates one.
    • +
    +
  • +
  • Operation + type combos should make semantic sense. If there is no + operation that can work with the type chosen, either:
      +
    • Choose a new type that is in semantic scope for the Action to attach to an + existing operation, with a semantically sensible result.
        +
      • Example: Say you want to fulfill a request for checking into a + reservation. CREATE_CHECKIN does not seem to make the most semantic + sense, since nothing is being created. Upon further thought, you decide + to choose a different operation and call the BII UPDATE_RESERVATION + instead, which makes more sense with the semantics of checking into a + reservation.
      • +
      +
    • +
    • Or, Create a new operation. Take this step only when there is no operation + in the list that can cover the Action requested for the schema.
        +
      • Example: Imagine you only had the operations START, STOP, and + RESUME for controlling an ongoing activity. A fulfillment request comes + in for temporarily stopping an ongoing activity of media playback but not + terminating it. You try to create a BII called STOP_MEDIA, but then + realize that this operation means the API must terminate the activity. + You then create a new operation, PAUSE, which acts to "temporarily + stop/pause activity", and does not overlap in scope with the existing + operation, STOP. Your new BII is PAUSE_MEDIA.
      • +
      +
    • +
    +
  • +
+

Types

+
    +
  • Types must be defined as Schema.org types.
  • +
  • The type must be the object upon which the operation is carried out.
  • +
  • Semantic scope of the type should be generalizable, specificity may + be in properties.
      +
    • Example: Reservation is a type, which has a property named provider. + The provider property specifies the service provider, service operator, + or service performer. This ensures that any BII created using the type + Reservation is generalizable to any service provider, and that the + service provider information is still passed forward through + Reservation’s property provider.
    • +
    +
  • +
  • Different types should take distinctly different properties.
  • +
  • BIIs must be specific enough to avoid semantic ambiguity when calling an + API. That is, we shouldn’t inadvertently trigger an Action that the user + isn’t expecting.
      +
    • Example: brokerage account vs. account: If we do not specify brokerage + account, a GET_ACCOUNT BII could call an API that fulfills the Action for + getting another sort of account’s information, such as a social media + account. GET_BROKERAGE_ACCOUNT ensures the correct scope of financial + account is retrieved by the API.
    • +
    +
  • +
  • The function prototype/set of parameters should be bound to the + operation. That is, the operation decides the fulfillment boundaries of the + Action.
  • +
  • Each BII operation must take a Schema.org type.
  • +
  • In BII schemas, the same Schema.org type, when combined with different verbs, + may take different properties.
      +
    • Example: GET_MESSAGE and CREATE_MESSAGE use a different but + overlapping set of properties of Message.
    • +
    +
  • +
+

Handling User Queries

+
    +
  • Generic/unresolved search criteria at the level of an object should be + passed through the Description field.
  • +
  • If a query argument can be recognized as a property of a type, it should + be passed through as a property; if, on the other hand, an argument is + recognized as just a description of the type, it should be passed through + Description field.
      +
    • Example: "find funky blues songs on YouTube" -> + get_media_object(description="funky blues").
    • +
    +
  • +
+

List of BII Operations

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VerbDefinitionExample BII schema
GETretrieve & present an object; if ambiguous, a list of objectsGET_CALL_HISTORY
CREATEcreate an objectCREATE_ORDER
DELETEremove or terminate an existing objectDELETE_RESERVATION
STARTcontrol an ongoing activity: start activitySTART_GAME
STOPcontrol an ongoing activity: stop activitySTOP_ALARM
PAUSEcontrol an ongoing activity: temporarily stop/pause activityPAUSE_SONG
RESUMEcontrol an ongoing activity: continue activityRESUME_TIMER
+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/aog/3021.html b/aog/3021.html new file mode 100644 index 0000000000..cbe9c74d5b --- /dev/null +++ b/aog/3021.html @@ -0,0 +1,339 @@ + + + + AIP-3021: Type protos in Actions on Google APIs + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-3021

+

Type protos in Actions on Google APIs

+

Many Actions on Google fulfillment APIs need to represent typed data (datetime, +money, etc.). In some cases, there are common components for representing these +types.

+

Guidance

+

Fulfillment APIs must use the Actions on Google common types when +applicable, and must not use alternative type protos. For example, an API +which needs to represent a monetary amount must use +google.type.Money, and must not use an alternative representation.

+

APIs may wrap existing types in new protos. This may be useful in order to +define compound types, provide additional metadata, provide semantic signals +(if the typed value was obtained from a user query), etc.

+

Actions on Google common types

+

The Actions on Google common types include all the protobuf types and API types +defined in AIP-213, as well as all the protos in +google.actions.type.*.

+

Adding new types

+

If a given API needs a type for which there is no existing common type, and the +type is not conceptually specific to that API, and the type is well understood +enough to be modeled in a permanent/unversioned way, then API author should +consider proposing a new Actions on Google common type in +google.actions.type.*.

+

The guidance in AIP-213 also applies to creating new +Actions on Google common types. Specifically, API authors proposing new types +should consider whether a new type should be a Google-wide common type +rather than an Actions on Google common type. One exception to this is that new +Actions on Google common types are not proposed by opening a GitHub ticket. +Instead, Actions on Google API authors who want to create a new type should +email the owners of the //google/actions/type directory directly.

+ + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/aog/3022.html b/aog/3022.html new file mode 100644 index 0000000000..9a644420e3 --- /dev/null +++ b/aog/3022.html @@ -0,0 +1,467 @@ + + + + AIP-3022: Built-in intent arguments and fulfillment APIs + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-3022

+

Built-in intent arguments and fulfillment APIs

+

Actions on Google's built-in intents (BIIs) are a fulfillment schema, +and use Schema.org as a foreign vocabulary. BIIs are not a fulfillment API, +and do not use the Actions on Google common types defined in AIP-3021.

+

Actions on Google has two types of generic fulfillment APIs:

+
    +
  • URI-based APIs like App Actions, which can only support string arguments.
  • +
  • Google standard APIs, which support JSON primitive types like string and + the Actions on Google common types.
  • +
+

These APIs do not support Schema.org JSON-LD objects. These APIs should +support BII arguments by mapping them, or their properties, to the argument +type schema they do support. For example, a BII argument of type +MonetaryAmount may be mapped to an API field of type +Money.

+

BII argument paths

+

Only certain Schema.org entity types should be mapped to a given common type. +In order to support BII arguments with types that cannot be mapped to an +appropriate type, APIs may support configuration via BII argument paths, +strings which allow users to specify a property of a Schema.org entity which +can be mapped to an appropriate type.

+

APIs which support BII argument paths should use the syntax defined in this +section.

+

BII argument paths are dot-delimited strings that identify a specific +Schema.org entity within the list of arguments to the BII.

+

For example, take the following hypothetical BII arguments grant and date:

+
{
+  "grant": {
+    "@context": "http://schema.org",
+    "@type": "MonetaryGrant",
+    "funder": {
+      "@type": "Organization",
+      "name": "Google"
+    },
+    "amount": {
+      "@type": "MonetaryAmount",
+      "currency": "USD",
+      "value": 100
+    }
+  },
+  "date": "2000-01-01"
+}
+
+

There is no common type to which MonetaryGrant can be mapped, but the grant +argument contains an amount property of type +MonetaryAmount, which can be mapped to Money. +This property can be referenced with the path string "grant.amount". +Similarly, grant.name can be mapped to a string field.

+

A URI-based API which does not support Money would instead need to use the +path strings "grant.amount.currency" and "grant.amount.value" to map +grant.amount to two separate URI parameters.

+

On the other hand, date can be mapped to DateTime, and so the path string +"date" would be sufficient for either URI-based APIs or string fields in JSON +APIs.

+

Properties with multiple values

+

Since any Schema.org property may have multiple values, values other than the +first may be referenced by indexing with square brackets. For example, take +this hypothetical BII argument:

+
{
+  "menuItem": {
+    "@context": "http://schema.org",
+    "@type": "MenuItem",
+    "name": "pizza",
+    "menuAddOn": {
+      "@type": "MenuItem",
+      "name": "pineapple"
+    },
+    "menuAddOn": {
+      "@type": "MenuItem",
+      "name": "extra cheese"
+    }
+  },
+  "date": "2000-01-01"
+}
+
+

In this example, the path "menuItem.menuAddOn[1].name" would evaluate to +"extra cheese".

+

When there are no square brackets, the first value is assumed; using [0] is a +no-op. That is, "menuItem.menuAddOn.name" and "menuItem.menuAddOn[0].name" +are equivalent, and would both evaluate to "pineapple".

+

BII argument to common type mappings

+

Google standard APIs which support BII argument mapping should support at +least these type mappings from Schema.org entity type to Actions on Google +common types:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Common typeSchema.org entity types
DateDate
DateTimeDateTime
TimeOfDayTime
DurationDuration
MoneyMonetaryAmount
PostalAddressPlace, PostalAddress
+

BII argument to JSON type mappings

+

Google standard APIs which support BII argument mapping should support at +least these type mappings from Schema.org entity type to JSON type:

+ + + + + + + + + + + + + + + + + + + + + +
JSON typeSchema.org entity types
stringText
numberNumber
boolBoolean
+

BII argument to string mappings

+

URI-based fulfillment APIs like App Actions can only map BII arguments to +strings (URI parameters). These APIs should support mapping at least the +following Schema.org entity types to URI parameters:

+ + + + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/apps.html b/apps.html new file mode 100644 index 0000000000..32314a2267 --- /dev/null +++ b/apps.html @@ -0,0 +1,346 @@ + + + + Workspace AIPs + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + + +
+
+ +
+

Workspace

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NumberTitle
2712 + API completeness +
2713 + One team owns each type +
2715 + Documenting authorization changes + + Reviewing + +
2716 + Standard terms in names +
2717 + Patterns for generic fields + + Reviewing + +
2718 + References to objects in other APIs + + Draft + +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/apps/2712.html b/apps/2712.html new file mode 100644 index 0000000000..5e26c122b8 --- /dev/null +++ b/apps/2712.html @@ -0,0 +1,327 @@ + + + + AIP-2712: API completeness + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-2712

+

API completeness

+

Our customers expect that they can be as productive in their Apps programs as +they can be sitting at the UI. When they can not, this is surprising and +disappointing. Historically, Google Workspace has not insisted on this kind of +completeness. However, we want to move towards that goal, hence this +requirement for a plan, while we only advise completeness itself.

+

For major changes, however, the desire for completeness will be amplified.

+

Guidance

+

Each action that can be performed in the UI should be possible to do via a +public API. For example, if there is a button in the UI to add a widget, there +should be some way to add a widget using the API. This simplifies the +user's understanding of the API, and makes it easier to record UI actions to be +replayed via the API.

+

The question of when the completeness ought to be achieved is not fixed. Each +team must have a plan for API completeness, even if it is a simple +statement, such as, "When we are given resources to do so." (We would prefer +more, but if that is your plan, then so be it.)

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/apps/2713.html b/apps/2713.html new file mode 100644 index 0000000000..19f90020bc --- /dev/null +++ b/apps/2713.html @@ -0,0 +1,326 @@ + + + + AIP-2713: One team owns each type + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-2713

+

One team owns each type

+

This guidance supplements AIP-213.

+

Sharing types is tempting, and it is possible. However, it is surrounded by +some complicated issues.

+

We will consider making shared types for classes that are useful across +multiple Apps APIs, we just will not do it lightly. If you feel you have a case +for this, please contact us at apps-api-reviewers@google.com.

+

Guidance

+

Each API owns its own types.

+

If your API needs to reference another API's objects, your API must contain +a reference (resource name or ID) that can be used to get the +information from that other API. For example, if your API wants to reference a +relevant Gmail message, you must store a Gmail message name, and the +message itself will be accessed via the Gmail API, passing in that name. Your +API must not contain an actual Gmail message object.

+

For smaller types, it is also reasonable to make a copy of the class.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/apps/2715.html b/apps/2715.html new file mode 100644 index 0000000000..dc5c01d031 --- /dev/null +++ b/apps/2715.html @@ -0,0 +1,366 @@ + + + + AIP-2715: Documenting authorization changes + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+

+ This AIP is currently under review. This means that the editors have read it + and are in high-level concurrence, and while it is not yet fully approved, we + have a good faith expectation that the AIP will be approved in something + close to its current state. +

+

AIP-2715

+

Documenting authorization changes

+

Authorization is critical to manage well. Understanding an API includes +understanding not only what operations do, but when one is allowed to do them. +Authorization changes, either new authorization constructs or new uses of +existing authorization constructs, should be easy to find in a design rather +than scattered through the document in individual sections.

+

In order to make it easy to see what (if any) authorization constructs are +being modified in your design, we want to be able to find them in a single, +clear place.

+

Note: This is not talking about RPC-level permissions, like those covered +by RpcSecurityPolicy, but about authorization constructs used by your API for +its own purposes.

+

Definitions

+

There are a couple of common types of authorization construct:

+

A role refers to an authorization construct which is granted to an +identity or an identity group on a resource. The most well known examples +of roles in G Suite are the commenter, reader, writer, and owner roles +from Drive.

+

A permission refers to an authorization construct which is used to check +whether a particular identity can execute some operation. For example, to +check whether the current user can delete a file, the application may check +whether the user has the file.delete permission on the file. Permissions are +most often assigned to roles, so that only roles are granted to identities or +identity groups, but some systems allow permissions to be granted directly. +Applications often only use each permission to authorize a single operation on +a resource, but there are cases where an application may use a permission to +authorize multiple different operations.

+

Within an application, authorization checks are made using only one of these +authorization constructs (typically permissions, if the application has that +concept). For example, in order to determine if a user can read a document, an +application would either check whether the user has a doc.read permission +or has the reader role, but not both.

+

Guidance

+

If your design creates new authorization constructs or extends/modifies the use +of any existing authorization constructs, you must have a separate section +in your design document that describes this. You may additionally discuss +these in any other place in your document.

+

It is not important whether this is a top-level section or subsection. It is +important that all such changes are listed together in a distinct section so +they are easy to find and analyze.

+

If the identifier of an authorization construct that is new or modified is +visible to users or developers, the way that it is identified should also be in +your document. Examples of this are:

+
    +
  • If access is granted using roles and a new role is being added, the way that + the role is identified in the role granting RPCs should be in your document.
  • +
  • If there is an API that allows permissions assigned to roles to be + manipulated, the way that the permission is identified in the role + manipulation RPCs should be in your document.
  • +
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/apps/2716.html b/apps/2716.html new file mode 100644 index 0000000000..2df388fd6a --- /dev/null +++ b/apps/2716.html @@ -0,0 +1,347 @@ + + + + AIP-2716: Standard terms in names + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+ +

AIP-2716

+

Standard terms in names

+

APIs have a lot of identifier names (fields, constants, methods, ...), that +often contain terms for things, such as url (getUrl(), doc_url, ...) or +id (lookupId(), student_id).

+

It is useful to have a standard set of terms for common concepts in these +various names. This makes it easier for developers to understand new APIs based +on previous experience. It is not (for example) that id is a better term than +uid or other options, but it also is not worse, and having different choices +in different APIs is confusing and unnecessary.

+

This AIP defines terms to use for such common concepts. These terms should be +used for the same concept in identifier names.

+

This is supplemental to the API design guide, which lists standard field +names and has other rules about identifiers.

+

Guidance

+

Absent other, more specific guidance, APIs should use the following +standard terms (as opposed to alternatives) as parts of identifier names to +refer to common concepts, and must not use them to refer to other things:

+
    +
  • uri for URIs/URLs (as opposed to url, link, href, etc.)
  • +
  • id for a unique identifier, either globally unique or within a specified + context
  • +
  • index to indicate an ordinal number of an item within a collection, such as + message_index on a message to say what place it occupies in a stream of + message (unless there is a more specific name to use, such as if the number + also is used as an ID, use id).
  • +
+

APIs should avoid use of the term resource in fields that have resource +names, as this is redundant.

+

Any more specific guidance overrides these rules. For example, the AIP-122 +rule to use name for the resource name overrides using the term id for +unique identifiers.

+

Fallback to schema.org

+

If you are looking for standard terms for things, schema.org is a good +place to look for terms that have been fairly widely vetted as being normal, +customary, and/or clear. You should consult it when choosing identifier +names when other strategies fail.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/apps/2717.html b/apps/2717.html new file mode 100644 index 0000000000..a7a713f065 --- /dev/null +++ b/apps/2717.html @@ -0,0 +1,374 @@ + + + + AIP-2717: Patterns for generic fields + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+

+ This AIP is currently under review. This means that the editors have read it + and are in high-level concurrence, and while it is not yet fully approved, we + have a good faith expectation that the AIP will be approved in something + close to its current state. +

+

AIP-2717

+

Patterns for generic fields

+

Developers have several options for how to represent generic values in proto +messages. There are reasons to choose one over the other. Understanding them +will lead to better and more consistent APIs.

+

Guidance

+

APIs should follow a consistent application of oneof vs. +map<string, Foo> vs. Any vs. Struct.

+

oneof

+

A oneof is used to create a restriction on a set of optional fields, +enforcing that only one of them may be set (these fields are still separate +individual fields). A common pattern is to have a message that contains a +single oneof collection of various message types. Such a oneof message is +conceptually similar to a C union, or C++ std::variant. These should be +used in most places where a generic message type is needed, in preference to +other approaches.

+

Note: Adding additional possible values to an existing oneof is a +non-breaking change, but moving existing fields into or out of a oneof is +breaking (it creates a backwards-incompatible change in Go protobuf stubs).

+

map<string, Foo>

+

If a more generic structure is needed, a map of strings to objects may be +used. Such a map is represented by a normal JSON object, such as +{"a": "foo", "b": "bar"}. The downside to such maps is that they are limited +to flat structures, and they can be difficult to work with because many string +constants may be needed.

+

Any

+

An Any allows any message to be packed into the field. This is +conceptually similar to a "bytes" field containing a serialized message. The +advantage of an Any is that a user-defined proto message can be stored along +with type information. The user must be able to know which kind of object is in +the Any, which complicates the design. The disadvantage is that working with +and debugging any protos is much more complicated since the code may or may not +know how to deserialize the packed message. Also, the developer must contend +with unexpected types of messages in the Any.

+

Any should not be used as a request parameter. Request parameters will +either be a fixed set of types, in which case a oneof should be used, or +a type descriptor would need to be sent along, in which case a struct +should be used, which achieves essentially the same thing with much simpler +semantics.

+ +

Struct

+

The Struct message can be used to represent arbitrary nested JSON. +For example, given the following code:

+
Struct.Builder builder = Struct.newBuilder();
+Value town = Value.newBuilder().setStringValue("Springfield").build();
+Value population = Value.newBuilder().setNumberValue(273).build();
+builder.putFields("town", town);
+builder.putFields("population", population);
+Struct survey = builder.build();
+
+

survey would serialize as the actual JSON +{"town": "Springfield": "population": 273}. This message type is fairly +uncommon, and should only be used rarely.

+ + +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/apps/2718.html b/apps/2718.html new file mode 100644 index 0000000000..11df541c28 --- /dev/null +++ b/apps/2718.html @@ -0,0 +1,362 @@ + + + + AIP-2718: References to objects in other APIs + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+ +
+
+
+
+ + + +
+
+ + + View on GitHub + +
+
+
+
+ +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+ + +
+ + +
+
+ +
+

+ This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

+

AIP-2718

+

References to objects in other APIs

+

Your API may need to refer to objects in other APIs. For example, a Sheets cell +may want to refer to the Slides deck that explains its meaning. This kind of +cross reference should be as natural to use as possible with the target API.

+

Guidance

+

When your API refers to an object accessed via another API (the "target" API), +the reference your API provides depends upon whether the reference is compliant +with One Platform or not.

+
    +
  • +

    If a field always holds a compliant reference to a single specific target + API, the reference you provide must be a relative URI from the top level + of the target API's naming hierarchy. For example, if the full URL of the + object is https://koalas.googleapis.com/koalas/123435 the reference you + return to it must be the relative URI koalas/123435. Further, your + documentation must make clear that the reference is used with + koalas.googleapis.com.

    +

    This provides the developer with a natural way to use the reference, using +the returned path directly. It also ensures that they know which API +understands that reference.

    +
  • +
  • +

    If a field always holds a compliant reference, but is not limited to a single + target API, the reference you provide must be a relative URI that + includes the path of its specific target API, such as + koalas.googleapis.com/koalas/123435. This provides the developer with the + correct target in a formalized, usable way.

    +
  • +
  • +

    Otherwise, the reference you return must be chosen to be as natural to + use as possible with the target API, and the API and its version must be + documented. For example, if the Apiary-based Koala API uses an ID in its + GetKoalaData method, you must return the ID that can be used as a + parameter, as well as documenting that you are using IDs that work in Koala + API 1.0.

    +
  • +
+

Naming

+

For compliant references, you should avoid the use of the terms "reference" +and "name" in the field name. That is, koala is preferred to +koala_reference or koala_name +(see [AIP-122][]).

+

For other target APIs, you should echo that API's terminology in the name +for clarity. For example, if the target API's GetKoalaDataRequest has a +koala_num field, your field name should probably be koala_num, or it +would include koala_num in its name, such as responsible_koala_num.

+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/assets/css/hero.css b/assets/css/hero.css new file mode 100644 index 0000000000..95fef13b04 --- /dev/null +++ b/assets/css/hero.css @@ -0,0 +1,32 @@ +.aip-hero .aip-hero-banner { + margin-top: 3em; + border-bottom: 1px solid #dadce0; } + .aip-hero .aip-hero-banner .aip-hero-title { + font-size: 250%; + font-weight: bold; } + .aip-hero .aip-hero-banner .aip-hero-subtitle { + font-size: 125%; + margin-top: 1em; } + .aip-hero .aip-hero-banner .aip-buttons { + padding-top: 2em; + padding-bottom: 2em; } + .aip-hero .aip-hero-banner .aip-buttons > a { + margin-right: 1em; } +.aip-hero .aip-landing-content { + padding-top: 1em; + padding-bottom: 1em; + border-bottom: 1px solid #dadce0; } + .aip-hero .aip-landing-content h1 { + font-size: 160%; + font-weight: bold; } + .aip-hero .aip-landing-content p { + font-size: 115%; } +.aip-hero .aip-shortcuts { + padding-top: 1em; } + .aip-hero .aip-shortcuts .aip-shortcut { + padding-top: 1em; } + .aip-hero .aip-shortcuts .aip-shortcut > h1 { + font-weight: bold; + font-size: 120%; } + .aip-hero .aip-shortcuts .aip-shortcut > a { + margin-top: 1em; } diff --git a/assets/css/print.css b/assets/css/print.css new file mode 100644 index 0000000000..0cc356f737 --- /dev/null +++ b/assets/css/print.css @@ -0,0 +1,57 @@ +footer { + border-top: 1px solid #dadce0; + color: #5f6368; + font-size: 13px; + font-style: italic; + margin-bottom: 10px; + margin-top: 25px; + padding-top: 10px; } + footer p { + font-size: 13px; } + +.aip-breadcrumbs, #aip-nav, #aip-nav-mobile, #aip-sidebar, .glue-header, +.glue-page svg:first-child, .no-print { + display: none; } + + h1, h2, h3, h4 { + font-family: 'Google Sans', 'Roboto', Arial, Helvetica, sans-serif; + font-weight: 400; + margin: 0.5em 0em 0em 0em; + padding: 0px; } + + h1 { + font-size: 2.5em; } + + h4 + h1 { + margin-top: 0in; } + + html { + font-family: sans-serif; } + + kbd, pre, samp { + font-family: monospace, monospace; + font-size: 1em; } + + body { + font-family: 'Roboto', Arial, Helvetica, sans-serif; + font-size: 1em; + font-style: normal; + font-weight: 300; + line-height: 1.444; } + + code { + font-family: 'Consolas', 'Monaco', 'Roboto Mono', 'Bitstream Vera Sans Mono', 'Courier New', + Courier, monospace; + font-weight: 300; } + + div.highlighter-rouge { + background: #f1f3f4; + border: 1px solid #dadce0; + margin-left: 0.5in; + margin-right: 0.5in; + padding-left: 0.2in; + padding-right: 0.2in; } + + a { + color: inherit; + text-decoration: none; } diff --git a/assets/css/search.css b/assets/css/search.css new file mode 100644 index 0000000000..92ae75e028 --- /dev/null +++ b/assets/css/search.css @@ -0,0 +1,58 @@ +.docs-component-sidebar-toc { + display: none; } + + .primary-search { + margin-top: 20px; } + .primary-search input { + font-size: 24px; + height: 48px; + padding-left: 8px; } + @media (min-width: 1024px) { + .primary-search input { + margin-right: 10px; + width: 500px; } +} + .primary-search button.glue-button { + margin-top: 1px; } + +#tipue_search_content { + margin-left: 2px; } + #tipue_search_content #tipue_search_results_count { + color: #5f6368; + font-size: 13px; + font-style: italic; } + #tipue_search_content .tipue_search_content_title a { + text-decoration: none; } + #tipue_search_content .tipue_search_content_url { + font-size: 75%; } + #tipue_search_content .tipue_search_content_url a { + color: #5bb974; + text-decoration: none; } + #tipue_search_content .tipue_search_content_text { + font-size: 85%; + margin-bottom: 1em; } + #tipue_search_content .tipue_search_content_bold { + font-weight: bold; } + +#tipue_search_foot_boxes li { + border: 1px solid #5f6368; + color: #202124; + display: inline-block; + list-style: none; + margin-left: -1px; + min-height: 40px; + min-width: 40px; + padding: 8px 12px; + position: relative; + text-align: center; } + #tipue_search_foot_boxes li.current { + background-color: #dadce0; } + #tipue_search_foot_boxes li:not(.current) { + cursor: pointer; } + #tipue_search_foot_boxes li:not(.current):hover { + background-color: #d2e3fc; } + #tipue_search_foot_boxes li a { + color: #202124; + text-decoration: none; } + #tipue_search_foot_boxes li a:hover { + background-color: transparent; } diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 0000000000..4e1a6e9472 --- /dev/null +++ b/assets/css/style.css @@ -0,0 +1,484 @@ +.callout, .important, .note, .tldr, .summary, .warning { + margin-top: 5px; + margin-left: 20px; + margin-right: 20px; + padding: 10px 20px; + color: #3c4043; } + + .important { + background-color: #fef7e0; + border: 1px solid #fde293; } + + .note { + background-color: #e8f0fe; + border: 1px solid #aecbfa; } + + .tldr, .summary { + background-color: #e6f4ea; + border: 1px solid #a8dab5; } + + .warning { + background-color: #fce8e6; + border: 1px solid #f6aea9; } + + code { + font-size: 90% !important; } + + .docs-component-main blockquote { + border-left: 4px solid #9aa0a6; + margin: 20px; + padding-left: 20px; } + .docs-component-main code { + font-size: 0.9em; } + .docs-component-main pre { + font-size: 14px; + margin: 20px; + padding: 9px 14px; } + .docs-component-main pre code { + color: #202124; } + +.digraph { + text-align: center; } + + footer { + border-top: 1px solid #dadce0; + color: #5f6368; + font-size: 13px; + font-style: italic; + margin-bottom: 10px; + margin-top: 25px; + padding-top: 10px; } + footer p { + font-size: 13px; } + +@media (max-width: 1200px) { + .glue-header .h-c-header__bar .h-c-header__hamburger:first-child { + display: table !important; } +} + +.github-logo { + width: 1em; + height: 1em; + margin-right: 10px; + margin-top: -2px; } + + .glue-button img.github-logo { + display: inline; } + + body .glue-header.glue-header--single .glue-header__bar { + box-shadow: 0 1px 2px 0 rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15); } + @media (min-width: 1024px) { + body .glue-header.glue-header--single .glue-header__bar { + transform: none !important; } +} + @media (min-width: 1024px) and (max-width: 1096px) { + body .glue-header.glue-header--single .glue-header__bar .glue-header__item.header-item-collapse { + display: none; } +} + @media (max-width: 599px) { + body .glue-header.glue-header--single .glue-header__bar.glue-header__bar--mobile { + height: 64px; + min-height: 64px; } + body .glue-header.glue-header--single .glue-header__bar.glue-header__bar--mobile .glue-header__cta { + display: none; } +} + +.glue-sitesearch label { + display: none; } + @media (max-width: 1023px) { + .glue-sitesearch { + display: none; } +} + @media (max-width: 1200px) { + .glue-sitesearch .glue-sitesearch__input { + width: 150px; } +} +.glue-sitesearch .glue-button.glue-sitesearch__submit { + background: transparent; + border: 0px; + border-radius: 0%; + min-width: 36px; } + .glue-sitesearch .glue-button.glue-sitesearch__submit svg { + display: block; + max-width: 24px; + width: 24px; } + +.docs-component-main h1::before, .docs-component-main h2::before, +.docs-component-main h3::before, .docs-component-main h4::before, +.docs-component-main h5::before { + display: block; + content: ' '; + height: 80px; + margin-top: -80px; + pointer-events: none; + visibility: hidden; } + .docs-component-main h1 a, .docs-component-main h2 a, .docs-component-main h3 a, + .docs-component-main h4 a, .docs-component-main h5 a { + text-decoration: none; } +.docs-component-main h4.aip-number { + line-height: 1em; } + .docs-component-main h4.aip-number + h1 { + margin-top: 0px; + margin-left: -2px; } + +.docs-component-main ul { + margin-top: 20px; + padding-left: 20px; } + .docs-component-main ul > li > ul { + margin-top: 0px; } + +main#page-content { + margin-top: 16px; } + + nav.docs-component-nav { + display: none; } + + nav li.drawer-heading { + padding-left: 16px; + padding-right: 16px; } + nav li.drawer-heading:not(:first-child) { + margin-top: 32px; } + nav li.drawer-heading .drawer-heading-text { + color: #80868b; + display: table-cell; + font-family: 'Google Sans', 'Roboto', Arial, Helvetica, sans-serif; + font-size: 14px; + font-weight: 700; + height: 48px; + letter-spacing: 0.25px; + vertical-align: middle; } + +nav.no-breadcrumb { + height: 0px; + visibility: hidden; } + nav.no-breadcrumb + h1 { + margin-top: -88px; } + +@media (min-width: 1200px) { + .docs-component-main { + padding-left: 320px; } + nav.docs-component-nav { + background-color: #f1f3f4; + display: block; + float: left; + margin-right: 40px; + overflow-x: hidden; + overflow-y: auto; + padding: 16px 12px; + position: fixed; + width: 280px; } + nav.docs-component-nav::-webkit-scrollbar { + height: 4px; + width: 4px; } + nav.docs-component-nav::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.25); } + nav.docs-component-nav ul.nav-list { + margin-left: 0px; + margin-bottom: 0px; } + nav.docs-component-nav ul.nav-list li.nav-item { + font-size: 13px; + font-weight: 400; + line-height: 16px; + list-style: none; + margin-top: 8px; + overflow-x: hidden; + overflow-y: hidden; + text-overflow: ellipsis; } + nav.docs-component-nav ul.nav-list li.nav-item:first-child { + margin-top: 0px; } + nav.docs-component-nav ul.nav-list li.nav-item a { + color: #202124; + text-decoration: none; } + nav.docs-component-nav ul.nav-list li.nav-item a:hover { + color: #1a73e8; } + nav.docs-component-nav ul.nav-list li.nav-item svg { + color: #9aa0a6; + height: 1.25em; + vertical-align: middle; + width: 1.25em; } + nav.docs-component-nav ul.nav-list li.nav-item.nav-item-active a { + color: #1a73e8; } + nav.docs-component-nav ul.nav-list li.nav-item.nav-item-header { + color: #80868b; + font-size: 14px; + font-weight: 500; } + nav.docs-component-nav ul.nav-list li.nav-item.nav-item-header:not(:first-child) { + border-top: 1px solid #cfd8dc; + margin: 15px -16px 0px -16px; + padding: 15px 16px 0px 16px; } +} + +.docs-component-sidebar { + display: none; } + + @media (min-width: 1024px) { + .docs-component-main { + padding-right: 250px; } + .docs-component-sidebar { + -webkit-position: sticky; + display: block; + float: right; + position: sticky; + right: 20px; + top: 80px; + width: 230px; } + .docs-component-sidebar .docs-component-sidebar-toc > .toc { + border-left: 3px solid #1967d2; + margin-left: 20px; + padding-left: 20px; } + .docs-component-sidebar .docs-component-sidebar-toc > .toc > ul { + margin-left: 0px; } + .docs-component-sidebar .docs-component-sidebar-toc > .toc .toctitle { + font-weight: 700; + text-transform: uppercase; } + .docs-component-sidebar .docs-component-sidebar-toc > .toc .toctitle:only-child { + display: none; } + .docs-component-sidebar .docs-component-sidebar-toc > .toc li { + font-size: 14px; + list-style: none; + margin-top: 12px; } + .docs-component-sidebar .docs-component-sidebar-toc > .toc li a { + color: #202124; + font-weight: 300; + text-decoration: none; } + .docs-component-sidebar .docs-component-sidebar-actions > ul li { + font-weight: 700; + font-size: 16px; + list-style: none; + margin-top: 12px; + text-transform: uppercase; } + .docs-component-sidebar .docs-component-sidebar-actions > ul li a, + .docs-component-sidebar .docs-component-sidebar-actions > ul li a:visited { + color: #1967d2; + text-decoration: none; } + .docs-component-sidebar .docs-component-sidebar-actions > ul li a:hover, + .docs-component-sidebar .docs-component-sidebar-actions > ul li a:active, + .docs-component-sidebar .docs-component-sidebar-actions > ul li a:focus { + color: #4285f4; } +} + +strong.spec-directive.spec-must { + color: #c5221f; } + strong.spec-directive.spec-should { + color: #f57c00; } + strong.spec-directive.spec-may { + color: #188038; } + +code, .highlighter-rouge { + background: transparent; + color: inherit; + padding: 0px; } + + .highlight .hll { + background-color: #ffffcc; } + .highlight .bp { + color: #03a9f4; } + .highlight .c, .highlight .c1, .highlight .cm, .highlight .cs { + color: #188038; + font-style: italic; } + .highlight .k, .highlight .kc, .highlight .kd, .highlight .kn, .highlight .kp, + .highlight .kr, .highlight .ow, .highlight .nt { + color: #174ea6; + font-weight: bold; } + .highlight .kt, .highlight .nb { + color: #ef6c00; } + .highlight .na { + color: #ad1457; } + .highlight .nc { + color: #fb8c00; } + .highlight .nk, .highlight .nx { + color: #6a1b9a; } + .highlight .m, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .mo, + .highlight .il, .highlight .sc, .highlight .ss { + color: #03a9f4; } + .highlight .s, .highlight .sb, .highlight .sd, .highlight .sh, .highlight .si, + .highlight .sx, .highlight .s1, .highlight .s2 { + color: #4285f4; } + .highlight .o { + font-weight: bold; } + .highlight .p.semi { + color: #bdc1c6; } + .highlight .gd { + color: black; + background-color: #fce8e6; } + .highlight .ge { + font-style: italic; } + .highlight .gr, .highlight .gt { + color: #a50e0e; } + .highlight .gh { + color: #9aa0a6; } + .highlight .gi { + color: black; + background-color: #e6f4ea; } + .highlight .go { + color: #80868b; } + .highlight .gp { + color: #3c4043; } + .highlight .gs { + font-weight: bold; } + .highlight .gu { + color: #bdc1c6; } + .highlight .cp { + color: #008080; } + .highlight .cs { + font-style: normal; + font-weight: bold; } + .highlight .err { + color: #c5221f; + background-color: #fad2cf; } + .highlight .w { + color: #bdc1c6; } + .highlight .se { + color: #03a9f4; } + .highlight .sr { + color: #1a73e8; } + .highlight .protobuf-annotation { + color: #f9ab00; } + +table:not(.no-h) { + margin-bottom: 20px !important; } + table:not(.no-h) tr td { + font-weight: 300; } + +.tabbed-set { + display: flex; + position: relative; + flex-wrap: wrap; } + .tabbed-set .tabbed-content { + display: none; + order: 99; + width: 100%; } + .tabbed-set label { + border-radius: 10px 10px 0px 0px; + color: #80868b; + cursor: pointer; + font-family: 'Google Sans', 'Roboto', Arial, Helvetica, sans-serif; + font-size: 80%; + font-weight: 500; + margin: 0 0.5em; + padding: 1.25em; + width: auto; } + .tabbed-set input { + position: absolute; + opacity: 0; } + .tabbed-set input:nth-child(n + 1) { + color: #202124; } + .tabbed-set input:checked + label { + background-color: #f1f3f4; + border-bottom: 2px solid #1967d2; + color: #202124; + z-index: 1; } + .tabbed-set input:checked + label + .tabbed-content { + border-top: 2px solid #f1f3f4; + display: block; + margin-top: -2px; + padding-top: 1em; } + +.aip-state, h3.reviewing::after { + border-radius: 4px; + font-size: 0.75em; + margin-left: 10px; + padding: 2px 5px; } + + .aip-state-reviewing, h3.reviewing::after { + background-color: #e8f0fe; + border: 1px solid #aecbfa; } + + .aip-state-draft { + background-color: #fef7e0; + border: 1px solid #fde293; } + + h3.reviewing::after { + content: 'Reviewing'; + font-size: 0.5em; } + + ol.aip-breadcrumbs { + margin-bottom: 0; } + ol.aip-breadcrumbs .glue-breadcrumbs__item:not(:last-child)::after { + color: #5f6368; + content: '»'; + margin-left: 3px; + margin-right: 1px; } + +.h-c-header__cta-li form.h-c-sitesearch { + padding-right: 20px; } + + #aip-nav .nav-item span.aip-number { + display: inline-block; + min-width: 26px; + text-align: right; } + #aip-nav .nav-item span.aip-number:after { + content: '. '; } + +.aip-newsletter-highlights > p { + font-size: 0.85em; + margin-top: 0.5em; } + .aip-newsletter-highlights ul.highlights-list { + margin-top: 0px; + margin-left: 0px; + padding-left: 10px; + list-style: none; } + .aip-newsletter-highlights ul.highlights-list > li { + font-size: 0.85em; } + .aip-newsletter-highlights ul.highlights-list > li:before { + content: '- '; } + .aip-newsletter-highlights ul.highlights-list > li > ul { + display: inline; + margin-left: 0px; + padding-left: 0px; } + .aip-newsletter-highlights ul.highlights-list > li > ul > li { + display: inline; } + .aip-newsletter-highlights ul.highlights-list > li > ul > li a { + text-decoration: none; } + .aip-newsletter-highlights ul.highlights-list > li > ul > li:after { + content: ', '; } + .aip-newsletter-highlights ul.highlights-list > li > ul > li:last-child:after { + content: ''; } + +#aip-main table:not(.no-h).aip-listing { + margin-top: 10px; } + #aip-main table:not(.no-h).aip-listing tr:first-child { + border-top: 2px solid #9aa0a6; } + #aip-main table:not(.no-h).aip-listing th { + display: none; } + #aip-main table:not(.no-h).aip-listing td { + text-align: left; } + #aip-main table:not(.no-h).aip-listing td:first-child { + text-align: right; + width: 70px; } + #aip-main table:not(.no-h).aip-listing td a { + text-decoration: none; } + #aip-main table:not(.no-h).aip-listing tr td { + padding-top: 10px; + padding-bottom: 10px; } +#aip-main table#aip-summary { + float: right; } + +table#aip-summary { + background-color: #f8f9fa; + border: 1px solid #e8eaed; + margin-top: 2px; + margin-left: 10px; + width: 220px; } + @media (max-width: 800px) { + table#aip-summary { + display: none; } +} + table#aip-summary th { + border: 0px; + color: #3c4043; + font-size: 14px; + padding: 8px 0px; + text-align: center; } + table#aip-summary tr td { + font-size: 12px; + padding: 2px 5px; } + table#aip-summary tr td:first-child { + color: #5f6368; + font-weight: bold; + padding-left: 12px; + width: 60px; } + table#aip-summary tr td a { + text-decoration: none; } + table#aip-summary tr:last-child td { + padding-bottom: 8px; } diff --git a/assets/favicon.ico b/assets/favicon.ico new file mode 100644 index 0000000000..a27c03a0c6 Binary files /dev/null and b/assets/favicon.ico differ diff --git a/assets/images/github.png b/assets/images/github.png new file mode 100644 index 0000000000..192846a120 Binary files /dev/null and b/assets/images/github.png differ diff --git a/assets/images/glue-icons.svg b/assets/images/glue-icons.svg new file mode 100644 index 0000000000..c6400ba2f3 --- /dev/null +++ b/assets/images/glue-icons.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/js/aip/aip-graphviz.js b/assets/js/aip/aip-graphviz.js new file mode 100644 index 0000000000..c0129eac79 --- /dev/null +++ b/assets/js/aip/aip-graphviz.js @@ -0,0 +1,36 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file contains JavaScript-applied rules that render graphviz objects +// in AIPs. +// +// Note: This script is not included in AIPs by default, because the scripts +// needed to render graphviz are nearly 1.5 MB in size that including them +// everywhere adds significant weight. +// +// See the front matter for AIP-1 or AIP-100 for examples of how to add this +// for AIPs that need graphviz rendering. +$.when($.ready).then(() => { + $('.language-graphviz').each((_, el) => { + let pre = $(el).children('pre'); + let graphviz = $(el).find('code').text(); + + // Render a SVG and replace the original graphviz code with it. + let viz = new Viz(); + viz.renderSVGElement(graphviz).then((svg) => { + $('

').append(svg).insertBefore(pre); + pre.remove(); + }); + }); +}); diff --git a/assets/js/aip/aip-index.js b/assets/js/aip/aip-index.js new file mode 100644 index 0000000000..19906eb9b2 --- /dev/null +++ b/assets/js/aip/aip-index.js @@ -0,0 +1,25 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file contains JavaScript-applied rules that apply to the AIP index +// specifically. +$.when($.ready).then(() => { + // The base README page should have tables that span the full width + // and look consistent with one another. + for (let topLeftCell of ['Number', 'Block']) { + $(`table th:first-child:contains(${topLeftCell})`) + .parents('table') + .addClass('aip-listing'); + } +}); diff --git a/assets/js/global.js b/assets/js/global.js new file mode 100644 index 0000000000..a4c946598e --- /dev/null +++ b/assets/js/global.js @@ -0,0 +1,78 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file contains JavaScript-applied rules that can be applied +// to documentation sites using this Jekyll theme generally. +$.when($.ready).then(() => { + // Certain selectors should apply Glue classes. + // (For our purposes, this essentially mimics the SCSS @extend directive.) + // In general, we can not apply these directly because the tags are generated + // while compiling from Markdown, so we do it ex post facto. + let extend = new Map(); + for (let h = 1; h <= 5; h += 1) { + let classes = [ + 'glue-headline', + 'glue-has-top-margin', + `glue-headline--headline-${h + 1}`, + ]; + if (h <= 3) { + classes.push('glue-has-bottom-margin'); + } + extend.set(`.docs-component-main h${h}`, classes); + } + extend.set('table:not(.no-h)', ['glue-table']); + extend.set('#aip-main table:not(.no-h)', ['glue-table--datatable']); + extend.set('.tipue_search_content_title', [ + 'glue-headline', + 'glue-headline--headline-4', + 'glue-has-top-margin', + ]); + for (let [selector, classes] of extend) { + $(selector).addClass(classes); + } + + // Make callouts for notes, warnings, etc. work. + for (let callout of ['Important', 'Note', 'TL;DR', 'Warning', 'Summary']) { + $(`p strong:contains(${callout}:)`) + .parent() + .addClass(callout.replace(';', '').toLowerCase()); + } + + // Make "spec terms" (must, should, may, must not, should not) that + // are bold-faced be further emphasized. + for (let directive of ['may', 'must', 'must not', 'must\nnot', + 'should', 'should not', 'should\nnot']) { + $('strong') + .filter((_, el) => $(el).text() === directive) + .addClass('spec-directive') + .addClass(`spec-${directive.split(' ')[0].split('\n')[0]}`); + } + + // Make "reviewing sections" of approved AIPs show a badge. + let reviewing = $('h3 + p').filter((_, el) => $(el).text() === '[^reviewing]'); + reviewing.prev('h3').addClass('reviewing'); + reviewing.remove(); + + // Make AIP banners appear in a better spot. + $('#aip-state-banner').insertAfter('#aip-main h1'); + + // Control the maximum height of the nav sidebar. + $(window) + .on('resize', () => { + $('nav.docs-component-nav').css({ + maxHeight: `${$(window).height() - 110}px`, + }); + }) + .resize(); +}); diff --git a/assets/js/graphviz/lite.render.js b/assets/js/graphviz/lite.render.js new file mode 100644 index 0000000000..c027a6a561 --- /dev/null +++ b/assets/js/graphviz/lite.render.js @@ -0,0 +1,90 @@ +/* +Viz.js 2.1.2 (Graphviz 2.40.1, Emscripten 1.37.36) +*/ +(function(global) { +var Module = function(Module) { + Module = Module || {}; +var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}Module["arguments"]=[];Module["thisProgram"]="./this.program";Module["quit"]=(function(status,toThrow){throw toThrow});Module["preRun"]=[];Module["postRun"]=[];var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module["ENVIRONMENT"]){if(Module["ENVIRONMENT"]==="WEB"){ENVIRONMENT_IS_WEB=true}else if(Module["ENVIRONMENT"]==="WORKER"){ENVIRONMENT_IS_WORKER=true}else if(Module["ENVIRONMENT"]==="NODE"){ENVIRONMENT_IS_NODE=true}else if(Module["ENVIRONMENT"]==="SHELL"){ENVIRONMENT_IS_SHELL=true}else{throw new Error("Module['ENVIRONMENT'] value is not valid. must be one of: WEB|WORKER|NODE|SHELL.")}}else{ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER}if(ENVIRONMENT_IS_NODE){var nodeFS;var nodePath;Module["read"]=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};Module["readBinary"]=function readBinary(filename){var ret=Module["read"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));process["on"]("unhandledRejection",(function(reason,p){process["exit"](1)}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){Module["read"]=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}Module["readBinary"]=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof quit==="function"){Module["quit"]=(function(status,toThrow){quit(status)})}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){Module["readBinary"]=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}Module["readAsync"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};if(typeof arguments!="undefined"){Module["arguments"]=arguments}Module["setWindowTitle"]=(function(title){document.title=title})}Module["print"]=typeof console!=="undefined"?console.log.bind(console):typeof print!=="undefined"?print:null;Module["printErr"]=typeof printErr!=="undefined"?printErr:typeof console!=="undefined"&&console.warn.bind(console)||Module["print"];Module.print=Module["print"];Module.printErr=Module["printErr"];for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var STACK_ALIGN=16;function staticAlloc(size){assert(!staticSealed);var ret=STATICTOP;STATICTOP=STATICTOP+size+15&-16;return ret}function dynamicAlloc(size){assert(DYNAMICTOP_PTR);var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}function alignMemory(size,factor){if(!factor)factor=STACK_ALIGN;var ret=size=Math.ceil(size/factor)*factor;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;Module.printErr(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var GLOBAL_BASE=8;var ABORT=0;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}var JSfuncs={"stackSave":(function(){stackSave()}),"stackRestore":(function(){stackRestore()}),"arrayToC":(function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};function ccall(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}var ALLOC_STATIC=2;var ALLOC_NONE=4;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[typeof _malloc==="function"?_malloc:staticAlloc,stackAlloc,staticAlloc,dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var stop;ptr=ret;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr>2]=0}stop=ret+size;while(ptr>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return UTF8ToString(ptr)}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function demangle(func){return func}function demangleAll(text){var regex=/__Z[\w\d_]+/g;return text.replace(regex,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}var PAGE_SIZE=16384;var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module["HEAP8"]=HEAP8=new Int8Array(buffer);Module["HEAP16"]=HEAP16=new Int16Array(buffer);Module["HEAP32"]=HEAP32=new Int32Array(buffer);Module["HEAPU8"]=HEAPU8=new Uint8Array(buffer);Module["HEAPU16"]=HEAPU16=new Uint16Array(buffer);Module["HEAPU32"]=HEAPU32=new Uint32Array(buffer);Module["HEAPF32"]=HEAPF32=new Float32Array(buffer);Module["HEAPF64"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(TOTAL_MEMORY0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];if(!Math["trunc"])Math["trunc"]=(function(x){return x<0?Math.ceil(x):Math.floor(x)});Math.trunc=Math["trunc"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_round=Math.round;var Math_min=Math.min;var Math_max=Math.max;var Math_clz32=Math.clz32;var Math_trunc=Math.trunc;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var ASM_CONSTS=[(function($0,$1){var path=Pointer_stringify($0);var data=Pointer_stringify($1);FS.createPath("/",PATH.dirname(path));FS.writeFile(PATH.join("/",path),data)})];function _emscripten_asm_const_iii(code,a0,a1){return ASM_CONSTS[code](a0,a1)}STATIC_BASE=GLOBAL_BASE;STATICTOP=STATIC_BASE+176368;__ATINIT__.push();memoryInitializer="data:application/octet-stream;base64,AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/ACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAIMEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSQAAAAAAAAFJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkAAIMEAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSQAAAAAAAAFJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkACEAAAAAAAAAAAAAAAABBAWC8AAAgAAAABAAAAAAAAAAIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICWQAAAAAAAgJZABJDDAAAAAAAAAAAAAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWEAAAAAAAABYQAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYQAAAAAAAAFhAAAAAAAAAAAAAAAAAAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUkAAAAAAAABSQAAgAwIAAAAAAAAAAAAAEEAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAABCQAAAAAAAAEJAAAAAAAAgg0AAAAAAAMCIQAAAAAAAAFJAAAAAAAAAUkAAAAAAAAAAAAAAAAAAAEJAAAAAAAAAQkAAAAAAACCDQAAAAAAAwIhAAAAAAAAAUkAAAAAAAABSQACwwQAAAAAAAAAAAAAAEED4NQAAkwAAAAEAAAAAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkAAEAACAAAAAAAAAAAAABBAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYQAAAAAAAAFhAALDBAAAAAAAAAAAAAAAAANQ5AAAQAAAAAQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWEAAAAAAAABYQEAgPgMAAAAAAAAAAAAAEEDcOgAAegAAAAEAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSQAAAAAAAAFJAAQAAAAAAAAABAAAAAAAAAAAAAAAAAPA/AQAAAAAAAAACAAAAAAAAAAAAAAAAAPA/AgAAAAAAAAADAAAAAAAAAAAAAAAAAOA/AwAAAAAAAAAEAAAAAAAAAAAAAAAAAPA/BAAAAAAAAAAFAAAAAAAAADMzMzMzM/M/BQAAAAAAAAAGAAAAAAAAAJqZmZmZmek/BgAAAAAAAAAHAAAAAAAAAAAAAAAAAPA/BwAAAAAAAAAIAAAAAAAAAAAAAAAAAOA/CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAzMzMzMzPTvwAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAACARkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAACamZmZmZnZvwAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMzMzM+M/AAAAAAAAAAAAAAAAAQAAAAUAAAAAAAAAAAAAAAAAAAB7FK5H4XrkvwAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAQAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiRSAAABAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAACAZkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAACAZkCamZmZmZnZvwAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAAAAAAAAAAAAACAZkB7FK5H4XrkvwAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAACARkAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAABAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFQAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAAAAAAAAAAQAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8L8AAAAAAAABAAAAAAAAAAAAAAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/WKg1zTtO1T8ldQKaCBvaPwAAAAAAAOA/AAAAAAAA4D8s1JrmHafqP2recYqO5Og/WKg1zTtO1T9YqDXNO07VP1ioNc07TtU/AAAAAAAA4D9d3EYDeAviPwAAAAAAANA/WKg1zTtO1T8AAAAAAADQP9O84xQdydE/AAAAAAAA4D8AAAAAAADgPwAAAAAAAOA/AAAAAAAA4D8AAAAAAADgPwAAAAAAAOA/AAAAAAAA4D8AAAAAAADgPwAAAAAAAOA/AAAAAAAA4D/TvOMUHcnRP9O84xQdydE/XdxGA3gL4j9d3EYDeAviP13cRgN4C+I/DXGsi9to3D9kXdxGA3jtP9JvXwfOGec/EHo2qz5X5T8QejarPlflP9JvXwfOGec/eAskKH6M4z+1FfvL7snhP9JvXwfOGec/0m9fB84Z5z9YqDXNO07VP4iFWtO849g/0m9fB84Z5z94CyQofozjP8RCrWnecew/0m9fB84Z5z/Sb18HzhnnP7UV+8vuyeE/0m9fB84Z5z8QejarPlflP7UV+8vuyeE/eAskKH6M4z/Sb18HzhnnP9JvXwfOGec/hjjWxW007j/Sb18HzhnnP9JvXwfOGec/eAskKH6M4z9YqDXNO07VP9O84xQdydE/WKg1zTtO1T+mCkYldQLePwAAAAAAAOA/WKg1zTtO1T8NcayL22jcPwAAAAAAAOA/DXGsi9to3D8AAAAAAADgPw1xrIvbaNw/WKg1zTtO1T8AAAAAAADgPwAAAAAAAOA/07zjFB3J0T/TvOMUHcnRPwAAAAAAAOA/07zjFB3J0T9q3nGKjuToPwAAAAAAAOA/AAAAAAAA4D8AAAAAAADgPwAAAAAAAOA/WKg1zTtO1T+IhVrTvOPYP9O84xQdydE/AAAAAAAA4D8AAAAAAADgP9JvXwfOGec/AAAAAAAA4D8AAAAAAADgPw1xrIvbaNw/9GxWfa623j8RNjy9UpbJP/RsVn2utt4/OwFNhA1P4T8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQP1ioNc07TtU/AAAAAAAA4D8AAAAAAADgPz7o2az6XMU/AAAAAAAA4D8AAAAAAADgPwAAAAAAAOA/AAAAAAAA4D+Cc0aU9gbHPw1xrIvbaNw/AAAAAAAA4D9YqDXNO07VP1ioNc07TtU/tRX7y+7J4T+1FfvL7snhPwAAAAAAANA/AAAAAAAA4D8AAAAAAADgPwAAAAAAAOA/AAAAAAAA0D8AAAAAAADQPwfwFkhQ/Nw/orQ3+MJk1j9YqDXNO07VPw1xrIvbaNw/DXGsi9to3D8AAAAAAADgPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADQPw1xrIvbaNw/AAAAAAAA0D9YqDXNO07VP1ioNc07TtU/WKg1zTtO1T9YqDXNO07VP1ioNc07TtU/WKg1zTtO1T9YqDXNO07VP1ioNc07TtU/AAAAAAAA0D9YqDXNO07VP1ioNc07TtU/AAAAAAAA0D9YqDXNO07VP1ioNc07TtU/WKg1zTtO1T8AAAAAAADwPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/xEKtad5x7D8AAAAAAADQP3/ZPXlYqNE/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D94CyQofozjP9JvXwfOGec/xEKtad5x7D8T8kHPZtXTPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8QejarPlflPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQP9O84xQdydE/AAAAAAAA0D8AAAAAAADQP9O84xQdydE/AAAAAAAA4D/Sb18HzhnnPwAAAAAAAOA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/9GxWfa621j+1FfvL7snhP7UV+8vuyeE/xEKtad5x7D8QejarPlflP/Xb14FzRsw/WKg1zTtO1T9YqDXNO07VP4iFWtO849g/AU2EDU+v4j/TvOMUHcnRP1ioNc07TtU/07zjFB3J0T/TvOMUHcnRP7UV+8vuyeE/tRX7y+7J4T+1FfvL7snhP7UV+8vuyeE/tRX7y+7J4T+1FfvL7snhP7UV+8vuyeE/tRX7y+7J4T+1FfvL7snhP7UV+8vuyeE/07zjFB3J0T/TvOMUHcnRPwFNhA1Pr+I/AU2EDU+v4j8BTYQNT6/iP7UV+8vuyeE/zF1LyAc98D8QejarPlflPxB6Nqs+V+U/0m9fB84Z5z/Sb18HzhnnPxB6Nqs+V+U/eAskKH6M4z9q3nGKjuToP9JvXwfOGec/07zjFB3J0T8AAAAAAADgPxB6Nqs+V+U/tRX7y+7J4T8s1JrmHafqP9JvXwfOGec/at5xio7k6D8QejarPlflP2recYqO5Og/0m9fB84Z5z8QejarPlflP3gLJCh+jOM/0m9fB84Z5z8QejarPlflP4Y41sVtNO4/EHo2qz5X5T8QejarPlflP3gLJCh+jOM/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/pgpGJXUC3j+1FfvL7snhP0i/fR04Z8w/tRX7y+7J4T+1FfvL7snhPwAAAAAAAOA/tRX7y+7J4T+1FfvL7snhP9O84xQdydE/tRX7y+7J4T+1FfvL7snhP0i/fR04Z8w/SL99HThnzD8AAAAAAADgP0i/fR04Z8w/LNSa5h2n6j+1FfvL7snhP7UV+8vuyeE/tRX7y+7J4T+1FfvL7snhP1ioNc07TtU/AAAAAAAA4D/TvOMUHcnRP7UV+8vuyeE/AAAAAAAA4D/Sb18HzhnnPwAAAAAAAOA/AAAAAAAA4D8AAAAAAADgPwKaCBueXtU/4L4OnDOi0D8Cmggbnl7VPwFNhA1Pr+I/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T9YqDXNO07VP7UV+8vuyeE/tRX7y+7J4T8+6Nms+lzFP7UV+8vuyeE/tRX7y+7J4T+1FfvL7snhP7UV+8vuyeE/HThnRGlvyD9YqDXNO07VP7UV+8vuyeE/WKg1zTtO1T9YqDXNO07VPwAAAAAAAOA/AAAAAAAA4D/TvOMUHcnRP7UV+8vuyeE/tRX7y+7J4T+1FfvL7snhP9O84xQdydE/07zjFB3J0T/nHafoSC7hP6K0N/jCZNY/SL99HThnzD9YqDXNO07VP1ioNc07TtU/tRX7y+7J4T8AAAAAAADwPwAAAAAAAPA/07zjFB3J0T94CyQofozjP9O84xQdydE/WKg1zTtO1T9YqDXNO07VP1ioNc07TtU/WKg1zTtO1T9YqDXNO07VP1ioNc07TtU/WKg1zTtO1T9YqDXNO07VP9O84xQdydE/WKg1zTtO1T9YqDXNO07VP9O84xQdydE/WKg1zTtO1T9YqDXNO07VP1ioNc07TtU/AAAAAAAA8D/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRPwAAAAAAAPA/07zjFB3J0T/qlbIMcazXP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/tRX7y+7J4T9q3nGKjuToPwAAAAAAAPA/mN2Th4Va1z/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/xEKtad5x7D/TvOMUHcnRP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/07zjFB3J0T9Iv30dOGfMP3gLJCh+jOM/hjjWxW007j94CyQofozjP9O84xQdydE/07zjFB3J0T/TvOMUHcnRP9O84xQdydE/UaBP5EnSDkC0yHa+nzo1wDoi36XUJdW/84I+R5ouij+f5Xlwd9b5v379EBssnOY/luzYCMTrzD/NzqJ3KuDQP7Djv0AQIO2/raHUXkTb2D87oXzmUZZ2P9NucPl6hHs/gczOoncq5L/Rrdf0oKDIP2rfNxmwP4Q/vsqQGV7/hD8clgZ+VMPEv6VJKej24iNAqdkDrcCQwT8IxJBBk2mJP/pEniRdM9C/AfCZNi3CXj8NnH0vz5SXP4m1+BQA44k/5alYRjTLsb+PAMnPoWemv1y1xvvMtIg/TaSPVDqzkD/mxwShYdagv8dpZxwT94K/Kn9r5S1wXL/kV2JUCJp1P9Hxh1VyBLc/ldQJaCI8M8BkIxCv63cQwKchqvBneMc/2v8Aa9WuwT9OKETAIVT3v6pIhbGFIPU/nWhXIeUn9j9NLsbAOo7NP1lrKLUX0dy/Az+qYb8nzD+mR1M9mX/aP7aBO1CnPK4/UUzeADPfub/1dpX/2gumP9SlNbwP9pQ/H60gvCzckD8oLPGAsskjQCNa4UwCirc/SKNlUZYpfz+7tIb3wZ6TPxeoe1NHfaC/ISuu4G2Uiz8zc9yE1h61v6B4hIn1/I8/aTUk7rH0kb+4zTN6Xr9qP5I+raI/NM2/frDnxk8+mL8HI5tQLcekPz4YwntYuZG/LXx9rUuNxj8AAABA+yH5PwAAAAAtRHQ+AAAAgJhG+DwAAABgUcx4OwAAAICDG/A5AAAAQCAlejgAAACAIoLjNgAAAAAd82k1tOgAAKAqAAADAAAAyCwAAAMAAACgLwAAAwAAAGgwAAADAAAAuDEAAAMAAAAwNQAAAwAAAGw4AAADAAAAfC4AAAMAAAA0OQAAAwAAADw6AAADAAAAyD4AAAMAAADsPAAAAAAAAIwsAAAAAAAAeC8AAAAAAADILwAAAAAAAJAxAAAAAAAA4DEAAAAAAABEOAAAAAAAABguAAAAAAAADDkAAAAAAAAUOgAAAAAAAKA+AAAAAAAAxDwAAAQAAADwPgAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAACAAAAAQAAAAEAAAADAAAAAAAAAAAAAADQjQIA4I0CAPCNAgAAjgIAEI4CACCOAgAwjgIAQI4CAOCNAgDgjQIAII4CACCOAgAfAAAAPwAAAH8AAAAAAAAAHUsBAAEAAABgKwAAaAAAAAQAAADW7AAAAQAAANgrAACIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbukAAAEAAAAAAAAA4AAAAAAAAAB26QAAAQAAAAAAAADgAAAAAQAAAH3pAAABAAAAAAAAAKgAAAACAAAAh+kAAAEAAAAAAAAA4AAAAAMAAACR6QAAAQAAAAAAAADgAAAABAAAAJ/pAAABAAAAAAAAAOAAAAAFAAAAqekAAAEAAAAAAAAA4AAAAAYAAAC26QAAAQAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAA/////wAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2+wAAAEAAAB8LQAAGAEAAAEAAADg7AAAAQAAAHwtAAAYAQAAAgAAAObsAAABAAAAfC0AABgBAAADAAAA7+wAAAEAAAB8LQAAGAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPnsAAABAAAAAAAAAHABAAABAAAAA+0AAAEAAAAAAAAAcAEAAAIAAAAO7QAAAQAAAAAAAAA4AQAAAwAAABztAAABAAAAAAAAADgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAkAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAwAAAANAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQAAAAYAAAACAAAAAgAAAAcAAAACAAAAAAAAAPrcAQD/xQEAkMcBANDNAQDH1AEABtkBAIbcAQCX3AEAAAAAAGPtAAABAAAA4C4AAKgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABn7QAAAQAAAAAAAADIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAb+0AAAEAAADwLwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAKfuAAABAAAAAAAAACACAAACAAAAse4AAAEAAAAAAAAAWAIAAAAAAAC67gAAAQAAAAAAAABYAgAAAwAAAMPuAAABAAAAAAAAAFgCAAAAAAAAze4AAAEAAAAAAAAAIAIAAAMAAADZ7gAAAQAAAAAAAAAgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAASAAAAAAAAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAVAAAAFgAAABcAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAMAAAAJAAAAAwAAAAMAAAAKAAAABAAAAAAAAAD63AEA/8UBANDNAQCQxwEABtkBAMfUAQCX3AEAhtwBAAAAAAAAAAAAlvAAAP/////0MAAAkAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJnwAAD/////AAAAALACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcUwEAAQAAAAgyAADoAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGQAAABoAAAAAAAAABAAAAAAAAAAbAAAAHAAAAB0AAAAeAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAgAAAAIQAAACIAAAACAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAMAAAABQAAAAQAAAANAAAABQAAAAMAAACW9AAApPQAALr0AABpqAIAyPQAANf0AADc9AAA+vQAAGmoAgAM9QAAPPUAAGmoAgBa9QAAgvUAAJD1AAC/9QAA8/UAAAT2AAAp9gAATPYAAFL2AABu9gAAi/YAAKb2AADH9gAA4fYAAAP3AAAi9wAASPcAAGD3AACA9wAAnfcAAMH3AADN9wAAaagCANj3AAD+9wAAIvgAAEj4AABpqAIAfvgAAJb4AACj+AAA0vgAAM33AABpqAIA3/gAAOj4AAAJ+QAARPkAAI/5AADj+QAABfoAABr6AAAx+gAAR/oAAF/6AABpqAIAdfoAAJD6AAC0+gAA2PoAAP36AABpqAIAHvsAADj7AABK+wAAV/sAAGT7AAB4+wAAh/sAAI/7AACk+wAAsvsAAPD7AAD7+wAAzfcAAGmoAgAB/AAADfwAABz8AABM9gAAaagCAC/8AABY/AAAdvwAAIb8AACX/AAAnvwAAK38AAC9/AAAAf0AAAj9AABM9gAAaagCABL9AAA+/QAASf0AAFL9AABb/QAAbP0AAH39AACR/QAAzfcAAGmoAgCd/QAArf0AALv9AADJ/QAA1v0AAOP9AAD5/QAAAv4AABH+AAAe/gAAL/4AAM33AABpqAIAOv4AAFn+AABpqAIAa/4AAHr+AACq/gAAtP4AAMH+AADO/gAA2/4AAOj+AADr/gAAaagCAO/+AABpqAIAEv8AAEP/AABy/wAAif8AAKT/AAC//wAAzfcAAGmoAgDb/wAAaagCAAMAAQAPAAEAIgABADUAAQBKAAEAXwABAGMAAQBM9gAAaagCAG8AAQBpqAIAfwABAI0AAQCZAAEApgABAMYAAQDcAAEAaagCAPAAAQA5AQEAfwEBAK8BAQDiAQEA6QEBABACAQA3AgEAaagCADwCAQAAAAAAAAAAAPorAQABAAAAAAAAAAgDAAABAAAAsAIBAAEAAAAAAAAACAMAAAIAAADzKwEAAQAAAAAAAABAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjAAAAAAAAACQAAAAlAAAABgAAACYAAAAnAAAAKAAAACkAAAAqAAAAAAAAAAAAAAAAAAAAAAAAACsAAAAsAAAALQAAAC4AAAAEAAAALwAAAAAAAAAAAAAADgAAAAAAAAAPAAAABwAAAAUAAAAQAAAABgAAAAAAAAAXxQEAIcUBAHoVAQBmxQEAocUBAMPFAQDJxQEA+twBAPDFAQD/xQEAHMYBACfGAQBJxgEAf8YBALXGAQDwxgEAJscBAEjHAQBXxwEAiMcBAJDHAQBACQEASQkBAK3HAQBSCQEA98cBAFsJAQAByAEAZAkBAAvIAQBayAEAlcgBAHAJAQDQyAEA28gBACDJAQAuyQEAeMkBAIbJAQCUyQEAn8kBANDJAQAQygEAGMoBACDKAQBbygEAkcoBAJ3KAQB/FQEAqcoBALPKAQC+ygEA28oBABHLAQDQzQEA8s0BAP7NAQC90AEA7tABABrRAQBQ0QEAXdEBAH/RAQCh0QEAqtEBAPTRAQD+0QEAQ9IBAHnSAQCE0gEACdMBAB7TAQB4CQEAKNMBADLTAQBo0wEAqNMBALbTAQAK1AEAGdQBACjUAQB31AEAhxUBALfUAQDB1AEAx9QBAPPUAQAa1QEAK9UBADbVAQB71QEAwNUBAM/VAQDf1QEA8dUBAAHWAQAR1gEAHtYBACjWAQBe1gEAZ9YBAKfWAQC61gEAjBUBAMLWAQD41gEAH9cBAFXXAQB81wEAitcBAMDXAQAK2AEAVNgBAF/YAQCV2AEAmtgBALfYAQDU2AEA39gBAAbZAQAe2QEAVNkBAIrZAQCW2QEAvdkBAMjZAQD52QEAKtoBAHkgAQBR2gEAfdoBALPaAQDp2gEA89oBABDbAQBQ2wEAhtsBAJIVAQCe2wEAytsBAPHbAQAn3AEAZNwBAIbcAQCM3AEAl9wBAL7cAQAAAAAAX1MBAAEAAACANQAAeAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANEsAQABAAAAAAAAAJgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgAAAAAAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAABIAAAAIAAAABgAAABMAAAAHAAAAAAAAAAAAAACuCgEAAQAAAJQ4AADQAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsQoBAAEAAAAAAAAA8AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAAAAAAAA1AAAANgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAADcAAAAAAAAAAAAAABQAAAAAAAAAFQAAAAkAAAAHAAAAFgAAAAgAAAAAAAAAehUBAPrcAQD/xQEAfxUBABHLAQDQzQEAhxUBAPPUAQCn1gEAjBUBAN/YAQAG2QEAeSABAJIVAQCG3AEAl9wBAAAAAACXFQEAAQAAAFw5AAAoBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmxUBAAEAAAAAAAAASAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAA5AAAAOgAAAAoAAAA7AAAAPAAAAD0AAAA+AAAAPwAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQQAAAEIAAABDAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAGAAAAAsAAAAIAAAAGQAAAAkAAAAAAAAAZsUBAA8fAQD63AEA/8UBABzGAQAaHwEAIB8BACsfAQAyHwEAJ8YBAH/GAQA6HwEAQB8BAEsfAQAmxwEASMcBAJDHAQBSHwEA98cBAAvIAQCVyAEAXB8BACDJAQAuyQEAeMkBAGcfAQCGyQEAbx8BAHgfAQCGHwEAkB8BAFvKAQCZHwEAncoBAL7KAQDbygEAnx8BACLLAQBNywEAdssBAJnLAQDCywEA5csBAA7MAQAxzAEAWswBAH3MAQCmzAEAycwBAPLMAQAVzQEAPs0BAGHNAQCKzQEArc0BANDNAQCmHwEA8s0BALIfAQAa0QEAf9EBAEPSAQC/HwEAKNQBAMwfAQC31AEAx9QBANYfAQDz1AEAGtUBACvVAQDlHwEA9x8BADbVAQDA1QEAz9UBAN/VAQDx1QEAAdYBAAcgAQASIAEAHSABABHWAQCn1gEArNYBACIgAQArIAEANCABAEQgAQBLIAEA+NYBAB/XAQBV1wEAitcBAJrYAQC32AEAUyABAAbZAQBaIAEAltkBAGMgAQDI2QEAayABACraAQB5IAEAUdoBAH3aAQCAIAEAENsBAFDbAQCKIAEAhtsBAJ7bAQDx2wEAlCABAKIgAQAn3AEALtwBAGTcAQCG3AEAl9wBAL7cAQAAAAAAtCABAAEAAABkOgAAgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALggAQABAAAAAAAAAKAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEUAAAAAAAAAAAAAAEYAAABHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAABsAAAAMAAAACQAAABwAAAAKAAAAAAAAAEFCAABEZwEAQUkAAB5nAQBBUgAA8WYBAEFYAABZZwEAQiAAAJVpAQBCSQAApmkBAENCAADeZwEAQ08AAMxnAQBDWAAA62cBAEggAAAPaAEASEIAABloAQBISQAApWgBAEhYAAAoaAEASGIAAFloAQBIaQAAjGgBAEhyAAA+aAEASHgAAG9oAQBJIAAAt2kBAEtCAABwZwEAS0kAALhnAQBLUgAApGcBAEtYAACRZwEATkIAALdoAQBOSQAA/mgBAE5SAAAWaQEATlgAAOJoAQBQQQAAd2kBAFBCAAAzaQEAUEkAAGdpAQBQWAAAU2kBAFIgAABjawEAUyAAAIZpAQBaRAAA9GkBAAAAAAAAAAAAAQAAAAAAAABnKwEA/////xQ9AADYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaysBAP////8AAAAA+AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAHMrAQABAAAA2EIAAAAAAAAQAAAAeysBAAEAAADYQgAAAAAAABEAAACDKwEAAQAAANhCAAAAAAAAEQAAAIwrAQABAAAA2EIAAAAAAAARAAAAlCsBAAEAAADYQgAAAAAAABMAAACcKwEAAQAAANxCAAAAAAAAFAAAAKQrAQABAAAA3EIAAAAAAAAVAAAArCsBAAEAAADcQgAAAAAAABUAAAC1KwEAAQAAANxCAAAAAAAAFQAAAL0rAQABAAAA3EIAAAAAAAAWAAAAxSsBAAEAAADgQgAAAAAAABcAAADOKwEAAQAAAOBCAAAAAAAAGAAAANcrAQABAAAA4EIAAAAAAAAYAAAA4SsBAAEAAADgQgAAAAAAABgAAADqKwEAAQAAAOBCAAAAAAAAGQAAAPMrAQABAAAA5EIAAAAAAAAZAAAA+isBAAEAAADkQgAAAAAAABoAAAAALAEAAQAAAOhCAAAAAAAACgAAAAksAQABAAAA7EIAAAAAAAALAAAAESwBAAEAAADsQgAAAAAAAAwAAAAZLAEAAQAAAOxCAAAAAAAADAAAACIsAQABAAAA7EIAAAAAAAAMAAAAKiwBAAEAAADsQgAAAAAAAA4AAAAyLAEAAQAAAOxCAAAAAAAADgAAADksAQABAAAA7EIAAAAAAAANAAAAQSwBAAEAAADsQgAAAAAAAAUAAABJLAEAAQAAAOxCAAAAAAAABgAAAFEsAQABAAAA7EIAAAAAAAAHAAAAWSwBAAEAAADsQgAAAAAAAAcAAABiLAEAAQAAAOxCAAAAAAAABwAAAGosAQABAAAA7EIAAAAAAAAJAAAAciwBAAEAAADsQgAAAAAAAAkAAAB5LAEAAQAAAOxCAAAAAAAACAAAAIEsAQABAAAA7EIAAAAAAAAAAAAAiSwBAAEAAADwQgAAAAAAAAEAAACSLAEAAQAAAPBCAAAAAAAAAgAAAJssAQABAAAA8EIAAAAAAAACAAAApSwBAAEAAADwQgAAAAAAAAIAAACuLAEAAQAAAPBCAAAAAAAABAAAALcsAQABAAAA8EIAAAAAAAAEAAAAvywBAAEAAADwQgAAAAAAAAMAAADILAEAAQAAAPBCAAAAAAAAEgAAANEsAQABAAAA2EIAAAAAAAAbAAAA2SwBAAEAAAD0QgAAAAAAABwAAADhLAEAAQAAAPRCAAAAAAAAHQAAAOksAQABAAAA9EIAAAAAAAAdAAAA8iwBAAEAAAD0QgAAAAAAAB0AAAD6LAEAAQAAAPRCAAAAAAAAHgAAAAItAQABAAAA+EIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAAFQAAAG0wAQAEQwAAAQAAACBDAAAAAAAAAAAAAEgAAABJAAAAAQAAAAAAAAAdSwEAAAAAABRDAAAcQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAAAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAABAAAAAgAAAAQAAAAYAQAAMAEAALAAAACXOAEAnDgBAKA4AQCnOAEAqzgBAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAAAAAAdAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAfAAAAAAAAAAAAAAABAAAAQAAAANhDAADoQwAAAgAAAAQAAAD0QwAAAgAAAAgAAAACAAAABAAAAPxDAAAABAAACAAAAP////8AAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAANQAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAwAAAAAAAAACAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAwAAAAAAAAACAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAkAAAALAAAACAAAAAoAAACARQAABEUAAGhFAAABAAAAAQAAAAUAAAAWAAAABgAAAEoAAAAhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAIAAAAAAAAAAIAAAAAAAAAAwAAAAIAAAADAAAABAAAAAAAAAAAAAAABAAAAAMAAAAJAAAACwAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAoAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIgAAAAsAAAAAAAAAAgAAAAAAAAAIAAAACAAAAAAAAAAAAAAAIwAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA/////wAAAAAAAAAAJAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAgAAAAMAAAABAAAAAQAAAAIAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAQAAAAQAAAAFAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAABgAAAAEAAAABAAAABwAAAAgAAAAJAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAEAAAABAAAACwAAAAEAAAAMAAAAAQAAAA0AAAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAATAAAAEwAAABMAAAATAAAAFwAAABgAAAAZAAAAEwAAABoAAAAbAAAAHAAAAB0AAAATAAAAEwAAABMAAAATAAAAEwAAAAEAAAAeAAAAAQAAAAEAAAATAAAAAQAAAB8AAAAgAAAAIQAAACIAAAAjAAAAEwAAACQAAAAlAAAAJgAAABMAAAATAAAAEwAAABMAAAAnAAAAKAAAACkAAAATAAAAKgAAACsAAAAsAAAALQAAABMAAAATAAAAEwAAABMAAAATAAAAAQAAAAEAAAABAAAAAQAAAAEAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAAC4AAAATAAAAEwAAABMAAAAvAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAwAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAAAAAAAABAAAAAQAAAAIAAAADAAAAAQAAAAQAAAABAAAABQAAAAEAAAAGAAAABwAAAAcAAAABAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAMAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAACAAAAAEXgBAO13AQBjQQEAHngBABZ4AQAkeAEAAAAAAGlFAQByRQEAeUUBAIdFAQCORQEAOngBAJVFAQCcRQEAAQAAAAgAAAD/////AAAAAAAAAAAlAAAAAAAAAAAAAAAAAAAAAAAAADpHAQAIAAAAAwAAAENHAQBHRwEACwAAAAYAAABcUwEAU0cBAAIAAAABAAAAVkcBAFpHAQAEAAAAAgAAAF9HAQBjRwEABAAAAAQAAABoRwEAbUcBAAUAAAAFAAAAc0cBAHdHAQAEAAAABwAAAHxHAQCARwEABQAAAAkAAACGRwEAikcBAAQAAAAKAAAAj0cBAJRHAQAEAAAADAAAAJlHAQBaTAEAAAAAAAEAAABiTAEAAQAAAAAAAAA4dwEAAQAAAAEAAAC11gEAAAAAAAAAAAAAAAAAAAAAAAAAAABGSwEAMQAAAAAAAAAAAAAAWXIBABAAAADw4gEAgAAAAD9LAQBAAAAAomUBABAAAABBSwEAQAAAAAAAAAAAAAAADUsBAAEAAAAUSwEAAgAAABlLAQADAAAAiWIBAAQAAADEYgEABQAAAB1LAQAGAAAAtdYBAAgAAAAhSwEAIQAAACVLAQAiAAAAKUsBACIAAAAtSwEAAQAAADJLAQAHAAAAOEsBACcAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAP////8AAAAAJgAAAAAAAAAAAAAAAAAAAAAAAACEUAEAi1ABAAAAAABZUwEAXFMBAF9TAQAAAAAAAAAAAAEAAAACAAAA/////xxTAQAiUwEAtdYBAAAAAABkAAAAZQAAAGYAAABkAAAACAAAAAgAAAAAAAAAAAAAACcAAAAMAAAAAAAAAAAAAAAAAAAACAAAAP////8AAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAiWIBAIxRAABABgAAAAAAAI1iAQCMUQAAcAYAAAAAAABbawEAjFEAAKAGAAAAAAAAlWIBAIxRAACgBgAAAAAAAJpiAQCMUQAA0AYAAAAAAAChYgEApFEAANAGAAAAAAAAp2IBAIxRAAAABwAAAAAAAKtiAQCMUQAAMAcAAAAAAAC11gEAjFEAAGAHAAAAAAAAtGIBAIxRAABgBwAAAAAAAL5iAQCMUQAAEAYAAAAAAADEYgEAjFEAAJAHAAAAAAAAzGIBAIxRAADABwAAAAAAANZiAQCMUQAA8AcAAAAAAADkYgEAjFEAACAIAAAAAAAA6mIBAIxRAABQCAAAAAAAAPNiAQCMUQAAgAgAAAAAAAD7YgEAjFEAALAIAAAAAAAABGMBAIxRAADgCAAAAAAAAAxjAQCMUQAAEAkAAAAAAAARYwEAjFEAAEAJAAAAAAAAFWMBAIxRAABwCQAAAAAAABxjAQCMUQAAoAkAAAAAAAAiYwEAjFEAANAJAAAAAAAALGMBALxRAAAACgAAAAAAADVjAQCMUQAAQAYAAAAAAAA6YwEAjFEAAEAGAAAAAAAARGMBAIxRAAAwCgAAAAAAAEtjAQCMUQAAYAoAAAAAAABYYwEAjFEAAJAKAAAAAAAAZmMBAIxRAADACgAAAAAAAHRjAQCMUQAA8AoAAAAAAACAYwEAjFEAACALAAAAAAAAjWMBAIxRAABQCwAAAAAAAJZjAQCMUQAAgAsAAAAAAACgYwEAjFEAALALAAAAAAAAqWMBAIxRAADgCwAAAAAAALFjAQCMUQAAEAwAAAAAAAC5YwEAjFEAAEAMAAAAAAAAwmMBAIxRAABwDAAAAAAAAMZjAQCMUQAAoAwAAAAAAADRYwEAjFEAANAMAAAAAAAA1WMBAIxRAAAADQAAAAAAAN9jAQCMUQAAMA0AAAAAAADoYwEAjFEAAGANAAAAAAAA8GMBAIxRAACQDQAAAAAAAP1jAQCMUQAAwA0AAAAAAAAJZAEAjFEAAPANAAAAAAAAFGQBAIxRAAAgDgAAAAAAACRkAQCMUQAAUA4AAAAAAAAyZAEAjFEAAIAOAAAAAAAAQWQBAIxRAACwDgAAAAAAAEtkAQCMUQAA4A4AAAAAAABUZAEAjFEAABAPAAAAAAAAXmQBAIxRAABADwAAAAAAAGhkAQCMUQAAcA8AAAAAAABvZAEAjFEAAKAPAAAAAAAAdmQBAIxRAADQDwAAAAAAAIBkAQDUUQAAAAAAAAAAAACHZAEA1FEAAAAAAAAAAAAAZWIBAOxRAAAAAAAAAAAAAI9kAQAEUgAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASwAAAEwAAAAXAAAABAAAAAIAAAAMAAAATQAAAEwAAAAXAAAABQAAAAAAAAANAAAASwAAAEwAAAAXAAAABAAAAAIAAAAMAAAATgAAAE8AAAAYAAAABgAAAAMAAAAOAAAAUAAAAFEAAAAXAAAABwAAAAAAAAAPAAAASwAAAEwAAAAXAAAACAAAAAIAAAAMAAAAEAAAABEAAAASAAAAEwAAAJFlAQCYZQEAAAAAAKBlAQCiZQEAKuMBAKRlAQAMAAAABAAAAAYAAAACAAAAAwAAAAEAAAAJAAAACAAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAABEAAAASAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAGwAAABwAAAAfAAAAIAAAACEAAAAiAAAAIwAAACQAAAAlAAAAJgAAACkAAAAqAAAAKwAAACwAAAAtAAAALgAAAC8AAAAwAAAAMwAAADQAAAA1AAAANgAAADcAAAA4AAAAOQAAADoAAAA9AAAAPgAAAD8AAABAAAAAQQAAAEIAAABDAAAARAAAAEcAAABIAAAASQAAAEoAAABLAAAATAAAAE0AAABOAAAAUQAAAFIAAABTAAAAVAAAAFUAAABWAAAAVwAAAFgAAADxZgEAAWcBAA5nAQAAAAAAAAAAAAQAAAATZwEAAAAAAAAAAAAeZwEAAWcBAA5nAQAAAAAANWcBAAUAAAATZwEAAAAAAD1nAQBEZwEAAWcBAFRnAQAAAAAAAAAAAAYAAAATZwEAoXYBAAAAAABZZwEAAWcBAFRnAQAAAAAANWcBAAcAAAATZwEAoXYBAD1nAQBwZwEAfWcBAFRnAQAAAAAAAAAAAAoAAACLZwEAoXYBAAAAAACRZwEAfWcBAFRnAQAAAAAAPWcBAAsAAACLZwEAoXYBAD1nAQCkZwEAfWcBALJnAQAAAAAAAAAAAAgAAACLZwEAAAAAAAAAAAC4ZwEAfWcBALJnAQAAAAAAPWcBAAkAAACLZwEAAAAAAD1nAQDMZwEAzGcBAAAAAAAAAAAAAAAAAAwAAADUZwEAAAAAAAAAAADeZwEAzGcBAKF2AQAAAAAAAAAAAA4AAADUZwEAoXYBAAAAAADrZwEAzGcBAKF2AQAAAAAANWcBAA8AAADUZwEAoXYBAD1nAQD/ZwEAzGcBAAAAAAAAAAAANWcBAA0AAADUZwEAAAAAAD1nAQAPaAEAD2gBAAAAAAAAAAAAAAAAABAAAAATZwEAAAAAAAAAAAAZaAEAD2gBAKF2AQAAAAAAAAAAABIAAAATZwEAoXYBAAAAAAAoaAEAD2gBAKF2AQAAAAAANWcBABMAAAATZwEAoXYBAD1nAQA+aAEAD2gBAAAAAABPaAEAAAAAABQAAAATZwEAAAAAAAAAAABZaAEAD2gBAKF2AQBPaAEAAAAAABYAAAATZwEAoXYBAAAAAABvaAEAD2gBAKF2AQBPaAEANWcBABcAAAATZwEAoXYBAD1nAQCMaAEAD2gBAAAAAABPaAEANWcBABUAAAATZwEAAAAAAD1nAQClaAEAD2gBAAAAAAAAAAAANWcBABEAAAATZwEAAAAAAD1nAQC3aAEAzWgBAKF2AQAAAAAAAAAAABoAAACLZwEAoXYBAAAAAADiaAEAzWgBAKF2AQAAAAAAPWcBABsAAACLZwEAoXYBAD1nAQD+aAEAzWgBAAAAAAAAAAAAPWcBABkAAACLZwEAAAAAAD1nAQAWaQEAzWgBAC1pAQAAAAAAAAAAABgAAACLZwEAAAAAAAAAAAAzaQEAQWkBAKF2AQAAAAAAAAAAAB4AAACLZwEAoXYBAAAAAABTaQEAQWkBAKF2AQAAAAAAPWcBAB8AAACLZwEAoXYBAD1nAQBnaQEAQWkBAAAAAAAAAAAAPWcBAB0AAACLZwEAAAAAAD1nAQB3aQEAQWkBAC1pAQAAAAAAAAAAABwAAACLZwEAAAAAAAAAAACGaQEAhmkBAAAAAAAAAAAAAAAAACAAAACNaQEAAAAAAAAAAACVaQEAoGkBAKF2AQAAAAAAAAAAAAIAAACLZwEAoXYBAAAAAACmaQEAoGkBAKF2AQAAAAAAPWcBAAMAAACLZwEAoXYBAD1nAQC3aQEAoGkBAAAAAAAAAAAAPWcBAAEAAACLZwEAAAAAAD1nAQBjawEAoGkBAAAAAAAAAAAAAAAAAAAAAACLZwEAAAAAAAAAAADEaQEA3mkBAO1pAQAAAAAAPWcBACEAAACLZwEAAAAAAD1nAQD0aQEAAWoBAAAAAAAAAAAAAAAAACIAAACNaQEAAAAAAAAAAAAIAAAA/////wAAAAAAAAAAKQAAAAAAAAAAAAAAAAAAAAAAAAC/awEAxgAAAMVrAQDBAAAAzGsBAMIAAADSawEAwAAAANlrAQCRAwAA32sBAMUAAADlawEAwwAAAOxrAQDEAAAA8WsBAJIDAAD2awEAxwAAAP1rAQCnAwAAAWwBACEgAAAIbAEAlAMAAA5sAQDQAAAAEmwBAMkAAAAZbAEAygAAAB9sAQDIAAAAJmwBAJUDAAAubAEAlwMAADJsAQDLAAAAN2wBAJMDAAA9bAEAzQAAAERsAQDOAAAASmwBAMwAAABRbAEAmQMAAFZsAQDPAAAAW2wBAJoDAABhbAEAmwMAAGhsAQCcAwAAa2wBANEAAABybAEAnQMAAHVsAQBSAQAAe2wBANMAAACCbAEA1AAAAIhsAQDSAAAAj2wBAKkDAACVbAEAnwMAAJ1sAQDYAAAApGwBANUAAACrbAEA1gAAALBsAQCmAwAAtGwBAKADAAC3bAEAMyAAAL1sAQCoAwAAwWwBAKEDAADFbAEAYAEAAMxsAQCjAwAA0mwBAN4AAADYbAEApAMAANxsAQCYAwAA4mwBANoAAADpbAEA2wAAAO9sAQDZAAAA9mwBAKUDAAD+bAEA3AAAAANtAQCeAwAABm0BAN0AAAANbQEAeAEAABJtAQCWAwAAF20BAOEAAAAebQEA4gAAACRtAQC0AAAAKm0BAOYAAAAwbQEA4AAAADdtAQA1IQAAP20BALEDAABFbQEAJgAAAEltAQAnIgAATW0BACAiAABRbQEA5QAAAFdtAQBIIgAAXW0BAOMAAABkbQEA5AAAAGltAQAeIAAAb20BALIDAAB0bQEApgAAAHttAQAiIAAAgG0BACkiAACEbQEA5wAAAIttAQC4AAAAkW0BAKIAAACWbQEAxwMAAJptAQDGAgAAn20BAGMmAAClbQEARSIAAKptAQCpAAAAr20BALUhAAC1bQEAKiIAALltAQCkAAAAwG0BANMhAADFbQEAICAAAMxtAQCTIQAA0W0BALAAAADVbQEAtAMAANttAQBmJgAA4W0BAPcAAADobQEA6QAAAO9tAQDqAAAA9W0BAOgAAAD8bQEABSIAAAJuAQADIAAAB24BAAIgAAAMbgEAtQMAABRuAQBhIgAAGm4BALcDAAAebgEA8AAAACJuAQDrAAAAJ24BAKwgAAAsbgEAAyIAADJuAQCSAQAAN24BAAAiAAA+bgEAvQAAAEVuAQC8AAAATG4BAL4AAABTbgEARCAAAFluAQCzAwAAX24BAGUiAABibgEAPgAAAGVuAQDUIQAAam4BAJQhAABvbgEAZSYAAHZuAQAmIAAAfW4BAO0AAACEbgEA7gAAAIpuAQChAAAAkG4BAOwAAACXbgEAESEAAJ1uAQAeIgAAo24BACsiAACnbgEAuQMAAKxuAQC/AAAAs24BAAgiAAC4bgEA7wAAAL1uAQC6AwAAw24BANAhAADIbgEAuwMAAM9uAQApIwAA1G4BAKsAAADabgEAkCEAAN9uAQAIIwAA5W4BABwgAADrbgEAZCIAAO5uAQAKIwAA9W4BABciAAD8bgEAyiUAAABvAQAOIAAABG8BADkgAAALbwEAGCAAABFvAQA8AAAAFG8BAK8AAAAZbwEAFCAAAB9vAQC1AAAAJW8BALcAAADRdwEAEiIAACxvAQC8AwAAL28BAAciAAA1bwEAoAAAADpvAQATIAAAQG8BAGAiAABDbwEACyIAAEZvAQCsAAAASm8BAAkiAABQbwEAhCIAAFVvAQDxAAAAXG8BAL0DAABfbwEA8wAAAGZvAQD0AAAAbG8BAFMBAABybwEA8gAAAHlvAQA+IAAAf28BAMkDAACFbwEAvwMAAI1vAQCVIgAAk28BACgiAACWbwEAqgAAAJtvAQC6AAAAoG8BAPgAAACnbwEA9QAAAK5vAQCXIgAAtW8BAPYAAAC6bwEAtgAAAL9vAQACIgAAxG8BADAgAADLbwEApSIAANBvAQDGAwAA1G8BAMADAADXbwEA1gMAANtvAQCxAAAA4m8BAKMAAADobwEAMiAAAO5vAQAPIgAA828BAB0iAAD4bwEAyAMAAPxvAQAiAAAAAXABANIhAAAGcAEAGiIAAAxwAQAqIwAAEXABALsAAAAXcAEAkiEAABxwAQAJIwAAInABAB0gAAAocAEAHCEAAC1wAQCuAAAAMXABAAsjAAA4cAEAwQMAADxwAQAPIAAAQHABADogAABHcAEAGSAAAE1wAQAaIAAAU3ABAGEBAABacAEAxSIAAF9wAQCnAAAAZHABAK0AAABocAEAwwMAAG5wAQDCAwAAdXABADwiAAB5cAEAYCYAAIBwAQCCIgAAhHABAIYiAACJcAEAESIAAI1wAQCDIgAAkXABALkAAACWcAEAsgAAAJtwAQCzAAAAoHABAIciAAClcAEA3wAAAKtwAQDEAwAAr3ABADQiAAC2cAEAuAMAALxwAQDRAwAAxXABAAkgAADMcAEA/gAAANJwAQDcAgAA2HABANcAAADecAEAIiEAAORwAQDRIQAA6XABAPoAAADwcAEAkSEAAPVwAQD7AAAA+3ABAPkAAAACcQEAqAAAAAZxAQDSAwAADHEBAMUDAAAUcQEA/AAAABlxAQAYIQAAIHEBAL4DAAAjcQEA/QAAACpxAQClAAAALnEBAP8AAAAzcQEAtgMAADhxAQANIAAAPHEBAAwgAAAFAAAABgAAAAEBAAAIAAAACAAAAAAAAAAAAAAAKgAAAA0AAAAAAAAAAAAAAAAAAAAIAAAAEAAAAAAAAAAAAAAAKwAAAA4AAAAAAAAAAAAAAAAAAACRdwEABwAAAJN3AQAIAAAAmHcBAAgAAACgdwEACQAAAKZ3AQAJAAAAr3cBAAoAAACydwEACgAAALh3AQALAAAAvXcBAAsAAADFdwEADAAAAMp3AQAMAAAA0XcBAA0AAADXdwEADQAAAON3AQAOAAAAUgAAACwAAAAtAAAAFAAAAC4AAABTAAAALwAAABUAAAAwAAAACAAAAAQAAAD/////AAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAO3kBAFVdyX/Jf/8ARnkBALst1L6u1P8AUXkBABR3/f3Ahv8AXHkBAFVdyX/Jf/8AZ3kBALst1L6u1P8AcnkBABR3/f3Ahv8AfXkBACpm////mf8AiHkBAFVdyX/Jf/8Ak3kBALst1L6u1P8AnnkBABR3/f3Ahv8AqXkBACpm////mf8AtHkBAJetsDhssP8Av3kBAFVdyX/Jf/8AynkBALst1L6u1P8A1XkBABR3/f3Ahv8A4HkBACpm////mf8A63kBAJetsDhssP8A9nkBAOj88PACf/8AAXoBAFVdyX/Jf/8ADHoBALst1L6u1P8AF3oBABR3/f3Ahv8AInoBACpm////mf8ALXoBAJetsDhssP8AOHoBAOj88PACf/8AQ3oBABHgv79bF/8ATnoBAFVdyX/Jf/8AWXoBALst1L6u1P8AZHoBABR3/f3Ahv8Ab3oBACpm////mf8AenoBAJetsDhssP8AhXoBAOj88PACf/8AkHoBABHgv79bF/8Am3oBAAAAZmZmZv8ApnoBAJMZ997r9/8AsHoBAI5L4Z7K4f8AunoBAJG8vTGCvf8AxHoBAJ8Q/+/z//8AznoBAI8u573X5/8A2HoBAI9/1muu1v8A4noBAJPQtSFxtf8A7HoBAJ8Q/+/z//8A9noBAI8u573X5/8AAHsBAI9/1muu1v8ACnsBAJG8vTGCvf8AFHsBAJXxnAhRnP8AHnsBAJ8Q/+/z//8AKHsBAJQr78bb7/8AMnsBAI5L4Z7K4f8APHsBAI9/1muu1v8ARnsBAJG8vTGCvf8AUHsBAJXxnAhRnP8AWnsBAJ8Q/+/z//8AZHsBAJQr78bb7/8AbnsBAI5L4Z7K4f8AeHsBAI9/1muu1v8AgnsBAJCpxkKSxv8AjHsBAJPQtSFxtf8AlnsBAJfxlAhFlP8AoHsBAJQI//f7//8AqnsBAJMZ997r9/8AtHsBAJQr78bb7/8AvnsBAI5L4Z7K4f8AyHsBAI9/1muu1v8A0nsBAJCpxkKSxv8A3HsBAJPQtSFxtf8A5nsBAJfxlAhFlP8A8HsBAJQI//f7//8A+nsBAJMZ997r9/8ABHwBAJQr78bb7/8ADnwBAI5L4Z7K4f8AGHwBAI9/1muu1v8AInwBAJCpxkKSxv8ALHwBAJPQtSFxtf8ANnwBAJXxnAhRnP8AQHwBAJjrawgwa/8ASnwBABfvVFQwBf8AVHwBAHf/PAA8MP8AX3wBABfsjIxRCv8AaXwBABjCv7+BLf8Ac3wBAB1w39/Cff8AfXwBAB409vbow/8Ah3wBAHkm6sfq5f8AkXwBAHhfzYDNwf8Am3wBAHyllzWXj/8ApXwBAHz8ZgFmXv8Ar3wBABfvVFQwBf8AuXwBAHz8ZgFmXv8AxHwBAHf/PAA8MP8Az3wBABfsjIxRCv8A2XwBABjCv7+BLf8A43wBAB1w39/Cff8A7XwBAB409vbow/8A93wBAAAA9fX19f8AAX0BAHkm6sfq5f8AC30BAHhfzYDNwf8AFX0BAHyllzWXj/8AH30BAByH2NizZf8AKH0BAAAA9fX19f8AMX0BAHt/tFq0rP8AOn0BABXXpqZhGv8AQ30BAB1w39/Cff8ATH0BAHhfzYDNwf8AVX0BAHn9hQGFcf8AXn0BABXXpqZhGv8AZ30BAB1w39/Cff8AcH0BAAAA9fX19f8AeX0BAHhfzYDNwf8Agn0BAHn9hQGFcf8Ai30BABfsjIxRCv8AlH0BAByH2NizZf8AnX0BAB409vbow/8Apn0BAHkm6sfq5f8Ar30BAHt/tFq0rP8AuH0BAHz8ZgFmXv8AwX0BABfsjIxRCv8Ayn0BAByH2NizZf8A030BAB409vbow/8A3H0BAAAA9fX19f8A5X0BAHkm6sfq5f8A7n0BAHt/tFq0rP8A930BAHz8ZgFmXv8AAH4BABfsjIxRCv8ACX4BABjCv7+BLf8AEn4BAB1w39/Cff8AG34BAB409vbow/8AJH4BAHkm6sfq5f8ALX4BAHhfzYDNwf8ANn4BAHyllzWXj/8AP34BAHz8ZgFmXv8ASH4BABfsjIxRCv8AUX4BABjCv7+BLf8AWn4BAB1w39/Cff8AY34BAB409vbow/8AbH4BAAAA9fX19f8AdX4BAHkm6sfq5f8Afn4BAHhfzYDNwf8Ah34BAHyllzWXj/8AkH4BAHz8ZgFmXv8AmX4BAIcU+eX1+f8Aon4BAHVK2JnYyf8Aq34BAGe5oiyiX/8AtH4BAIgO++34+/8AvX4BAH824rLi4v8Axn4BAHF4wmbCpP8Az34BAGK+iyOLRf8A2H4BAIgO++34+/8A4X4BAH824rLi4v8A6n4BAHF4wmbCpP8A834BAGe5oiyiX/8A/H4BAGb/bQBtLP8ABX8BAIgO++34+/8ADn8BAHci7Mzs5v8AF38BAHVK2JnYyf8AIH8BAHF4wmbCpP8AKX8BAGe5oiyiX/8AMn8BAGb/bQBtLP8AO38BAIgO++34+/8ARH8BAHci7Mzs5v8ATX8BAHVK2JnYyf8AVn8BAHF4wmbCpP8AX38BAGmfrkGudv8AaH8BAGK+iyOLRf8AcX8BAGb/WABYJP8Aen8BAIYG/ff8/f8Ag38BAIcU+eX1+f8AjH8BAHci7Mzs5v8AlX8BAHVK2JnYyf8Ann8BAHF4wmbCpP8Ap38BAGmfrkGudv8AsH8BAGK+iyOLRf8AuX8BAGb/WABYJP8Awn8BAIYG/ff8/f8Ay38BAIcU+eX1+f8A1H8BAHci7Mzs5v8A3X8BAHVK2JnYyf8A5n8BAHF4wmbCpP8A738BAGmfrkGudv8A+H8BAGK+iyOLRf8AAYABAGb/bQBtLP8ACoABAGX/RABEG/8AE4ABAJAU9ODs9P8AHIABAJRG2p682v8AJYABAMR7p4hWp/8ALoABAIgO++34+/8AN4ABAJI147PN4/8AQIABAKJKxoyWxv8ASYABAMqVnYhBnf8AUoABAIgO++34+/8AW4ABAJI147PN4/8AZIABAKJKxoyWxv8AbYABAMR7p4hWp/8AdoABANbhgYEPfP8Af4ABAIgO++34+/8AiIABAJQr5r/T5v8AkYABAJRG2p682v8AmoABAKJKxoyWxv8Ao4ABAMR7p4hWp/8ArIABANbhgYEPfP8AtYABAIgO++34+/8AvoABAJQr5r/T5v8Ax4ABAJRG2p682v8A0IABAKJKxoyWxv8A2YABAL5ksYxrsf8A4oABAMqVnYhBnf8A64ABANX8bm4Ba/8A9IABAIYG/ff8/f8A/YABAJAU9ODs9P8ABoEBAJQr5r/T5v8AD4EBAJRG2p682v8AGIEBAKJKxoyWxv8AIYEBAL5ksYxrsf8AKoEBAMqVnYhBnf8AM4EBANX8bm4Ba/8APIEBAIYG/ff8/f8ARYEBAJAU9ODs9P8AToEBAJQr5r/T5v8AV4EBAJRG2p682v8AYIEBAKJKxoyWxv8AaYEBAL5ksYxrsf8AcoEBAMqVnYhBnf8Ae4EBANbhgYEPfP8AhIEBANX/TU0AS/8AjYEBAHLTnhued/8Al4EBABL82dlfAv8AoYEBAK1fs3Vws/8Aq4EBAHLTnhued/8AtYEBABL82dlfAv8Av4EBAK1fs3Vws/8AyYEBAOnR5+cpiv8A04EBAHLTnhued/8A3YEBABL82dlfAv8A54EBAK1fs3Vws/8A8YEBAOnR5+cpiv8A+4EBAD7QpmamHv8ABYIBAHLTnhued/8AD4IBABL82dlfAv8AGYIBAK1fs3Vws/8AI4IBAOnR5+cpiv8ALYIBAD7QpmamHv8AN4IBAB/85uarAv8AQYIBAHLTnhued/8AS4IBABL82dlfAv8AVYIBAK1fs3Vws/8AX4IBAOnR5+cpiv8AaYIBAD7QpmamHv8Ac4IBAB/85uarAv8AfYIBABvSpqZ2Hf8Ah4IBAHLTnhued/8AkYIBABL82dlfAv8Am4IBAK1fs3Vws/8ApYIBAOnR5+cpiv8Ar4IBAD7QpmamHv8AuYIBAB/85uarAv8Aw4IBABvSpqZ2Hf8AzYIBAAAAZmZmZv8A14IBAEwZ8+Dz2/8A4IIBAF893ajdtf8A6YIBAIyqykOiyv8A8oIBAEER+fD56P8A+4IBAFcu5LrkvP8ABIMBAHtlzHvMxP8ADYMBAI3FviuMvv8AFoMBAEER+fD56P8AH4MBAFcu5LrkvP8AKIMBAHtlzHvMxP8AMYMBAIyqykOiyv8AOoMBAJHzrAhorP8AQ4MBAEER+fD56P8ATIMBAE0p68zrxf8AVYMBAF893ajdtf8AXoMBAHtlzHvMxP8AZ4MBAIyqykOiyv8AcIMBAJHzrAhorP8AeYMBAEER+fD56P8AgoMBAE0p68zrxf8Ai4MBAF893ajdtf8AlIMBAHtlzHvMxP8AnYMBAImg006z0/8ApoMBAI3FviuMvv8Ar4MBAJPynghYnv8AuIMBADwM/Pf88P8AwYMBAEwZ8+Dz2/8AyoMBAE0p68zrxf8A04MBAF893ajdtf8A3IMBAHtlzHvMxP8A5YMBAImg006z0/8A7oMBAI3FviuMvv8A94MBAJPynghYnv8AAIQBADwM/Pf88P8ACYQBAEwZ8+Dz2/8AEoQBAE0p68zrxf8AG4QBAF893ajdtf8AJIQBAHtlzHvMxP8ALYQBAImg006z0/8ANoQBAI3FviuMvv8AP4QBAJHzrAhorP8ASIQBAJbvgQhAgf8AUYQBAEoV9eX14P8AXIQBAFBI2aHZm/8AZ4QBAGKyozGjVP8AcoQBAEkP+O346f8AfYQBAE425Lrks/8AiIQBAFZoxHTEdv8Ak4QBAGK+iyOLRf8AnoQBAEkP+O346f8AqYQBAE425Lrks/8AtIQBAFZoxHTEdv8Av4QBAGKyozGjVP8AyoQBAGb/bQBtLP8A1YQBAEkP+O346f8A4IQBAE0s6cfpwP8A64QBAFBI2aHZm/8A9oQBAFZoxHTEdv8AAYUBAGKyozGjVP8ADIUBAGb/bQBtLP8AF4UBAEkP+O346f8AIoUBAE0s6cfpwP8ALYUBAFBI2aHZm/8AOIUBAFZoxHTEdv8AQ4UBAGCeq0GrXf8AToUBAGK+iyOLRf8AWYUBAGz/WgBaMv8AZIUBAEgH/Pf89f8Ab4UBAEoV9eX14P8AeoUBAE0s6cfpwP8AhYUBAFBI2aHZm/8AkIUBAFZoxHTEdv8Am4UBAGCeq0GrXf8ApoUBAGK+iyOLRf8AsYUBAGz/WgBaMv8AvIUBAEgH/Pf89f8Ax4UBAEoV9eX14P8A0oUBAE0s6cfpwP8A3YUBAFBI2aHZm/8A6IUBAFZoxHTEdv8A84UBAGCeq0GrXf8A/oUBAGK+iyOLRf8ACYYBAGb/bQBtLP8AFIYBAGX/RABEG/8AH4YBAAAA8PDw8P8AKYYBAAAAvb29vf8AM4YBAAAAY2NjY/8APYYBAAAA9/f39/8AR4YBAAAAzMzMzP8AUYYBAAAAlpaWlv8AW4YBAAAAUlJSUv8AZYYBAAAA9/f39/8Ab4YBAAAAzMzMzP8AeYYBAAAAlpaWlv8Ag4YBAAAAY2NjY/8AjYYBAAAAJSUlJf8Al4YBAAAA9/f39/8AoYYBAAAA2dnZ2f8Aq4YBAAAAvb29vf8AtYYBAAAAlpaWlv8Av4YBAAAAY2NjY/8AyYYBAAAAJSUlJf8A04YBAAAA9/f39/8A3YYBAAAA2dnZ2f8A54YBAAAAvb29vf8A8YYBAAAAlpaWlv8A+4YBAAAAc3Nzc/8ABYcBAAAAUlJSUv8AD4cBAAAAJSUlJf8AGYcBAAAA//////8AI4cBAAAA8PDw8P8ALYcBAAAA2dnZ2f8AN4cBAAAAvb29vf8AQYcBAAAAlpaWlv8AS4cBAAAAc3Nzc/8AVYcBAAAAUlJSUv8AX4cBAAAAJSUlJf8AaYcBAAAA//////8Ac4cBAAAA8PDw8P8AfYcBAAAA2dnZ2f8Ah4cBAAAAvb29vf8AkYcBAAAAlpaWlv8Am4cBAAAAc3Nzc/8ApYcBAAAAUlJSUv8Ar4cBAAAAJSUlJf8AuYcBAAAAAAAAAP8Aw4cBABUw/v7mzv8Az4cBABOT/f2ua/8A24cBAA7w5uZVDf8A54cBABMg/v7t3v8A84cBABR4/f2+hf8A/4cBABHC/f2NPP8AC4gBAA392dlHAf8AF4gBABMg/v7t3v8AI4gBABR4/f2+hf8AL4gBABHC/f2NPP8AO4gBAA7w5uZVDf8AR4gBAA36pqY2A/8AU4gBABMg/v7t3v8AX4gBABVb/f3Qov8Aa4gBABOT/f2ua/8Ad4gBABHC/f2NPP8Ag4gBAA7w5uZVDf8Aj4gBAA36pqY2A/8Am4gBABMg/v7t3v8Ap4gBABVb/f3Qov8As4gBABOT/f2ua/8Av4gBABHC/f2NPP8Ay4gBABDq8fFpE/8A14gBAA392dlIAf8A44gBAAz3jIwtBP8A74gBABUU///16/8A+4gBABUw/v7mzv8AB4kBABVb/f3Qov8AE4kBABOT/f2ua/8AH4kBABHC/f2NPP8AK4kBABDq8fFpE/8AN4kBAA392dlIAf8AQ4kBAAz3jIwtBP8AT4kBABUU///16/8AW4kBABUw/v7mzv8AZ4kBABVb/f3Qov8Ac4kBABOT/f2ua/8Af4kBABHC/f2NPP8Ai4kBABDq8fFpE/8Al4kBAA392dlIAf8Ao4kBAA36pqY2A/8Ar4kBAAz2f38nBP8Au4kBABk2/v7oyP8AxIkBABN5/f27hP8AzYkBAAXF4+NKM/8A1okBABol/v7w2f8A34kBABhz/f3Miv8A6IkBAA2k/PyNWf8A8YkBAAPa19cwH/8A+okBABol/v7w2f8AA4oBABhz/f3Miv8ADIoBAA2k/PyNWf8AFYoBAAXF4+NKM/8AHooBAAD/s7MAAP8AJ4oBABol/v7w2f8AMIoBABhf/f3Unv8AOYoBABN5/f27hP8AQooBAA2k/PyNWf8AS4oBAAXF4+NKM/8AVIoBAAD/s7MAAP8AXYoBABol/v7w2f8AZooBABhf/f3Unv8Ab4oBABN5/f27hP8AeIoBAA2k/PyNWf8AgYoBAAey7+9lSP8AiooBAAPa19cwH/8Ak4oBAAD/mZkAAP8AnIoBABgS///37P8ApYoBABk2/v7oyP8ArooBABhf/f3Unv8At4oBABN5/f27hP8AwIoBAA2k/PyNWf8AyYoBAAey7+9lSP8A0ooBAAPa19cwH/8A24oBAAD/mZkAAP8A5IoBABgS///37P8A7YoBABk2/v7oyP8A9ooBABhf/f3Unv8A/4oBABN5/f27hP8ACIsBAA2k/PyNWf8AEYsBAAey7+9lSP8AGosBAAPa19cwH/8AI4sBAAD/s7MAAP8ALIsBAAD/f38AAP8ANYsBAI5E46bO4/8AQYsBAL6Zmmo9mv8ATosBAJDTtB94tP8AWosBAEFh37Lfiv8AZosBAFK4oDOgLP8AcosBAABj+/uamf8AfosBAP7h4+MaHP8AiosBABeP/f2/b/8AlosBABX///9/AP8AoosBAMYq1sqy1v8ArosBAI5E46bO4/8AuosBAL6Zmmo9mv8Ax4sBACpm////mf8A1IsBAJDTtB94tP8A4IsBAEFh37Lfiv8A7IsBAFK4oDOgLP8A+IsBAABj+/uamf8ABIwBAP7h4+MaHP8AEIwBABeP/f2/b/8AHIwBABX///9/AP8AKIwBAMYq1sqy1v8ANIwBAI5E46bO4/8AQIwBAL6Zmmo9mv8ATYwBACpm////mf8AWowBAA/FsbFZKP8AZ4wBAJDTtB94tP8Ac4wBAEFh37Lfiv8Af4wBAFK4oDOgLP8Ai4wBAABj+/uamf8Al4wBAP7h4+MaHP8Ao4wBABeP/f2/b/8Ar4wBABX///9/AP8Au4wBAMYq1sqy1v8Ax4wBAI5E46bO4/8A0owBAJDTtB94tP8A3YwBAEFh37Lfiv8A6IwBAI5E46bO4/8A84wBAJDTtB94tP8A/owBAEFh37Lfiv8ACY0BAFK4oDOgLP8AFI0BAI5E46bO4/8AH40BAJDTtB94tP8AKo0BAEFh37Lfiv8ANY0BAFK4oDOgLP8AQI0BAABj+/uamf8AS40BAI5E46bO4/8AVo0BAJDTtB94tP8AYY0BAEFh37Lfiv8AbI0BAFK4oDOgLP8Ad40BAABj+/uamf8Ago0BAP7h4+MaHP8AjY0BAI5E46bO4/8AmI0BAJDTtB94tP8Ao40BAEFh37Lfiv8Aro0BAFK4oDOgLP8AuY0BAABj+/uamf8AxI0BAP7h4+MaHP8Az40BABeP/f2/b/8A2o0BAI5E46bO4/8A5Y0BAJDTtB94tP8A8I0BAEFh37Lfiv8A+40BAFK4oDOgLP8ABo4BAABj+/uamf8AEY4BAP7h4+MaHP8AHI4BABeP/f2/b/8AJ44BABX///9/AP8AMo4BAI5E46bO4/8APY4BAJDTtB94tP8ASI4BAEFh37Lfiv8AU44BAFK4oDOgLP8AXo4BAABj+/uamf8AaY4BAP7h4+MaHP8AdI4BABeP/f2/b/8Af44BABX///9/AP8Aio4BAMYq1sqy1v8AlY4BAANO+/u0rv8AoY4BAJI147PN4/8ArY4BAE0p68zrxf8AuY4BAANO+/u0rv8AxY4BAJI147PN4/8A0Y4BAE0p68zrxf8A3Y4BAMob5N7L5P8A6Y4BAANO+/u0rv8A9Y4BAJI147PN4/8AAY8BAE0p68zrxf8ADY8BAMob5N7L5P8AGY8BABhY/v7Zpv8AJY8BAANO+/u0rv8AMY8BAJI147PN4/8APY8BAE0p68zrxf8ASY8BAMob5N7L5P8AVY8BABhY/v7Zpv8AYY8BACoy////zP8AbY8BAANO+/u0rv8AeY8BAJI147PN4/8AhY8BAE0p68zrxf8AkY8BAMob5N7L5P8AnY8BABhY/v7Zpv8AqY8BACoy////zP8AtY8BABws5eXYvf8AwY8BAANO+/u0rv8AzY8BAJI147PN4/8A2Y8BAE0p68zrxf8A5Y8BAMob5N7L5P8A8Y8BABhY/v7Zpv8A/Y8BACoy////zP8ACZABABws5eXYvf8AFZABAOkj/f3a7P8AIZABAANO+/u0rv8ALZABAJI147PN4/8AOZABAE0p68zrxf8ARZABAMob5N7L5P8AUZABABhY/v7Zpv8AXZABACoy////zP8AaZABABws5eXYvf8AdZABAOkj/f3a7P8AgZABAAAA8vLy8v8AjZABAGw14rPizf8AmZABABFR/f3NrP8ApZABAJsf6MvV6P8AsZABAGw14rPizf8AvZABABFR/f3NrP8AyZABAJsf6MvV6P8A1ZABAOQr9PTK5P8A4ZABAGw14rPizf8A7ZABABFR/f3NrP8A+ZABAJsf6MvV6P8ABZEBAOQr9PTK5P8AEZEBADgt9eb1yf8AHZEBAGw14rPizf8AKZEBABFR/f3NrP8ANZEBAJsf6MvV6P8AQZEBAOQr9PTK5P8ATZEBADgt9eb1yf8AWZEBACNR///yrv8AZZEBAGw14rPizf8AcZEBABFR/f3NrP8AfZEBAJsf6MvV6P8AiZEBAOQr9PTK5P8AlZEBADgt9eb1yf8AoZEBACNR///yrv8ArZEBABkn8fHizP8AuZEBAGw14rPizf8AxZEBABFR/f3NrP8A0ZEBAJsf6MvV6P8A3ZEBAOQr9PTK5P8A6ZEBADgt9eb1yf8A9ZEBACNR///yrv8AAZIBABkn8fHizP8ADZIBAAAAzMzMzP8AGZIBAOb9jo4BUv8AI5IBAE2/ZCdkGf8ALpIBAObcxcUbff8AOJIBAOh23t53rv8AQpIBAOU+8fG22v8ATJIBAOkd/f3g7/8AVpIBADsm9eb10P8AYJIBAD1n4bjhhv8AapIBAD+mvH+8Qf8AdJIBAETFkk2SIf8AfpIBAOb9jo4BUv8AiJIBAETFkk2SIf8Ak5IBAE2/ZCdkGf8AnpIBAObcxcUbff8AqJIBAOh23t53rv8AspIBAOU+8fG22v8AvJIBAOkd/f3g7/8AxpIBAAAA9/f39/8A0JIBADsm9eb10P8A2pIBAD1n4bjhhv8A5JIBAD+mvH+8Qf8A7pIBAOdM6emjyf8A95IBAAAA9/f39/8AAJMBAD+B16HXav8ACZMBAOTc0NAci/8AEpMBAOU+8fG22v8AG5MBAD1n4bjhhv8AJJMBAEjGrE2sJv8ALZMBAOTc0NAci/8ANpMBAOU+8fG22v8AP5MBAAAA9/f39/8ASJMBAD1n4bjhhv8AUZMBAEjGrE2sJv8AWpMBAObcxcUbff8AY5MBAOdM6emjyf8AbJMBAOkd/f3g7/8AdZMBADsm9eb10P8AfpMBAD+B16HXav8Ah5MBAETFkk2SIf8AkJMBAObcxcUbff8AmZMBAOdM6emjyf8AopMBAOkd/f3g7/8Aq5MBAAAA9/f39/8AtJMBADsm9eb10P8AvZMBAD+B16HXav8AxpMBAETFkk2SIf8Az5MBAObcxcUbff8A2JMBAOh23t53rv8A4ZMBAOU+8fG22v8A6pMBAOkd/f3g7/8A85MBADsm9eb10P8A/JMBAD1n4bjhhv8ABZQBAD+mvH+8Qf8ADpQBAETFkk2SIf8AF5QBAObcxcUbff8AIJQBAOh23t53rv8AKZQBAOU+8fG22v8AMpQBAOkd/f3g7/8AO5QBAAAA9/f39/8ARJQBADsm9eb10P8ATZQBAD1n4bjhhv8AVpQBAD+mvH+8Qf8AX5QBAETFkk2SIf8AaJQBAM7/S0AAS/8AcpQBAGX/RABEG/8AfZQBAM6tg3Yqg/8Ah5QBAMdXq5lwq/8AkZQBAMczz8Klz/8Am5QBANIV6OfU6P8ApZQBAEwe8Nnw0/8Ar5QBAFBE26bboP8AuZQBAFh7rlquYf8Aw5QBAGHFeBt4N/8AzZQBAM7/S0AAS/8A15QBAGHFeBt4N/8A4pQBAGX/RABEG/8A7ZQBAM6tg3Yqg/8A95QBAMdXq5lwq/8AAZUBAMczz8Klz/8AC5UBANIV6OfU6P8AFZUBAAAA9/f39/8AH5UBAEwe8Nnw0/8AKZUBAFBE26bboP8AM5UBAFh7rlquYf8APZUBAMRGw6+Nw/8ARpUBAAAA9/f39/8AT5UBAFJav3+/e/8AWJUBAMmolHsylP8AYZUBAMczz8Klz/8AapUBAFBE26bboP8Ac5UBAGb/iACIN/8AfJUBAMmolHsylP8AhZUBAMczz8Klz/8AjpUBAAAA9/f39/8Al5UBAFBE26bboP8AoJUBAGb/iACIN/8AqZUBAM6tg3Yqg/8AspUBAMRGw6+Nw/8Au5UBANIV6OfU6P8AxJUBAEwe8Nnw0/8AzZUBAFJav3+/e/8A1pUBAGHFeBt4N/8A35UBAM6tg3Yqg/8A6JUBAMRGw6+Nw/8A8ZUBANIV6OfU6P8A+pUBAAAA9/f39/8AA5YBAEwe8Nnw0/8ADJYBAFJav3+/e/8AFZYBAGHFeBt4N/8AHpYBAM6tg3Yqg/8AJ5YBAMdXq5lwq/8AMJYBAMczz8Klz/8AOZYBANIV6OfU6P8AQpYBAEwe8Nnw0/8AS5YBAFBE26bboP8AVJYBAFh7rlquYf8AXZYBAGHFeBt4N/8AZpYBAM6tg3Yqg/8Ab5YBAMdXq5lwq/8AeJYBAMczz8Klz/8AgZYBANIV6OfU6P8AipYBAAAA9/f39/8Ak5YBAEwe8Nnw0/8AnJYBAFBE26bboP8ApZYBAFh7rlquYf8ArpYBAGHFeBt4N/8At5YBAL0L8uzn8v8AwJYBAJc926a92/8AyZYBAI3FviuMvv8A0pYBALkI9vHu9v8A25YBAJso4b3J4f8A5JYBAJFwz3Spz/8A7ZYBAI/3sAVwsP8A9pYBALkI9vHu9v8A/5YBAJso4b3J4f8ACJcBAJFwz3Spz/8AEZcBAI3FviuMvv8AGpcBAI/3jQRajf8AI5cBALkI9vHu9v8ALJcBAKgY5tDR5v8ANZcBAJc926a92/8APpcBAJFwz3Spz/8AR5cBAI3FviuMvv8AUJcBAI/3jQRajf8AWZcBALkI9vHu9v8AYpcBAKgY5tDR5v8Aa5cBAJc926a92/8AdJcBAJFwz3Spz/8AfZcBAI63wDaQwP8AhpcBAI/3sAVwsP8Aj5cBAI/4ewNOe/8AmJcBAOkI///3+/8AoZcBAL0L8uzn8v8AqpcBAKgY5tDR5v8As5cBAJc926a92/8AvJcBAJFwz3Spz/8AxZcBAI63wDaQwP8AzpcBAI/3sAVwsP8A15cBAI/4ewNOe/8A4JcBAOkI///3+/8A6ZcBAL0L8uzn8v8A8pcBAKgY5tDR5v8A+5cBAJc926a92/8ABJgBAJFwz3Spz/8ADZgBAI63wDaQwP8AFpgBAI/3sAVwsP8AH5gBAI/3jQRajf8AKJgBAI/5WAI4WP8AMZgBAMgO8Ozi8P8APJgBAJc926a92/8AR5gBAILQmRyQmf8AUpgBAM8I9/bv9/8AXZgBAJso4b3J4f8AaJgBAI+Az2epz/8Ac5gBAIL7igKBiv8AfpgBAM8I9/bv9/8AiZgBAJso4b3J4f8AlJgBAI+Az2epz/8An5gBAILQmRyQmf8AqpgBAHf8bAFsWf8AtZgBAM8I9/bv9/8AwJgBAKgY5tDR5v8Ay5gBAJc926a92/8A1pgBAI+Az2epz/8A4ZgBAILQmRyQmf8A7JgBAHf8bAFsWf8A95gBAM8I9/bv9/8AApkBAKgY5tDR5v8ADZkBAJc926a92/8AGJkBAI+Az2epz/8AI5kBAI63wDaQwP8ALpkBAIL7igKBiv8AOZkBAHb8ZAFkUP8ARJkBAOkI///3+/8AT5kBAMgO8Ozi8P8AWpkBAKgY5tDR5v8AZZkBAJc926a92/8AcJkBAI+Az2epz/8Ae5kBAI63wDaQwP8AhpkBAIL7igKBiv8AkZkBAHb8ZAFkUP8AnJkBAOkI///3+/8Ap5kBAMgO8Ozi8P8AspkBAKgY5tDR5v8AvZkBAJc926a92/8AyJkBAI+Az2epz/8A05kBAI63wDaQwP8A3pkBAIL7igKBiv8A6ZkBAHf8bAFsWf8A9JkBAHX7RgFGNv8A/5kBABLuf387CP8ACZoBAMP/Sy0AS/8AFJoBABT2s7NYBv8AHpoBABbo4OCCFP8AKJoBABeb/f24Y/8AMpoBABhI/v7gtv8APJoBAKUU69ja6/8ARpoBALEv0rKr0v8AUJoBALNUrIBzrP8AWpoBAL21iFQniP8AZJoBABLuf387CP8AbpoBAL21iFQniP8AeZoBAMP/Sy0AS/8AhJoBABT2s7NYBv8AjpoBABbo4OCCFP8AmJoBABeb/f24Y/8AopoBABhI/v7gtv8ArJoBAAAA9/f39/8AtpoBAKUU69ja6/8AwJoBALEv0rKr0v8AypoBALNUrIBzrP8A1JoBABe78fGjQP8A3ZoBAAAA9/f39/8A5poBALJFw5mOw/8A75oBABH95uZhAf8A+JoBABeb/f24Y/8AAZsBALEv0rKr0v8ACpsBALmbmV48mf8AE5sBABH95uZhAf8AHJsBABeb/f24Y/8AJZsBAAAA9/f39/8ALpsBALEv0rKr0v8AN5sBALmbmV48mf8AQJsBABT2s7NYBv8ASZsBABe78fGjQP8AUpsBABhI/v7gtv8AW5sBAKUU69ja6/8AZJsBALJFw5mOw/8AbZsBAL21iFQniP8AdpsBABT2s7NYBv8Af5sBABe78fGjQP8AiJsBABhI/v7gtv8AkZsBAAAA9/f39/8AmpsBAKUU69ja6/8Ao5sBALJFw5mOw/8ArJsBAL21iFQniP8AtZsBABT2s7NYBv8AvpsBABbo4OCCFP8Ax5sBABeb/f24Y/8A0JsBABhI/v7gtv8A2ZsBAKUU69ja6/8A4psBALEv0rKr0v8A65sBALNUrIBzrP8A9JsBAL21iFQniP8A/ZsBABT2s7NYBv8ABpwBABbo4OCCFP8AD5wBABeb/f24Y/8AGJwBABhI/v7gtv8AIZwBAAAA9/f39/8AKpwBAKUU69ja6/8AM5wBALEv0rKr0v8APJwBALNUrIBzrP8ARZwBAL21iFQniP8ATpwBALwO7+fh7/8AV5wBANZDycmUx/8AYJwBAOre3d0cd/8AaZwBALkI9vHu9v8AcpwBANMp2Ne12P8Ae5wBAOSL399lsP8AhJwBAO/ozs4SVv8AjZwBALkI9vHu9v8AlpwBANMp2Ne12P8An5wBAOSL399lsP8AqJwBAOre3d0cd/8AsZwBAOz/mJgAQ/8AupwBALkI9vHu9v8Aw5wBAMwm2tS52v8AzJwBANZDycmUx/8A1ZwBAOSL399lsP8A3pwBAOre3d0cd/8A55wBAOz/mJgAQ/8A8JwBALkI9vHu9v8A+ZwBAMwm2tS52v8AAp0BANZDycmUx/8AC50BAOSL399lsP8AFJ0BAOnR5+cpiv8AHZ0BAO/ozs4SVv8AJp0BAOz/kZEAP/8AL50BAMMF+ff0+f8AOJ0BALwO7+fh7/8AQZ0BAMwm2tS52v8ASp0BANZDycmUx/8AU50BAOSL399lsP8AXJ0BAOnR5+cpiv8AZZ0BAO/ozs4SVv8Abp0BAOz/kZEAP/8Ad50BAMMF+ff0+f8AgJ0BALwO7+fh7/8AiZ0BAMwm2tS52v8Akp0BANZDycmUx/8Am50BAOSL399lsP8ApJ0BAOnR5+cpiv8ArZ0BAO/ozs4SVv8Atp0BAOz/mJgAQ/8Av50BAPL/Z2cAH/8AyJ0BALQI9e/t9f8A1J0BAKgl3Ly93P8A4J0BALBksXVrsf8A7J0BALYH9/Lw9/8A+J0BAK0c4svJ4v8ABJ4BAK06yJ6ayP8AEJ4BALaAo2pRo/8AHJ4BALYH9/Lw9/8AKJ4BAK0c4svJ4v8ANJ4BAK06yJ6ayP8AQJ4BALBksXVrsf8ATJ4BALy5j1Qnj/8AWJ4BALYH9/Lw9/8AZJ4BAKoS69ra6/8AcJ4BAKgl3Ly93P8AfJ4BAK06yJ6ayP8AiJ4BALBksXVrsf8AlJ4BALy5j1Qnj/8AoJ4BALYH9/Lw9/8ArJ4BAKoS69ra6/8AuJ4BAKgl3Ly93P8AxJ4BAK06yJ6ayP8A0J4BAKxTuoB9uv8A3J4BALaAo2pRo/8A6J4BAL7YhkoUhv8A9J4BAL8C/fz7/f8AAJ8BALQI9e/t9f8ADJ8BAKoS69ra6/8AGJ8BAKgl3Ly93P8AJJ8BAK06yJ6ayP8AMJ8BAKxTuoB9uv8APJ8BALaAo2pRo/8ASJ8BAL7YhkoUhv8AVJ8BAL8C/fz7/f8AYJ8BALQI9e/t9f8AbJ8BAKoS69ra6/8AeJ8BAKgl3Ly93P8AhJ8BAK06yJ6ayP8AkJ8BAKxTuoB9uv8AnJ8BALaAo2pRo/8AqJ8BALy5j1Qnj/8AtJ8BAL//fT8Aff8AwJ8BAPL/Z2cAH/8Ayp8BAJbxYQUwYf8A1Z8BAPncsrIYK/8A358BAAWj1tZgTf8A6Z8BAA139PSlgv8A858BAA82/f3bx/8A/Z8BAI4g8NHl8P8AB6ABAI1X3pLF3v8AEaABAI+nw0OTw/8AG6ABAJTOrCFmrP8AJaABAPL/Z2cAH/8AL6ABAJTOrCFmrP8AOqABAJbxYQUwYf8ARaABAPncsrIYK/8AT6ABAAWj1tZgTf8AWaABAA139PSlgv8AY6ABAA82/f3bx/8AbaABAAAA9/f39/8Ad6ABAI4g8NHl8P8AgaABAI1X3pLF3v8Ai6ABAI+nw0OTw/8AlaABAAyW7++KYv8AnqABAAAA9/f39/8Ap6ABAI+Az2epz/8AsKABAPj/ysoAIP8AuaABAA139PSlgv8AwqABAI1X3pLF3v8Ay6ABAI/3sAVxsP8A1KABAPj/ysoAIP8A3aABAA139PSlgv8A5qABAAAA9/f39/8A76ABAI1X3pLF3v8A+KABAI/3sAVxsP8AAaEBAPncsrIYK/8ACqEBAAyW7++KYv8AE6EBAA82/f3bx/8AHKEBAI4g8NHl8P8AJaEBAI+Az2epz/8ALqEBAJTOrCFmrP8AN6EBAPncsrIYK/8AQKEBAAyW7++KYv8ASaEBAA82/f3bx/8AUqEBAAAA9/f39/8AW6EBAI4g8NHl8P8AZKEBAI+Az2epz/8AbaEBAJTOrCFmrP8AdqEBAPncsrIYK/8Af6EBAAWj1tZgTf8AiKEBAA139PSlgv8AkaEBAA82/f3bx/8AmqEBAI4g8NHl8P8Ao6EBAI1X3pLF3v8ArKEBAI+nw0OTw/8AtaEBAJTOrCFmrP8AvqEBAPncsrIYK/8Ax6EBAAWj1tZgTf8A0KEBAA139PSlgv8A2aEBAA82/f3bx/8A4qEBAAAA9/f39/8A66EBAI4g8NHl8P8A9KEBAI1X3pLF3v8A/aEBAI+nw0OTw/8ABqIBAJTOrCFmrP8AD6IBAPL/Z2cAH/8AGaIBAAAAGhoaGv8AJKIBAPncsrIYK/8ALqIBAAWj1tZgTf8AOKIBAA139PSlgv8AQqIBAA82/f3bx/8ATKIBAAAA4ODg4P8AVqIBAAAAurq6uv8AYKIBAAAAh4eHh/8AaqIBAAAATU1NTf8AdKIBAPL/Z2cAH/8AfqIBAAAATU1NTf8AiaIBAAAAGhoaGv8AlKIBAPncsrIYK/8AnqIBAAWj1tZgTf8AqKIBAA139PSlgv8AsqIBAA82/f3bx/8AvKIBAAAA//////8AxqIBAAAA4ODg4P8A0KIBAAAAurq6uv8A2qIBAAAAh4eHh/8A5KIBAAyW7++KYv8A7aIBAAAA//////8A9qIBAAAAmZmZmf8A/6IBAPj/ysoAIP8ACKMBAA139PSlgv8AEaMBAAAAurq6uv8AGqMBAAAAQEBAQP8AI6MBAPj/ysoAIP8ALKMBAA139PSlgv8ANaMBAAAA//////8APqMBAAAAurq6uv8AR6MBAAAAQEBAQP8AUKMBAPncsrIYK/8AWaMBAAyW7++KYv8AYqMBAA82/f3bx/8Aa6MBAAAA4ODg4P8AdKMBAAAAmZmZmf8AfaMBAAAATU1NTf8AhqMBAPncsrIYK/8Aj6MBAAyW7++KYv8AmKMBAA82/f3bx/8AoaMBAAAA//////8AqqMBAAAA4ODg4P8As6MBAAAAmZmZmf8AvKMBAAAATU1NTf8AxaMBAPncsrIYK/8AzqMBAAWj1tZgTf8A16MBAA139PSlgv8A4KMBAA82/f3bx/8A6aMBAAAA4ODg4P8A8qMBAAAAurq6uv8A+6MBAAAAh4eHh/8ABKQBAAAATU1NTf8ADaQBAPncsrIYK/8AFqQBAAWj1tZgTf8AH6QBAA139PSlgv8AKKQBAA82/f3bx/8AMaQBAAAA//////8AOqQBAAAA4ODg4P8AQ6QBAAAAurq6uv8ATKQBAAAAh4eHh/8AVaQBAAAATU1NTf8AXqQBAAMg/f3g3f8AZ6QBAPRc+vqftf8AcKQBAOPcxcUbiv8AeaQBAA0c/v7r4v8AgqQBAPxI+/u0uf8Ai6QBAO6T9/doof8AlKQBAOD9rq4Bfv8AnaQBAA0c/v7r4v8ApqQBAPxI+/u0uf8Ar6QBAO6T9/doof8AuKQBAOPcxcUbiv8AwaQBANX8enoBd/8AyqQBAA0c/v7r4v8A06QBAAM8/PzFwP8A3KQBAPRc+vqftf8A5aQBAO6T9/doof8A7qQBAOPcxcUbiv8A96QBANX8enoBd/8AAKUBAA0c/v7r4v8ACaUBAAM8/PzFwP8AEqUBAPRc+vqftf8AG6UBAO6T9/doof8AJKUBAObD3d00l/8ALaUBAOD9rq4Bfv8ANqUBANX8enoBd/8AP6UBAA4M///38/8ASKUBAAMg/f3g3f8AUaUBAAM8/PzFwP8AWqUBAPRc+vqftf8AY6UBAO6T9/doof8AbKUBAObD3d00l/8AdaUBAOD9rq4Bfv8AfqUBANX8enoBd/8Ah6UBAA4M///38/8AkKUBAAMg/f3g3f8AmaUBAAM8/PzFwP8AoqUBAPRc+vqftf8Aq6UBAO6T9/doof8AtKUBAObD3d00l/8AvaUBAOD9rq4Bfv8AxqUBANX8enoBd/8Az6UBAMf/akkAav8A2KUBAPX/paUAJv8A5KUBAKerlTE2lf8A8aUBAALQ19cwJ/8A/aUBAAq49PRtQ/8ACaYBABSd/f2uYf8AFaYBAB5u/v7gkP8AIaYBAIgY+ODz+P8ALaYBAIpD6avZ6f8AOaYBAI9x0XSt0f8ARaYBAJedtEV1tP8AUaYBAPX/paUAJv8AXaYBAJedtEV1tP8AaqYBAKerlTE2lf8Ad6YBAALQ19cwJ/8Ag6YBAAq49PRtQ/8Aj6YBABSd/f2uYf8Am6YBAB5u/v7gkP8Ap6YBACpA////v/8As6YBAIgY+ODz+P8Av6YBAIpD6avZ6f8Ay6YBAI9x0XSt0f8A16YBAA2k/PyNWf8A4qYBACpA////v/8A7aYBAI9W25G/2/8A+KYBAP7h19cZHP8AA6cBABSd/f2uYf8ADqcBAIpD6avZ6f8AGacBAJHBtix7tv8AJKcBAP7h19cZHP8AL6cBABSd/f2uYf8AOqcBACpA////v/8ARacBAIpD6avZ6f8AUKcBAJHBtix7tv8AW6cBAALQ19cwJ/8AZqcBAA2k/PyNWf8AcacBAB5u/v7gkP8AfKcBAIgY+ODz+P8Ah6cBAI9W25G/2/8AkqcBAJedtEV1tP8AnacBAALQ19cwJ/8AqKcBAA2k/PyNWf8As6cBAB5u/v7gkP8AvqcBACpA////v/8AyacBAIgY+ODz+P8A1KcBAI9W25G/2/8A36cBAJedtEV1tP8A6qcBAALQ19cwJ/8A9acBAAq49PRtQ/8AAKgBABSd/f2uYf8AC6gBAB5u/v7gkP8AFqgBAIgY+ODz+P8AIagBAIpD6avZ6f8ALKgBAI9x0XSt0f8AN6gBAJedtEV1tP8AQqgBAALQ19cwJ/8ATagBAAq49PRtQ/8AWKgBABSd/f2uYf8AY6gBAB5u/v7gkP8AbqgBACpA////v/8AeagBAIgY+ODz+P8AhKgBAIpD6avZ6f8Aj6gBAI9x0XSt0f8AmqgBAJedtEV1tP8ApagBAPX/paUAJv8AsagBAGv/aABoN/8AvqgBAALQ19cwJ/8AyqgBAAq49PRtQ/8A1qgBABSd/f2uYf8A4qgBAB9z/v7gi/8A7qgBADNq79nvi/8A+qgBAD6C2abZav8ABqkBAFN5vWa9Y/8AEqkBAGfTmBqYUP8AHqkBAPX/paUAJv8AKqkBAGfTmBqYUP8AN6kBAGv/aABoN/8ARKkBAALQ19cwJ/8AUKkBAAq49PRtQ/8AXKkBABSd/f2uYf8AaKkBAB9z/v7gi/8AdKkBACpA////v/8AgKkBADNq79nvi/8AjKkBAD6C2abZav8AmKkBAFN5vWa9Y/8ApKkBAA2k/PyNWf8Ar6kBACpA////v/8AuqkBAEKIz5HPYP8AxakBAP7h19cZHP8A0KkBABSd/f2uYf8A26kBAD6C2abZav8A5qkBAGLSlhqWQf8A8akBAP7h19cZHP8A/KkBABSd/f2uYf8AB6oBACpA////v/8AEqoBAD6C2abZav8AHaoBAGLSlhqWQf8AKKoBAALQ19cwJ/8AM6oBAA2k/PyNWf8APqoBAB9z/v7gi/8ASaoBADNq79nvi/8AVKoBAEKIz5HPYP8AX6oBAGfTmBqYUP8AaqoBAALQ19cwJ/8AdaoBAA2k/PyNWf8AgKoBAB9z/v7gi/8Ai6oBACpA////v/8AlqoBADNq79nvi/8AoaoBAEKIz5HPYP8ArKoBAGfTmBqYUP8At6oBAALQ19cwJ/8AwqoBAAq49PRtQ/8AzaoBABSd/f2uYf8A2KoBAB9z/v7gi/8A46oBADNq79nvi/8A7qoBAD6C2abZav8A+aoBAFN5vWa9Y/8ABKsBAGfTmBqYUP8AD6sBAALQ19cwJ/8AGqsBAAq49PRtQ/8AJasBABSd/f2uYf8AMKsBAB9z/v7gi/8AO6sBACpA////v/8ARqsBADNq79nvi/8AUasBAD6C2abZav8AXKsBAFN5vWa9Y/8AZ6sBAGfTmBqYUP8AcqsBAA0s/v7g0v8Ae6sBAAmL/PyScv8AhKsBAAHT3t4tJv8AjasBAA0l/v7l2f8AlqsBAAts/Pyukf8An6sBAAez+/tqSv8AqKsBAP3gy8sYHf8AsasBAA0l/v7l2f8AuqsBAAts/Pyukf8Aw6sBAAez+/tqSv8AzKsBAAHT3t4tJv8A1asBAP3npaUPFf8A3qsBAA0l/v7l2f8A56sBAAxc/Py7of8A8KsBAAmL/PyScv8A+asBAAez+/tqSv8AAqwBAAHT3t4tJv8AC6wBAP3npaUPFf8AFKwBAA0l/v7l2f8AHawBAAxc/Py7of8AJqwBAAmL/PyScv8AL6wBAAez+/tqSv8AOKwBAAPQ7+87LP8AQawBAP3gy8sYHf8ASqwBAPv/mZkADf8AU6wBAA4P///18P8AXKwBAA0s/v7g0v8AZawBAAxc/Py7of8AbqwBAAmL/PyScv8Ad6wBAAez+/tqSv8AgKwBAAPQ7+87LP8AiawBAP3gy8sYHf8AkqwBAPv/mZkADf8Am6wBAA4P///18P8ApKwBAA0s/v7g0v8ArawBAAxc/Py7of8AtqwBAAmL/PyScv8Av6wBAAez+/tqSv8AyKwBAAPQ7+87LP8A0awBAP3gy8sYHf8A2qwBAP3npaUPFf8A46wBAPn/Z2cADf8A7KwBAP7h5OQaHP8A9awBAJKyuDd+uP8A/qwBAFOTr02vSv8AB60BAP7h5OQaHP8AEK0BAJKyuDd+uP8AGa0BAFOTr02vSv8AIq0BAM+Eo5hOo/8AK60BAP7h5OQaHP8ANK0BAJKyuDd+uP8APa0BAFOTr02vSv8ARq0BAM+Eo5hOo/8AT60BABX///9/AP8AWK0BAP7h5OQaHP8AYa0BAJKyuDd+uP8Aaq0BAFOTr02vSv8Ac60BAM+Eo5hOo/8AfK0BABX///9/AP8Aha0BACrM////M/8Ajq0BAP7h5OQaHP8Al60BAJKyuDd+uP8AoK0BAFOTr02vSv8Aqa0BAM+Eo5hOo/8Asq0BABX///9/AP8Au60BACrM////M/8AxK0BAA/BpqZWKP8Aza0BAP7h5OQaHP8A1q0BAJKyuDd+uP8A360BAFOTr02vSv8A6K0BAM+Eo5hOo/8A8a0BABX///9/AP8A+q0BACrM////M/8AA64BAA/BpqZWKP8ADK4BAOh59/eBv/8AFa4BAP7h5OQaHP8AHq4BAJKyuDd+uP8AJ64BAFOTr02vSv8AMK4BAM+Eo5hOo/8AOa4BABX///9/AP8AQq4BACrM////M/8AS64BAA/BpqZWKP8AVK4BAOh59/eBv/8AXa4BAAAAmZmZmf8AZq4BAHJ4wmbCpf8Ab64BAAub/PyNYv8AeK4BAJxNy42gy/8Aga4BAHJ4wmbCpf8Aiq4BAAub/PyNYv8Ak64BAJxNy42gy/8AnK4BAORm5+eKw/8Apa4BAHJ4wmbCpf8Arq4BAAub/PyNYv8At64BAJxNy42gy/8AwK4BAORm5+eKw/8Aya4BADqb2KbYVP8A0q4BAHJ4wmbCpf8A264BAAub/PyNYv8A5K4BAJxNy42gy/8A7a4BAORm5+eKw/8A9q4BADqb2KbYVP8A/64BACLQ///ZL/8ACK8BAHJ4wmbCpf8AEa8BAAub/PyNYv8AGq8BAJxNy42gy/8AI68BAORm5+eKw/8ALK8BADqb2KbYVP8ANa8BACLQ///ZL/8APq8BABla5eXElP8AR68BAHJ4wmbCpf8AUK8BAAub/PyNYv8AWa8BAJxNy42gy/8AYq8BAORm5+eKw/8Aa68BADqb2KbYVP8AdK8BACLQ///ZL/8Afa8BABla5eXElP8Ahq8BAAAAs7Ozs/8Aj68BAHhU043Tx/8Ama8BANNSvbyAvf8ApK8BACpM////s/8Arq8BAK8l2r662v8AuK8BAASL+/uAcv8Awq8BAJBk04Cx0/8AzK8BABac/f20Yv8A1q8BADqG3rPeaf8A4K8BAOkv/PzN5f8A6q8BAAAA2dnZ2f8A9K8BAHhU043Tx/8A/q8BANNSvbyAvf8ACbABAE0p68zrxf8AFLABACpM////s/8AHrABAK8l2r662v8AKLABAASL+/uAcv8AMrABAJBk04Cx0/8APLABABac/f20Yv8ARrABADqG3rPeaf8AULABAOkv/PzN5f8AWrABAAAA2dnZ2f8AZLABAHhU043Tx/8AbrABANNSvbyAvf8AebABAE0p68zrxf8AhLABACWQ///tb/8Aj7ABACpM////s/8AmbABAK8l2r662v8Ao7ABAASL+/uAcv8ArbABAJBk04Cx0/8At7ABABac/f20Yv8AwbABADqG3rPeaf8Ay7ABAOkv/PzN5f8A1bABAAAA2dnZ2f8A37ABAHhU043Tx/8A6LABACpM////s/8A8bABAK8l2r662v8A+rABAHhU043Tx/8AA7EBACpM////s/8ADLEBAK8l2r662v8AFbEBAASL+/uAcv8AHrEBAHhU043Tx/8AJ7EBACpM////s/8AMLEBAK8l2r662v8AObEBAASL+/uAcv8AQrEBAJBk04Cx0/8AS7EBAHhU043Tx/8AVLEBACpM////s/8AXbEBAK8l2r662v8AZrEBAASL+/uAcv8Ab7EBAJBk04Cx0/8AeLEBABac/f20Yv8AgbEBAHhU043Tx/8AirEBACpM////s/8Ak7EBAK8l2r662v8AnLEBAASL+/uAcv8ApbEBAJBk04Cx0/8ArrEBABac/f20Yv8At7EBADqG3rPeaf8AwLEBAHhU043Tx/8AybEBACpM////s/8A0rEBAK8l2r662v8A27EBAASL+/uAcv8A5LEBAJBk04Cx0/8A7bEBABac/f20Yv8A9rEBADqG3rPeaf8A/7EBAOkv/PzN5f8ACLIBAHhU043Tx/8AEbIBACpM////s/8AGrIBAK8l2r662v8AI7IBAASL+/uAcv8ALLIBAJBk04Cx0/8ANbIBABac/f20Yv8APrIBADqG3rPeaf8AR7IBAOkv/PzN5f8AULIBAAAA2dnZ2f8AWbIBAO39np4BQv8AZ7IBALGCol5Pov8AdrIBAPq01dU+T/8AhLIBAAq49PRtQ/8AkrIBABSd/f2uYf8AoLIBAB9z/v7gi/8ArrIBADFg9eb1mP8AvLIBAE9B3avdpP8AyrIBAHJ4wmbCpf8A2LIBAI+7vTKIvf8A5rIBAO39np4BQv8A9LIBAI+7vTKIvf8AA7MBALGCol5Pov8AErMBAPq01dU+T/8AILMBAAq49PRtQ/8ALrMBABSd/f2uYf8APLMBAB9z/v7gi/8ASrMBACpA////v/8AWLMBADFg9eb1mP8AZrMBAE9B3avdpP8AdLMBAHJ4wmbCpf8AgrMBAA2k/PyNWf8Aj7MBACpA////v/8AnLMBAFFN1ZnVlP8AqbMBAP7h19cZHP8AtrMBABSd/f2uYf8Aw7MBAE9B3avdpP8A0LMBAI/EuiuDuv8A3bMBAP7h19cZHP8A6rMBABSd/f2uYf8A97MBACpA////v/8ABLQBAE9B3avdpP8AEbQBAI/EuiuDuv8AHrQBAPq01dU+T/8AK7QBAA2k/PyNWf8AOLQBAB9z/v7gi/8ARbQBADFg9eb1mP8AUrQBAFFN1ZnVlP8AX7QBAI+7vTKIvf8AbLQBAPq01dU+T/8AebQBAA2k/PyNWf8AhrQBAB9z/v7gi/8Ak7QBACpA////v/8AoLQBADFg9eb1mP8ArbQBAFFN1ZnVlP8AurQBAI+7vTKIvf8Ax7QBAPq01dU+T/8A1LQBAAq49PRtQ/8A4bQBABSd/f2uYf8A7rQBAB9z/v7gi/8A+7QBADFg9eb1mP8ACLUBAE9B3avdpP8AFbUBAHJ4wmbCpf8AIrUBAI+7vTKIvf8AL7UBAPq01dU+T/8APLUBAAq49PRtQ/8ASbUBABSd/f2uYf8AVrUBAB9z/v7gi/8AY7UBACpA////v/8AcLUBADFg9eb1mP8AfbUBAE9B3avdpP8AirUBAHJ4wmbCpf8Al7UBAI+7vTKIvf8ApLUBAJMP//D4//8As7UBABgj+vrr1/8AxbUBAH///wD///8Az7UBAHGA/3//1P8A37UBAH8P//D///8A6rUBACoa9fX13P8A9bUBABc6///kxP8AAbYBAAAAAAAAAP8ADLYBABkx///rzf8AILYBAKr//wAA//8AKrYBAMDO4oor4v8AOrYBAAC+paUqKv8ARbYBABdj3t64h/8AVLYBAIBnoF+eoP8AY7YBAD///3//AP8Ac7YBABHa0tJpHv8AgrYBAAuv//9/UP8AjbYBAJqT7WSV7f8AobYBACEi///43P8Ar7YBAPbn3NwUPP8AvLYBAH///wD///8AxrYBAKr/iwAAi/8A1LYBAH//iwCLi/8A4rYBAB7vuLiGC/8A9bYBAAAAqampqf8AA7cBAFX/ZABkAP8AErcBAAAAqampqf8AILcBACduvb23a/8AL7cBANT/i4sAi/8AQLcBADqOa1VrL/8AVLcBABf///+MAP8AZLcBAMbAzJkyzP8AdLcBAAD/i4sAAP8AgbcBAAp56emWev8AkbcBAFU9vI+8j/8Ao7cBAK+Pi0g9i/8AtrcBAH9nTy9PT/8AybcBAH9nTy9PT/8A3LcBAID/0QDO0f8A77cBAMf/05QA0/8A/7cBAOjr//8Uk/8ADbgBAIr//wC///8AHrgBAAAAaWlpaf8AK7gBAAAAaWlpaf8AOLgBAJTh/x6Q//8ASLgBAADOsrIiIv8AV7gBABwP///68P8AaLgBAFXAiyKLIv8AebgBANT///8A//8AhrgBAAAA3Nzc3P8AlbgBAKoH//j4//8ApbgBACP////XAP8Ar7gBAB7Z2tqlIP8AvrgBAAAAgICAgP8AyLgBAFX/gACAAP8A07gBADvQ/63/L/8A5LgBAAAAgICAgP8A7rgBAFUP//D/8P8A/LgBAOmW//9ptP8ACbkBAACMzc1cXP8AGLkBAML/gksAgv8AJLkBACoP////8P8AL7kBACZq8PDmjP8AOrkBAKoU+ubm+v8ASLkBAPAP///w9f8AW7kBAED//Hz8AP8AarkBACYx///6zf8AfLkBAIk/5q3Y5v8Ai7kBAAB38PCAgP8Am7kBAH8f/+D///8AqrkBACoo+vr60v8AxLkBAAAA09PT0/8A07kBAFVk7pDukP8A47kBAAAA09PT0/8A8rkBAPhJ//+2wf8AAboBAAyE//+gev8AEroBAH3RsiCyqv8AJboBAI91+ofO+v8AN7oBAJQ4mXeImf8AS7oBAJQ4mXeImf8AX7oBAJc03rDE3v8Ac7oBACof////4P8AhLoBAFX//wD/AP8AjroBAFXAzTLNMv8AnboBABUU+vrw5v8AqLoBANT///8A//8AtboBAAD/gIAAAP8AwboBAHGAzWbNqv8A17oBAKr/zQAAzf8A57oBAMyY07pV0/8A+boBALd825Nw2/8AC7sBAGepszyzcf8AH7sBALCP7nto7v8ANLsBAG//+gD6mv8AS7sBAH2n0UjRzP8AYLsBAOTkx8cVhf8AdbsBAKrGcBkZcP8Ah7sBAGoJ//X/+v8AlrsBAAQe///k4f8ApbsBABpJ///ktf8As7sBABlR///erf8AxLsBAKr/gAAAgP8AzrsBABsX/f315v8A27sBACr/gICAAP8A5rsBADjAjmuOI/8A9bsBABv///+lAP8AAbwBAAv///9FAP8AELwBANZ72tpw1v8AHLwBACZI7u7oqv8AL7wBAFVk+5j7mP8APrwBAH9D7q/u7v8AUbwBAPF829twk/8AZLwBABop///v1f8AdLwBABRG///auf8Ag7wBABSwzc2FP/8AjbwBAPc////Ay/8Al7wBANRG3d2g3f8AobwBAIQ75rDg5v8AsbwBANT/gIAAgP8AvbwBAAD///8AAP8AxrwBAAA9vLyPj/8A1bwBAJ+14UFp4f8A5LwBABHci4tFE/8A9bwBAASK+vqAcv8AAb0BABOa9PSkYP8AEb0BAGeqiy6LV/8AH70BABEQ///17v8ALb0BAA23oKBSLf8AOb0BAAAAwMDAwP8ARb0BAIts64fO6/8AUr0BAK+PzWpazf8AYb0BAJQ4kHCAkP8AcL0BAJQ4kHCAkP8Af70BAAAF///6+v8Aib0BAGr//wD/f/8Amr0BAJKbtEaCtP8Aqb0BABhU0tK0jP8Asr0BAH//gACAgP8AvL0BANQd2Ni/2P8Ayb0BAAa4//9jR/8A1b0BAHu24EDg0P8A5L0BANRz7u6C7v8A8L0BABtE9fXes/8A+70BAAAA//////8ABr4BAAAA9fX19f8AFr4BACr/////AP8AIr4BADjAzZrNMv8AM74BAC1D/Pf8uf8APL4BAERb3a3djv8ARb4BAGKyozGjVP8ATr4BACoy////zP8AV74BAD5V5sLmmf8AYL4BAFVkxnjGef8Aab4BAGO7hCOEQ/8Acr4BACoy////zP8Ae74BAD5V5sLmmf8AhL4BAFVkxnjGef8Ajb4BAGKyozGjVP8Alr4BAGv/aABoN/8An74BACoy////zP8AqL4BADdR8Nnwo/8Asb4BAERb3a3djv8Aur4BAFVkxnjGef8Aw74BAGKyozGjVP8AzL4BAGv/aABoN/8A1b4BACoy////zP8A3r4BADdR8Nnwo/8A574BAERb3a3djv8A8L4BAFVkxnjGef8A+b4BAGCeq0GrXf8AAr8BAGO7hCOEQ/8AC78BAGz/WgBaMv8AFL8BACoZ////5f8AHb8BAC1D/Pf8uf8AJr8BADdR8Nnwo/8AL78BAERb3a3djv8AOL8BAFVkxnjGef8AQb8BAGCeq0GrXf8ASr8BAGO7hCOEQ/8AU78BAGz/WgBaMv8AXL8BACoZ////5f8AZb8BAC1D/Pf8uf8Abr8BADdR8Nnwo/8Ad78BAERb3a3djv8AgL8BAFVkxnjGef8Aib8BAGCeq0GrXf8Akr8BAGO7hCOEQ/8Am78BAGv/aABoN/8ApL8BAG7/RQBFKf8Arb8BADFJ+O34sf8AuL8BAHVhzX/Nu/8Aw78BAJDCuCx/uP8Azr8BACoy////zP8A2b8BAGNC2qHatP8A5L8BAISqxEG2xP8A778BAJbLqCJeqP8A+r8BACoy////zP8ABcABAGNC2qHatP8AEMABAISqxEG2xP8AG8ABAJDCuCx/uP8AJsABAKS/lCU0lP8AMcABACoy////zP8APMABAEU66cfptP8AR8ABAHVhzX/Nu/8AUsABAISqxEG2xP8AXcABAJDCuCx/uP8AaMABAKS/lCU0lP8Ac8ABACoy////zP8AfsABAEU66cfptP8AicABAHVhzX/Nu/8AlMABAISqxEG2xP8An8ABAIvYwB2RwP8AqsABAJbLqCJeqP8AtcABAJ7nhAwshP8AwMABACom////2f8Ay8ABADFJ+O34sf8A1sABAEU66cfptP8A4cABAHVhzX/Nu/8A7MABAISqxEG2xP8A98ABAIvYwB2RwP8AAsEBAJbLqCJeqP8ADcEBAJ7nhAwshP8AGMEBACom////2f8AI8EBADFJ+O34sf8ALsEBAEU66cfptP8AOcEBAHVhzX/Nu/8ARMEBAISqxEG2xP8AT8EBAIvYwB2RwP8AWsEBAJbLqCJeqP8AZcEBAKS/lCU0lP8AcMEBAJ7nWAgdWP8Ae8EBACVC///3vP8AhsEBAByv/v7ET/8AkcEBABDu2dlfDv8AnMEBACoq////1P8Ap8EBABxw/v7Zjv8AssEBABbV/v6ZKf8AvcEBAA/8zMxMAv8AyMEBACoq////1P8A08EBABxw/v7Zjv8A3sEBABbV/v6ZKf8A6cEBABDu2dlfDv8A9MEBAA34mZk0BP8A/8EBACoq////1P8ACsIBAB9t/v7jkf8AFcIBAByv/v7ET/8AIMIBABbV/v6ZKf8AK8IBABDu2dlfDv8ANsIBAA34mZk0BP8AQcIBACoq////1P8ATMIBAB9t/v7jkf8AV8IBAByv/v7ET/8AYsIBABbV/v6ZKf8AbcIBABLp7OxwFP8AeMIBAA/8zMxMAv8Ag8IBAAz3jIwtBP8AjsIBACoZ////5f8AmcIBACVC///3vP8ApMIBAB9t/v7jkf8Ar8IBAByv/v7ET/8AusIBABbV/v6ZKf8AxcIBABLp7OxwFP8A0MIBAA/8zMxMAv8A28IBAAz3jIwtBP8A5sIBACoZ////5f8A8cIBACVC///3vP8A/MIBAB9t/v7jkf8AB8MBAByv/v7ET/8AEsMBABbV/v6ZKf8AHcMBABLp7OxwFP8AKMMBAA/8zMxMAv8AM8MBAA34mZk0BP8APsMBAA3wZmYlBv8AScMBACJf///toP8AVMMBABiy/v6yTP8AX8MBAAXd8PA7IP8AasMBACpN////sv8AdcMBAB2i/v7MXP8AgMMBABHC/f2NPP8Ai8MBAP7h4+MaHP8AlsMBACpN////sv8AocMBAB2i/v7MXP8ArMMBABHC/f2NPP8At8MBAAXd8PA7IP8AwsMBAPb/vb0AJv8AzcMBACpN////sv8A2MMBAB6I/v7Zdv8A48MBABiy/v6yTP8A7sMBABHC/f2NPP8A+cMBAAXd8PA7IP8ABMQBAPb/vb0AJv8AD8QBACpN////sv8AGsQBAB6I/v7Zdv8AJcQBABiy/v6yTP8AMMQBABHC/f2NPP8AO8QBAAfU/PxOKv8ARsQBAP7h4+MaHP8AUcQBAPX/sbEAJv8AXMQBACoy////zP8AZ8QBACJf///toP8AcsQBAB6I/v7Zdv8AfcQBABiy/v6yTP8AiMQBABHC/f2NPP8Ak8QBAAfU/PxOKv8AnsQBAP7h4+MaHP8AqcQBAPX/sbEAJv8AtMQBACoy////zP8Av8QBACJf///toP8AysQBAB6I/v7Zdv8A1cQBABiy/v6yTP8A4MQBABHC/f2NPP8A68QBAAfU/PxOKv8A9sQBAP7h4+MaHP8AAcUBAPb/vb0AJv8ADMUBAPL/gIAAJv8AF8UBAJMP//D4//8AIcUBABgj+vrr1/8ALsUBABck///v2/8APMUBABck7u7fzP8ASsUBABckzc3AsP8AWMUBABgii4uDeP8AZsUBAHGA/3//1P8AccUBAHGA/3//1P8AfcUBAHGA7nbuxv8AicUBAHGAzWbNqv8AlcUBAHGAi0WLdP8AocUBAH8P//D///8Ap8UBAH8P//D///8ArsUBAH8P7uDu7v8AtcUBAH8OzcHNzf8AvMUBAH8Oi4OLi/8Aw8UBACoa9fX13P8AycUBABc6///kxP8A0MUBABc6///kxP8A2MUBABc67u7Vt/8A4MUBABY6zc23nv8A6MUBABc6i4t9a/8A+twBAAAAAAAAAP8A8MUBABkx///rzf8A/8UBAKr//wAA//8ABMYBAKr//wAA//8ACsYBAKr/7gAA7v8AEMYBAKr/zQAAzf8AFsYBAKr/iwAAi/8AHMYBAMDO4oor4v8AJ8YBAAC+paUqKv8ALcYBAAC///9AQP8ANMYBAAC/7u47O/8AO8YBAAC/zc0zM/8AQsYBAAC+i4sjI/8AScYBABdj3t64h/8AU8YBABdk///Tm/8AXsYBABdj7u7Fkf8AacYBABdjzc2qff8AdMYBABdji4tzVf8Af8YBAIBnoF+eoP8AicYBAINn/5j1//8AlMYBAINm7o7l7v8An8YBAINnzXrFzf8AqsYBAINmi1OGi/8AtcYBAD///3//AP8AwMYBAD///3//AP8AzMYBAD//7nbuAP8A2MYBAD//zWbNAP8A5MYBAD//i0WLAP8A8MYBABHa0tJpHv8A+sYBABHb//9/JP8ABccBABHb7u52If8AEMcBABHazc1mHf8AG8cBABHci4tFE/8AJscBAAuv//9/UP8ALMcBAAep//9yVv8AM8cBAAap7u5qUP8AOscBAAapzc1bRf8AQccBAAaoi4s+L/8ASMcBAJqT7WSV7f8AV8cBACEi///43P8AYMcBACEi///43P8AascBACIj7u7ozf8AdMcBACIizc3Isf8AfscBACMii4uIeP8AiMcBAPbn3NwUPP8AkMcBAH///wD///8AlccBAH///wD///8Am8cBAH//7gDu7v8AoccBAH//zQDNzf8Ap8cBAH//iwCLi/8ArccBAB7vuLiGC/8Au8cBAB7w//+5D/8AyscBAB7w7u6tDv8A2ccBAB7wzc2VDP8A6McBAB7wi4tlCP8A98cBAFX/ZABkAP8AAcgBACduvb23a/8AC8gBADqOa1VrL/8AGsgBADqP/8r/cP8AKsgBADqP7rzuaP8AOsgBADqPzaLNWv8ASsgBADqPi26LPf8AWsgBABf///+MAP8AZcgBABX///9/AP8AccgBABX/7u52AP8AfcgBABX/zc1mAP8AicgBABX/i4tFAP8AlcgBAMbAzJkyzP8AoMgBAMbB/78+//8ArMgBAMbA7rI67v8AuMgBAMbAzZoyzf8AxMgBAMbAi2gii/8A0MgBAAp56emWev8A28gBAFU9vI+8j/8A6MgBAFU+/8H/wf8A9sgBAFU+7rTutP8ABMkBAFU+zZvNm/8AEskBAFU+i2mLaf8AIMkBAK+Pi0g9i/8ALskBAH9nTy9PT/8APMkBAH9o/5f///8AS8kBAH9n7o3u7v8AWskBAH9ozXnNzf8AackBAH9oi1KLi/8AeMkBAH9nTy9PT/8AhskBAID/0QDO0f8AlMkBAMf/05QA0/8An8kBAOjr//8Uk/8AqMkBAOjr//8Uk/8AsskBAOjr7u4Sif8AvMkBAOjrzc0Qdv8AxskBAOfsi4sKUP8A0MkBAIr//wC///8A3MkBAIr//wC///8A6ckBAIr/7gCy7v8A9skBAIr/zQCazf8AA8oBAIr/iwBoi/8AEMoBAAAAaWlpaf8AGMoBAAAAaWlpaf8AIMoBAJTh/x6Q//8AK8oBAJTh/x6Q//8AN8oBAJTh7hyG7v8AQ8oBAJThzRh0zf8AT8oBAJThixBOi/8AW8oBAADOsrIiIv8AZcoBAADP//8wMP8AcMoBAADP7u4sLP8Ae8oBAADPzc0mJv8AhsoBAADPi4saGv8AkcoBABwP///68P8AncoBAFXAiyKLIv8AqcoBAAAA3Nzc3P8As8oBAKoH//j4//8AvsoBACP////XAP8Aw8oBACP////XAP8AycoBACP/7u7JAP8Az8oBACP/zc2tAP8A1coBACP/i4t1AP8A28oBAB7Z2tqlIP8A5coBAB7a///BJf8A8MoBAB7a7u60Iv8A+8oBAB7azc2bHf8ABssBAB7ai4tpFP8AEcsBAAAAwMDAwP8AFssBAAAAAAAAAP8AHMsBAAAAAwMDA/8AIssBAAAAGhoaGv8AKcsBAAAA//////8AMcsBAAAAHBwcHP8AOMsBAAAAHx8fH/8AP8sBAAAAISEhIf8ARssBAAAAJCQkJP8ATcsBAAAAJiYmJv8AVMsBAAAAKSkpKf8AW8sBAAAAKysrK/8AYssBAAAALi4uLv8AacsBAAAAMDAwMP8AcMsBAAAABQUFBf8AdssBAAAAMzMzM/8AfcsBAAAANjY2Nv8AhMsBAAAAODg4OP8Ai8sBAAAAOzs7O/8AkssBAAAAPT09Pf8AmcsBAAAAQEBAQP8AoMsBAAAAQkJCQv8Ap8sBAAAARUVFRf8ArssBAAAAR0dHR/8AtcsBAAAASkpKSv8AvMsBAAAACAgICP8AwssBAAAATU1NTf8AycsBAAAAT09PT/8A0MsBAAAAUlJSUv8A18sBAAAAVFRUVP8A3ssBAAAAV1dXV/8A5csBAAAAWVlZWf8A7MsBAAAAXFxcXP8A88sBAAAAXl5eXv8A+ssBAAAAYWFhYf8AAcwBAAAAY2NjY/8ACMwBAAAACgoKCv8ADswBAAAAZmZmZv8AFcwBAAAAaWlpaf8AHMwBAAAAa2tra/8AI8wBAAAAbm5ubv8AKswBAAAAcHBwcP8AMcwBAAAAc3Nzc/8AOMwBAAAAdXV1df8AP8wBAAAAeHh4eP8ARswBAAAAenp6ev8ATcwBAAAAfX19ff8AVMwBAAAADQ0NDf8AWswBAAAAf39/f/8AYcwBAAAAgoKCgv8AaMwBAAAAhYWFhf8Ab8wBAAAAh4eHh/8AdswBAAAAioqKiv8AfcwBAAAAjIyMjP8AhMwBAAAAj4+Pj/8Ai8wBAAAAkZGRkf8AkswBAAAAlJSUlP8AmcwBAAAAlpaWlv8AoMwBAAAADw8PD/8ApswBAAAAmZmZmf8ArcwBAAAAnJycnP8AtMwBAAAAnp6env8Au8wBAAAAoaGhof8AwswBAAAAo6Ojo/8AycwBAAAApqampv8A0MwBAAAAqKioqP8A18wBAAAAq6urq/8A3swBAAAAra2trf8A5cwBAAAAsLCwsP8A7MwBAAAAEhISEv8A8swBAAAAs7Ozs/8A+cwBAAAAtbW1tf8AAM0BAAAAuLi4uP8AB80BAAAAurq6uv8ADs0BAAAAvb29vf8AFc0BAAAAv7+/v/8AHM0BAAAAwsLCwv8AI80BAAAAxMTExP8AKs0BAAAAx8fHx/8AMc0BAAAAycnJyf8AOM0BAAAAFBQUFP8APs0BAAAAzMzMzP8ARc0BAAAAz8/Pz/8ATM0BAAAA0dHR0f8AU80BAAAA1NTU1P8AWs0BAAAA1tbW1v8AYc0BAAAA2dnZ2f8AaM0BAAAA29vb2/8Ab80BAAAA3t7e3v8Ads0BAAAA4ODg4P8Afc0BAAAA4+Pj4/8AhM0BAAAAFxcXF/8Ais0BAAAA5eXl5f8Akc0BAAAA6Ojo6P8AmM0BAAAA6+vr6/8An80BAAAA7e3t7f8Aps0BAAAA8PDw8P8Arc0BAAAA8vLy8v8AtM0BAAAA9fX19f8Au80BAAAA9/f39/8Aws0BAAAA+vr6+v8Ayc0BAAAA/Pz8/P8A0M0BAFX//wD/AP8A1s0BAFX//wD/AP8A3c0BAFX/7gDuAP8A5M0BAFX/zQDNAP8A680BAFX/iwCLAP8A8s0BADvQ/63/L/8A/s0BAAAAwMDAwP8AA84BAAAAAAAAAP8ACc4BAAAAAwMDA/8AD84BAAAAGhoaGv8AFs4BAAAA//////8AHs4BAAAAHBwcHP8AJc4BAAAAHx8fH/8ALM4BAAAAISEhIf8AM84BAAAAJCQkJP8AOs4BAAAAJiYmJv8AQc4BAAAAKSkpKf8ASM4BAAAAKysrK/8AT84BAAAALi4uLv8AVs4BAAAAMDAwMP8AXc4BAAAABQUFBf8AY84BAAAAMzMzM/8Aas4BAAAANjY2Nv8Acc4BAAAAODg4OP8AeM4BAAAAOzs7O/8Af84BAAAAPT09Pf8Ahs4BAAAAQEBAQP8Ajc4BAAAAQkJCQv8AlM4BAAAARUVFRf8Am84BAAAAR0dHR/8Aos4BAAAASkpKSv8Aqc4BAAAACAgICP8Ar84BAAAATU1NTf8Ats4BAAAAT09PT/8Avc4BAAAAUlJSUv8AxM4BAAAAVFRUVP8Ay84BAAAAV1dXV/8A0s4BAAAAWVlZWf8A2c4BAAAAXFxcXP8A4M4BAAAAXl5eXv8A584BAAAAYWFhYf8A7s4BAAAAY2NjY/8A9c4BAAAACgoKCv8A+84BAAAAZmZmZv8AAs8BAAAAaWlpaf8ACc8BAAAAa2tra/8AEM8BAAAAbm5ubv8AF88BAAAAcHBwcP8AHs8BAAAAc3Nzc/8AJc8BAAAAdXV1df8ALM8BAAAAeHh4eP8AM88BAAAAenp6ev8AOs8BAAAAfX19ff8AQc8BAAAADQ0NDf8AR88BAAAAf39/f/8ATs8BAAAAgoKCgv8AVc8BAAAAhYWFhf8AXM8BAAAAh4eHh/8AY88BAAAAioqKiv8Aas8BAAAAjIyMjP8Acc8BAAAAj4+Pj/8AeM8BAAAAkZGRkf8Af88BAAAAlJSUlP8Ahs8BAAAAlpaWlv8Ajc8BAAAADw8PD/8Ak88BAAAAmZmZmf8Ams8BAAAAnJycnP8Aoc8BAAAAnp6env8AqM8BAAAAoaGhof8Ar88BAAAAo6Ojo/8Ats8BAAAApqampv8Avc8BAAAAqKioqP8AxM8BAAAAq6urq/8Ay88BAAAAra2trf8A0s8BAAAAsLCwsP8A2c8BAAAAEhISEv8A388BAAAAs7Ozs/8A5s8BAAAAtbW1tf8A7c8BAAAAuLi4uP8A9M8BAAAAurq6uv8A+88BAAAAvb29vf8AAtABAAAAv7+/v/8ACdABAAAAwsLCwv8AENABAAAAxMTExP8AF9ABAAAAx8fHx/8AHtABAAAAycnJyf8AJdABAAAAFBQUFP8AK9ABAAAAzMzMzP8AMtABAAAAz8/Pz/8AOdABAAAA0dHR0f8AQNABAAAA1NTU1P8AR9ABAAAA1tbW1v8ATtABAAAA2dnZ2f8AVdABAAAA29vb2/8AXNABAAAA3t7e3v8AY9ABAAAA4ODg4P8AatABAAAA4+Pj4/8AcdABAAAAFxcXF/8Ad9ABAAAA5eXl5f8AftABAAAA6Ojo6P8AhdABAAAA6+vr6/8AjNABAAAA7e3t7f8Ak9ABAAAA8PDw8P8AmtABAAAA8vLy8v8AodABAAAA9fX19f8AqNABAAAA9/f39/8Ar9ABAAAA+vr6+v8AttABAAAA/Pz8/P8AvdABAFUP//D/8P8AxtABAFUP//D/8P8A0NABAFUP7uDu4P8A2tABAFUOzcHNwf8A5NABAFUOi4OLg/8A7tABAOmW//9ptP8A9tABAOqR//9utP8A/9ABAOuN7u5qp/8ACNEBAOyHzc1gkP8AEdEBAOqUi4s6Yv8AGtEBAACMzc1cXP8AJNEBAACU//9qav8AL9EBAACU7u5jY/8AOtEBAACVzc1VVf8ARdEBAACUi4s6Ov8AUNEBAML/gksAgv8AV9EBACoA/////gAAXdEBACoP////8P8AY9EBACoP////8P8AatEBACoP7u7u4P8AcdEBACoOzc3Nwf8AeNEBACoOi4uLg/8Af9EBACZq8PDmjP8AhdEBACdw///2j/8AjNEBACdw7u7mhf8Ak9EBACdvzc3Gc/8AmtEBACdvi4uGTv8AodEBAKoU+ubm+v8AqtEBAPAP///w9f8AuNEBAPAP///w9f8Ax9EBAO8P7u7g5f8A1tEBAPAOzc3Bxf8A5dEBAO8Oi4uDhv8A9NEBAED//Hz8AP8A/tEBACYx///6zf8AC9IBACYx///6zf8AGdIBACUy7u7pv/8AJ9IBACYxzc3Jpf8ANdIBACcxi4uJcP8AQ9IBAIk/5q3Y5v8ATdIBAIpA/7/v//8AWNIBAIpA7rLf7v8AY9IBAIo/zZrAzf8AbtIBAIlAi2iDi/8AedIBAAB38PCAgP8AhNIBAH8f/+D///8AjtIBAH8f/+D///8AmdIBAH8f7tHu7v8ApNIBAH8fzbTNzf8Ar9IBAH8fi3qLi/8AutIBACNz7u7dgv8AydIBACN0///si/8A2dIBACNz7u7cgv8A6dIBACNzzc2+cP8A+dIBACNzi4uBTP8ACdMBACoo+vr60v8AHtMBAAAA09PT0/8AKNMBAAAA09PT0/8AMtMBAPhJ//+2wf8APNMBAPlR//+uuf8AR9MBAPhR7u6irf8AUtMBAPlQzc2Mlf8AXdMBAPlQi4tfZf8AaNMBAAyE//+gev8AdNMBAAyE//+gev8AgdMBAAuE7u6Vcv8AjtMBAAyFzc2BYv8Am9MBAAyFi4tXQv8AqNMBAH3RsiCyqv8AttMBAI91+ofO+v8Aw9MBAI9P/7Di//8A0dMBAI9P7qTT7v8A39MBAI5PzY22zf8A7dMBAI9Oi2B7i/8A+9MBAK+P/4Rw//8ACtQBAJQ4mXeImf8AGdQBAJQ4mXeImf8AKNQBAJc03rDE3v8AN9QBAJc1/8rh//8AR9QBAJc17rzS7v8AV9QBAJc1zaK1zf8AZ9QBAJY1i257i/8Ad9QBACof////4P8Ag9QBACof////4P8AkNQBACof7u7u0f8AndQBACofzc3NtP8AqtQBACofi4uLev8At9QBAFXAzTLNMv8AwdQBABUU+vrw5v8Ax9QBANT///8A//8Az9QBANT///8A//8A2NQBANT/7u4A7v8A4dQBANT/zc0Azf8A6tQBANT/i4sAi/8A89QBAO+5sLAwYP8A+tQBAOTL//80s/8AAtUBAOTL7u4wp/8ACtUBAOTMzc0pkP8AEtUBAOTLi4scYv8AGtUBAHGAzWbNqv8AK9UBAKr/zQAAzf8ANtUBAMyY07pV0/8AQ9UBAMuZ/+Bm//8AUdUBAMuZ7tFf7v8AX9UBAMuZzbRSzf8AbdUBAMuai3o3i/8Ae9UBALd825Nw2/8AiNUBALd9/6uC//8AltUBALd97p957v8ApNUBALd9zYlozf8AstUBALd8i11Hi/8AwNUBAGepszyzcf8Az9UBALCP7nto7v8A39UBAG//+gD6mv8A8dUBAH2n0UjRzP8AAdYBAOTkx8cVhf8AEdYBAKrGcBkZcP8AHtYBAGoJ//X/+v8AKNYBAAQe///k4f8AMtYBAAQe///k4f8APdYBAAQe7u7V0v8ASNYBAAMdzc23tf8AU9YBAAUdi4t9e/8AXtYBABpJ///ktf8AZ9YBABlR///erf8Ac9YBABlR///erf8AgNYBABlS7u7Pof8AjdYBABlSzc2zi/8AmtYBABlSi4t5Xv8Ap9YBAKr/gAAAgP8ArNYBAKr/gAAAgP8AtdYBACoA/////gAAutYBABsX/f315v8AwtYBADjAjmuOI/8AzNYBADjB/8D/Pv8A19YBADjA7rPuOv8A4tYBADjAzZrNMv8A7dYBADjAi2mLIv8A+NYBABv///+lAP8A/9YBABv///+lAP8AB9cBABv/7u6aAP8AD9cBABv/zc2FAP8AF9cBABv/i4taAP8AH9cBAAv///9FAP8AKdcBAAv///9FAP8ANNcBAAv/7u5AAP8AP9cBAAv/zc03AP8AStcBAAv/i4slAP8AVdcBANZ72tpw1v8AXNcBANZ8//+D+v8AZNcBANZ87u566f8AbNcBANZ8zc1pyf8AdNcBANV8i4tHif8AfNcBACZI7u7oqv8AitcBAFVk+5j7mP8AlNcBAFVl/5r/mv8An9cBAFVk7pDukP8AqtcBAFVkzXzNfP8AtdcBAFVki1SLVP8AwNcBAH9D7q/u7v8AztcBAH9E/7v///8A3dcBAH9E7q7u7v8A7NcBAH9EzZbNzf8A+9cBAH9Di2aLi/8ACtgBAPF829twk/8AGNgBAPF9//+Cq/8AJ9gBAPF97u55n/8ANtgBAPF9zc1oif8ARdgBAPF8i4tHXf8AVNgBABop///v1f8AX9gBABRG///auf8AadgBABRG///auf8AdNgBABNF7u7Lrf8Af9gBABNFzc2vlf8AitgBABRFi4t3Zf8AldgBABSwzc2FP/8AmtgBAPc////Ay/8An9gBAPVJ//+1xf8ApdgBAPVJ7u6puP8Aq9gBAPVKzc2Rnv8AsdgBAPVJi4tjbP8At9gBANRG3d2g3f8AvNgBANRE//+7//8AwtgBANRE7u6u7v8AyNgBANREzc2Wzf8AztgBANRDi4tmi/8A1NgBAIQ75rDg5v8A39gBAMTd8KAg8P8A5tgBAL/P/5sw//8A7tgBAMDP7pEs7v8A9tgBAMDPzX0mzf8A/tgBAMDPi1Uai/8ABtkBAAD///8AAP8ACtkBAAD///8AAP8AD9kBAAD/7u4AAP8AFNkBAAD/zc0AAP8AGdkBAAD/i4sAAP8AHtkBAAA9vLyPj/8AKNkBAAA+///Bwf8AM9kBAAA+7u60tP8APtkBAAA+zc2bm/8ASdkBAAA+i4tpaf8AVNkBAJ+14UFp4f8AXtkBAJ+3/0h2//8AadkBAJ+37kNu7v8AdNkBAJ+2zTpfzf8Af9kBAJ+3iydAi/8AitkBABHci4tFE/8AltkBAASK+vqAcv8AndkBAAmW//+Maf8ApdkBAAmW7u6CYv8ArdkBAAmWzc1wVP8AtdkBAAmWi4tMOf8AvdkBABOa9PSkYP8AyNkBAGeqiy6LV/8A0dkBAGer/1T/n/8A29kBAGer7k7ulP8A5dkBAGerzUPNgP8A79kBAGeqiy6LV/8A+dkBABEQ///17v8AAtoBABEQ///17v8ADNoBABIR7u7l3v8AFtoBABIRzc3Fv/8AINoBABIQi4uGgv8AKtoBAA23oKBSLf8AMdoBAA24//+CR/8AOdoBAA247u55Qv8AQdoBAA24zc1oOf8ASdoBAA25i4tHJv8AUdoBAIts64fO6/8AWdoBAJB4/4fO//8AYtoBAJB47n7A7v8Aa9oBAJB4zWymzf8AdNoBAJF3i0pwi/8AfdoBAK+PzWpazf8Ah9oBAK+Q/4Nv//8AktoBAK+Q7npn7v8AndoBAK+QzWlZzf8AqNoBAK+Qi0c8i/8As9oBAJQ4kHCAkP8AvdoBAJU4/8bi//8AyNoBAJU47rnT7v8A09oBAJQ5zZ+2zf8A3toBAJU4i2x7i/8A6doBAJQ4kHCAkP8A89oBAAAF///6+v8A+NoBAAAF///6+v8A/toBAAAF7u7p6f8ABNsBAAAEzc3Jyf8ACtsBAAADi4uJif8AENsBAGr//wD/f/8AHNsBAGr//wD/f/8AKdsBAGr/7gDudv8ANtsBAGr/zQDNZv8AQ9sBAGr/iwCLRf8AUNsBAJKbtEaCtP8AWtsBAJKc/2O4//8AZdsBAJKc7lys7v8AcNsBAJKczU+Uzf8Ae9sBAJObizZki/8AhtsBABhU0tK0jP8AitsBABSw//+lT/8Aj9sBABSw7u6aSf8AlNsBABSwzc2FP/8AmdsBABSwi4taK/8AntsBANQd2Ni/2P8AptsBANQe///h//8Ar9sBANQe7u7S7v8AuNsBANQdzc21zf8AwdsBANQdi4t7i/8AytsBAAa4//9jR/8A0dsBAAa4//9jR/8A2dsBAAa47u5cQv8A4dsBAAa4zc1POf8A6dsBAAa5i4s2Jv8AO90BACoA/////gAA8dsBAHu24EDg0P8A+9sBAIH//wD1//8ABtwBAIH/7gDl7v8AEdwBAIH/zQDFzf8AHNwBAIH/iwCGi/8AJ9wBANRz7u6C7v8ALtwBAOPX0NAgkP8AONwBAOvB//8+lv8AQ9wBAOvA7u46jP8ATtwBAOvAzc0yeP8AWdwBAOvAi4siUv8AZNwBABtE9fXes/8AatwBABtF///nuv8AcdwBABtE7u7Yrv8AeNwBABtEzc26lv8Af9wBABtDi4t+Zv8AhtwBAAAA//////8AjNwBAAAA9fX19f8Al9wBACr/////AP8AntwBACr/////AP8AptwBACr/7u7uAP8ArtwBACr/zc3NAP8AttwBACr/i4uLAP8AvtwBADjAzZrNMv8AReEBAE7dAQBQ3QEAUt0BAFTdAQBW3QEAWN0BAFrdAQBc3QEAXt0BAGDdAQBj3QEAZt0BAGndAQBs3QEAb90BAHLdAQB13QEAeN0BAHvdAQB+3QEAAAAAAAQAAAAEAAAABQAAADEAAAAQAAAAAAAAAAAAAAAAAAAACAAAABAAAAAYAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAACAAAABAAAAAYAAAAAAAAAAAAAAASAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAAAAAAADIAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAAAAAAADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMAAAAAAAAAAAAAAAAAAAAAAAAAlNcAABQAAABDLlVURi04AAAAAAAAAAAAAAAAAN4SBJUAAAAA////////////////AgAAwAMAAMAEAADABQAAwAYAAMAHAADACAAAwAkAAMAKAADACwAAwAwAAMANAADADgAAwA8AAMAQAADAEQAAwBIAAMATAADAFAAAwBUAAMAWAADAFwAAwBgAAMAZAADAGgAAwBsAAMAcAADAHQAAwB4AAMAfAADAAAAAswEAAMMCAADDAwAAwwQAAMMFAADDBgAAwwcAAMMIAADDCQAAwwoAAMMLAADDDAAAww0AANMOAADDDwAAwwAADLsBAAzDAgAMwwMADMMEAAzTeNgAAAkAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAHAAAAcqgCAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD42AAABQAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAcAAAB6rAIAAAQAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACv////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPjYAAB82QAABQAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAcAAACCsAIAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA//////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+JoCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAABAAAAAQAAAAGAAAAg/miAERObgD8KRUA0VcnAN009QBi28AAPJmVAEGQQwBjUf4Au96rALdhxQA6biQA0k1CAEkG4AAJ6i4AHJLRAOsd/gApsRwA6D6nAPU1ggBEuy4AnOmEALQmcABBfl8A1pE5AFODOQCc9DkAi1+EACj5vQD4HzsA3v+XAA+YBQARL+8AClqLAG0fbQDPfjYACcsnAEZPtwCeZj8ALepfALondQDl68cAPXvxAPc5BwCSUooA+2vqAB+xXwAIXY0AMANWAHv8RgDwq2sAILzPADb0mgDjqR0AXmGRAAgb5gCFmWUAoBRfAI1AaACA2P8AJ3NNAAYGMQDKVhUAyahzAHviYABrjMAAIAAAAAkAAAAKAAAADQAAAAsAAAAMAAAAhQAAAAAgAAABIAAAAiAAAAMgAAAEIAAABSAAAAYgAAAIIAAACSAAAAogAAAoIAAAKSAAAF8gAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAZAAAAOgDAAAQJwAAoIYBAEBCDwCAlpgAAOH1BV9wiQD/CS8PdAAAAPMOAgBuAAAA9Q4CAHIAAAD3DgIAZgAAAPkOAgBhAAAA+w4CAGUAAAD9DgIAdwAAAP8OAgBXAAAADA8CAHMAAAAaDwIAUwAAACYPAgBkAAAAMw8CAEQAAAA/DwIAAAAAAAAAAAAAAAAAAAAEAAQAGwAbACAAIAAjACEACgACABYACQAhACEAIQAVABwAAQAUABQAFAAUABQAFAAUAAgABAAFABsAAgAXABsAIAAfAB4AHQAJABMAAAAVABIAFQADAAcAFQAVABQAFAAUABQAFAAUABQAFAAIAAQABQAFAAYAGwAaABgAGQAgAAcAFQAUABQAFAAUABQAFAALABQADQAUAAwAFAAUABQADgAUABQAFAAQABQADwAUABEAAAAAAAAArgAuAC8AMwA1ADAANwCqANsA2wDbANsAAAA9AIcANwA3ANsA2wAAACgANQAuADIALwBiAAAAAABHAAAAAADbAFEAAADbANsA2wAAANsAhABVANsAggDbAAAAgQDbAAAAPgBCAEEASABEAFIAWwAAAAAAXgBfANsAAADbANsA2wAAAAAAewBJAFcAUgBaAFoAXQAAAF8AAABfAAAAZQBdAF8AAABdAG4AagAAAGkAAABuAAAA2wCTAJoAoQCoAKsAcACxALgAvwDGAM0A0wAAAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAMABAAHAAMABAAFAAUABgAGAAgABwAHABEAFgASABEAEgAIAAgADwAPABcADwAYAA8AGQAaABoAHgAWADQAHgAFADIABgAiACIAMwAXABgANQAZABoAGgAqADYAKgA0ADcAMgBFADsAPAAzADsAPABGADUARwBIAEwANgAiAEkASgA3AEUATgBQAGIAUQBSAFQARgBHAFUASABMAFYASQBKAFgAWgBOAEQAUABRAFIAVAA4AC8ALABVACkAVgAbABAAWABaAF0AXQBdAF0AXQBdAF0AXgBeAF4AXgBeAF4AXgBfAF8AXwBfAF8AXwBfAGAACQBgAGAAYABgAGAAYQBhAGMAAgBjAGMAYwBjAGMAZAAAAGQAAABkAGQAZABlAAAAZQBlAGUAZQBlAGYAZgAAAGYAZgBmAGYAZwAAAGcAZwBnAGcAaAAAAGgAaABoAGgAaABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAAAAXAABAF0AXQBeAF4AXwBfAFwAXABcAFwAXABgAFwAXABcAGEAXABcAGIAYgBiAGIAYgBiAGIAYwBkAGUAZgBmAFwAXABnAFwAXABcAGAAXABcAGEAXABhAFwAaABhAFwAYgBiAGIAYgBiAGIAYgBiAGMAZABlAGUAXABmAFwAXABcAGcAaABhAGIAYgBiAGIAYgBiAGIAYgBiAGIAYgBiAGIAYgBiAGIAYgBiAGIAYgBiAGIAYgAAAFwAXABcAFwAXABcAFwAXABcAFwAXABcAAAACgALAAwADQAOAAoADwAQABEAEgATAAoAFAAVABUAFQAWABcAFQAYABUAFQAZABUAFQAVABoAFQAVAAoAFQAVABUAFgAXABgAFQAVABkAFQAVABUAGgAVABUAFQAVABsADAAMACQAHgAeACAAIQAgACEAJAAlACYALQAyAC8ALgAqACUAJgAoACkAMwAqADQAKwA1ADYANwA8ADIARwA9ACIARQAiAD8AQABGADMANABIADUANgA3AC8ASQAqAEcASgBFAEwAXAA8AEYAXAA9AE0ASABOAE8AUgBJAEEAUABRAEoATABTAFQAMQBVAFYAVwBNAE4AWABPAFIAWQBQAFEAWgBbAFMARABUAFUAVgBXAEsARAAsAFgALABZADgALABaAFsAHQAdAB0AHQAdAB0AHQAfAB8AHwAfAB8AHwAfACMAIwAjACMAIwAjACMAJwBcACcAJwAnACcAJwAwADAAOQAcADkAOQA5ADkAOQA6AFwAOgBcADoAOgA6ADsAXAA7ADsAOwA7ADsAPgA+AFwAPgA+AD4APgBCAFwAQgBCAEIAQgBDAFwAQwBDAEMAQwBDAAkAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwACACu/9EACgCu/67/CwCu/67/rv+u/67/rv+u/67/BQDRAK7/0QDRANEA0QDRANEA0QDRAK7/+/+u/w4A7P+u/67/rv+u/9EA0QDRANEA0QANACUADABCABAAUAATAG0AewAUAJgADwCmAMMArv+u/67/rv+u/67/rv+u/67/rv+u/67/rv+u/67/rv+u/67/rv+u/67/rv+u/67/FwCu/3cArv8HAC4Arv8mAK7/FwARACMArv8NAK7/rv+u/67/OgCu/67/NQCu/67/rv8oAK7/BwCu/zsARQCu/0gArv+u/67/rv+u/67/rv/8/+gA9v///xoAAAAnAAEAMgCu/67/AgAkAAMALwCu/67/rv+u/67//v+UAK7/CQAbAK7/vP+u/67/r/+u/67/rv+u/67/rv+u/wAAAAAAAG3m7N4FAAsASQAxAVMAfwEwAWkAeAH/AIEBUwKCAYMBhAGFAYYBVAKHAYgBiQFWAooBVwKLAYwBjgHdAY8BWQKQAVsCkQGSAZMBYAKUAWMClgFpApcBaAKYAZkBnAFvAp0BcgKfAXUCpgGAAqcBqAGpAYMCrAGtAa4BiAKvAbABsQGKArIBiwK3AZICuAG5AbwBvQHEAcYBxAHFAcUBxgHHAckBxwHIAcgByQHKAcwBygHLAcsBzAHxAfMB8QHyAfIB8wH0AfUB9gGVAfcBvwEgAp4BhgOsA4gDrQOJA64DigOvA4wDzAOOA80DjwPOA5kDRQOZA74fowPCA/cD+AP6A/sDYB6bHp4e3wBZH1EfWx9TH10fVR9fH1cfvB+zH8wfwx/sH+Uf/B/zHzoCZSw7AjwCPQKaAT4CZixBAkICQwKAAUQCiQJFAowC9AO4A/kD8gP9A3sD/gN8A/8DfQPABM8EJiHJAyohawArIeUAMiFOIYMhhCFgLGEsYixrAmMsfR1kLH0CbSxRAm4scQJvLFACcCxSAnIscyx1LHYsfiw/An8sQALyLPMsfad5HYunjKeNp2UCqqdmAscQJy3NEC0tdgN3A5wDtQCSA9ADmAPRA6YD1QOgA9YDmgPwA6ED8QOVA/UDzwPXAwAAAABBACAawAAgHwABAS8yAQEFOQEBD0oBAS15AQEFcAMBA5EDIBGjAyAJAARQEBAEICBgBAEhigQBNcEEAQ3QBAE/FAUBEzEFMCagAQEFswEBA80BAQ/eAQER+AEBJyICARHYAwEXAB4BlaAeAV8IH/gIGB/4Bigf+Ag4H/gISB/4Bmgf+AiIH/gImB/4CKgf+Ai4H/gCuh+2AsgfqgTYH/gC2h+cAugf+ALqH5AC+B+AAvofggJGAgEJEAUBA2AhEBAALDAvZywBBYAsAWPrLAEDQKYBLYCmARcipwENMqcBPXmnAQN+pwEJkKcBA6CnAQkh/yAaAAAAAHsgdmFyIHBhdGggPSBQb2ludGVyX3N0cmluZ2lmeSgkMCk7IHZhciBkYXRhID0gUG9pbnRlcl9zdHJpbmdpZnkoJDEpOyBGUy5jcmVhdGVQYXRoKCIvIiwgUEFUSC5kaXJuYW1lKHBhdGgpKTsgRlMud3JpdGVGaWxlKFBBVEguam9pbigiLyIsIHBhdGgpLCBkYXRhKTsgfQBjb3JlAHhkb3R2ZXJzaW9uADEuNwAxLjQAMS4yAF9sZHJhd18AX2hkcmF3XwBfdGRyYXdfAF9obGRyYXdfAF90bGRyYXdfAHhkb3QgdmVyc2lvbiAiJXMiIHRvbyBsb25nACAlZCAAJS4wMmYAJXMlZCAtACMlMDJ4JTAyeCUwMnglMDJ4AHNldGxpbmV3aWR0aCgAJS4zZgBTIABDIAAyIAAlLjAzZgBFIABlIABGIAB0ICV1IABUIABkb3Q6ZG90AGd2OmRvdABjYW5vbjpkb3QAcGxhaW46ZG90AHBsYWluLWV4dDpkb3QAeGRvdDp4ZG90AHhkb3QxLjI6eGRvdAB4ZG90MS40Onhkb3QASSAAIl9zdWJncmFwaF9jbnQiOiAlZAAiX2d2aWQiOiAlZAAiZWRnZXMiOiBbCgAiX2d2aWQiOiAlZCwKACJ0YWlsIjogJWQsCgAiaGVhZCI6ICVkACJvYmplY3RzIjogWwoAIm5vZGVzIjogWwoAIm5hbWUiOiAiJXMiAFwiAFwvAFxiAFxmAFxuAFxyAFx0ACJzdWJncmFwaHMiOiBbCgAiJXMiOiAAIiVzIgBDb3VsZCBub3QgcGFyc2UgeGRvdCAiJXMiCgBbCgAib3AiOiAiJWMiLAoAInJlY3QiOiBbJS4wM2YsJS4wM2YsJS4wM2YsJS4wM2ZdCgAib3AiOiAiTCIsCgAib3AiOiAiVCIsCgAicHQiOiBbJS4wM2YsJS4wM2ZdLAoAImFsaWduIjogIiVjIiwKACJ3aWR0aCI6ICUuMDNmLAoAInRleHQiOiAiJXMiCgAiZ3JhZCI6ICJub25lIiwKACJjb2xvciI6ICIlcyIKACJncmFkIjogImxpbmVhciIsCgAiZ3JhZCI6ICJyYWRpYWwiLAoAIm9wIjogIkYiLAoAInNpemUiOiAlLjAzZiwKACJmYWNlIjogIiVzIgoAIm9wIjogIlMiLAoAInN0eWxlIjogIiVzIgoAIm9wIjogInQiLAoAImZvbnRjaGFyIjogJWQKACJwMCI6IFslLjAzZiwlLjAzZiwlLjAzZl0sCgAicDEiOiBbJS4wM2YsJS4wM2YsJS4wM2ZdLAoAInN0b3BzIjogWwB7ImZyYWMiOiAlLjAzZiwgImNvbG9yIjogIiVzIn0AXQoAInAwIjogWyUuMDNmLCUuMDNmXSwKACJwMSI6IFslLjAzZiwlLjAzZl0sCgAicG9pbnRzIjogWwBbJS4wM2YsJS4wM2ZdAGRyYXdfAGxkcmF3XwBoZHJhd18AdGRyYXdfAGhsZHJhd18AdGxkcmF3XwAiZGlyZWN0ZWQiOiAlcywKACJzdHJpY3QiOiAlcwAgIABEdXBsaWNhdGUgY2x1c3RlciBuYW1lICIlcyIKAHhkb3QAanNvbgBqc29uMABkb3RfanNvbgB4ZG90X2pzb24AanNvbjpqc29uAGpzb24wOmpzb24AZG90X2pzb246anNvbgB4ZG90X2pzb246anNvbgBuID49IDQAZ3ZyZW5kZXJfY29yZV9maWcuYwBmaWdfYmV6aWVyAGZpZ19yZXNvbHZlX2NvbG9yAGZpZwBmaWc6ZmlnAG1hcAByZWN0ICVzICVkLCVkICVkLCVkCgBjaXJjbGUgJXMgJWQsJWQsJWQKAHBvbHkgJXMAICVkLCVkAGd2cmVuZGVyX2NvcmVfbWFwLmMAbWFwX291dHB1dF9zaGFwZQByZWN0YW5nbGUgKCVkLCVkKSAoJWQsJWQpICVzICVzCgA8YXJlYSBzaGFwZT0iY2lyY2xlIgA8YXJlYSBzaGFwZT0icmVjdCIAPGFyZWEgc2hhcGU9InBvbHkiACBocmVmPSIAIHRpdGxlPSIAIGFsdD0iIgAgY29vcmRzPSIAJWQsJWQsJWQAJWQsJWQsJWQsJWQAJWQsJWQALCVkLCVkACI+CgA8L21hcD4KAGJhc2UgcmVmZXJlcgoAZGVmYXVsdCAAPG1hcCBpZD0iACIgbmFtZT0iAGlzbWFwOm1hcABjbWFwOm1hcABpbWFwOm1hcABjbWFweDptYXAAaW1hcF9ucDptYXAAY21hcHhfbnA6bWFwACMgJXMKACVkICVkICVkICVkICVkICVkICVkICVkICVkICUuMWYgJWQgJWQgJWQgJWQgJWQgJWQKACVkICVkICVkICVkICVkICVkICVkICVkICVkICUuMWYgJWQgJWQgJWQgJWQKACVkICVkICVkICVkICVkICVkICVkICVkICVkICUuM2YgJWQgJS40ZiAlZCAlZCAlZCAlZCAlZCAlZCAlZCAlZAoAJWQgJWQgIyUwMnglMDJ4JTAyeAoAZ3ZyZW5kZXJfY29yZV9tcC5jAG1wX3Jlc29sdmVfY29sb3IAJWQgJWQgJWQgJWQgJWQgJWQgJS4xZiAlLjRmICVkICUuMWYgJS4xZiAlZCAlZCAlc1wwMDEKACMgZW5kIG9mIEZJRyBmaWxlCgAjRklHIDMuMgoAIyBHZW5lcmF0ZWQgYnkgJXMgdmVyc2lvbiAlcyAoJXMpCgAjIFRpdGxlOiAlcwoAIyBQYWdlczogJWQKAFBvcnRyYWl0CgBDZW50ZXIKAEluY2hlcwoATGV0dGVyCgAxMDAuMDAKAFNpbmdsZQoALTIKADEyMDAAIDIKAG1wAG1wOm1wACBdICAlZCB0cnVlICVzCgAgXSAgJWQgZmFsc2UgJXMKACBzZXRsaW5ld2lkdGgKACVzIABzZXRoc2IAJS41ZyAlLjVnICUuNWcgJXNjb2xvcgoAJSAAbmV3cGF0aCAAIG1vdmV0bwoAIGxpbmV0bwoAc3Ryb2tlCgAgY3VydmV0bwoAY2xvc2VwYXRoIGZpbGwKAGNsb3NlcGF0aCBzdHJva2UKACBlbGxpcHNlX3BhdGggZmlsbAoAIGVsbGlwc2VfcGF0aCBzdHJva2UKACAvJXMgc2V0X2ZvbnQKACBtb3ZldG8gACAlcyBhbGlnbmVkdGV4dAoAWyAvUmVjdCBbIAAgXQoAICAvQm9yZGVyIFsgMCAwIDAgXQogIC9BY3Rpb24gPDwgL1N1YnR5cGUgL1VSSSAvVVJJICVzID4+CiAgL1N1YnR5cGUgL0xpbmsKL0FOTiBwZGZtYXJrCgBnc2F2ZQoAJSUgJXMKADAgMCAwIGVkZ2Vjb2xvcgoAZW5kcGFnZQpzaG93cGFnZQpncmVzdG9yZQoAJSVQYWdlVHJhaWxlcgoAJSUlJUVuZFBhZ2U6ICVkCgAlJSUlUGFnZTogJWQgJWQKACUlJSVQYWdlQm91bmRpbmdCb3g6ICVkICVkICVkICVkCgBMYW5kc2NhcGUAUG9ydHJhaXQAJSUlJVBhZ2VPcmllbnRhdGlvbjogJXMKADw8IC9QYWdlU2l6ZSBbJWQgJWRdID4+IHNldHBhZ2VkZXZpY2UKACVkICVkICVkIGJlZ2lucGFnZQoAZ3NhdmUKJWQgJWQgJWQgJWQgYm94cHJpbSBjbGlwIG5ld3BhdGgKACVnICVnIHNldF9zY2FsZSAlZCByb3RhdGUgJWcgJWcgdHJhbnNsYXRlCgBjYW52YXMgc2l6ZSAoJWQsJWQpIGV4Y2VlZHMgUERGIGxpbWl0ICglZCkKCShzdWdnZXN0IHNldHRpbmcgYSBib3VuZGluZyBib3ggc2l6ZSwgc2VlIGRvdCgxKSkKAFsgL0Nyb3BCb3ggWyVkICVkICVkICVkXSAvUEFHRVMgcGRmbWFyawoAJWQgJWQgc2V0bGF5ZXIKACUlJSVUaXRsZTogJXMKACUlUGFnZXM6IChhdGVuZCkKACUlUGFnZXM6IDEKACUlQm91bmRpbmdCb3g6IChhdGVuZCkKACUlJSVCb3VuZGluZ0JveDogJWQgJWQgJWQgJWQKACUlRW5kQ29tbWVudHMKc2F2ZQoAc2V0dXBMYXRpbjEKAFsge0NhdGFsb2d9IDw8IC9VUkkgPDwgL0Jhc2UgJXMgPj4gPj4KL1BVVCBwZGZtYXJrCgAlJUJlZ2luUHJvbG9nAC9Eb3REaWN0IDIwMCBkaWN0IGRlZgBEb3REaWN0IGJlZ2luAC9zZXR1cExhdGluMSB7AG1hcmsAL0VuY29kaW5nVmVjdG9yIDI1NiBhcnJheSBkZWYAIEVuY29kaW5nVmVjdG9yIDAASVNPTGF0aW4xRW5jb2RpbmcgMCAyNTUgZ2V0aW50ZXJ2YWwgcHV0aW50ZXJ2YWwARW5jb2RpbmdWZWN0b3IgNDUgL2h5cGhlbiBwdXQAJSBTZXQgdXAgSVNPIExhdGluIDEgY2hhcmFjdGVyIGVuY29kaW5nAC9zdGFybmV0SVNPIHsAICAgICAgICBkdXAgZHVwIGZpbmRmb250IGR1cCBsZW5ndGggZGljdCBiZWdpbgAgICAgICAgIHsgMSBpbmRleCAvRklEIG5lIHsgZGVmIH17IHBvcCBwb3AgfSBpZmVsc2UAICAgICAgICB9IGZvcmFsbAAgICAgICAgIC9FbmNvZGluZyBFbmNvZGluZ1ZlY3RvciBkZWYAICAgICAgICBjdXJyZW50ZGljdCBlbmQgZGVmaW5lZm9udAB9IGRlZgAvVGltZXMtUm9tYW4gc3Rhcm5ldElTTyBkZWYAL1RpbWVzLUl0YWxpYyBzdGFybmV0SVNPIGRlZgAvVGltZXMtQm9sZCBzdGFybmV0SVNPIGRlZgAvVGltZXMtQm9sZEl0YWxpYyBzdGFybmV0SVNPIGRlZgAvSGVsdmV0aWNhIHN0YXJuZXRJU08gZGVmAC9IZWx2ZXRpY2EtT2JsaXF1ZSBzdGFybmV0SVNPIGRlZgAvSGVsdmV0aWNhLUJvbGQgc3Rhcm5ldElTTyBkZWYAL0hlbHZldGljYS1Cb2xkT2JsaXF1ZSBzdGFybmV0SVNPIGRlZgAvQ291cmllciBzdGFybmV0SVNPIGRlZgAvQ291cmllci1PYmxpcXVlIHN0YXJuZXRJU08gZGVmAC9Db3VyaWVyLUJvbGQgc3Rhcm5ldElTTyBkZWYAL0NvdXJpZXItQm9sZE9ibGlxdWUgc3Rhcm5ldElTTyBkZWYAY2xlYXJ0b21hcmsAfSBiaW5kIGRlZgAlJUJlZ2luUmVzb3VyY2U6IHByb2NzZXQgZ3JhcGh2aXogMCAwAC9jb29yZC1mb250LWZhbWlseSAvVGltZXMtUm9tYW4gZGVmAC9kZWZhdWx0LWZvbnQtZmFtaWx5IC9UaW1lcy1Sb21hbiBkZWYAL2Nvb3JkZm9udCBjb29yZC1mb250LWZhbWlseSBmaW5kZm9udCA4IHNjYWxlZm9udCBkZWYAL0ludlNjYWxlRmFjdG9yIDEuMCBkZWYAL3NldF9zY2FsZSB7ACAgICAgICBkdXAgMSBleGNoIGRpdiAvSW52U2NhbGVGYWN0b3IgZXhjaCBkZWYAICAgICAgIHNjYWxlACUgc3R5bGVzAC9zb2xpZCB7IFtdIDAgc2V0ZGFzaCB9IGJpbmQgZGVmAC9kYXNoZWQgeyBbOSBJbnZTY2FsZUZhY3RvciBtdWwgZHVwIF0gMCBzZXRkYXNoIH0gYmluZCBkZWYAL2RvdHRlZCB7IFsxIEludlNjYWxlRmFjdG9yIG11bCA2IEludlNjYWxlRmFjdG9yIG11bF0gMCBzZXRkYXNoIH0gYmluZCBkZWYAL2ludmlzIHsvZmlsbCB7bmV3cGF0aH0gZGVmIC9zdHJva2Uge25ld3BhdGh9IGRlZiAvc2hvdyB7cG9wIG5ld3BhdGh9IGRlZn0gYmluZCBkZWYAL2JvbGQgeyAyIHNldGxpbmV3aWR0aCB9IGJpbmQgZGVmAC9maWxsZWQgeyB9IGJpbmQgZGVmAC91bmZpbGxlZCB7IH0gYmluZCBkZWYAL3JvdW5kZWQgeyB9IGJpbmQgZGVmAC9kaWFnb25hbHMgeyB9IGJpbmQgZGVmAC90YXBlcmVkIHsgfSBiaW5kIGRlZgAlIGhvb2tzIGZvciBzZXR0aW5nIGNvbG9yIAAvbm9kZWNvbG9yIHsgc2V0aHNiY29sb3IgfSBiaW5kIGRlZgAvZWRnZWNvbG9yIHsgc2V0aHNiY29sb3IgfSBiaW5kIGRlZgAvZ3JhcGhjb2xvciB7IHNldGhzYmNvbG9yIH0gYmluZCBkZWYAL25vcGNvbG9yIHtwb3AgcG9wIHBvcH0gYmluZCBkZWYAL2JlZ2lucGFnZSB7CSUgaSBqIG5wYWdlcwAJL25wYWdlcyBleGNoIGRlZgAJL2ogZXhjaCBkZWYACS9pIGV4Y2ggZGVmAAkvc3RyIDEwIHN0cmluZyBkZWYACW5wYWdlcyAxIGd0IHsACQlnc2F2ZQAJCQljb29yZGZvbnQgc2V0Zm9udAAJCQkwIDAgbW92ZXRvAAkJCShcKCkgc2hvdyBpIHN0ciBjdnMgc2hvdyAoLCkgc2hvdyBqIHN0ciBjdnMgc2hvdyAoXCkpIHNob3cACQlncmVzdG9yZQAJfSBpZgAvc2V0X2ZvbnQgewAJZmluZGZvbnQgZXhjaAAJc2NhbGVmb250IHNldGZvbnQAJSBkcmF3IHRleHQgZml0dGVkIHRvIGl0cyBleHBlY3RlZCB3aWR0aAAvYWxpZ25lZHRleHQgewkJCSUgd2lkdGggdGV4dAAJL3RleHQgZXhjaCBkZWYACS93aWR0aCBleGNoIGRlZgAJZ3NhdmUACQl3aWR0aCAwIGd0IHsACQkJW10gMCBzZXRkYXNoAAkJCXRleHQgc3RyaW5nd2lkdGggcG9wIHdpZHRoIGV4Y2ggc3ViIHRleHQgbGVuZ3RoIGRpdiAwIHRleHQgYXNob3cACQl9IGlmAAlncmVzdG9yZQAvYm94cHJpbSB7CQkJCSUgeGNvcm5lciB5Y29ybmVyIHhzaXplIHlzaXplAAkJNCAyIHJvbGwACQltb3ZldG8ACQkyIGNvcHkACQlleGNoIDAgcmxpbmV0bwAJCTAgZXhjaCBybGluZXRvAAkJcG9wIG5lZyAwIHJsaW5ldG8ACQljbG9zZXBhdGgAL2VsbGlwc2VfcGF0aCB7AAkvcnkgZXhjaCBkZWYACS9yeCBleGNoIGRlZgAJL3kgZXhjaCBkZWYACS94IGV4Y2ggZGVmAAltYXRyaXggY3VycmVudG1hdHJpeAAJbmV3cGF0aAAJeCB5IHRyYW5zbGF0ZQAJcnggcnkgc2NhbGUACTAgMCAxIDAgMzYwIGFyYwAJc2V0bWF0cml4AC9lbmRwYWdlIHsgc2hvd3BhZ2UgfSBiaW5kIGRlZgAvc2hvd3BhZ2UgeyB9IGRlZgAvbGF5ZXJjb2xvcnNlcQAJWwklIGxheWVyIGNvbG9yIHNlcXVlbmNlIC0gZGFya2VzdCB0byBsaWdodGVzdAAJCVswIDAgMF0ACQlbLjIgLjggLjhdAAkJWy40IC44IC44XQAJCVsuNiAuOCAuOF0ACQlbLjggLjggLjhdAAldAGRlZgAvbGF5ZXJsZW4gbGF5ZXJjb2xvcnNlcSBsZW5ndGggZGVmAC9zZXRsYXllciB7L21heGxheWVyIGV4Y2ggZGVmIC9jdXJsYXllciBleGNoIGRlZgAJbGF5ZXJjb2xvcnNlcSBjdXJsYXllciAxIHN1YiBsYXllcmxlbiBtb2QgZ2V0AAlhbG9hZCBwb3Agc2V0aHNiY29sb3IACS9ub2RlY29sb3Ige25vcGNvbG9yfSBkZWYACS9lZGdlY29sb3Ige25vcGNvbG9yfSBkZWYACS9ncmFwaGNvbG9yIHtub3Bjb2xvcn0gZGVmAC9vbmxheWVyIHsgY3VybGF5ZXIgbmUge2ludmlzfSBpZiB9IGRlZgAvb25sYXllcnMgewAJL215dXBwZXIgZXhjaCBkZWYACS9teWxvd2VyIGV4Y2ggZGVmAAljdXJsYXllciBteWxvd2VyIGx0AAljdXJsYXllciBteXVwcGVyIGd0AAlvcgAJe2ludmlzfSBpZgAvY3VybGF5ZXIgMCBkZWYAJSVFbmRSZXNvdXJjZQAlJUVuZFByb2xvZwAlJUJlZ2luU2V0dXAAMTQgZGVmYXVsdC1mb250LWZhbWlseSBzZXRfZm9udAAlIC9hcnJvd2xlbmd0aCAxMCBkZWYAJSAvYXJyb3d3aWR0aCA1IGRlZgAlIG1ha2Ugc3VyZSBwZGZtYXJrIGlzIGhhcm1sZXNzIGZvciBQUy1pbnRlcnByZXRlcnMgb3RoZXIgdGhhbiBEaXN0aWxsZXIAL3BkZm1hcmsgd2hlcmUge3BvcH0ge3VzZXJkaWN0IC9wZGZtYXJrIC9jbGVhcnRvbWFyayBsb2FkIHB1dH0gaWZlbHNlACUgbWFrZSAnPDwnIGFuZCAnPj4nIHNhZmUgb24gUFMgTGV2ZWwgMSBkZXZpY2VzAC9sYW5ndWFnZWxldmVsIHdoZXJlIHtwb3AgbGFuZ3VhZ2VsZXZlbH17MX0gaWZlbHNlADIgbHQgewAgICAgdXNlcmRpY3QgKDw8KSBjdm4gKFspIGN2biBsb2FkIHB1dAAgICAgdXNlcmRpY3QgKD4+KSBjdm4gKFspIGN2biBsb2FkIHB1dAB9IGlmACUlRW5kU2V0dXAAJSVUcmFpbGVyCgAlJSUlUGFnZXM6ICVkCgBlbmQKcmVzdG9yZQoAJSVFT0YKACUhUFMtQWRvYmUtMy4wACBFUFNGLTMuMAoAJSUlJUNyZWF0b3I6ICVzIHZlcnNpb24gJXMgKCVzKQoAcHMyOnBzADwhLS0gADxwb2x5bGluZQAgcG9pbnRzPSIAIi8+CgAgZmlsbD0iAHVybCgjbF8lZCkAdXJsKCNyXyVkKQAiIGZpbGwtb3BhY2l0eT0iJWYAIiBzdHJva2U9IgAiIHN0cm9rZS13aWR0aD0iACIgc3Ryb2tlLWRhc2hhcnJheT0iJXMANSwyADEsNQAiIHN0cm9rZS1vcGFjaXR5PSIlZgBndnJlbmRlcl9jb3JlX3N2Zy5jAHN2Z19wcmludF9jb2xvcgA8cGF0aAAgaWQ9IgBfcCIgACBkPSIAJWMAPGRlZnM+CjxyYWRpYWxHcmFkaWVudCBpZD0icl8lZCIgY3g9IjUwJSUiIGN5PSI1MCUlIiByPSI3NSUlIiBmeD0iJWQlJSIgZnk9IiVkJSUiPgoAPHN0b3Agb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjoAO3N0b3Atb3BhY2l0eToAMS4AOyIvPgoAPHN0b3Agb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjoAOyIvPgo8L3JhZGlhbEdyYWRpZW50Pgo8L2RlZnM+CgA8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJsXyVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgAHgxPSIAIiB5MT0iACIgeDI9IgAiIHkyPSIAIiA+CgA8c3RvcCBvZmZzZXQ9IiUuMDNmIiBzdHlsZT0ic3RvcC1jb2xvcjoAOyIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+CgA8cG9seWdvbgA8ZWxsaXBzZQAgY3g9IgAiIGN5PSIAIiByeD0iACIgcnk9IgA8dGV4dAAgdGV4dC1hbmNob3I9InN0YXJ0IgAgdGV4dC1hbmNob3I9ImVuZCIAIHRleHQtYW5jaG9yPSJtaWRkbGUiACB4PSIAIiB5PSIAIGZvbnQtZmFtaWx5PSIlcwAsJXMAIGZvbnQtd2VpZ2h0PSIlcyIAIGZvbnQtc3RyZXRjaD0iJXMiACBmb250LXN0eWxlPSIlcyIAIGZvbnQtZmFtaWx5PSIlcyIAIGZvbnQtd2VpZ2h0PSJib2xkIgAgZm9udC1zdHlsZT0iaXRhbGljIgAgdGV4dC1kZWNvcmF0aW9uPSIAJXNvdmVybGluZQAlc2xpbmUtdGhyb3VnaAAgYmFzZWxpbmUtc2hpZnQ9InN1cGVyIgAgYmFzZWxpbmUtc2hpZnQ9InN1YiIAIGZvbnQtc2l6ZT0iJS4yZiIAIGZpbGw9IiVzIgAgZmlsbD0iIyUwMnglMDJ4JTAyeCIAc3ZnX3RleHRzcGFuAD4APHRleHRQYXRoIHhsaW5rOmhyZWY9IiMlc19wIiBzdGFydE9mZnNldD0iNTAlJSI+ADx0c3BhbiB4PSIwIiBkeT0iACI+ADwvdHNwYW4+PC90ZXh0UGF0aD4APC90ZXh0PgoAPC9nPgoAPGcAIGlkPSJhXwAgeGxpbms6aHJlZj0iACB4bGluazp0aXRsZT0iACB0YXJnZXQ9IgA8dGl0bGU+ADwvdGl0bGU+CgA8ZyBpZD0iAF8lcwAiIGNsYXNzPSIlcwBjbGFzcwAgdHJhbnNmb3JtPSJzY2FsZSgAKSByb3RhdGUoJWQpIHRyYW5zbGF0ZSgAKSI+CgA8L3N2Zz4KADwhLS0AIFBhZ2VzOiAlZCAtLT4KADxzdmcgd2lkdGg9IiVkcHQiIGhlaWdodD0iJWRwdCIKACB2aWV3Qm94PSIlLjJmICUuMmYgJS4yZiAlLjJmIgAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgAgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJubyI/PgoAc3R5bGVzaGVldAA8P3htbC1zdHlsZXNoZWV0IGhyZWY9IgAiIHR5cGU9InRleHQvY3NzIj8+CgA8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iCgAgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CgA8IS0tIEdlbmVyYXRlZCBieSAAZGFya2JsdWUAZGFya2N5YW4AZGFya2dyYXkAZGFya2dyZXkAZGFya21hZ2VudGEAZGFya3JlZABsaWdodGdyZWVuACMgACBjcmVhdGUgbGluZSAAIC1maWxsIAAgLWRhc2ggNQAgLWRhc2ggMgBndnJlbmRlcl9jb3JlX3RrLmMAdGtnZW5fcHJpbnRfdGFncwBncmFwaCBsYWJlbAAgLXRhZ3MgeyVkJXMlcH0AdGtnZW5fcHJpbnRfY29sb3IAJGMAIC13aWR0aCAAIC1zbW9vdGggYmV6aWVyIAAgY3JlYXRlIHBvbHlnb24gACAtb3V0bGluZSAAIGNyZWF0ZSBvdmFsIAAgY3JlYXRlIHRleHQgACAtdGV4dCB7AH0AIC1mb250IHsAICVkfQAgLWFuY2hvciB3ACAtYW5jaG9yIGUAIwAgVGl0bGU6IAAgUGFnZXM6ICVkCgAjIEdlbmVyYXRlZCBieSAAKQoAdGsAdGs6dGsAICAgICAgPCEtLSAAIC0tPgoARXJyb3IgZHVyaW5nIGNvbnZlcnNpb24gdG8gIlVURi04Ii4gIFF1aXRpbmcuCgAgPHY6c2hhcGUgc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyAAIHdpZHRoOiAlZDsgaGVpZ2h0OiAlZCIgZmlsbGVkPSJmYWxzZSI+ADx2OnBhdGggdj0iACBtIAAlLjBmLCUuMGYgACBsIAAgZSAAIi8+ADwvdjpzaGFwZT4KADx2OnN0cm9rZSBjb2xvcj0iACIgd2VpZ2h0PSIlLjBmcHQAIiBkYXNoc3R5bGU9ImRhc2gAIiBkYXNoc3R5bGU9ImRvdAAiIC8+ACMlMDJ4JTAyeCUwMngAZ3ZyZW5kZXJfY29yZV92bWwuYwB2bWxfcHJpbnRfY29sb3IAIHdpZHRoOiAlZDsgaGVpZ2h0OiAlZCIAID4APHY6cGF0aCAgdj0iAC8+PC92OnNoYXBlPgoAbSAAJXMlLjBmLCUuMGYgAGMgACBmaWxsZWQ9InRydWUiIGZpbGxjb2xvcj0iACIgACBmaWxsZWQ9ImZhbHNlIiAAJS4wZiAlLjBmIABsIAB4IGUgIi8+ACAgPHY6b3ZhbCBzdHlsZT0icG9zaXRpb246YWJzb2x1dGU7ACBsZWZ0OiAlLjJmOyB0b3A6ICUuMmY7ACB3aWR0aDogJS4yZjsgaGVpZ2h0OiAlLjJmIgA8L3Y6b3ZhbD4KADx2OnJlY3Qgc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyAAIHN0cm9rZWQ9ImZhbHNlIiBmaWxsZWQ9ImZhbHNlIj4KADx2OnRleHRib3ggaW5zZXQ9IjAsMCwwLDAiIHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTsgdi10ZXh0LXdyYXBwaW5nOidmYWxzZSc7cGFkZGluZzonMCc7AGZvbnQtZmFtaWx5OiAnJXMnOwBmb250LXdlaWdodDogJXM7AGZvbnQtc3RyZXRjaDogJXM7AGZvbnQtc3R5bGU6ICVzOwAgZm9udC1zaXplOiAlLjJmcHQ7AGNvbG9yOiVzOwBjb2xvcjojJTAyeCUwMnglMDJ4OwB2bWxfdGV4dHNwYW4AIj48Y2VudGVyPgA8L2NlbnRlcj48L3Y6dGV4dGJveD4KADwvdjpyZWN0PgoAPC9hPgoAPGEAIGhyZWY9IiVzIgAgdGl0bGU9IiVzIgAgdGFyZ2V0PSIlcyIAPgoAPC92Omdyb3VwPgoAPC9ESVY+CgA8RElWIGlkPSdfVk1MMl8nIHN0eWxlPSJwb3NpdGlvbjpyZWxhdGl2ZTt2aXNpYmlsaXR5OmhpZGRlbiI+CgA8IS0tIGluc2VydCBhbnkgb3RoZXIgaHRtbCBjb250ZW50IGhlcmUgLS0+CgA8RElWIGlkPSdfbm90Vk1MMV8nIHN0eWxlPSJwb3NpdGlvbjpyZWxhdGl2ZTsiPgoAPCEtLSB0aGlzIHNob3VsZCBvbmx5IGRpc3BsYXkgb24gTk9OLUlFIGJyb3dzZXJzIC0tPgoAPEgyPlNvcnJ5LCB0aGlzIGRpYWdyYW0gd2lsbCBvbmx5IGRpc3BsYXkgY29ycmVjdGx5IG9uIEludGVybmV0IEV4cGxvcmVyIDUgKGFuZCB1cCkgYnJvd3NlcnMuPC9IMj4KADxESVYgaWQ9J19ub3RWTUwyXycgc3R5bGU9InBvc2l0aW9uOnJlbGF0aXZlOyI+CgA8IS0tIGluc2VydCBhbnkgb3RoZXIgTk9OLUlFIGh0bWwgY29udGVudCBoZXJlIC0tPgoAPC9CT0RZPgo8L0hUTUw+CgA8SEVBRD4APE1FVEEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9VVRGLTgiPgoAPFRJVExFPgA8L1RJVExFPgA8IS0tIFBhZ2VzOiAlZCAtLT4KACAgIDxTQ1JJUFQgTEFOR1VBR0U9J0phdmFzY3JpcHQnPgoAICAgZnVuY3Rpb24gYnJvd3NlcmNoZWNrKCkKACAgIHsKACAgICAgIHZhciB1YSA9IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50CgAgICAgICB2YXIgbXNpZSA9IHVhLmluZGV4T2YgKCAnTVNJRSAnICkKACAgICAgIHZhciBpZXZlcnM7CgAgICAgICB2YXIgaXRlbTsKACAgICAgIHZhciBWTUx5ZXM9bmV3IEFycmF5KCdfVk1MMV8nLCdfVk1MMl8nKTsKACAgICAgIHZhciBWTUxubz1uZXcgQXJyYXkoJ19ub3RWTUwxXycsJ19ub3RWTUwyXycpOwoAICAgICAgaWYgKCBtc2llID4gMCApeyAgICAgIC8vIElmIEludGVybmV0IEV4cGxvcmVyLCByZXR1cm4gdmVyc2lvbiBudW1iZXIKACAgICAgICAgIGlldmVycz0gcGFyc2VJbnQgKHVhLnN1YnN0cmluZyAobXNpZSs1LCB1YS5pbmRleE9mICgnLicsIG1zaWUgKSkpCgAgICAgICB9CgAgICAgICBpZiAoaWV2ZXJzPj01KXsKACAgICAgICBmb3IgKHggaW4gVk1MeWVzKXsKACAgICAgICAgIGl0ZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChWTUx5ZXNbeF0pOwoAICAgICAgICAgaWYgKGl0ZW0pIHsKACAgICAgICAgICAgaXRlbS5zdHlsZS52aXNpYmlsaXR5PSd2aXNpYmxlJzsKACAgICAgICAgIH0KACAgICAgICB9CgAgICAgICAgZm9yICh4IGluIFZNTG5vKXsKACAgICAgICAgIGl0ZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChWTUxub1t4XSk7CgAgICAgICAgICAgIGl0ZW0uc3R5bGUudmlzaWJpbGl0eT0naGlkZGVuJzsKACAgICAgfWVsc2V7CgAgICAgIH0KACAgIH0KACAgIDwvU0NSSVBUPgoAPC9IRUFEPgA8Qk9EWSBvbmxvYWQ9J2Jyb3dzZXJjaGVjaygpOyc+CgA8RElWIGlkPSdfVk1MMV8nIHN0eWxlPSJwb3NpdGlvbjpyZWxhdGl2ZTsgZGlzcGxheTppbmxpbmU7IHZpc2liaWxpdHk6aGlkZGVuACB3aWR0aDogJWRwdDsgaGVpZ2h0OiAlZHB0Ij4KADxTVFlMRT4KAHZcOiogeyBiZWhhdmlvcjogdXJsKCNkZWZhdWx0I1ZNTCk7ZGlzcGxheTppbmxpbmUtYmxvY2t9CgA8L1NUWUxFPgoAPHhtbDpuYW1lc3BhY2UgbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206dm1sIiBwcmVmaXg9InYiIC8+CgAgPHY6Z3JvdXAgc3R5bGU9InBvc2l0aW9uOnJlbGF0aXZlOyAAIHdpZHRoOiAlZHB0OyBoZWlnaHQ6ICVkcHQiACBjb29yZG9yaWdpbj0iMCwwIiBjb29yZHNpemU9IiVkLCVkIiA+ADxIVE1MPgoACjwhLS0gR2VuZXJhdGVkIGJ5IAAgdmVyc2lvbiAAICgAKQotLT4KAGFxdWEAZnVjaHNpYQBsaW1lAG9saXZlAHRlYWwAdm1sAHZtbDp2bWwALy8qKiogY29tbWVudDogJXMKAC8vKioqIHBvbHlsaW5lCgBzY2FsZSAgICA8JTkuM2YsICU5LjNmLCAlOS4zZj4KAHJvdGF0ZSAgIDwlOS4zZiwgJTkuM2YsICU5LjNmPgoAdHJhbnNsYXRlPCU5LjNmLCAlOS4zZiwgJTkuM2Y+CgBzcGhlcmVfc3dlZXAgewogICAgJXMKICAgICVkLAoAbGluZWFyX3NwbGluZQA8JTkuM2YsICU5LjNmLCAlOS4zZj4sICUuM2YKACVzICAgICVzACAgICB0b2xlcmFuY2UgMC4wMQogICAgJXMgICAgJXMgICAgJXMgICAgJXN9CgAlcyVzACVzIHRyYW5zbWl0ICUuM2YAUmVkAEdyZWVuAEJsdWUAcmdiPCU5LjNmLCAlOS4zZiwgJTkuM2Y+IHRyYW5zbWl0ICUuM2YAb29wcywgaW50ZXJuYWwgZXJyb3I6IHVuaGFuZGxlZCBjb2xvciB0eXBlPSVkICVzCgBndnJlbmRlcl9jb3JlX3Bvdi5jAHBvdl9jb2xvcl9hc19zdHIAcGlnbWVudCB7IGNvbG9yICVzIH0KAHBvdiByZW5kZXJlcjplbCAtICVzCgAvLyoqKiBiZXppZXIKAGJfc3BsaW5lACAgICAgICAgdG9sZXJhbmNlIDAuMDEKICAgICVzICAgICVzICAgICVzICAgICVzfQoALy8qKiogcG9seWdvbgoAICAgIHRvbGVyYW5jZSAwLjEKICAgICVzICAgICVzICAgICVzICAgICVzfQoAcG9seWdvbiB7ICVkLAoAPCU5LjNmLCAlOS4zZiwgJTkuM2Y+ACVzCiAgICAlcwAKICAgICVzICAgICVzICAgICVzICAgICVzfQoALy8qKiogZWxsaXBzZQoAdG9ydXMgeyAlLjNmLCAlLjNmCiAgICAlcyAgICAlcyAgICAlcyAgICAlc30KAHNwaGVyZSB7PCU5LjNmLCAlOS4zZiwgJTkuM2Y+LCAxLjAKICAgICVzICAgICVzICAgICVzICAgICVzfQoALy8qKiogdGV4dHNwYW46ICVzLCBmb250c2l6ZSA9ICUuM2YsIGZvbnRuYW1lID0gJXMKAHNjYWxlICUuM2YKAHRleHQgewogICAgdHRmICIlcyIsCiAgICAiJXMiLCAlLjNmLCAlLjNmCiAgICAlcyAgICAlcyAgICAlcyAgICAlcyAgICAlc30KACAgICBub19zaGFkb3cKAC8vKioqIGVuZF9lZGdlCgAvLyoqKiBiZWdpbl9lZGdlCgAvLyoqKiBlbmRfbm9kZQoALy8qKiogYmVnaW5fbm9kZTogJXMKAC8vKioqIGVuZF9jbHVzdGVyCgAvLyoqKiBiZWdpbl9jbHVzdGVyCgAvLyoqKiBlbmRfcGFnZQoALy8qKiogYmVnaW5fcGFnZQoALy8qKiogZW5kX2xheWVyCgAvLyoqKiBiZWdpbl9sYXllcjogJXMsICVkLyVkCgAvLyoqKiBlbmRfZ3JhcGgKAC8vKioqIGJlZ2luX2dyYXBoICVzCgBjYW1lcmEgeyBsb2NhdGlvbiA8JS4zZiAsICUuM2YgLCAlLjNmPgogICAgICAgICBsb29rX2F0ICA8JS4zZiAsICUuM2YgLCAlLjNmPgogICAgICAgICByaWdodCB4ICogaW1hZ2Vfd2lkdGggLyBpbWFnZV9oZWlnaHQKICAgICAgICAgYW5nbGUgJS4zZgp9CgAvL3NreQpwbGFuZSB7IDwwLCAxLCAwPiwgMSBob2xsb3cKICAgIHRleHR1cmUgewogICAgICAgIHBpZ21lbnQgeyBib3pvIHR1cmJ1bGVuY2UgMC45NQogICAgICAgICAgICBjb2xvcl9tYXAgewogICAgICAgICAgICAgICAgWzAuMDAgcmdiIDwwLjA1LCAwLjIwLCAwLjUwPl0KICAgICAgICAgICAgICAgIFswLjUwIHJnYiA8MC4wNSwgMC4yMCwgMC41MD5dCiAgICAgICAgICAgICAgICBbMC43NSByZ2IgPDEuMDAsIDEuMDAsIDEuMDA+XQogICAgICAgICAgICAgICAgWzAuNzUgcmdiIDwwLjI1LCAwLjI1LCAwLjI1Pl0KICAgICAgICAgICAgICAgIFsxLjAwIHJnYiA8MC41MCwgMC41MCwgMC41MD5dCiAgICAgICAgICAgIH0KICAgICAgICAgICAgc2NhbGUgPDEuMDAsIDEuMDAsIDEuNTA+ICogMi41MAogICAgICAgICAgICB0cmFuc2xhdGUgPDAuMDAsIDAuMDAsIDAuMDA+CiAgICAgICAgfQogICAgICAgIGZpbmlzaCB7IGFtYmllbnQgMSBkaWZmdXNlIDAgfQogICAgfQogICAgc2NhbGUgMTAwMDAKfQovL21pc3QKZm9nIHsgZm9nX3R5cGUgMgogICAgZGlzdGFuY2UgNTAKICAgIGNvbG9yIHJnYiA8MS4wMCwgMS4wMCwgMS4wMD4gKiAwLjc1CiAgICBmb2dfb2Zmc2V0IDAuMTAKICAgIGZvZ19hbHQgMS41MAogICAgdHVyYnVsZW5jZSAxLjc1Cn0KLy9nbmQKcGxhbmUgeyA8MC4wMCwgMS4wMCwgMC4wMD4sIDAKICAgIHRleHR1cmUgewogICAgICAgIHBpZ21lbnR7IGNvbG9yIHJnYiA8MC4yNSwgMC40NSwgMC4wMD4gfQogICAgICAgIG5vcm1hbCB7IGJ1bXBzIDAuNzUgc2NhbGUgMC4wMSB9CiAgICAgICAgZmluaXNoIHsgcGhvbmcgMC4xMCB9CiAgICB9Cn0KAGxpZ2h0X3NvdXJjZSB7IDwxNTAwLDMwMDAsLTI1MDA+IGNvbG9yIFdoaXRlIH0KACN2ZXJzaW9uIDMuNjsKAGdsb2JhbF9zZXR0aW5ncyB7IGFzc3VtZWRfZ2FtbWEgMS4wIH0KACNkZWZhdWx0IHsgZmluaXNoIHsgYW1iaWVudCAwLjEgZGlmZnVzZSAwLjkgfSB9CgAjaW5jbHVkZSAiY29sb3JzLmluYyIKI2luY2x1ZGUgInRleHR1cmVzLmluYyIKI2luY2x1ZGUgInNoYXBlcy5pbmMiCgAjZGVjbGFyZSAlcyA9ICVzOwoAQmxhY2sAV2hpdGUAYmFrZXJzY2hvYwBicmFzcwBicmlnaHRnb2xkAGJyb256ZQBicm9uemUyAGNsZWFyAGNvb2xjb3BwZXIAY29wcGVyAGRhcmticm93bgBkYXJrcHVycGxlAGRhcmt0YW4AZGFya3dvb2QAZGtncmVlbmNvcHBlcgBkdXN0eXJvc2UAZmVsZHNwYXIAZmxlc2gAZ3JheTA1AGdyZWVuY29wcGVyAGh1bnRlcnNncmVlbgBsaWdodF9wdXJwbGUAbGlnaHR3b29kAG1hbmRhcmlub3JhbmdlAG1lZGl1bWZvcmVzdGdyZWVuAG1lZGl1bWdvbGRlbnJvZABtZWRpdW13b29kAG1lZF9wdXJwbGUAbWljYQBuZW9uYmx1ZQBuZW9ucGluawBuZXdtaWRuaWdodGJsdWUAbmV3dGFuAG9sZGdvbGQAcXVhcnR6AHJpY2hibHVlAHNjYXJsZXQAc2VtaVN3ZWV0Q2hvYwBzaWx2ZXIAc3BpY3lwaW5rAHN1bW1lcnNreQB2ZXJ5ZGFya2Jyb3duAHZlcnlfbGlnaHRfcHVycGxlAHBvdgBwb3Y6cG92ACVzICVzCgAuXCIgACAlZCAlZAAgJXMKACAlZABmaWxsIABlbGxpcHNlIGF0dHJzJWQgJXN3aWQgJS41ZiBodCAlLjVmIGF0ICglLjVmLCUuNWYpOwoALmZ0ICVzCgAucHMgJWQqXG4oU0Z1LyUuMGZ1CgAiJXMiIGF0ICglLjVmLCUuNWYpOwoAJTAzbwAlcyVzIGlzIG5vdCBhIHRyb2ZmIGZvbnQKAGRvdCBwaWMgcGx1Z2luOiAAUgBdCi5QRQoALlBTICUuNWYgJS41ZgoAJXMgdG8gY2hhbmdlIGRyYXdpbmcgc2l6ZSwgbXVsdGlwbHkgdGhlIHdpZHRoIGFuZCBoZWlnaHQgb24gdGhlIC5QUyBsaW5lIGFib3ZlIGFuZCB0aGUgbnVtYmVyIG9uIHRoZSB0d28gbGluZXMgYmVsb3cgKHJvdW5kZWQgdG8gdGhlIG5lYXJlc3QgaW50ZWdlcikgYnkgYSBzY2FsZSBmYWN0b3IKAC5uciBTRiAlLjBmCnNjYWxldGhpY2tuZXNzID0gJS4wZgoAJXMgZG9uJ3QgY2hhbmdlIGFueXRoaW5nIGJlbG93IHRoaXMgbGluZSBpbiB0aGlzIGRyYXdpbmcKACVzIG5vbi1mYXRhbCBydW4tdGltZSBwaWMgdmVyc2lvbiBkZXRlcm1pbmF0aW9uLCB2ZXJzaW9uIDIKAGJveHJhZD0yLjAgJXMgd2lsbCBiZSByZXNldCB0byAwLjAgYnkgZ3BpYyBvbmx5CgBzY2FsZT0xLjAgJXMgcmVxdWlyZWQgZm9yIGNvbXBhcmlzb25zCgAlcyBib3hyYWQgaXMgbm93IDAuMCBpbiBncGljLCBlbHNlIGl0IHJlbWFpbnMgMi4wCgAlcyBkYXNod2lkIGlzIDAuMSBpbiAxMHRoIEVkaXRpb24sIDAuMDUgaW4gRFdCIDIgYW5kIGluIGdwaWMKACVzIGZpbGx2YWwgaXMgMC4zIGluIDEwdGggRWRpdGlvbiAoZmlsbCAwIG1lYW5zIGJsYWNrKSwgMC41IGluIGdwaWMgKGZpbGwgMCBtZWFucyB3aGl0ZSksIHVuZGVmaW5lZCBpbiBEV0IgMgoAJXMgZmlsbCBoYXMgbm8gbWVhbmluZyBpbiBEV0IgMiwgZ3BpYyBjYW4gdXNlIGZpbGwgb3IgZmlsbGVkLCAxMHRoIEVkaXRpb24gdXNlcyBmaWxsIG9ubHkKACVzIERXQiAyIGRvZXNuJ3QgdXNlIGZpbGwgYW5kIGRvZXNuJ3QgZGVmaW5lIGZpbGx2YWwKACVzIHJlc2V0IHdvcmtzIGluIGdwaWMgYW5kIDEwdGggZWRpdGlvbiwgYnV0IGlzbid0IGRlZmluZWQgaW4gRFdCIDIKACVzIERXQiAyIGNvbXBhdGliaWxpdHkgZGVmaW5pdGlvbnMKAGlmIGJveHJhZCA+IDEuMCAmJiBkYXNod2lkIDwgMC4wNzUgdGhlbiBYCglmaWxsdmFsID0gMTsKCWRlZmluZSBmaWxsIFkgWTsKCWRlZmluZSBzb2xpZCBZIFk7CglkZWZpbmUgcmVzZXQgWSBzY2FsZT0xLjAgWTsKWAoAcmVzZXQgJXMgc2V0IHRvIGtub3duIHN0YXRlCgAlcyBHTlUgcGljIHZzLiAxMHRoIEVkaXRpb24gZFwoZSd0ZW50ZQoAaWYgZmlsbHZhbCA+IDAuNCB0aGVuIFgKCWRlZmluZSBzZXRmaWxsdmFsIFkgZmlsbHZhbCA9IDEgLSBZOwoJZGVmaW5lIGJvbGQgWSB0aGlja25lc3MgMiBZOwoACSVzIGlmIHlvdSB1c2UgZ3BpYyBhbmQgaXQgYmFyZnMgb24gZW5jb3VudGVyaW5nICJzb2xpZCIsCgAJJXMJaW5zdGFsbCBhIG1vcmUgcmVjZW50IHZlcnNpb24gb2YgZ3BpYyBvciBzd2l0Y2ggdG8gRFdCIG9yIDEwdGggRWRpdGlvbiBwaWM7CgAJJXMJc29ycnksIHRoZSBncm9mZiBmb2xrcyBjaGFuZ2VkIGdwaWM7IHNlbmQgYW55IGNvbXBsYWludCB0byB0aGVtOwoAWCBlbHNlIFoKCWRlZmluZSBzZXRmaWxsdmFsIFkgZmlsbHZhbCA9IFk7CglkZWZpbmUgYm9sZCBZIFk7CglkZWZpbmUgZmlsbGVkIFkgZmlsbCBZOwpaCgAlcyBhcnJvd2hlYWQgaGFzIG5vIG1lYW5pbmcgaW4gRFdCIDIsIGFycm93aGVhZCA9IDcgbWFrZXMgZmlsbGVkIGFycm93aGVhZHMgaW4gZ3BpYyBhbmQgaW4gMTB0aCBFZGl0aW9uCgAlcyBhcnJvd2hlYWQgaXMgdW5kZWZpbmVkIGluIERXQiAyLCBpbml0aWFsbHkgMSBpbiBncGljLCAyIGluIDEwdGggRWRpdGlvbgoAYXJyb3doZWFkID0gNyAlcyBub3QgdXNlZCBieSBncmFwaHZpegoAJXMgR05VIHBpYyBzdXBwb3J0cyBhIGJveHJhZCB2YXJpYWJsZSB0byBkcmF3IGJveGVzIHdpdGggcm91bmRlZCBjb3JuZXJzOyBEV0IgYW5kIDEwdGggRWQuIGRvIG5vdAoAYm94cmFkID0gMCAlcyBubyByb3VuZGVkIGNvcm5lcnMgaW4gZ3JhcGh2aXoKACVzIEdOVSBwaWMgc3VwcG9ydHMgYSBsaW5ldGhpY2sgdmFyaWFibGUgdG8gc2V0IGxpbmUgdGhpY2tuZXNzOyBEV0IgYW5kIDEwdGggRWQuIGRvIG5vdAoAbGluZXRoaWNrID0gMDsgb2xkbGluZXRoaWNrID0gbGluZXRoaWNrCgAlcyAuUFMgdy9vIGFyZ3MgY2F1c2VzIEdOVSBwaWMgdG8gc2NhbGUgZHJhd2luZyB0byBmaXQgOC41eDExIHBhcGVyOyBEV0IgZG9lcyBub3QKACVzIG1heHBzaHQgYW5kIG1heHBzd2lkIGhhdmUgbm8gbWVhbmluZyBpbiBEV0IgMi4wLCBzZXQgcGFnZSBib3VuZGFyaWVzIGluIGdwaWMgYW5kIGluIDEwdGggRWRpdGlvbgoAJXMgbWF4cHNodCBhbmQgbWF4cHN3aWQgYXJlIHByZWRlZmluZWQgdG8gMTEuMCBhbmQgOC41IGluIGdwaWMKAG1heHBzaHQgPSAlZgptYXhwc3dpZCA9ICVmCgBEb3Q6IFsKAGRlZmluZSBhdHRyczAgJSUgJSU7IGRlZmluZSB1bmZpbGxlZCAlJSAlJTsgZGVmaW5lIHJvdW5kZWQgJSUgJSU7IGRlZmluZSBkaWFnb25hbHMgJSUgJSUKACVzJXMgdW5zdXBwb3J0ZWQKAHJvdGF0aW9uACVzIHJlc3RvcmUgcG9pbnQgc2l6ZSBhbmQgZm9udAoucHMgXG4oLlMKLmZ0IFxuKERGCgAlcyBDcmVhdG9yOiAlcyB2ZXJzaW9uICVzICglcykKACVzIFRpdGxlOiAlcwoAJXMgc2F2ZSBwb2ludCBzaXplIGFuZCBmb250Ci5uciAuUyBcbigucwoubnIgREYgXG4oLmYKAHBpYwBwaWM6cGljAHBuZzpzdmcAZ2lmOnN2ZwBqcGVnOnN2ZwBqcGU6c3ZnAGpwZzpzdmcAcG5nOmZpZwBnaWY6ZmlnAGpwZWc6ZmlnAGpwZTpmaWcAanBnOmZpZwBwbmc6dnJtbABnaWY6dnJtbABqcGVnOnZybWwAanBlOnZybWwAanBnOnZybWwAZXBzOnBzAHBzOnBzAChsaWIpOnBzAHBuZzptYXAAZ2lmOm1hcABqcGVnOm1hcABqcGU6bWFwAGpwZzptYXAAcHM6bWFwAGVwczptYXAAc3ZnOm1hcABwbmc6ZG90AGdpZjpkb3QAanBlZzpkb3QAanBlOmRvdABqcGc6ZG90AHBzOmRvdABlcHM6ZG90AHN2Zzpkb3QAcG5nOnhkb3QAZ2lmOnhkb3QAanBlZzp4ZG90AGpwZTp4ZG90AGpwZzp4ZG90AHBzOnhkb3QAZXBzOnhkb3QAc3ZnOnhkb3QAc3ZnOnN2ZwBwbmc6dm1sAGdpZjp2bWwAanBlZzp2bWwAanBlOnZtbABqcGc6dm1sAGdpZjp0awBpbWFnZSBjcmVhdGUgcGhvdG8gInBob3RvXyVzIiAtZmlsZSAiJXMiCgAkYyBjcmVhdGUgaW1hZ2UgJS4yZiAlLjJmIC1pbWFnZSAicGhvdG9fJXMiCgA8djppbWFnZSBzcmM9IiVzIiBzdHlsZT0iIHBvc2l0aW9uOmFic29sdXRlOyB3aWR0aDolLjJmOyBoZWlnaHQ6JS4yZjsgbGVmdDolLjJmIDsgdG9wOiUuMmYiACAvPgoAZ3Zsb2FkaW1hZ2VfY29yZS5jAGNvcmVfbG9hZGltYWdlX3BzbGliAFsgACVnICVnIABdICAlZCB0cnVlICVzCgBdICAlZCBmYWxzZSAlcwoAY29yZV9sb2FkaW1hZ2VfcHMAZ3NhdmUgJWcgJWcgdHJhbnNsYXRlIG5ld3BhdGgKAHVzZXJfc2hhcGVfJWQKAGdyZXN0b3JlCgBjb3JlX2xvYWRpbWFnZV92cm1sAFNoYXBlIHsKACAgYXBwZWFyYW5jZSBBcHBlYXJhbmNlIHsKACAgICBtYXRlcmlhbCBNYXRlcmlhbCB7CgAgICAgICBhbWJpZW50SW50ZW5zaXR5IDAuMzMKACAgICAgICAgZGlmZnVzZUNvbG9yIDEgMSAxCgAgICAgfQoAICAgIHRleHR1cmUgSW1hZ2VUZXh0dXJlIHsgdXJsICIlcyIgfQoAICB9CgBjb3JlX2xvYWRpbWFnZV9maWcAJWQgJWQgJWQgJWQgJWQgJWQgJWQgJWQgJWQgJS4xZiAlZCAlZCAlZCAlZCAlZCAlZAogJWQgJXMKACAlZCAlZCAlZCAlZCAlZCAlZCAlZCAlZCAlZCAlZAoAY29yZV9sb2FkaW1hZ2Vfc3ZnADxpbWFnZSB4bGluazpocmVmPSIAIiB3aWR0aD0iJWdweCIgaGVpZ2h0PSIlZ3B4IiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB4PSIlZyIgeT0iJWciACB0cmFuc2Zvcm09InJvdGF0ZSglZCAlZyAlZykiACIgd2lkdGg9IiVncHgiIGhlaWdodD0iJWdweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pbllNaW4gbWVldCIgeD0iJWciIHk9IiVnIgAvPgoAZG90X2xheW91dABwaGFzZQBkb3QgZG9lcyBub3Qgc3VwcG9ydCB0aGUgYXNwZWN0IGF0dHJpYnV0ZSBmb3IgZGlzY29ubmVjdGVkIGdyYXBocyBvciBncmFwaHMgd2l0aCBjbHVzdGVycwoAY29tcG91bmQAdiA9PSBuAGRvdGluaXQuYwByZW1vdmVfZnJvbV9yYW5rAG9yZGVyAGVkZ2UgbGFiZWxzIHdpdGggc3BsaW5lcz1jdXJ2ZWQgbm90IHN1cHBvcnRlZCBpbiBkb3QgLSB1c2UgeGxhYmVscwoARURfbGFiZWwoZmUpAGRvdHNwbGluZXMuYwBfZG90X3NwbGluZXMAZmxhdCBlZGdlIGJldHdlZW4gYWRqYWNlbnQgbm9kZXMgb25lIG9mIHdoaWNoIGhhcyBhIHJlY29yZCBzaGFwZSAtIHJlcGxhY2UgcmVjb3JkcyB3aXRoIEhUTUwtbGlrZSBsYWJlbHMKACAgRWRnZSAlcyAlcyAlcwoAeHh4ADEwMDAwAHslc30AYXV4ZwBsYWJlbF9mbG9hdABmaXhlZAAobCA9IEVEX2xhYmVsKGZlKSkAc2V0RWRnZUxhYmVsUG9zAGUgIT0gTlVMTABmYXN0Z3IuYwBkZWxldGVfZmFzdF9lZGdlAG4gIT0gTkRfbmV4dChuKQBmYXN0X25vZGUAdSAhPSB2AGZhc3Rfbm9kZWFwcABORF9uZXh0KHYpID09IE5VTEwAZmluZF9mYXN0X25vZGUoZywgbikAZGVsZXRlX2Zhc3Rfbm9kZQBkZWxldGVfZmxhdF9lZGdlAG1lcmdlX29uZXdheSBnbGl0Y2gKAG1lcmdlX29uZXdheQBzYWZlX2RlbGV0ZV9mYXN0X2VkZ2UAbGcAaW5mbwBjb21wAGNudCA9PSBzegBtaW5jcm9zcy5jAGZpeExhYmVsT3JkZXIAcmVtaW5jcm9zcwBtaW5jcm9zcyAlczogJWQgY3Jvc3NpbmdzLCAlLjJmIHNlY3MuCgB2AG5laWdoYm9yAChydiA9PSAwKSB8fCAoTkRfb3JkZXIocnYpLU5EX29yZGVyKHYpKSpkaXIgPiAwAGNvbnN0cmFpbmluZ19mbGF0X2VkZ2UoZyx2LGUpID09IEZBTFNFAGZsYXRfcmVvcmRlcgBORF9yYW5rKHYpID09IHIAcG9zdG9yZGVyAGZsYXRpbmRleChhZ2hlYWQoZSkpIDwgTS0+bnJvd3MAZmxhdF9zZWFyY2gAZmxhdGluZGV4KGFndGFpbChlKSkgPCBNLT5uY29scwBvdXQAb3JkZXJpbmcgJyVzJyBub3QgcmVjb2duaXplZC4KAG9yZGVyaW5nICclcycgbm90IHJlY29nbml6ZWQgZm9yIG5vZGUgJyVzJy4KAG1lcmdlMjogZ3JhcGggJXMsIHJhbmsgJWQgaGFzIG9ubHkgJWQgPCAlZCBub2RlcwoAbWluY3Jvc3M6IHBhc3MgJWQgaXRlciAlZCB0cnlpbmcgJWQgY3VyX2Nyb3NzICVkIGJlc3RfY3Jvc3MgJWQKAE5EX29yZGVyKHYpIDwgTkRfb3JkZXIodykAYmFsYW5jZQB0cmFuc3Bvc2Vfc3RlcABzdXJwcmlzZQoAaW5zdGFsbF9pbl9yYW5rLCBsaW5lICVkOiAlcyAlcyByYW5rICVkIGkgPSAlZCBhbiA9IDAKAEdEX3JhbmsoZylbcl0ubiA8PSBHRF9yYW5rKGcpW3JdLmFuAGluc3RhbGxfaW5fcmFuawBpbnN0YWxsX2luX3JhbmssIGxpbmUgJWQ6IE5EX29yZGVyKCVzKSBbJWRdID4gR0RfcmFuayhSb290KVslZF0uYW4gWyVkXQoAaW5zdGFsbF9pbl9yYW5rLCBsaW5lICVkOiByYW5rICVkIG5vdCBpbiByYW5rIHJhbmdlIFslZCwlZF0KAGluc3RhbGxfaW5fcmFuaywgbGluZSAlZDogR0RfcmFuayhnKVslZF0udiArIE5EX29yZGVyKCVzKSBbJWRdID4gR0RfcmFuayhnKVslZF0uYXYgKyBHRF9yYW5rKFJvb3QpWyVkXS5hbiBbJWRdCgBfbmV3X3JhbmsAbWNsaW1pdAByYW5rKGcsIDIsIG5zaXRlcjIoZykpID09IDAAcG9zaXRpb24uYwBkb3RfcG9zaXRpb24AQVI9JTAuNGxmCSBBcmVhPSAlMC40bGYJAER1bW15PSVkCgBHb2luZyB0byBhcHBseSBhbm90aGVyIGV4cGFuc2lvbi4KAG5leHQjaXRlcj0lZAoAaHAAY29ubmVjdEdyYXBoAEVkZ2UgbGVuZ3RoICVmIGxhcmdlciB0aGFuIG1heGltdW0gJXUgYWxsb3dlZC4KQ2hlY2sgZm9yIG92ZXJ3aWRlIG5vZGUocykuCgBuc2xpbWl0AGNvbnRhaW5fbm9kZXMgY2x1c3QgJXMgcmFuayAlZCBtaXNzaW5nIG5vZGUKAG5zbGltaXQxAG5ld3JhbmsATWF4cmFuayA9ICVkLCBtaW5yYW5rID0gJWQKAGxlYWRlciAhPSBOVUxMAHJhbmsuYwBjbHVzdGVyX2xlYWRlcgAoTkRfVUZfc2l6ZShuKSA8PSAxKSB8fCAobiA9PSBsZWFkZXIpAGFnaGVhZChlKSA9PSBVRl9maW5kKGFnaGVhZChlKSkAbWlubWF4X2VkZ2VzAGFndGFpbChlKSA9PSBVRl9maW5kKGFndGFpbChlKSkAcmFuawBzYW1lAG1pbgBzb3VyY2UAbWF4AHNpbmsAbGV2ZWwgYXNzaWdubWVudCBjb25zdHJhaW50cwBsZXZlbCBncmFwaCByZWMAf3Jvb3QAf3RvcAB/Ym90AGNvbXBhY3QAX3dlYWtfJWQAcmFua2luZzogZmFpbHVyZSB0byBjcmVhdGUgc3Ryb25nIGNvbnN0cmFpbnQgZWRnZSBiZXR3ZWVuIG5vZGVzICVzIGFuZCAlcwoAJXMgaGFzIHVucmVjb2duaXplZCByYW5rPSVzAGxldmVsIGVkZ2UgcmVjAGxldmVsIG5vZGUgcmVjAHNhbWVoZWFkAHNhbWV0YWlsAHRvbyBtYW55ICg+ICVkKSBzYW1le2hlYWQsdGFpbH0gZ3JvdXBzIGZvciBub2RlICVzCgBjb21iaUFSID0gJWxmCgAlbGYsJWQAdGhlIGFzcGVjdCBhdHRyaWJ1dGUgaGFzIGJlZW4gZGlzYWJsZWQgZHVlIHRvIGltcGxlbWVudGF0aW9uIGZsYXdzIC0gYXR0cmlidXRlIGlnbm9yZWQuCgBFRF90b192aXJ0KGUpID09IE5VTEwAY2xhc3MyLmMAbWVyZ2VfY2hhaW4ARURfdG9fdmlydChvcmlnKSA9PSBOVUxMAG1ha2VfY2hhaW4ARURfdG9fdmlydChvcmlnKSAhPSBOVUxMAE5EX3JhbmsoZnJvbSkgPCBORF9yYW5rKHRvKQBjbHVzdGVyLmMAbWFwX3BhdGgAJXMgd2FzIGFscmVhZHkgaW4gYSByYW5rc2V0LCBkZWxldGVkIGZyb20gY2x1c3RlciAlcwoAbGhlYWQAbHRhaWwAJXMgLT4gJXM6IHNwbGluZSBzaXplID4gMSBub3Qgc3VwcG9ydGVkCgAlcyAtPiAlczogaGVhZCBub3QgaW5zaWRlIGhlYWQgY2x1c3RlciAlcwoAJXMgLT4gJXM6IHRhaWwgaXMgaW5zaWRlIGhlYWQgY2x1c3RlciAlcwoAYmV6LT5zZmxhZwBjb21wb3VuZC5jAG1ha2VDb21wb3VuZEVkZ2UAYmV6LT5lZmxhZwAlcyAtPiAlczogdGFpbCBub3QgaW5zaWRlIHRhaWwgY2x1c3RlciAlcwoAJXMgLT4gJXM6IGhlYWQgaXMgaW5zaWRlIHRhaWwgY2x1c3RlciAlcwoAc2VnbWVudCBbJXMsJXNdIGRvZXMgbm90IGludGVyc2VjdCBib3ggbGw9JXMsdXI9JXMKAGJveEludGVyc2VjdGYAKCUuNWcsJS41ZykAY2x1c3RlciBuYW1lZCAlcyBub3QgZm91bmQKAGNvbmNlbnRyYXRlPXRydWUgbWF5IG5vdCB3b3JrIGNvcnJlY3RseS4KAHJlYnVpbHRkX3ZsaXN0czogcmFuayBsZWFkICVzIG5vdCBpbiBvcmRlciAlZCBvZiByYW5rICVkCgBkZWdlbmVyYXRlIGNvbmNlbnRyYXRlZCByYW5rICVzLCVkCgBORF9pbihyaWdodCkuc2l6ZSArIE5EX291dChyaWdodCkuc2l6ZSA9PSAwAGNvbmMuYwBtZXJnZXZpcnR1YWwAZG90OiBPdXQgb2YgbWVtb3J5CgBORF9vdXQodikuc2l6ZSA9PSAyAGZsYXQuYwBzZXRib3VuZHMAR0RfbWlucmFuayhnKSA9PSAwAGFib21pbmF0aW9uAEVycm9yAFdhcm5pbmcAJXM6IAB1c2Vyb3V0OiBjb3VsZCBub3QgYWxsb2NhdGUgbWVtb3J5CgBfQUdfc3RyZGF0YQBfQUdfZGF0YWRpY3QAYWdkaWN0b2Y6IHVua25vd24ga2luZCAlZAoAJWMlbGQAbWVtb3J5IGFsbG9jYXRpb24gZmFpbHVyZQBhZ2RlbGV0ZSBvbiB3cm9uZyBncmFwaABfQUdfcGVuZGluZwBhZ3JlY29yZF9jYWxsYmFjayBvZiBhIGJhZCBvYmplY3QAcGVuZCBkaWN0b2YgYSBiYWQgb2JqZWN0AG1vdmUgdG8gZnJvbnQgbG9jayBpbmNvbnNpc3RlbmN5AFxcAGZhdGFsIGZsZXggc2Nhbm5lciBpbnRlcm5hbCBlcnJvci0tbm8gYWN0aW9uIGZvdW5kACVzCgBmYXRhbCBmbGV4IHNjYW5uZXIgaW50ZXJuYWwgZXJyb3ItLWVuZCBvZiBidWZmZXIgbWlzc2VkAGZhdGFsIGVycm9yIC0gc2Nhbm5lciBpbnB1dCBidWZmZXIgb3ZlcmZsb3cAb3V0IG9mIGR5bmFtaWMgbWVtb3J5IGluIGFhZ19nZXRfbmV4dF9idWZmZXIoKQBpbnB1dABzeW50YXggYW1iaWd1aXR5IC0gYmFkbHkgZGVsaW1pdGVkIG51bWJlciAnACcgaW4gbGluZSAlZCBvZiAAIHNwbGl0cyBpbnRvIHR3byB0b2tlbnMKACVzAGxpbmUAJWQgJTFbIl0lbgBvdXQgb2YgZHluYW1pYyBtZW1vcnkgaW4gYWFnX2NyZWF0ZV9idWZmZXIoKQBvdXQgb2YgZHluYW1pYyBtZW1vcnkgaW4gYWFnZW5zdXJlX2J1ZmZlcl9zdGFjaygpADogACBpbiBsaW5lICVkACBuZWFyICcAIHNjYW5uaW5nIGEgcXVvdGVkIHN0cmluZyAobWlzc2luZyBlbmRxdW90ZT8gbG9uZ2VyIHRoYW4gJWQ/KQAKU3RyaW5nIHN0YXJ0aW5nOiIAIHNjYW5uaW5nIGEgSFRNTCBzdHJpbmcgKG1pc3NpbmcgJz4nPyBiYWQgbmVzdGluZz8gbG9uZ2VyIHRoYW4gJWQ/KQAKU3RyaW5nIHN0YXJ0aW5nOjwAIHNjYW5uaW5nIGEgLyouLi4qLyBjb21tZW50IChtaXNzaW5nICcqLz8gbG9uZ2VyIHRoYW4gJWQ/KQBmbGV4IHNjYW5uZXIgcHVzaC1iYWNrIG92ZXJmbG93ACIiAHN0cmljdABsaW5lbGVuZ3RoADsKACBba2V5PQBdACBbACwKAD0AXyVsZF9TVVNQRUNUAGRpAHN0cmljdCAAewoAXTsKABLu7hQJA+7+7u7uAe7u7gHu7gr+7hMZFe4TAe7u7u4LEe7u7u7u7u7u7gHu7hYJAQEdDxfu7hoXG+7uHO7u7u4BGfvu7u4B7hDu7h7u7u7uAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhcRAgICAgICAgICAgICAhIQAhMCAhYCAgICAgICAgICAgICAgICAgICAgICAgICAhQCFQICAgICAgICAgICAgICAgICAgICAgICAgICAgICDgIPAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgECAwQFBgcICQoLDA0LAwQFDwcDDA0GDA0ODA0aFRYAAQADBw4GDwgMDRITKhARCRAvMBEyFxMNFBIuEhRBEzITLEAqQhksQkYiDA0OIw8JEBEKEBHJEBEtRUb8AQb2Dwf2JAIQES8wNk1OKCY7PCo2MTk9Py86QNhEMD4lN0M1Sys4SUwAAwkAAAABDgILDAgjJCU2Oz0ADRASGxYcEicyIhczHjwGBzUFDxEUGCkAEykAAAAAADcVKB0eACEmNB8wPhksABsAIBoqACs6Li8AMTg5LQACAgEAAwMBAAEAAQEBAAIBAQACAgMBAQAABQABAwEDBQMBAQEBAgABAAQCAAIBAQMCAQADAgEAAQEAAQEBAwAYGRkZGhscHB0dHh4fHyAgISEiIiMkJCYnJSUoKCkpKSoqKysrLCwtLS4vLzAxMTIzNDY1Nzc3ODg4OTk6Ou7u/+7u7u7u7h8g7gDv7u7uDO7u7ggN7u7u+O7u7u7u7vXu/wMIBCEFCxITJxQVFikyQRcYGRosMzRCR0gbShwdLh5PHyBrZXkAYXR0cmlidXRlIG1hY3JvcyBub3QgaW1wbGVtZW50ZWQAJXM6JXMAQ291bGQgbm90IG9wZW4gIiVzIiBmb3Igd3JpdGluZyA6ICVzCgBObyBsaWJ6IHN1cHBvcnQuCgAuJWQAbm9uYW1lLmd2AGd2d3JpdGVfbm9feiBwcm9ibGVtICVkCgBtZW1vcnkgYWxsb2NhdGlvbiBmYWlsdXJlCgBObyBsaWJ6IHN1cHBvcnQKAGd2cHJpbnRmOiAlcwoALTk5OTk5OTk5OTk5OTk5OS45OQBncmFwaHZpegAyLjQwLjEAMjAxNjEyMjUuMDMwNAByZW5kZXIAbGF5b3V0AGRldmljZQBsb2FkaW1hZ2UAZHluYW1pYyBsb2FkaW5nIG5vdCBhdmFpbGFibGUKAFVzaW5nICVzOiAlczolcwoAZ3Z1c2Vyc2hhcGUuYwBndnVzZXJzaGFwZV9maW5kAGd2dXNlcnNoYXBlX2ZpbGVfYWNjZXNzAEZpbGVuYW1lICIlcyIgaXMgdW5zYWZlCgAlcyB3aGlsZSBvcGVuaW5nICVzCgB1cy0+ZgBndnVzZXJzaGFwZV9vcGVuACIlcyIgd2FzIG5vdCBmb3VuZCBhcyBhIGZpbGUgb3IgYXMgYSBzaGFwZSBsaWJyYXJ5IG1lbWJlcgoAL01lZGlhQm94AChbYS16XVthLXpBLVpdKik9IihbXiJdKikiAGNhbm5vdCBjb21waWxlIHJlZ3VsYXIgZXhwcmVzc2lvbiAlcwAlbGYlMnMAcHQAdmlld0JveAAlbGYgJWxmICVsZiAlbGYAaW4AcHgAcGMAIgBjbQBtbQAlJUJvdW5kaW5nQm94OgAB0NHS09TV1tfY2QA8c3ZnAFdFQlAAd2VicAAobGliKQCJUE5HDQoaCgBwbmcAJSFQUy1BZG9iZS0AQk0AYm1wAEdJRjgAZ2lmAP/Y/+AAanBlZwAlUERGLQBwZGYAxdDTxgBlcHMAPD94bWwAeG1sAFJJRkYAcmlmZgAAAAEAAGljbwBMYXlvdXQgdHlwZTogIiVzIiBub3QgcmVjb2duaXplZC4gVXNlIG9uZSBvZjolcwoAJWQgJWQgJWQgJWQATGF5b3V0IHdhcyBub3QgZG9uZQoAZmFpbHVyZSBtYWxsb2MnaW5nIGZvciByZXN1bHQgc3RyaW5nAGdjOiBPdXQgb2YgbWVtb3J5CgBfY2NfAG9yaWcAb3AAY2NvbXBzLmMAbWFwQ2x1c3QAY2NncmFwaGluZm8AY2Nnbm9kZWluZm8AKCU0bGQpICU3bGQgbm9kZXMgJTdsZCBlZGdlcwoAICAgICAgICU3ZCBub2RlcyAlN2QgZWRnZXMgJTdsZCBjb21wb25lbnRzICVzCgBkZwBFcnJvcjogbm9kZSAiJXMiIGJlbG9uZ3MgdG8gdHdvIG5vbi1uZXN0ZWQgY2x1c3RlcnMgIiVzIiBhbmQgIiVzIgoAc29ydHYAcm93IG1ham9yAGNvbHVtbiBtYWpvcgBhcnJheSBwYWNraW5nOiAlcyAlZCByb3dzICVkIGNvbHVtbnMKAGJiWyVzXSAlLjVnICUuNWcgJS41ZyAlLjVnCgBzdGVwIHNpemUgPSAlZAoAcG9zWyVkXSAlZCAlZAoAY2MgKCVkIGNlbGxzKSBhdCAoJWQsJWQpICglZCwlZCkKAGNjICglZCBjZWxscykgYXQgKCVkLCVkKQoAJXMgbm8uIGNlbGxzICVkIFcgJWQgSCAlZAoAICAlZCAlZCBjZWxsCgBsaWJwYWNrOiBkaXNjID0gJWYgKCA8IDApCgBQYWNraW5nOiBjb21wdXRlIGdyaWQgc2l6ZQoAYSAlZiBiICVmIGMgJWYgZCAlZiByICVmCgByb290ICVkICglZikgJWQgKCVmKQoAIHIxICVmIHIyICVmCgBwaW5mbwBwYWNrLmMAZ2V0UGFja0luZm8AICBtYXJnaW4gJWQKAHBhY2ttb2RlAHBhcnNlUGFja01vZGVJbmZvAGFycmF5AGFzcGVjdAAlZgBwYWNrIGluZm86CgAgIG1vZGUgICAlcwoAICBhc3BlY3QgJWYKACAgc2l6ZSAgICVkCgAgIGZsYWdzICAlZAoAdW5kZWZpbmVkAHBhY2sAQXJyb3cgdHlwZSAiJXMiIHVua25vd24gLSBpZ25vcmluZwoAbm9ybWFsAGNyb3cAdGVlAGRvdABpbnYAdmVlAHBlbgBtcHR5AGN1cnZlAGljdXJ2ZQBsAGhhbGYAaW52ZW1wdHkAX2JhY2tncm91bmQAX2RyYXdfAENvdWxkIG5vdCBwYXJzZSAiX2JhY2tncm91bmQiIGF0dHJpYnV0ZSBpbiBncmFwaCAlcwoAICAiJXMiCgBubyBtZW1vcnkgZnJvbSB6bWFsbG9jKCkKAG9iagBlbWl0LmMAcG9wX29ial9zdGF0ZQBjbHVzdAAlbGQAcGFnZSVkLCVkXwBUb3RhbCBzaXplID4gMSBpbiAiJXMiIGNvbG9yIHNwZWMgAElsbGVnYWwgbGVuZ3RoIHZhbHVlIGluICIlcyIgY29sb3IgYXR0cmlidXRlIABjb2xvcnNjaGVtZQBlbWl0X2VkZ2VfbGFiZWwAJXMtJXMAZm9yd2FyZABiYWNrACAtPiAAIC0tIABpbiBlZGdlICVzJXMlcwoAbGFiZWxhbGlnbmVkAGVkZ2VocmVmAGVkZ2VVUkwAbGFiZWxocmVmAGxhYmVsVVJMAHRhaWxocmVmAHRhaWxVUkwAaGVhZGhyZWYAaGVhZFVSTAB0YXJnZXQAZWRnZXRhcmdldABsYWJlbHRhcmdldAB0YWlsdGFyZ2V0AGhlYWR0YXJnZXQAZWRnZXRvb2x0aXAAbGFiZWx0b29sdGlwAHRhaWx0b29sdGlwAGhlYWR0b29sdGlwAAFuZXN0aW5nIG5vdCBhbGxvd2VkIGluIHN0eWxlOiAlcwoAdW5tYXRjaGVkICcpJyBpbiBzdHlsZTogJXMKAHRydW5jYXRpbmcgc3R5bGUgJyVzJwoAdW5tYXRjaGVkICcoJyBpbiBzdHlsZTogJXMKAGFsbABiZ2NvbG9yAGluIGNsdXN0ZXIgJXMKAE1vcmUgdGhhbiAyIGNvbG9ycyBzcGVjaWZpZWQgZm9yIGEgZ3JhZGllbnQgLSBpZ25vcmluZyByZW1haW5pbmcKAGdyYWRpZW50IHBlbiBjb2xvcnMgbm90IHlldCBzdXBwb3J0ZWQuCgBJbWFnZXMgdW5zdXBwb3J0ZWQgaW4gImJhY2tncm91bmQiIGF0dHJpYnV0ZQoAbGF5ZXJzIG5vdCBzdXBwb3J0ZWQgaW4gJXMgb3V0cHV0CgBMYXlvdXQgd2FzIG5vdCBkb25lLiAgTWlzc2luZyBsYXlvdXQgcGx1Z2lucz8gCgBndlJlbmRlckpvYnMgJXM6ICUuMmYgc2Vjcy4KAGxheW91dCB3YXMgbm90IGRvbmUKAHJlbmRlcmVyIGZvciAlcyBpcyB1bmF2YWlsYWJsZQoAcGFnZWRpcj0lcyBpZ25vcmVkCgB2aWV3cG9ydAAlbGYsJWxmLCVsZiwnJVteJ10nACVsZiwlbGYsJWxmLCVbXixdJXMAJWxmLCVsZiwlbGYsJWxmLCVsZgBvdXRwdXRvcmRlcgBvZGVzZmlyc3QAZGdlc2ZpcnN0AGxheWVycwBsYXllcnNlbGVjdABUaGUgbGF5ZXJzZWxlY3QgYXR0cmlidXRlICIlcyIgZG9lcyBub3QgbWF0Y2ggYW55IGxheWVyIHNwZWNpZmVkIGJ5IHRoZSBsYXllcnMgYXR0cmlidXRlIC0gaWdub3JlZC4KAGxheWVyc2VwADoJIABsYXllcmxpc3RzZXAALABUaGUgY2hhcmFjdGVyICclYycgYXBwZWFycyBpbiBib3RoIHRoZSBsYXllcnNlcCBhbmQgbGF5ZXJsaXN0c2VwIGF0dHJpYnV0ZXMgLSBsYXllcmxpc3RzZXAgaWdub3JlZC4KAHBhZABCTABwYWdlZGlyAHNvbGlkAABzZXRsaW5ld2lkdGgAMQAAc3BsLT5zaXplID4gMABpbml0X3NwbGluZXNfYmIAYnouc2l6ZSA+IDAAYmV6aWVyX2JiAGJ6LnNpemUgJSAzID09IDEAbGFiZWwAJWxmAGZvbnRwYXRoAERPVEZPTlRQQVRIAEdERk9OVFBBVEgAaW1hZ2VwYXRoAHF1YW50dW0AcmFua2RpcgBMUgBCVABSTABub2Rlc2VwAHJhbmtzZXAAZXF1YWxseQBzaG93Ym94ZXMAZm9udG5hbWVzAHNpemUAcGFnZQBjZW50ZXIAcm90YXRlAG9yaWVudGF0aW9uAGxhbmRzY2FwZQBjbHVzdGVycmFuawBjb25jZW50cmF0ZQBkcGkAcmVzb2x1dGlvbgBvcmRlcmluZwBncmFkaWVudGFuZ2xlAGZpbGxjb2xvcgBzdHlsZQBmb250c2l6ZQBmb250bmFtZQBmb250Y29sb3IAeGxhYmVsAHBlbndpZHRoAHNpZGVzAHBlcmlwaGVyaWVzAHNrZXcAZGlzdG9ydGlvbgBmaXhlZHNpemUAbm9qdXN0aWZ5AGxheWVyAGdyb3VwAGNvbW1lbnQAdmVydGljZXMAegB3ZWlnaHQAbGFiZWxmbG9hdABkaXIAYXJyb3doZWFkAGFycm93dGFpbABoZWFkbGFiZWwAdGFpbGxhYmVsAGxhYmVsZm9udHNpemUAbGFiZWxmb250bmFtZQBsYWJlbGZvbnRjb2xvcgBsYWJlbGRpc3RhbmNlAGxhYmVsYW5nbGUAbWlubGVuAGRlY29yYXRlAGFycm93c2l6ZQBjb25zdHJhaW50AHRhaWxjbGlwAGhlYWRjbGlwAGlkAGxhYmVsanVzdABsb2NhbABnbG9iYWwAJWxmLCVsZiVjACVsZiVjAHJhdGlvAGF1dG8AY29tcHJlc3MAZXhwYW5kAGZpbGwAZ2QAcHMAc3ZnAGNoYXJzZXQAdXRmLTgAbGF0aW4tMQBsYXRpbjEAbDEASVNPLTg4NTktMQBJU09fODg1OS0xAElTTzg4NTktMQBJU08tSVItMTAwAGJpZy01AGJpZzUAdXRmOABVbnN1cHBvcnRlZCBjaGFyc2V0ICIlcyIgLSBhc3N1bWluZyB1dGYtOAoAaW4gbGFiZWwgb2YgZ3JhcGggJXMKAGluIGxhYmVsIG9mIG5vZGUgJXMKAGluIGxhYmVsIG9mIGVkZ2UgJXMgJXMgJXMKAGtpbmQgPT0gTFRfTk9ORQBsYWJlbHMuYwBtYWtlX2xhYmVsAFxMAFxHAFxFAFxIAFxUACYjMTM7ACYjMTA7ACZxdW90OwAmIzE2MDsAJmFtcDsAJmd0OwAmIzM5OwAmIzQ1OwAmbHQ7ACVzICVkIG5vZGVzICVkIGVkZ2VzIG1heGl0ZXI9JWQgYmFsYW5jZT0lZAoAbmV0d29yayBzaW1wbGV4OiAAJWQgACVzJWQgbm9kZXMgJWQgZWRnZXMgJWQgaXRlciAlLjJmIHNlYwoAdXBkYXRlOiBtaXNtYXRjaGVkIGxjYSBpbiB0cmVldXBkYXRlcwoAVHJlZV9lZGdlLnNpemUgPT0gTl9ub2RlcyAtIDEAbnMuYwBmZWFzaWJsZV90cmVlACFUUkVFX0VER0UoZSkAbWVyZ2VfdHJlZXMAKHIwLT5oZWFwX2luZGV4ID4gLTEpIHx8IChyMS0+aGVhcF9pbmRleCA+IC0xKQBTVHNldFVuaW9uAHItPmhlYXBfaW5kZXggPj0gMABhZGRfdHJlZV9lZGdlOiBtaXNzaW5nIHRyZWUgZWRnZQoAYWRkX3RyZWVfZWRnZTogZW1wdHkgb3V0ZWRnZSBsaXN0CgBhZGRfdHJlZV9lZGdlOiBlbXB0eSBpbmVkZ2UgbGlzdAoAdHJvdWJsZSBpbiBpbml0X3JhbmsKAAklcyAlZAoAc2VhcmNoc2l6ZQBncmFwaCAAIABub2RlIABzdG9wCgAlLjVnAHBvcwByZWN0cwB4bHAAbHAAaGVhZF9scAB0YWlsX2xwAGx3aWR0aABsaGVpZ2h0AGJiACUuNWcsJS41ZywlLjVnACwlLjVnACUuNWcsJS41ZwBzYW1wbGVwb2ludHMAJS41ZyAlLjVnAHMsJS41ZywlLjVnIABlLCUuNWcsJS41ZyAAJS41ZywlLjVnLCUuNWcsJS41ZwAlLjJmACUuNWcsJS41ZywlLjVnLCUuNWcgAC9wYXRoYm94IHsKICAgIC9YIGV4Y2ggbmVnICUuNWcgc3ViIGRlZgogICAgL1kgZXhjaCAlLjVnIHN1YiBkZWYKICAgIC94IGV4Y2ggbmVnICUuNWcgc3ViIGRlZgogICAgL3kgZXhjaCAlLjVnIHN1YiBkZWYKICAgIG5ld3BhdGggeCB5IG1vdmV0bwogICAgWCB5IGxpbmV0bwogICAgWCBZIGxpbmV0bwogICAgeCBZIGxpbmV0bwogICAgY2xvc2VwYXRoIHN0cm9rZQp9IGRlZgoAL3BhdGhib3ggewogICAgL1kgZXhjaCAlLjVnIHN1YiBkZWYKICAgIC9YIGV4Y2ggJS41ZyBzdWIgZGVmCiAgICAveSBleGNoICUuNWcgc3ViIGRlZgogICAgL3ggZXhjaCAlLjVnIHN1YiBkZWYKICAgIG5ld3BhdGggeCB5IG1vdmV0bwogICAgWCB5IGxpbmV0bwogICAgWCBZIGxpbmV0bwogICAgeCBZIGxpbmV0bwogICAgY2xvc2VwYXRoIHN0cm9rZQogfSBkZWYKL2RiZ3N0YXJ0IHsgZ3NhdmUgJS41ZyAlLjVnIHRyYW5zbGF0ZSB9IGRlZgovYXJyb3dsZW5ndGggMTAgZGVmCi9hcnJvd3dpZHRoIGFycm93bGVuZ3RoIDIgZGl2IGRlZgovYXJyb3doZWFkIHsKICAgIGdzYXZlCiAgICByb3RhdGUKICAgIGN1cnJlbnRwb2ludAogICAgbmV3cGF0aAogICAgbW92ZXRvCiAgICBhcnJvd2xlbmd0aCBhcnJvd3dpZHRoIDIgZGl2IHJsaW5ldG8KICAgIDAgYXJyb3d3aWR0aCBuZWcgcmxpbmV0bwogICAgY2xvc2VwYXRoIGZpbGwKICAgIGdyZXN0b3JlCn0gYmluZCBkZWYKL21ha2VhcnJvdyB7CiAgICBjdXJyZW50cG9pbnQgZXhjaCBwb3Agc3ViIGV4Y2ggY3VycmVudHBvaW50IHBvcCBzdWIgYXRhbgogICAgYXJyb3doZWFkCn0gYmluZCBkZWYKL3BvaW50IHsgICAgbmV3cGF0aCAgICAyIDAgMzYwIGFyYyBmaWxsfSBkZWYvbWFrZXZlYyB7CiAgICAvWSBleGNoIGRlZgogICAgL1ggZXhjaCBkZWYKICAgIC95IGV4Y2ggZGVmCiAgICAveCBleGNoIGRlZgogICAgbmV3cGF0aCB4IHkgbW92ZXRvCiAgICBYIFkgbGluZXRvIHN0cm9rZQogICAgWCBZIG1vdmV0bwogICAgeCB5IG1ha2VhcnJvdwp9IGRlZgoAbG9zdCAlcyAlcyBlZGdlCgBubyBwb3NpdGlvbiBmb3IgZWRnZSB3aXRoIGxhYmVsICVzAG5vIHBvc2l0aW9uIGZvciBlZGdlIHdpdGggdGFpbCBsYWJlbCAlcwBubyBwb3NpdGlvbiBmb3IgZWRnZSB3aXRoIGhlYWQgbGFiZWwgJXMAbm8gcG9zaXRpb24gZm9yIGVkZ2Ugd2l0aCB4bGFiZWwgJXMAZm9yY2VsYWJlbHMAJWQgb3V0IG9mICVkIGxhYmVscyBwb3NpdGlvbmVkLgoAJWQgb3V0IG9mICVkIGV4dGVyaW9yIGxhYmVscyBwb3NpdGlvbmVkLgoAJWQgb2JqcyAlZCB4bGFiZWxzIGZvcmNlPSVkIGJiPSglLjAyZiwlLjAyZikgKCUuMDJmLCUuMDJmKQoAb2JqZWN0cwoAIFslZF0gKCUuMDJmLCUuMDJmKSAoJS4wMmYsJS4wMmYpICVwICIlcyIKAHhsYWJlbHMKACBbJWRdICVwIHNldCAlZCAoJS4wMmYsJS4wMmYpICglLjAyZiwlLjAyZikgJXMKAHNoYXBlZmlsZSBub3Qgc2V0IG9yIG5vdCBmb3VuZCBmb3IgZXBzZiBub2RlICVzCgBjb3VsZG4ndCBvcGVuIGVwc2YgZmlsZSAlcwoAJSUlJUJvdW5kaW5nQm94OiAlZCAlZCAlZCAlZAByZWFkAEJvdW5kaW5nQm94IG5vdCBmb3VuZCBpbiBlcHNmIGZpbGUgJXMKAGNhbid0IGZpbmQgbGlicmFyeSBmaWxlICVzCgBjYW4ndCBvcGVuIGxpYnJhcnkgZmlsZSAlcwoARU9GAEJFR0lOAEVORABUUkFJTEVSAC91c2VyX3NoYXBlXyVkIHsKACUlQmVnaW5Eb2N1bWVudDoKACUlRW5kRG9jdW1lbnQKAH0gYmluZCBkZWYKAFVURi04IGlucHV0IHVzZXMgbm9uLUxhdGluMSBjaGFyYWN0ZXJzIHdoaWNoIGNhbm5vdCBiZSBoYW5kbGVkIGJ5IHRoaXMgUG9zdFNjcmlwdCBkcml2ZXIKAGNhbm5vdCByZS1hbGxvY2F0ZSBwcwoAcm91dGVzcGxpbmVzaW5pdDogY2Fubm90IGFsbG9jYXRlIHBzCgByb3V0ZXNwbGluZXM6ICVkIGVkZ2VzLCAlZCBib3hlcyAlLjJmIHNlYwoAaW4gcm91dGVzcGxpbmVzLCBjYW5ub3QgZmluZCBOT1JNQUwgZWRnZQoAaW4gcm91dGVzcGxpbmVzLCBpbGxlZ2FsIHZhbHVlcyBvZiBwcmV2ICVkIGFuZCBuZXh0ICVkLCBsaW5lICVkCgBpbiByb3V0ZXNwbGluZXMsIGVkZ2UgaXMgYSBsb29wIGF0ICVzCgBpbiByb3V0ZXNwbGluZXMsIFBzaG9ydGVzdHBhdGggZmFpbGVkCgBpbiByb3V0ZXNwbGluZXMsIFByb3V0ZXNwbGluZSBmYWlsZWQKAFVuYWJsZSB0byByZWNsYWltIGJveCBzcGFjZSBpbiBzcGxpbmUgcm91dGluZyBmb3IgZWRnZSAiJXMiIC0+ICIlcyIuIFNvbWV0aGluZyBpcyBwcm9iYWJseSBzZXJpb3VzbHkgd3JvbmcuCgBpbiBjaGVja3BhdGgsIGJveCAwIGhhcyBMTCBjb29yZCA+IFVSIGNvb3JkCgBpbiBjaGVja3BhdGgsIGJveCAlZCBoYXMgTEwgY29vcmQgPiBVUiBjb29yZAoAaW4gY2hlY2twYXRoLCBib3hlcyAlZCBhbmQgJWQgZG9uJ3QgdG91Y2gKAGluIGNoZWNrcGF0aCwgc3RhcnQgcG9ydCBub3QgaW4gZmlyc3QgYm94CgBpbiBjaGVja3BhdGgsIGVuZCBwb3J0IG5vdCBpbiBsYXN0IGJveAoAJWQgYm94ZXM6CgAlZCAoJS41ZywgJS41ZyksICglLjVnLCAlLjVnKQoAY29uc3RyYWluZWQAbm90IGNvbnN0cmFpbmVkAHN0YXJ0IHBvcnQ6ICglLjVnLCAlLjVnKSwgdGFuZ2VudCBhbmdsZTogJS41ZywgJXMKAGVuZCBwb3J0OiAoJS41ZywgJS41ZyksIHRhbmdlbnQgYW5nbGU6ICUuNWcsICVzCgBzaWRlcyA9PSA0AHNoYXBlcy5jAHJvdW5kX2Nvcm5lcnMAYmFkIGxhYmVsIGZvcm1hdCAlcwoAXE4AbWFyZ2luACVsZiwlbGYAcmVndWxhcgBjdXN0b20Ac2hhcGVmaWxlADxuaWw+AE5vIG9yIGltcHJvcGVyIHNoYXBlZmlsZT0iJXMiIGZvciBub2RlICIlcyIKAE5vIG9yIGltcHJvcGVyIGltYWdlPSIlcyIgZm9yIG5vZGUgIiVzIgoAbGFiZWxsb2MAc2hhcGUAbm9kZSAnJXMnLCBncmFwaCAnJXMnIHNpemUgdG9vIHNtYWxsIGZvciBsYWJlbAoAZXBzZgB1c2luZyAlcyBmb3IgdW5rbm93biBzaGFwZSAlcwoAYm94AHBvbHlnb24Ab3ZhbABjaXJjbGUAcG9pbnQAZWdnAHRyaWFuZ2xlAHBsYWludGV4dABwbGFpbgBkaWFtb25kAHRyYXBleml1bQBwYXJhbGxlbG9ncmFtAGhvdXNlAHBlbnRhZ29uAGhleGFnb24Ac2VwdGFnb24Ab2N0YWdvbgBub3RlAHRhYgBmb2xkZXIAYm94M2QAY29tcG9uZW50AGN5bGluZGVyAHJlY3QAcmVjdGFuZ2xlAHNxdWFyZQBkb3VibGVjaXJjbGUAZG91Ymxlb2N0YWdvbgB0cmlwbGVvY3RhZ29uAGludnRyaWFuZ2xlAGludnRyYXBleml1bQBpbnZob3VzZQB1bmRlcmxpbmUATWRpYW1vbmQATXNxdWFyZQBNY2lyY2xlAHByb21vdGVyAGNkcwB0ZXJtaW5hdG9yAHV0cgBpbnN1bGF0b3IAcmlib3NpdGUAcm5hc3RhYgBwcm90ZWFzZXNpdGUAcHJvdGVpbnN0YWIAcHJpbWVyc2l0ZQByZXN0cmljdGlvbnNpdGUAZml2ZXBvdmVyaGFuZwB0aHJlZXBvdmVyaGFuZwBub3ZlcmhhbmcAYXNzZW1ibHkAc2lnbmF0dXJlAHJwcm9tb3RlcgBsYXJyb3cAcmFycm93AGxwcm9tb3RlcgByZWNvcmQATXJlY29yZABzdGFyACM4MDgwODAAI2ZjZmNmYwAjMzAzMDMwACNlOGU4ZTgAI2UwZTBlMAAjZjBmMGYwACMxMDEwMTAAI2Y4ZjhmOABpbiBub2RlICVzCgByb3VuZGVkAGRpYWdvbmFscwByYWRpYWwAc3RyaXBlZAB3ZWRnZWQAXwBub2RlICVzLCBwb3J0ICVzLCB1bnJlY29nbml6ZWQgY29tcGFzcyBwb2ludCAnJXMnIC0gaWdub3JlZAoAbm9kZSAlcywgcG9ydCAlcyB1bnJlY29nbml6ZWQKACUuNWcgJS41ZyB0cmFuc2xhdGUgbmV3cGF0aCB1c2VyX3NoYXBlXyVkCgBpbnZpcwAAZmlsbGVkAABzAGUAdwBzcGxpbmVzLmMAYmVnaW5wYXRoAFAtPmVuZC50aGV0YSA8IDIgKiBNX1BJAGVuZHBhdGgAbWFrZVNlbGZFZGdlAGdldHNwbGluZXBvaW50czogbm8gc3BsaW5lIHBvaW50cyBhdmFpbGFibGUgZm9yIGVkZ2UgKCVzLCVzKQoAcG9seWxpbmVNaWRwb2ludABzcGFuLT5mb250AHRleHRzcGFuLmMAdGV4dHNwYW5fc2l6ZQBmb250LT5uYW1lAGZvbnRuYW1lOiAiJXMiIHJlc29sdmVkIHRvOiAlcwoAZm9udG5hbWU6IHVuYWJsZSB0byByZXNvbHZlICIlcyIKAGNvdXIAYXJpYWwAaGVsdmV0aWNhAFtpbnRlcm5hbCB0aW1lc10AW2ludGVybmFsIGNvdXJpZXJdAFtpbnRlcm5hbCBhcmlhbF0AQXZhbnRHYXJkZS1Cb29rAFVSVyBHb3RoaWMgTABib29rAHNhbnMtU2VyaWYAQXZhbnRHYXJkZS1Cb29rT2JsaXF1ZQBvYmxpcXVlAGl0YWxpYwBBdmFudEdhcmRlLURlbWkAZGVtaQBBdmFudEdhcmRlLURlbWlPYmxpcXVlAEJvb2ttYW4tRGVtaQBVUlcgQm9va21hbiBMAHNlcmlmAEJvb2ttYW4tRGVtaUl0YWxpYwBCb29rbWFuLUxpZ2h0AGxpZ2h0AEJvb2ttYW4tTGlnaHRJdGFsaWMAQ291cmllcgBtb25vc3BhY2UAQ291cmllci1Cb2xkAENvdXJpZXItQm9sZE9ibGlxdWUAQ291cmllci1PYmxpcXVlAEhlbHZldGljYQBIZWx2ZXRpY2EtQm9sZABIZWx2ZXRpY2EtQm9sZE9ibGlxdWUASGVsdmV0aWNhLU5hcnJvdwBjb25kZW5zZWQASGVsdmV0aWNhLU5hcnJvdy1Cb2xkAEhlbHZldGljYS1OYXJyb3ctQm9sZE9ibGlxdWUASGVsdmV0aWNhLU5hcnJvdy1PYmxpcXVlAEhlbHZldGljYS1PYmxpcXVlAE5ld0NlbnR1cnlTY2hsYmstQm9sZABDZW50dXJ5IFNjaG9vbGJvb2sgTABOZXdDZW50dXJ5U2NobGJrLUJvbGRJdGFsaWMATmV3Q2VudHVyeVNjaGxiay1JdGFsaWMATmV3Q2VudHVyeVNjaGxiay1Sb21hbgByb21hbgBQYWxhdGluby1Cb2xkAFBhbGF0aW5vIExpbm90eXBlAFBhbGF0aW5vLUJvbGRJdGFsaWMAUGFsYXRpbm8tSXRhbGljAFBhbGF0aW5vLVJvbWFuAFN5bWJvbABmYW50YXN5AFRpbWVzLUJvbGQAVGltZXMAVGltZXMtQm9sZEl0YWxpYwBUaW1lcy1JdGFsaWMAWmFwZkNoYW5jZXJ5LU1lZGl1bUl0YWxpYwBVUlcgQ2hhbmNlcnkgTABtZWRpdW0AWmFwZkRpbmdiYXRzAERpbmdiYXRzAG5vAHRydWUAeWVzAHV0aWxzLmMAdSA9PSBVRl9maW5kKHUpAFVGX3NldG5hbWUAAWZpbGUgbG9hZGluZyBpcyBkaXNhYmxlZCBiZWNhdXNlIHRoZSBlbnZpcm9ubWVudCBjb250YWlucyBTRVJWRVJfTkFNRT0iJXMiCmFuZCB0aGUgR1ZfRklMRV9QQVRIIHZhcmlhYmxlIGlzIHVuc2V0IG9yIGVtcHR5LgoAUGF0aCBwcm92aWRlZCB0byBmaWxlOiAiJXMiIGhhcyBiZWVuIGlnbm9yZWQgYmVjYXVzZSBmaWxlcyBhcmUgb25seSBwZXJtaXR0ZWQgdG8gYmUgbG9hZGVkIGZyb20gdGhlIGRpcmVjdG9yaWVzIGluICIlcyIgd2hlbiBydW5uaW5nIGluIGFuIGh0dHAgc2VydmVyLgoAJXMlcyVzAC8AOgBlbGxpcHNlAFRpbWVzLVJvbWFuAGNsdXN0ZXIAX19jbHVzdGVybm9kZXMAVHdvIGNsdXN0ZXJzIG5hbWVkICVzIC0gdGhlIHNlY29uZCB3aWxsIGJlIGlnbm9yZWQKAG1hcE4AQUVsaWcAQWFjdXRlAEFjaXJjAEFncmF2ZQBBbHBoYQBBcmluZwBBdGlsZGUAQXVtbABCZXRhAENjZWRpbABDaGkARGFnZ2VyAERlbHRhAEVUSABFYWN1dGUARWNpcmMARWdyYXZlAEVwc2lsb24ARXRhAEV1bWwAR2FtbWEASWFjdXRlAEljaXJjAElncmF2ZQBJb3RhAEl1bWwAS2FwcGEATGFtYmRhAE11AE50aWxkZQBOdQBPRWxpZwBPYWN1dGUAT2NpcmMAT2dyYXZlAE9tZWdhAE9taWNyb24AT3NsYXNoAE90aWxkZQBPdW1sAFBoaQBQaQBQcmltZQBQc2kAUmhvAFNjYXJvbgBTaWdtYQBUSE9STgBUYXUAVGhldGEAVWFjdXRlAFVjaXJjAFVncmF2ZQBVcHNpbG9uAFV1bWwAWGkAWWFjdXRlAFl1bWwAWmV0YQBhYWN1dGUAYWNpcmMAYWN1dGUAYWVsaWcAYWdyYXZlAGFsZWZzeW0AYWxwaGEAYW1wAGFuZABhbmcAYXJpbmcAYXN5bXAAYXRpbGRlAGF1bWwAYmRxdW8AYmV0YQBicnZiYXIAYnVsbABjYXAAY2NlZGlsAGNlZGlsAGNlbnQAY2hpAGNpcmMAY2x1YnMAY29uZwBjb3B5AGNyYXJyAGN1cABjdXJyZW4AZEFycgBkYWdnZXIAZGFycgBkZWcAZGVsdGEAZGlhbXMAZGl2aWRlAGVhY3V0ZQBlY2lyYwBlZ3JhdmUAZW1wdHkAZW1zcABlbnNwAGVwc2lsb24AZXF1aXYAZXRhAGV0aABldW1sAGV1cm8AZXhpc3QAZm5vZgBmb3JhbGwAZnJhYzEyAGZyYWMxNABmcmFjMzQAZnJhc2wAZ2FtbWEAZ2UAZ3QAaEFycgBoYXJyAGhlYXJ0cwBoZWxsaXAAaWFjdXRlAGljaXJjAGlleGNsAGlncmF2ZQBpbWFnZQBpbmZpbgBpbnQAaW90YQBpcXVlc3QAaXNpbgBpdW1sAGthcHBhAGxBcnIAbGFtYmRhAGxhbmcAbGFxdW8AbGFycgBsY2VpbABsZHF1bwBsZQBsZmxvb3IAbG93YXN0AGxvegBscm0AbHNhcXVvAGxzcXVvAGx0AG1hY3IAbWRhc2gAbWljcm8AbWlkZG90AG11AG5hYmxhAG5ic3AAbmRhc2gAbmUAbmkAbm90AG5vdGluAG5zdWIAbnRpbGRlAG51AG9hY3V0ZQBvY2lyYwBvZWxpZwBvZ3JhdmUAb2xpbmUAb21lZ2EAb21pY3JvbgBvcGx1cwBvcgBvcmRmAG9yZG0Ab3NsYXNoAG90aWxkZQBvdGltZXMAb3VtbABwYXJhAHBhcnQAcGVybWlsAHBlcnAAcGhpAHBpAHBpdgBwbHVzbW4AcG91bmQAcHJpbWUAcHJvZABwcm9wAHBzaQBxdW90AHJBcnIAcmFkaWMAcmFuZwByYXF1bwByYXJyAHJjZWlsAHJkcXVvAHJlYWwAcmVnAHJmbG9vcgByaG8AcmxtAHJzYXF1bwByc3F1bwBzYnF1bwBzY2Fyb24Ac2RvdABzZWN0AHNoeQBzaWdtYQBzaWdtYWYAc2ltAHNwYWRlcwBzdWIAc3ViZQBzdW0Ac3VwAHN1cDEAc3VwMgBzdXAzAHN1cGUAc3psaWcAdGF1AHRoZXJlNAB0aGV0YQB0aGV0YXN5bQB0aGluc3AAdGhvcm4AdGlsZGUAdGltZXMAdHJhZGUAdUFycgB1YWN1dGUAdWFycgB1Y2lyYwB1Z3JhdmUAdW1sAHVwc2loAHVwc2lsb24AdXVtbAB3ZWllcnAAeGkAeWFjdXRlAHllbgB5dW1sAHpldGEAendqAHp3bmoAVVRGOCBjb2RlcyA+IDQgYnl0ZXMgYXJlIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkIChncmFwaCAlcykgLSB0cmVhdGVkIGFzIExhdGluLTEuIFBlcmhhcHMgIi1HY2hhcnNldD1sYXRpbjEiIGlzIG5lZWRlZD8KAEludmFsaWQgJWQtYnl0ZSBVVEY4IGZvdW5kIGluIGlucHV0IG9mIGdyYXBoICVzIC0gdHJlYXRlZCBhcyBMYXRpbi0xLiBQZXJoYXBzICItR2NoYXJzZXQ9bGF0aW4xIiBpcyBuZWVkZWQ/CgBiei5zaXplAG92ZXJsYXBfYmV6aWVyAHVydmVkAG9tcG91bmQAYWxzZQBpbmUAb25lAG8AcnRobwBvbHlsaW5lAHBsaW5lAHJ1ZQBlcwBVbmtub3duICJzcGxpbmVzIiB2YWx1ZTogIiVzIiAtIGlnbm9yZWQKAHNwbGluZXMAb2RiAE9ydGhvZ29uYWwgZWRnZXMgZG8gbm90IGN1cnJlbnRseSBoYW5kbGUgZWRnZSBsYWJlbHMuIFRyeSB1c2luZyB4bGFiZWxzLgoAb3J0aG8gJXMgJXMKAGNoYW5pAG9ydGhvLmMAY2hhblNlYXJjaABjcAAlJSFQUy1BZG9iZS0yLjAKJSUlJUJvdW5kaW5nQm94OiAoYXRlbmQpCi9wb2ludCB7CiAgL1kgZXhjaCBkZWYKICAvWCBleGNoIGRlZgogIG5ld3BhdGgKICBYIFkgMyAwIDM2MCBhcmMgZmlsbAp9IGRlZgovY2VsbCB7CiAgL1kgZXhjaCBkZWYKICAvWCBleGNoIGRlZgogIC95IGV4Y2ggZGVmCiAgL3ggZXhjaCBkZWYKICBuZXdwYXRoCiAgeCB5IG1vdmV0bwogIHggWSBsaW5ldG8KICBYIFkgbGluZXRvCiAgWCB5IGxpbmV0bwogIGNsb3NlcGF0aCBzdHJva2UKfSBkZWYKL25vZGUgewogL3UgZXhjaCBkZWYKIC9yIGV4Y2ggZGVmCiAvZCBleGNoIGRlZgogL2wgZXhjaCBkZWYKIG5ld3BhdGggbCBkIG1vdmV0bwogciBkIGxpbmV0byByIHUgbGluZXRvIGwgdSBsaW5ldG8KIGNsb3NlcGF0aCBmaWxsCn0gZGVmCgoAJWQgJWQgdHJhbnNsYXRlCgAwLjggMC44IDAuOCBzZXRyZ2Jjb2xvcgoAc2hvd3BhZ2UKJSUlJVRyYWlsZXIKJSUlJUJvdW5kaW5nQm94OiAlZCAlZCAlZCAlZAoAbmV3cGF0aCAlZCAlZCBtb3ZldG8KACVkICVkIGxpbmV0bwoAJWQgJWQgbGluZXRvIHN0cm9rZQoAY2hhbm5lbCAlZCAoJWYsJWYpCgAgLT4KACAgICAgACgoJWYsJWYpLCglZiwlZikpICVzICVzAEJfUklHSFQAQl9ET1dOAEJfTEVGVABCX1VQAEJfTk9ERQBzZWcAbmV4dF9zZWcAZGVjaWRlX3BvaW50AGluY29tcGFyYWJsZSBzZWdtZW50cyAhISAtLSBBYm9ydGluZwoAczEtPmNvbW1fY29vcmQ9PXMyLT5jb21tX2Nvb3JkAGlzX3BhcmFsbGVsAGdyYXBoIEcgewoAIG5vZGVbc2hhcGU9cG9pbnRdCgAgICVkIFtwb3M9IiVkLCVkIl0KACAgJWQgLS0gJWRbbGVuPSIlZiJdCgB9CgBjb2xvciAlcwAlcyBpcyBub3QgYSBrbm93biBjb2xvci4KAGVycm9yIGluIGNvbHhsYXRlKCkKAHNvbGlkAGludmlzaWJsZQBib2xkAHNldGxpbmV3aWR0aABmaWxsZWQAdW5maWxsZWQAdGFwZXJlZABndnJlbmRlcl9zZXRfc3R5bGU6IHVuc3VwcG9ydGVkIHN0eWxlICVzIC0gaWdub3JpbmcKAGd2cmVuZGVyLmMAZ3ZyZW5kZXJfdXNlcnNoYXBlAG5hbWUAbmFtZVswXQB3aWR0aABoZWlnaHQAYm90aABqb2IAZ3Zsb2FkaW1hZ2UuYwBndmxvYWRpbWFnZQB1cwB1cy0+bmFtZQB1cy0+bmFtZVswXQBObyBsb2FkaW1hZ2UgcGx1Z2luIGZvciAiJXMiCgBRAExlZnQAS1BfTGVmdABSaWdodABLUF9SaWdodABVcABLUF9VcABEb3duAEtQX0Rvd24AcGx1cwBLUF9BZGQAbWludXMAS1BfU3VidHJhY3QARgB0b29sdGlwAGVkZ2UAdGFpbHBvcnQAaGVhZHBvcnQAa2V5AGhyZWYAVVJMAG5vZGUAZGlncmFwaABncmFwaABzdWJncmFwaABfTFRYX2xpYnJhcnkAdGV4dGxheW91dABvYmpwLT5sYmwAeGxhYmVscy5jAHhsYWRqdXN0AHhsaW50ZXJzZWN0aW9ucwBscCAhPSBjbHAAZ2V0aW50cnN4aQBvYmpwMS0+c3oueCA9PSAwICYmIG9ianAxLT5zei55ID09IDAAbGJsZW5jbG9zaW5nAHZwAHhsaGR4dW5sb2FkAHNpemU9PWZyZWVkAHJlY3QuYm91bmRhcnlbMl0gPCBJTlRfTUFYAG9ianBscG1rcwByZWN0LmJvdW5kYXJ5WzNdIDwgSU5UX01BWABvdXQgb2YgbWVtb3J5CgAjJTJ4JTJ4JTJ4JTJ4ACVsZiVsZiVsZgAvYWNjZW50My8xAC9hY2NlbnQzLzIAL2FjY2VudDMvMwAvYWNjZW50NC8xAC9hY2NlbnQ0LzIAL2FjY2VudDQvMwAvYWNjZW50NC80AC9hY2NlbnQ1LzEAL2FjY2VudDUvMgAvYWNjZW50NS8zAC9hY2NlbnQ1LzQAL2FjY2VudDUvNQAvYWNjZW50Ni8xAC9hY2NlbnQ2LzIAL2FjY2VudDYvMwAvYWNjZW50Ni80AC9hY2NlbnQ2LzUAL2FjY2VudDYvNgAvYWNjZW50Ny8xAC9hY2NlbnQ3LzIAL2FjY2VudDcvMwAvYWNjZW50Ny80AC9hY2NlbnQ3LzUAL2FjY2VudDcvNgAvYWNjZW50Ny83AC9hY2NlbnQ4LzEAL2FjY2VudDgvMgAvYWNjZW50OC8zAC9hY2NlbnQ4LzQAL2FjY2VudDgvNQAvYWNjZW50OC82AC9hY2NlbnQ4LzcAL2FjY2VudDgvOAAvYmx1ZXMzLzEAL2JsdWVzMy8yAC9ibHVlczMvMwAvYmx1ZXM0LzEAL2JsdWVzNC8yAC9ibHVlczQvMwAvYmx1ZXM0LzQAL2JsdWVzNS8xAC9ibHVlczUvMgAvYmx1ZXM1LzMAL2JsdWVzNS80AC9ibHVlczUvNQAvYmx1ZXM2LzEAL2JsdWVzNi8yAC9ibHVlczYvMwAvYmx1ZXM2LzQAL2JsdWVzNi81AC9ibHVlczYvNgAvYmx1ZXM3LzEAL2JsdWVzNy8yAC9ibHVlczcvMwAvYmx1ZXM3LzQAL2JsdWVzNy81AC9ibHVlczcvNgAvYmx1ZXM3LzcAL2JsdWVzOC8xAC9ibHVlczgvMgAvYmx1ZXM4LzMAL2JsdWVzOC80AC9ibHVlczgvNQAvYmx1ZXM4LzYAL2JsdWVzOC83AC9ibHVlczgvOAAvYmx1ZXM5LzEAL2JsdWVzOS8yAC9ibHVlczkvMwAvYmx1ZXM5LzQAL2JsdWVzOS81AC9ibHVlczkvNgAvYmx1ZXM5LzcAL2JsdWVzOS84AC9ibHVlczkvOQAvYnJiZzEwLzEAL2JyYmcxMC8xMAAvYnJiZzEwLzIAL2JyYmcxMC8zAC9icmJnMTAvNAAvYnJiZzEwLzUAL2JyYmcxMC82AC9icmJnMTAvNwAvYnJiZzEwLzgAL2JyYmcxMC85AC9icmJnMTEvMQAvYnJiZzExLzEwAC9icmJnMTEvMTEAL2JyYmcxMS8yAC9icmJnMTEvMwAvYnJiZzExLzQAL2JyYmcxMS81AC9icmJnMTEvNgAvYnJiZzExLzcAL2JyYmcxMS84AC9icmJnMTEvOQAvYnJiZzMvMQAvYnJiZzMvMgAvYnJiZzMvMwAvYnJiZzQvMQAvYnJiZzQvMgAvYnJiZzQvMwAvYnJiZzQvNAAvYnJiZzUvMQAvYnJiZzUvMgAvYnJiZzUvMwAvYnJiZzUvNAAvYnJiZzUvNQAvYnJiZzYvMQAvYnJiZzYvMgAvYnJiZzYvMwAvYnJiZzYvNAAvYnJiZzYvNQAvYnJiZzYvNgAvYnJiZzcvMQAvYnJiZzcvMgAvYnJiZzcvMwAvYnJiZzcvNAAvYnJiZzcvNQAvYnJiZzcvNgAvYnJiZzcvNwAvYnJiZzgvMQAvYnJiZzgvMgAvYnJiZzgvMwAvYnJiZzgvNAAvYnJiZzgvNQAvYnJiZzgvNgAvYnJiZzgvNwAvYnJiZzgvOAAvYnJiZzkvMQAvYnJiZzkvMgAvYnJiZzkvMwAvYnJiZzkvNAAvYnJiZzkvNQAvYnJiZzkvNgAvYnJiZzkvNwAvYnJiZzkvOAAvYnJiZzkvOQAvYnVnbjMvMQAvYnVnbjMvMgAvYnVnbjMvMwAvYnVnbjQvMQAvYnVnbjQvMgAvYnVnbjQvMwAvYnVnbjQvNAAvYnVnbjUvMQAvYnVnbjUvMgAvYnVnbjUvMwAvYnVnbjUvNAAvYnVnbjUvNQAvYnVnbjYvMQAvYnVnbjYvMgAvYnVnbjYvMwAvYnVnbjYvNAAvYnVnbjYvNQAvYnVnbjYvNgAvYnVnbjcvMQAvYnVnbjcvMgAvYnVnbjcvMwAvYnVnbjcvNAAvYnVnbjcvNQAvYnVnbjcvNgAvYnVnbjcvNwAvYnVnbjgvMQAvYnVnbjgvMgAvYnVnbjgvMwAvYnVnbjgvNAAvYnVnbjgvNQAvYnVnbjgvNgAvYnVnbjgvNwAvYnVnbjgvOAAvYnVnbjkvMQAvYnVnbjkvMgAvYnVnbjkvMwAvYnVnbjkvNAAvYnVnbjkvNQAvYnVnbjkvNgAvYnVnbjkvNwAvYnVnbjkvOAAvYnVnbjkvOQAvYnVwdTMvMQAvYnVwdTMvMgAvYnVwdTMvMwAvYnVwdTQvMQAvYnVwdTQvMgAvYnVwdTQvMwAvYnVwdTQvNAAvYnVwdTUvMQAvYnVwdTUvMgAvYnVwdTUvMwAvYnVwdTUvNAAvYnVwdTUvNQAvYnVwdTYvMQAvYnVwdTYvMgAvYnVwdTYvMwAvYnVwdTYvNAAvYnVwdTYvNQAvYnVwdTYvNgAvYnVwdTcvMQAvYnVwdTcvMgAvYnVwdTcvMwAvYnVwdTcvNAAvYnVwdTcvNQAvYnVwdTcvNgAvYnVwdTcvNwAvYnVwdTgvMQAvYnVwdTgvMgAvYnVwdTgvMwAvYnVwdTgvNAAvYnVwdTgvNQAvYnVwdTgvNgAvYnVwdTgvNwAvYnVwdTgvOAAvYnVwdTkvMQAvYnVwdTkvMgAvYnVwdTkvMwAvYnVwdTkvNAAvYnVwdTkvNQAvYnVwdTkvNgAvYnVwdTkvNwAvYnVwdTkvOAAvYnVwdTkvOQAvZGFyazIzLzEAL2RhcmsyMy8yAC9kYXJrMjMvMwAvZGFyazI0LzEAL2RhcmsyNC8yAC9kYXJrMjQvMwAvZGFyazI0LzQAL2RhcmsyNS8xAC9kYXJrMjUvMgAvZGFyazI1LzMAL2RhcmsyNS80AC9kYXJrMjUvNQAvZGFyazI2LzEAL2RhcmsyNi8yAC9kYXJrMjYvMwAvZGFyazI2LzQAL2RhcmsyNi81AC9kYXJrMjYvNgAvZGFyazI3LzEAL2RhcmsyNy8yAC9kYXJrMjcvMwAvZGFyazI3LzQAL2RhcmsyNy81AC9kYXJrMjcvNgAvZGFyazI3LzcAL2RhcmsyOC8xAC9kYXJrMjgvMgAvZGFyazI4LzMAL2RhcmsyOC80AC9kYXJrMjgvNQAvZGFyazI4LzYAL2RhcmsyOC83AC9kYXJrMjgvOAAvZ25idTMvMQAvZ25idTMvMgAvZ25idTMvMwAvZ25idTQvMQAvZ25idTQvMgAvZ25idTQvMwAvZ25idTQvNAAvZ25idTUvMQAvZ25idTUvMgAvZ25idTUvMwAvZ25idTUvNAAvZ25idTUvNQAvZ25idTYvMQAvZ25idTYvMgAvZ25idTYvMwAvZ25idTYvNAAvZ25idTYvNQAvZ25idTYvNgAvZ25idTcvMQAvZ25idTcvMgAvZ25idTcvMwAvZ25idTcvNAAvZ25idTcvNQAvZ25idTcvNgAvZ25idTcvNwAvZ25idTgvMQAvZ25idTgvMgAvZ25idTgvMwAvZ25idTgvNAAvZ25idTgvNQAvZ25idTgvNgAvZ25idTgvNwAvZ25idTgvOAAvZ25idTkvMQAvZ25idTkvMgAvZ25idTkvMwAvZ25idTkvNAAvZ25idTkvNQAvZ25idTkvNgAvZ25idTkvNwAvZ25idTkvOAAvZ25idTkvOQAvZ3JlZW5zMy8xAC9ncmVlbnMzLzIAL2dyZWVuczMvMwAvZ3JlZW5zNC8xAC9ncmVlbnM0LzIAL2dyZWVuczQvMwAvZ3JlZW5zNC80AC9ncmVlbnM1LzEAL2dyZWVuczUvMgAvZ3JlZW5zNS8zAC9ncmVlbnM1LzQAL2dyZWVuczUvNQAvZ3JlZW5zNi8xAC9ncmVlbnM2LzIAL2dyZWVuczYvMwAvZ3JlZW5zNi80AC9ncmVlbnM2LzUAL2dyZWVuczYvNgAvZ3JlZW5zNy8xAC9ncmVlbnM3LzIAL2dyZWVuczcvMwAvZ3JlZW5zNy80AC9ncmVlbnM3LzUAL2dyZWVuczcvNgAvZ3JlZW5zNy83AC9ncmVlbnM4LzEAL2dyZWVuczgvMgAvZ3JlZW5zOC8zAC9ncmVlbnM4LzQAL2dyZWVuczgvNQAvZ3JlZW5zOC82AC9ncmVlbnM4LzcAL2dyZWVuczgvOAAvZ3JlZW5zOS8xAC9ncmVlbnM5LzIAL2dyZWVuczkvMwAvZ3JlZW5zOS80AC9ncmVlbnM5LzUAL2dyZWVuczkvNgAvZ3JlZW5zOS83AC9ncmVlbnM5LzgAL2dyZWVuczkvOQAvZ3JleXMzLzEAL2dyZXlzMy8yAC9ncmV5czMvMwAvZ3JleXM0LzEAL2dyZXlzNC8yAC9ncmV5czQvMwAvZ3JleXM0LzQAL2dyZXlzNS8xAC9ncmV5czUvMgAvZ3JleXM1LzMAL2dyZXlzNS80AC9ncmV5czUvNQAvZ3JleXM2LzEAL2dyZXlzNi8yAC9ncmV5czYvMwAvZ3JleXM2LzQAL2dyZXlzNi81AC9ncmV5czYvNgAvZ3JleXM3LzEAL2dyZXlzNy8yAC9ncmV5czcvMwAvZ3JleXM3LzQAL2dyZXlzNy81AC9ncmV5czcvNgAvZ3JleXM3LzcAL2dyZXlzOC8xAC9ncmV5czgvMgAvZ3JleXM4LzMAL2dyZXlzOC80AC9ncmV5czgvNQAvZ3JleXM4LzYAL2dyZXlzOC83AC9ncmV5czgvOAAvZ3JleXM5LzEAL2dyZXlzOS8yAC9ncmV5czkvMwAvZ3JleXM5LzQAL2dyZXlzOS81AC9ncmV5czkvNgAvZ3JleXM5LzcAL2dyZXlzOS84AC9ncmV5czkvOQAvb3JhbmdlczMvMQAvb3JhbmdlczMvMgAvb3JhbmdlczMvMwAvb3JhbmdlczQvMQAvb3JhbmdlczQvMgAvb3JhbmdlczQvMwAvb3JhbmdlczQvNAAvb3JhbmdlczUvMQAvb3JhbmdlczUvMgAvb3JhbmdlczUvMwAvb3JhbmdlczUvNAAvb3JhbmdlczUvNQAvb3JhbmdlczYvMQAvb3JhbmdlczYvMgAvb3JhbmdlczYvMwAvb3JhbmdlczYvNAAvb3JhbmdlczYvNQAvb3JhbmdlczYvNgAvb3JhbmdlczcvMQAvb3JhbmdlczcvMgAvb3JhbmdlczcvMwAvb3JhbmdlczcvNAAvb3JhbmdlczcvNQAvb3JhbmdlczcvNgAvb3JhbmdlczcvNwAvb3JhbmdlczgvMQAvb3JhbmdlczgvMgAvb3JhbmdlczgvMwAvb3JhbmdlczgvNAAvb3JhbmdlczgvNQAvb3JhbmdlczgvNgAvb3JhbmdlczgvNwAvb3JhbmdlczgvOAAvb3JhbmdlczkvMQAvb3JhbmdlczkvMgAvb3JhbmdlczkvMwAvb3JhbmdlczkvNAAvb3JhbmdlczkvNQAvb3JhbmdlczkvNgAvb3JhbmdlczkvNwAvb3JhbmdlczkvOAAvb3JhbmdlczkvOQAvb3JyZDMvMQAvb3JyZDMvMgAvb3JyZDMvMwAvb3JyZDQvMQAvb3JyZDQvMgAvb3JyZDQvMwAvb3JyZDQvNAAvb3JyZDUvMQAvb3JyZDUvMgAvb3JyZDUvMwAvb3JyZDUvNAAvb3JyZDUvNQAvb3JyZDYvMQAvb3JyZDYvMgAvb3JyZDYvMwAvb3JyZDYvNAAvb3JyZDYvNQAvb3JyZDYvNgAvb3JyZDcvMQAvb3JyZDcvMgAvb3JyZDcvMwAvb3JyZDcvNAAvb3JyZDcvNQAvb3JyZDcvNgAvb3JyZDcvNwAvb3JyZDgvMQAvb3JyZDgvMgAvb3JyZDgvMwAvb3JyZDgvNAAvb3JyZDgvNQAvb3JyZDgvNgAvb3JyZDgvNwAvb3JyZDgvOAAvb3JyZDkvMQAvb3JyZDkvMgAvb3JyZDkvMwAvb3JyZDkvNAAvb3JyZDkvNQAvb3JyZDkvNgAvb3JyZDkvNwAvb3JyZDkvOAAvb3JyZDkvOQAvcGFpcmVkMTAvMQAvcGFpcmVkMTAvMTAAL3BhaXJlZDEwLzIAL3BhaXJlZDEwLzMAL3BhaXJlZDEwLzQAL3BhaXJlZDEwLzUAL3BhaXJlZDEwLzYAL3BhaXJlZDEwLzcAL3BhaXJlZDEwLzgAL3BhaXJlZDEwLzkAL3BhaXJlZDExLzEAL3BhaXJlZDExLzEwAC9wYWlyZWQxMS8xMQAvcGFpcmVkMTEvMgAvcGFpcmVkMTEvMwAvcGFpcmVkMTEvNAAvcGFpcmVkMTEvNQAvcGFpcmVkMTEvNgAvcGFpcmVkMTEvNwAvcGFpcmVkMTEvOAAvcGFpcmVkMTEvOQAvcGFpcmVkMTIvMQAvcGFpcmVkMTIvMTAAL3BhaXJlZDEyLzExAC9wYWlyZWQxMi8xMgAvcGFpcmVkMTIvMgAvcGFpcmVkMTIvMwAvcGFpcmVkMTIvNAAvcGFpcmVkMTIvNQAvcGFpcmVkMTIvNgAvcGFpcmVkMTIvNwAvcGFpcmVkMTIvOAAvcGFpcmVkMTIvOQAvcGFpcmVkMy8xAC9wYWlyZWQzLzIAL3BhaXJlZDMvMwAvcGFpcmVkNC8xAC9wYWlyZWQ0LzIAL3BhaXJlZDQvMwAvcGFpcmVkNC80AC9wYWlyZWQ1LzEAL3BhaXJlZDUvMgAvcGFpcmVkNS8zAC9wYWlyZWQ1LzQAL3BhaXJlZDUvNQAvcGFpcmVkNi8xAC9wYWlyZWQ2LzIAL3BhaXJlZDYvMwAvcGFpcmVkNi80AC9wYWlyZWQ2LzUAL3BhaXJlZDYvNgAvcGFpcmVkNy8xAC9wYWlyZWQ3LzIAL3BhaXJlZDcvMwAvcGFpcmVkNy80AC9wYWlyZWQ3LzUAL3BhaXJlZDcvNgAvcGFpcmVkNy83AC9wYWlyZWQ4LzEAL3BhaXJlZDgvMgAvcGFpcmVkOC8zAC9wYWlyZWQ4LzQAL3BhaXJlZDgvNQAvcGFpcmVkOC82AC9wYWlyZWQ4LzcAL3BhaXJlZDgvOAAvcGFpcmVkOS8xAC9wYWlyZWQ5LzIAL3BhaXJlZDkvMwAvcGFpcmVkOS80AC9wYWlyZWQ5LzUAL3BhaXJlZDkvNgAvcGFpcmVkOS83AC9wYWlyZWQ5LzgAL3BhaXJlZDkvOQAvcGFzdGVsMTMvMQAvcGFzdGVsMTMvMgAvcGFzdGVsMTMvMwAvcGFzdGVsMTQvMQAvcGFzdGVsMTQvMgAvcGFzdGVsMTQvMwAvcGFzdGVsMTQvNAAvcGFzdGVsMTUvMQAvcGFzdGVsMTUvMgAvcGFzdGVsMTUvMwAvcGFzdGVsMTUvNAAvcGFzdGVsMTUvNQAvcGFzdGVsMTYvMQAvcGFzdGVsMTYvMgAvcGFzdGVsMTYvMwAvcGFzdGVsMTYvNAAvcGFzdGVsMTYvNQAvcGFzdGVsMTYvNgAvcGFzdGVsMTcvMQAvcGFzdGVsMTcvMgAvcGFzdGVsMTcvMwAvcGFzdGVsMTcvNAAvcGFzdGVsMTcvNQAvcGFzdGVsMTcvNgAvcGFzdGVsMTcvNwAvcGFzdGVsMTgvMQAvcGFzdGVsMTgvMgAvcGFzdGVsMTgvMwAvcGFzdGVsMTgvNAAvcGFzdGVsMTgvNQAvcGFzdGVsMTgvNgAvcGFzdGVsMTgvNwAvcGFzdGVsMTgvOAAvcGFzdGVsMTkvMQAvcGFzdGVsMTkvMgAvcGFzdGVsMTkvMwAvcGFzdGVsMTkvNAAvcGFzdGVsMTkvNQAvcGFzdGVsMTkvNgAvcGFzdGVsMTkvNwAvcGFzdGVsMTkvOAAvcGFzdGVsMTkvOQAvcGFzdGVsMjMvMQAvcGFzdGVsMjMvMgAvcGFzdGVsMjMvMwAvcGFzdGVsMjQvMQAvcGFzdGVsMjQvMgAvcGFzdGVsMjQvMwAvcGFzdGVsMjQvNAAvcGFzdGVsMjUvMQAvcGFzdGVsMjUvMgAvcGFzdGVsMjUvMwAvcGFzdGVsMjUvNAAvcGFzdGVsMjUvNQAvcGFzdGVsMjYvMQAvcGFzdGVsMjYvMgAvcGFzdGVsMjYvMwAvcGFzdGVsMjYvNAAvcGFzdGVsMjYvNQAvcGFzdGVsMjYvNgAvcGFzdGVsMjcvMQAvcGFzdGVsMjcvMgAvcGFzdGVsMjcvMwAvcGFzdGVsMjcvNAAvcGFzdGVsMjcvNQAvcGFzdGVsMjcvNgAvcGFzdGVsMjcvNwAvcGFzdGVsMjgvMQAvcGFzdGVsMjgvMgAvcGFzdGVsMjgvMwAvcGFzdGVsMjgvNAAvcGFzdGVsMjgvNQAvcGFzdGVsMjgvNgAvcGFzdGVsMjgvNwAvcGFzdGVsMjgvOAAvcGl5ZzEwLzEAL3BpeWcxMC8xMAAvcGl5ZzEwLzIAL3BpeWcxMC8zAC9waXlnMTAvNAAvcGl5ZzEwLzUAL3BpeWcxMC82AC9waXlnMTAvNwAvcGl5ZzEwLzgAL3BpeWcxMC85AC9waXlnMTEvMQAvcGl5ZzExLzEwAC9waXlnMTEvMTEAL3BpeWcxMS8yAC9waXlnMTEvMwAvcGl5ZzExLzQAL3BpeWcxMS81AC9waXlnMTEvNgAvcGl5ZzExLzcAL3BpeWcxMS84AC9waXlnMTEvOQAvcGl5ZzMvMQAvcGl5ZzMvMgAvcGl5ZzMvMwAvcGl5ZzQvMQAvcGl5ZzQvMgAvcGl5ZzQvMwAvcGl5ZzQvNAAvcGl5ZzUvMQAvcGl5ZzUvMgAvcGl5ZzUvMwAvcGl5ZzUvNAAvcGl5ZzUvNQAvcGl5ZzYvMQAvcGl5ZzYvMgAvcGl5ZzYvMwAvcGl5ZzYvNAAvcGl5ZzYvNQAvcGl5ZzYvNgAvcGl5ZzcvMQAvcGl5ZzcvMgAvcGl5ZzcvMwAvcGl5ZzcvNAAvcGl5ZzcvNQAvcGl5ZzcvNgAvcGl5ZzcvNwAvcGl5ZzgvMQAvcGl5ZzgvMgAvcGl5ZzgvMwAvcGl5ZzgvNAAvcGl5ZzgvNQAvcGl5ZzgvNgAvcGl5ZzgvNwAvcGl5ZzgvOAAvcGl5ZzkvMQAvcGl5ZzkvMgAvcGl5ZzkvMwAvcGl5ZzkvNAAvcGl5ZzkvNQAvcGl5ZzkvNgAvcGl5ZzkvNwAvcGl5ZzkvOAAvcGl5ZzkvOQAvcHJnbjEwLzEAL3ByZ24xMC8xMAAvcHJnbjEwLzIAL3ByZ24xMC8zAC9wcmduMTAvNAAvcHJnbjEwLzUAL3ByZ24xMC82AC9wcmduMTAvNwAvcHJnbjEwLzgAL3ByZ24xMC85AC9wcmduMTEvMQAvcHJnbjExLzEwAC9wcmduMTEvMTEAL3ByZ24xMS8yAC9wcmduMTEvMwAvcHJnbjExLzQAL3ByZ24xMS81AC9wcmduMTEvNgAvcHJnbjExLzcAL3ByZ24xMS84AC9wcmduMTEvOQAvcHJnbjMvMQAvcHJnbjMvMgAvcHJnbjMvMwAvcHJnbjQvMQAvcHJnbjQvMgAvcHJnbjQvMwAvcHJnbjQvNAAvcHJnbjUvMQAvcHJnbjUvMgAvcHJnbjUvMwAvcHJnbjUvNAAvcHJnbjUvNQAvcHJnbjYvMQAvcHJnbjYvMgAvcHJnbjYvMwAvcHJnbjYvNAAvcHJnbjYvNQAvcHJnbjYvNgAvcHJnbjcvMQAvcHJnbjcvMgAvcHJnbjcvMwAvcHJnbjcvNAAvcHJnbjcvNQAvcHJnbjcvNgAvcHJnbjcvNwAvcHJnbjgvMQAvcHJnbjgvMgAvcHJnbjgvMwAvcHJnbjgvNAAvcHJnbjgvNQAvcHJnbjgvNgAvcHJnbjgvNwAvcHJnbjgvOAAvcHJnbjkvMQAvcHJnbjkvMgAvcHJnbjkvMwAvcHJnbjkvNAAvcHJnbjkvNQAvcHJnbjkvNgAvcHJnbjkvNwAvcHJnbjkvOAAvcHJnbjkvOQAvcHVidTMvMQAvcHVidTMvMgAvcHVidTMvMwAvcHVidTQvMQAvcHVidTQvMgAvcHVidTQvMwAvcHVidTQvNAAvcHVidTUvMQAvcHVidTUvMgAvcHVidTUvMwAvcHVidTUvNAAvcHVidTUvNQAvcHVidTYvMQAvcHVidTYvMgAvcHVidTYvMwAvcHVidTYvNAAvcHVidTYvNQAvcHVidTYvNgAvcHVidTcvMQAvcHVidTcvMgAvcHVidTcvMwAvcHVidTcvNAAvcHVidTcvNQAvcHVidTcvNgAvcHVidTcvNwAvcHVidTgvMQAvcHVidTgvMgAvcHVidTgvMwAvcHVidTgvNAAvcHVidTgvNQAvcHVidTgvNgAvcHVidTgvNwAvcHVidTgvOAAvcHVidTkvMQAvcHVidTkvMgAvcHVidTkvMwAvcHVidTkvNAAvcHVidTkvNQAvcHVidTkvNgAvcHVidTkvNwAvcHVidTkvOAAvcHVidTkvOQAvcHVidWduMy8xAC9wdWJ1Z24zLzIAL3B1YnVnbjMvMwAvcHVidWduNC8xAC9wdWJ1Z240LzIAL3B1YnVnbjQvMwAvcHVidWduNC80AC9wdWJ1Z241LzEAL3B1YnVnbjUvMgAvcHVidWduNS8zAC9wdWJ1Z241LzQAL3B1YnVnbjUvNQAvcHVidWduNi8xAC9wdWJ1Z242LzIAL3B1YnVnbjYvMwAvcHVidWduNi80AC9wdWJ1Z242LzUAL3B1YnVnbjYvNgAvcHVidWduNy8xAC9wdWJ1Z243LzIAL3B1YnVnbjcvMwAvcHVidWduNy80AC9wdWJ1Z243LzUAL3B1YnVnbjcvNgAvcHVidWduNy83AC9wdWJ1Z244LzEAL3B1YnVnbjgvMgAvcHVidWduOC8zAC9wdWJ1Z244LzQAL3B1YnVnbjgvNQAvcHVidWduOC82AC9wdWJ1Z244LzcAL3B1YnVnbjgvOAAvcHVidWduOS8xAC9wdWJ1Z245LzIAL3B1YnVnbjkvMwAvcHVidWduOS80AC9wdWJ1Z245LzUAL3B1YnVnbjkvNgAvcHVidWduOS83AC9wdWJ1Z245LzgAL3B1YnVnbjkvOQAvcHVvcjEwLzEAL3B1b3IxMC8xMAAvcHVvcjEwLzIAL3B1b3IxMC8zAC9wdW9yMTAvNAAvcHVvcjEwLzUAL3B1b3IxMC82AC9wdW9yMTAvNwAvcHVvcjEwLzgAL3B1b3IxMC85AC9wdW9yMTEvMQAvcHVvcjExLzEwAC9wdW9yMTEvMTEAL3B1b3IxMS8yAC9wdW9yMTEvMwAvcHVvcjExLzQAL3B1b3IxMS81AC9wdW9yMTEvNgAvcHVvcjExLzcAL3B1b3IxMS84AC9wdW9yMTEvOQAvcHVvcjMvMQAvcHVvcjMvMgAvcHVvcjMvMwAvcHVvcjQvMQAvcHVvcjQvMgAvcHVvcjQvMwAvcHVvcjQvNAAvcHVvcjUvMQAvcHVvcjUvMgAvcHVvcjUvMwAvcHVvcjUvNAAvcHVvcjUvNQAvcHVvcjYvMQAvcHVvcjYvMgAvcHVvcjYvMwAvcHVvcjYvNAAvcHVvcjYvNQAvcHVvcjYvNgAvcHVvcjcvMQAvcHVvcjcvMgAvcHVvcjcvMwAvcHVvcjcvNAAvcHVvcjcvNQAvcHVvcjcvNgAvcHVvcjcvNwAvcHVvcjgvMQAvcHVvcjgvMgAvcHVvcjgvMwAvcHVvcjgvNAAvcHVvcjgvNQAvcHVvcjgvNgAvcHVvcjgvNwAvcHVvcjgvOAAvcHVvcjkvMQAvcHVvcjkvMgAvcHVvcjkvMwAvcHVvcjkvNAAvcHVvcjkvNQAvcHVvcjkvNgAvcHVvcjkvNwAvcHVvcjkvOAAvcHVvcjkvOQAvcHVyZDMvMQAvcHVyZDMvMgAvcHVyZDMvMwAvcHVyZDQvMQAvcHVyZDQvMgAvcHVyZDQvMwAvcHVyZDQvNAAvcHVyZDUvMQAvcHVyZDUvMgAvcHVyZDUvMwAvcHVyZDUvNAAvcHVyZDUvNQAvcHVyZDYvMQAvcHVyZDYvMgAvcHVyZDYvMwAvcHVyZDYvNAAvcHVyZDYvNQAvcHVyZDYvNgAvcHVyZDcvMQAvcHVyZDcvMgAvcHVyZDcvMwAvcHVyZDcvNAAvcHVyZDcvNQAvcHVyZDcvNgAvcHVyZDcvNwAvcHVyZDgvMQAvcHVyZDgvMgAvcHVyZDgvMwAvcHVyZDgvNAAvcHVyZDgvNQAvcHVyZDgvNgAvcHVyZDgvNwAvcHVyZDgvOAAvcHVyZDkvMQAvcHVyZDkvMgAvcHVyZDkvMwAvcHVyZDkvNAAvcHVyZDkvNQAvcHVyZDkvNgAvcHVyZDkvNwAvcHVyZDkvOAAvcHVyZDkvOQAvcHVycGxlczMvMQAvcHVycGxlczMvMgAvcHVycGxlczMvMwAvcHVycGxlczQvMQAvcHVycGxlczQvMgAvcHVycGxlczQvMwAvcHVycGxlczQvNAAvcHVycGxlczUvMQAvcHVycGxlczUvMgAvcHVycGxlczUvMwAvcHVycGxlczUvNAAvcHVycGxlczUvNQAvcHVycGxlczYvMQAvcHVycGxlczYvMgAvcHVycGxlczYvMwAvcHVycGxlczYvNAAvcHVycGxlczYvNQAvcHVycGxlczYvNgAvcHVycGxlczcvMQAvcHVycGxlczcvMgAvcHVycGxlczcvMwAvcHVycGxlczcvNAAvcHVycGxlczcvNQAvcHVycGxlczcvNgAvcHVycGxlczcvNwAvcHVycGxlczgvMQAvcHVycGxlczgvMgAvcHVycGxlczgvMwAvcHVycGxlczgvNAAvcHVycGxlczgvNQAvcHVycGxlczgvNgAvcHVycGxlczgvNwAvcHVycGxlczgvOAAvcHVycGxlczkvMQAvcHVycGxlczkvMgAvcHVycGxlczkvMwAvcHVycGxlczkvNAAvcHVycGxlczkvNQAvcHVycGxlczkvNgAvcHVycGxlczkvNwAvcHVycGxlczkvOAAvcHVycGxlczkvOQAvcmRidTEwLzEAL3JkYnUxMC8xMAAvcmRidTEwLzIAL3JkYnUxMC8zAC9yZGJ1MTAvNAAvcmRidTEwLzUAL3JkYnUxMC82AC9yZGJ1MTAvNwAvcmRidTEwLzgAL3JkYnUxMC85AC9yZGJ1MTEvMQAvcmRidTExLzEwAC9yZGJ1MTEvMTEAL3JkYnUxMS8yAC9yZGJ1MTEvMwAvcmRidTExLzQAL3JkYnUxMS81AC9yZGJ1MTEvNgAvcmRidTExLzcAL3JkYnUxMS84AC9yZGJ1MTEvOQAvcmRidTMvMQAvcmRidTMvMgAvcmRidTMvMwAvcmRidTQvMQAvcmRidTQvMgAvcmRidTQvMwAvcmRidTQvNAAvcmRidTUvMQAvcmRidTUvMgAvcmRidTUvMwAvcmRidTUvNAAvcmRidTUvNQAvcmRidTYvMQAvcmRidTYvMgAvcmRidTYvMwAvcmRidTYvNAAvcmRidTYvNQAvcmRidTYvNgAvcmRidTcvMQAvcmRidTcvMgAvcmRidTcvMwAvcmRidTcvNAAvcmRidTcvNQAvcmRidTcvNgAvcmRidTcvNwAvcmRidTgvMQAvcmRidTgvMgAvcmRidTgvMwAvcmRidTgvNAAvcmRidTgvNQAvcmRidTgvNgAvcmRidTgvNwAvcmRidTgvOAAvcmRidTkvMQAvcmRidTkvMgAvcmRidTkvMwAvcmRidTkvNAAvcmRidTkvNQAvcmRidTkvNgAvcmRidTkvNwAvcmRidTkvOAAvcmRidTkvOQAvcmRneTEwLzEAL3JkZ3kxMC8xMAAvcmRneTEwLzIAL3JkZ3kxMC8zAC9yZGd5MTAvNAAvcmRneTEwLzUAL3JkZ3kxMC82AC9yZGd5MTAvNwAvcmRneTEwLzgAL3JkZ3kxMC85AC9yZGd5MTEvMQAvcmRneTExLzEwAC9yZGd5MTEvMTEAL3JkZ3kxMS8yAC9yZGd5MTEvMwAvcmRneTExLzQAL3JkZ3kxMS81AC9yZGd5MTEvNgAvcmRneTExLzcAL3JkZ3kxMS84AC9yZGd5MTEvOQAvcmRneTMvMQAvcmRneTMvMgAvcmRneTMvMwAvcmRneTQvMQAvcmRneTQvMgAvcmRneTQvMwAvcmRneTQvNAAvcmRneTUvMQAvcmRneTUvMgAvcmRneTUvMwAvcmRneTUvNAAvcmRneTUvNQAvcmRneTYvMQAvcmRneTYvMgAvcmRneTYvMwAvcmRneTYvNAAvcmRneTYvNQAvcmRneTYvNgAvcmRneTcvMQAvcmRneTcvMgAvcmRneTcvMwAvcmRneTcvNAAvcmRneTcvNQAvcmRneTcvNgAvcmRneTcvNwAvcmRneTgvMQAvcmRneTgvMgAvcmRneTgvMwAvcmRneTgvNAAvcmRneTgvNQAvcmRneTgvNgAvcmRneTgvNwAvcmRneTgvOAAvcmRneTkvMQAvcmRneTkvMgAvcmRneTkvMwAvcmRneTkvNAAvcmRneTkvNQAvcmRneTkvNgAvcmRneTkvNwAvcmRneTkvOAAvcmRneTkvOQAvcmRwdTMvMQAvcmRwdTMvMgAvcmRwdTMvMwAvcmRwdTQvMQAvcmRwdTQvMgAvcmRwdTQvMwAvcmRwdTQvNAAvcmRwdTUvMQAvcmRwdTUvMgAvcmRwdTUvMwAvcmRwdTUvNAAvcmRwdTUvNQAvcmRwdTYvMQAvcmRwdTYvMgAvcmRwdTYvMwAvcmRwdTYvNAAvcmRwdTYvNQAvcmRwdTYvNgAvcmRwdTcvMQAvcmRwdTcvMgAvcmRwdTcvMwAvcmRwdTcvNAAvcmRwdTcvNQAvcmRwdTcvNgAvcmRwdTcvNwAvcmRwdTgvMQAvcmRwdTgvMgAvcmRwdTgvMwAvcmRwdTgvNAAvcmRwdTgvNQAvcmRwdTgvNgAvcmRwdTgvNwAvcmRwdTgvOAAvcmRwdTkvMQAvcmRwdTkvMgAvcmRwdTkvMwAvcmRwdTkvNAAvcmRwdTkvNQAvcmRwdTkvNgAvcmRwdTkvNwAvcmRwdTkvOAAvcmRwdTkvOQAvcmR5bGJ1MTAvMQAvcmR5bGJ1MTAvMTAAL3JkeWxidTEwLzIAL3JkeWxidTEwLzMAL3JkeWxidTEwLzQAL3JkeWxidTEwLzUAL3JkeWxidTEwLzYAL3JkeWxidTEwLzcAL3JkeWxidTEwLzgAL3JkeWxidTEwLzkAL3JkeWxidTExLzEAL3JkeWxidTExLzEwAC9yZHlsYnUxMS8xMQAvcmR5bGJ1MTEvMgAvcmR5bGJ1MTEvMwAvcmR5bGJ1MTEvNAAvcmR5bGJ1MTEvNQAvcmR5bGJ1MTEvNgAvcmR5bGJ1MTEvNwAvcmR5bGJ1MTEvOAAvcmR5bGJ1MTEvOQAvcmR5bGJ1My8xAC9yZHlsYnUzLzIAL3JkeWxidTMvMwAvcmR5bGJ1NC8xAC9yZHlsYnU0LzIAL3JkeWxidTQvMwAvcmR5bGJ1NC80AC9yZHlsYnU1LzEAL3JkeWxidTUvMgAvcmR5bGJ1NS8zAC9yZHlsYnU1LzQAL3JkeWxidTUvNQAvcmR5bGJ1Ni8xAC9yZHlsYnU2LzIAL3JkeWxidTYvMwAvcmR5bGJ1Ni80AC9yZHlsYnU2LzUAL3JkeWxidTYvNgAvcmR5bGJ1Ny8xAC9yZHlsYnU3LzIAL3JkeWxidTcvMwAvcmR5bGJ1Ny80AC9yZHlsYnU3LzUAL3JkeWxidTcvNgAvcmR5bGJ1Ny83AC9yZHlsYnU4LzEAL3JkeWxidTgvMgAvcmR5bGJ1OC8zAC9yZHlsYnU4LzQAL3JkeWxidTgvNQAvcmR5bGJ1OC82AC9yZHlsYnU4LzcAL3JkeWxidTgvOAAvcmR5bGJ1OS8xAC9yZHlsYnU5LzIAL3JkeWxidTkvMwAvcmR5bGJ1OS80AC9yZHlsYnU5LzUAL3JkeWxidTkvNgAvcmR5bGJ1OS83AC9yZHlsYnU5LzgAL3JkeWxidTkvOQAvcmR5bGduMTAvMQAvcmR5bGduMTAvMTAAL3JkeWxnbjEwLzIAL3JkeWxnbjEwLzMAL3JkeWxnbjEwLzQAL3JkeWxnbjEwLzUAL3JkeWxnbjEwLzYAL3JkeWxnbjEwLzcAL3JkeWxnbjEwLzgAL3JkeWxnbjEwLzkAL3JkeWxnbjExLzEAL3JkeWxnbjExLzEwAC9yZHlsZ24xMS8xMQAvcmR5bGduMTEvMgAvcmR5bGduMTEvMwAvcmR5bGduMTEvNAAvcmR5bGduMTEvNQAvcmR5bGduMTEvNgAvcmR5bGduMTEvNwAvcmR5bGduMTEvOAAvcmR5bGduMTEvOQAvcmR5bGduMy8xAC9yZHlsZ24zLzIAL3JkeWxnbjMvMwAvcmR5bGduNC8xAC9yZHlsZ240LzIAL3JkeWxnbjQvMwAvcmR5bGduNC80AC9yZHlsZ241LzEAL3JkeWxnbjUvMgAvcmR5bGduNS8zAC9yZHlsZ241LzQAL3JkeWxnbjUvNQAvcmR5bGduNi8xAC9yZHlsZ242LzIAL3JkeWxnbjYvMwAvcmR5bGduNi80AC9yZHlsZ242LzUAL3JkeWxnbjYvNgAvcmR5bGduNy8xAC9yZHlsZ243LzIAL3JkeWxnbjcvMwAvcmR5bGduNy80AC9yZHlsZ243LzUAL3JkeWxnbjcvNgAvcmR5bGduNy83AC9yZHlsZ244LzEAL3JkeWxnbjgvMgAvcmR5bGduOC8zAC9yZHlsZ244LzQAL3JkeWxnbjgvNQAvcmR5bGduOC82AC9yZHlsZ244LzcAL3JkeWxnbjgvOAAvcmR5bGduOS8xAC9yZHlsZ245LzIAL3JkeWxnbjkvMwAvcmR5bGduOS80AC9yZHlsZ245LzUAL3JkeWxnbjkvNgAvcmR5bGduOS83AC9yZHlsZ245LzgAL3JkeWxnbjkvOQAvcmVkczMvMQAvcmVkczMvMgAvcmVkczMvMwAvcmVkczQvMQAvcmVkczQvMgAvcmVkczQvMwAvcmVkczQvNAAvcmVkczUvMQAvcmVkczUvMgAvcmVkczUvMwAvcmVkczUvNAAvcmVkczUvNQAvcmVkczYvMQAvcmVkczYvMgAvcmVkczYvMwAvcmVkczYvNAAvcmVkczYvNQAvcmVkczYvNgAvcmVkczcvMQAvcmVkczcvMgAvcmVkczcvMwAvcmVkczcvNAAvcmVkczcvNQAvcmVkczcvNgAvcmVkczcvNwAvcmVkczgvMQAvcmVkczgvMgAvcmVkczgvMwAvcmVkczgvNAAvcmVkczgvNQAvcmVkczgvNgAvcmVkczgvNwAvcmVkczgvOAAvcmVkczkvMQAvcmVkczkvMgAvcmVkczkvMwAvcmVkczkvNAAvcmVkczkvNQAvcmVkczkvNgAvcmVkczkvNwAvcmVkczkvOAAvcmVkczkvOQAvc2V0MTMvMQAvc2V0MTMvMgAvc2V0MTMvMwAvc2V0MTQvMQAvc2V0MTQvMgAvc2V0MTQvMwAvc2V0MTQvNAAvc2V0MTUvMQAvc2V0MTUvMgAvc2V0MTUvMwAvc2V0MTUvNAAvc2V0MTUvNQAvc2V0MTYvMQAvc2V0MTYvMgAvc2V0MTYvMwAvc2V0MTYvNAAvc2V0MTYvNQAvc2V0MTYvNgAvc2V0MTcvMQAvc2V0MTcvMgAvc2V0MTcvMwAvc2V0MTcvNAAvc2V0MTcvNQAvc2V0MTcvNgAvc2V0MTcvNwAvc2V0MTgvMQAvc2V0MTgvMgAvc2V0MTgvMwAvc2V0MTgvNAAvc2V0MTgvNQAvc2V0MTgvNgAvc2V0MTgvNwAvc2V0MTgvOAAvc2V0MTkvMQAvc2V0MTkvMgAvc2V0MTkvMwAvc2V0MTkvNAAvc2V0MTkvNQAvc2V0MTkvNgAvc2V0MTkvNwAvc2V0MTkvOAAvc2V0MTkvOQAvc2V0MjMvMQAvc2V0MjMvMgAvc2V0MjMvMwAvc2V0MjQvMQAvc2V0MjQvMgAvc2V0MjQvMwAvc2V0MjQvNAAvc2V0MjUvMQAvc2V0MjUvMgAvc2V0MjUvMwAvc2V0MjUvNAAvc2V0MjUvNQAvc2V0MjYvMQAvc2V0MjYvMgAvc2V0MjYvMwAvc2V0MjYvNAAvc2V0MjYvNQAvc2V0MjYvNgAvc2V0MjcvMQAvc2V0MjcvMgAvc2V0MjcvMwAvc2V0MjcvNAAvc2V0MjcvNQAvc2V0MjcvNgAvc2V0MjcvNwAvc2V0MjgvMQAvc2V0MjgvMgAvc2V0MjgvMwAvc2V0MjgvNAAvc2V0MjgvNQAvc2V0MjgvNgAvc2V0MjgvNwAvc2V0MjgvOAAvc2V0MzEwLzEAL3NldDMxMC8xMAAvc2V0MzEwLzIAL3NldDMxMC8zAC9zZXQzMTAvNAAvc2V0MzEwLzUAL3NldDMxMC82AC9zZXQzMTAvNwAvc2V0MzEwLzgAL3NldDMxMC85AC9zZXQzMTEvMQAvc2V0MzExLzEwAC9zZXQzMTEvMTEAL3NldDMxMS8yAC9zZXQzMTEvMwAvc2V0MzExLzQAL3NldDMxMS81AC9zZXQzMTEvNgAvc2V0MzExLzcAL3NldDMxMS84AC9zZXQzMTEvOQAvc2V0MzEyLzEAL3NldDMxMi8xMAAvc2V0MzEyLzExAC9zZXQzMTIvMTIAL3NldDMxMi8yAC9zZXQzMTIvMwAvc2V0MzEyLzQAL3NldDMxMi81AC9zZXQzMTIvNgAvc2V0MzEyLzcAL3NldDMxMi84AC9zZXQzMTIvOQAvc2V0MzMvMQAvc2V0MzMvMgAvc2V0MzMvMwAvc2V0MzQvMQAvc2V0MzQvMgAvc2V0MzQvMwAvc2V0MzQvNAAvc2V0MzUvMQAvc2V0MzUvMgAvc2V0MzUvMwAvc2V0MzUvNAAvc2V0MzUvNQAvc2V0MzYvMQAvc2V0MzYvMgAvc2V0MzYvMwAvc2V0MzYvNAAvc2V0MzYvNQAvc2V0MzYvNgAvc2V0MzcvMQAvc2V0MzcvMgAvc2V0MzcvMwAvc2V0MzcvNAAvc2V0MzcvNQAvc2V0MzcvNgAvc2V0MzcvNwAvc2V0MzgvMQAvc2V0MzgvMgAvc2V0MzgvMwAvc2V0MzgvNAAvc2V0MzgvNQAvc2V0MzgvNgAvc2V0MzgvNwAvc2V0MzgvOAAvc2V0MzkvMQAvc2V0MzkvMgAvc2V0MzkvMwAvc2V0MzkvNAAvc2V0MzkvNQAvc2V0MzkvNgAvc2V0MzkvNwAvc2V0MzkvOAAvc2V0MzkvOQAvc3BlY3RyYWwxMC8xAC9zcGVjdHJhbDEwLzEwAC9zcGVjdHJhbDEwLzIAL3NwZWN0cmFsMTAvMwAvc3BlY3RyYWwxMC80AC9zcGVjdHJhbDEwLzUAL3NwZWN0cmFsMTAvNgAvc3BlY3RyYWwxMC83AC9zcGVjdHJhbDEwLzgAL3NwZWN0cmFsMTAvOQAvc3BlY3RyYWwxMS8xAC9zcGVjdHJhbDExLzEwAC9zcGVjdHJhbDExLzExAC9zcGVjdHJhbDExLzIAL3NwZWN0cmFsMTEvMwAvc3BlY3RyYWwxMS80AC9zcGVjdHJhbDExLzUAL3NwZWN0cmFsMTEvNgAvc3BlY3RyYWwxMS83AC9zcGVjdHJhbDExLzgAL3NwZWN0cmFsMTEvOQAvc3BlY3RyYWwzLzEAL3NwZWN0cmFsMy8yAC9zcGVjdHJhbDMvMwAvc3BlY3RyYWw0LzEAL3NwZWN0cmFsNC8yAC9zcGVjdHJhbDQvMwAvc3BlY3RyYWw0LzQAL3NwZWN0cmFsNS8xAC9zcGVjdHJhbDUvMgAvc3BlY3RyYWw1LzMAL3NwZWN0cmFsNS80AC9zcGVjdHJhbDUvNQAvc3BlY3RyYWw2LzEAL3NwZWN0cmFsNi8yAC9zcGVjdHJhbDYvMwAvc3BlY3RyYWw2LzQAL3NwZWN0cmFsNi81AC9zcGVjdHJhbDYvNgAvc3BlY3RyYWw3LzEAL3NwZWN0cmFsNy8yAC9zcGVjdHJhbDcvMwAvc3BlY3RyYWw3LzQAL3NwZWN0cmFsNy81AC9zcGVjdHJhbDcvNgAvc3BlY3RyYWw3LzcAL3NwZWN0cmFsOC8xAC9zcGVjdHJhbDgvMgAvc3BlY3RyYWw4LzMAL3NwZWN0cmFsOC80AC9zcGVjdHJhbDgvNQAvc3BlY3RyYWw4LzYAL3NwZWN0cmFsOC83AC9zcGVjdHJhbDgvOAAvc3BlY3RyYWw5LzEAL3NwZWN0cmFsOS8yAC9zcGVjdHJhbDkvMwAvc3BlY3RyYWw5LzQAL3NwZWN0cmFsOS81AC9zcGVjdHJhbDkvNgAvc3BlY3RyYWw5LzcAL3NwZWN0cmFsOS84AC9zcGVjdHJhbDkvOQAvc3ZnL2FsaWNlYmx1ZQAvc3ZnL2FudGlxdWV3aGl0ZQAvc3ZnL2FxdWEAL3N2Zy9hcXVhbWFyaW5lAC9zdmcvYXp1cmUAL3N2Zy9iZWlnZQAvc3ZnL2Jpc3F1ZQAvc3ZnL2JsYWNrAC9zdmcvYmxhbmNoZWRhbG1vbmQAL3N2Zy9ibHVlAC9zdmcvYmx1ZXZpb2xldAAvc3ZnL2Jyb3duAC9zdmcvYnVybHl3b29kAC9zdmcvY2FkZXRibHVlAC9zdmcvY2hhcnRyZXVzZQAvc3ZnL2Nob2NvbGF0ZQAvc3ZnL2NvcmFsAC9zdmcvY29ybmZsb3dlcmJsdWUAL3N2Zy9jb3Juc2lsawAvc3ZnL2NyaW1zb24AL3N2Zy9jeWFuAC9zdmcvZGFya2JsdWUAL3N2Zy9kYXJrY3lhbgAvc3ZnL2Rhcmtnb2xkZW5yb2QAL3N2Zy9kYXJrZ3JheQAvc3ZnL2RhcmtncmVlbgAvc3ZnL2RhcmtncmV5AC9zdmcvZGFya2toYWtpAC9zdmcvZGFya21hZ2VudGEAL3N2Zy9kYXJrb2xpdmVncmVlbgAvc3ZnL2RhcmtvcmFuZ2UAL3N2Zy9kYXJrb3JjaGlkAC9zdmcvZGFya3JlZAAvc3ZnL2RhcmtzYWxtb24AL3N2Zy9kYXJrc2VhZ3JlZW4AL3N2Zy9kYXJrc2xhdGVibHVlAC9zdmcvZGFya3NsYXRlZ3JheQAvc3ZnL2RhcmtzbGF0ZWdyZXkAL3N2Zy9kYXJrdHVycXVvaXNlAC9zdmcvZGFya3Zpb2xldAAvc3ZnL2RlZXBwaW5rAC9zdmcvZGVlcHNreWJsdWUAL3N2Zy9kaW1ncmF5AC9zdmcvZGltZ3JleQAvc3ZnL2RvZGdlcmJsdWUAL3N2Zy9maXJlYnJpY2sAL3N2Zy9mbG9yYWx3aGl0ZQAvc3ZnL2ZvcmVzdGdyZWVuAC9zdmcvZnVjaHNpYQAvc3ZnL2dhaW5zYm9ybwAvc3ZnL2dob3N0d2hpdGUAL3N2Zy9nb2xkAC9zdmcvZ29sZGVucm9kAC9zdmcvZ3JheQAvc3ZnL2dyZWVuAC9zdmcvZ3JlZW55ZWxsb3cAL3N2Zy9ncmV5AC9zdmcvaG9uZXlkZXcAL3N2Zy9ob3RwaW5rAC9zdmcvaW5kaWFucmVkAC9zdmcvaW5kaWdvAC9zdmcvaXZvcnkAL3N2Zy9raGFraQAvc3ZnL2xhdmVuZGVyAC9zdmcvbGF2ZW5kZXJibHVzaAAvc3ZnL2xhd25ncmVlbgAvc3ZnL2xlbW9uY2hpZmZvbgAvc3ZnL2xpZ2h0Ymx1ZQAvc3ZnL2xpZ2h0Y29yYWwAL3N2Zy9saWdodGN5YW4AL3N2Zy9saWdodGdvbGRlbnJvZHllbGxvdwAvc3ZnL2xpZ2h0Z3JheQAvc3ZnL2xpZ2h0Z3JlZW4AL3N2Zy9saWdodGdyZXkAL3N2Zy9saWdodHBpbmsAL3N2Zy9saWdodHNhbG1vbgAvc3ZnL2xpZ2h0c2VhZ3JlZW4AL3N2Zy9saWdodHNreWJsdWUAL3N2Zy9saWdodHNsYXRlZ3JheQAvc3ZnL2xpZ2h0c2xhdGVncmV5AC9zdmcvbGlnaHRzdGVlbGJsdWUAL3N2Zy9saWdodHllbGxvdwAvc3ZnL2xpbWUAL3N2Zy9saW1lZ3JlZW4AL3N2Zy9saW5lbgAvc3ZnL21hZ2VudGEAL3N2Zy9tYXJvb24AL3N2Zy9tZWRpdW1hcXVhbWFyaW5lAC9zdmcvbWVkaXVtYmx1ZQAvc3ZnL21lZGl1bW9yY2hpZAAvc3ZnL21lZGl1bXB1cnBsZQAvc3ZnL21lZGl1bXNlYWdyZWVuAC9zdmcvbWVkaXVtc2xhdGVibHVlAC9zdmcvbWVkaXVtc3ByaW5nZ3JlZW4AL3N2Zy9tZWRpdW10dXJxdW9pc2UAL3N2Zy9tZWRpdW12aW9sZXRyZWQAL3N2Zy9taWRuaWdodGJsdWUAL3N2Zy9taW50Y3JlYW0AL3N2Zy9taXN0eXJvc2UAL3N2Zy9tb2NjYXNpbgAvc3ZnL25hdmFqb3doaXRlAC9zdmcvbmF2eQAvc3ZnL29sZGxhY2UAL3N2Zy9vbGl2ZQAvc3ZnL29saXZlZHJhYgAvc3ZnL29yYW5nZQAvc3ZnL29yYW5nZXJlZAAvc3ZnL29yY2hpZAAvc3ZnL3BhbGVnb2xkZW5yb2QAL3N2Zy9wYWxlZ3JlZW4AL3N2Zy9wYWxldHVycXVvaXNlAC9zdmcvcGFsZXZpb2xldHJlZAAvc3ZnL3BhcGF5YXdoaXAAL3N2Zy9wZWFjaHB1ZmYAL3N2Zy9wZXJ1AC9zdmcvcGluawAvc3ZnL3BsdW0AL3N2Zy9wb3dkZXJibHVlAC9zdmcvcHVycGxlAC9zdmcvcmVkAC9zdmcvcm9zeWJyb3duAC9zdmcvcm95YWxibHVlAC9zdmcvc2FkZGxlYnJvd24AL3N2Zy9zYWxtb24AL3N2Zy9zYW5keWJyb3duAC9zdmcvc2VhZ3JlZW4AL3N2Zy9zZWFzaGVsbAAvc3ZnL3NpZW5uYQAvc3ZnL3NpbHZlcgAvc3ZnL3NreWJsdWUAL3N2Zy9zbGF0ZWJsdWUAL3N2Zy9zbGF0ZWdyYXkAL3N2Zy9zbGF0ZWdyZXkAL3N2Zy9zbm93AC9zdmcvc3ByaW5nZ3JlZW4AL3N2Zy9zdGVlbGJsdWUAL3N2Zy90YW4AL3N2Zy90ZWFsAC9zdmcvdGhpc3RsZQAvc3ZnL3RvbWF0bwAvc3ZnL3R1cnF1b2lzZQAvc3ZnL3Zpb2xldAAvc3ZnL3doZWF0AC9zdmcvd2hpdGUAL3N2Zy93aGl0ZXNtb2tlAC9zdmcveWVsbG93AC9zdmcveWVsbG93Z3JlZW4AL3lsZ24zLzEAL3lsZ24zLzIAL3lsZ24zLzMAL3lsZ240LzEAL3lsZ240LzIAL3lsZ240LzMAL3lsZ240LzQAL3lsZ241LzEAL3lsZ241LzIAL3lsZ241LzMAL3lsZ241LzQAL3lsZ241LzUAL3lsZ242LzEAL3lsZ242LzIAL3lsZ242LzMAL3lsZ242LzQAL3lsZ242LzUAL3lsZ242LzYAL3lsZ243LzEAL3lsZ243LzIAL3lsZ243LzMAL3lsZ243LzQAL3lsZ243LzUAL3lsZ243LzYAL3lsZ243LzcAL3lsZ244LzEAL3lsZ244LzIAL3lsZ244LzMAL3lsZ244LzQAL3lsZ244LzUAL3lsZ244LzYAL3lsZ244LzcAL3lsZ244LzgAL3lsZ245LzEAL3lsZ245LzIAL3lsZ245LzMAL3lsZ245LzQAL3lsZ245LzUAL3lsZ245LzYAL3lsZ245LzcAL3lsZ245LzgAL3lsZ245LzkAL3lsZ25idTMvMQAveWxnbmJ1My8yAC95bGduYnUzLzMAL3lsZ25idTQvMQAveWxnbmJ1NC8yAC95bGduYnU0LzMAL3lsZ25idTQvNAAveWxnbmJ1NS8xAC95bGduYnU1LzIAL3lsZ25idTUvMwAveWxnbmJ1NS80AC95bGduYnU1LzUAL3lsZ25idTYvMQAveWxnbmJ1Ni8yAC95bGduYnU2LzMAL3lsZ25idTYvNAAveWxnbmJ1Ni81AC95bGduYnU2LzYAL3lsZ25idTcvMQAveWxnbmJ1Ny8yAC95bGduYnU3LzMAL3lsZ25idTcvNAAveWxnbmJ1Ny81AC95bGduYnU3LzYAL3lsZ25idTcvNwAveWxnbmJ1OC8xAC95bGduYnU4LzIAL3lsZ25idTgvMwAveWxnbmJ1OC80AC95bGduYnU4LzUAL3lsZ25idTgvNgAveWxnbmJ1OC83AC95bGduYnU4LzgAL3lsZ25idTkvMQAveWxnbmJ1OS8yAC95bGduYnU5LzMAL3lsZ25idTkvNAAveWxnbmJ1OS81AC95bGduYnU5LzYAL3lsZ25idTkvNwAveWxnbmJ1OS84AC95bGduYnU5LzkAL3lsb3JicjMvMQAveWxvcmJyMy8yAC95bG9yYnIzLzMAL3lsb3JicjQvMQAveWxvcmJyNC8yAC95bG9yYnI0LzMAL3lsb3JicjQvNAAveWxvcmJyNS8xAC95bG9yYnI1LzIAL3lsb3JicjUvMwAveWxvcmJyNS80AC95bG9yYnI1LzUAL3lsb3JicjYvMQAveWxvcmJyNi8yAC95bG9yYnI2LzMAL3lsb3JicjYvNAAveWxvcmJyNi81AC95bG9yYnI2LzYAL3lsb3JicjcvMQAveWxvcmJyNy8yAC95bG9yYnI3LzMAL3lsb3JicjcvNAAveWxvcmJyNy81AC95bG9yYnI3LzYAL3lsb3JicjcvNwAveWxvcmJyOC8xAC95bG9yYnI4LzIAL3lsb3JicjgvMwAveWxvcmJyOC80AC95bG9yYnI4LzUAL3lsb3JicjgvNgAveWxvcmJyOC83AC95bG9yYnI4LzgAL3lsb3JicjkvMQAveWxvcmJyOS8yAC95bG9yYnI5LzMAL3lsb3JicjkvNAAveWxvcmJyOS81AC95bG9yYnI5LzYAL3lsb3JicjkvNwAveWxvcmJyOS84AC95bG9yYnI5LzkAL3lsb3JyZDMvMQAveWxvcnJkMy8yAC95bG9ycmQzLzMAL3lsb3JyZDQvMQAveWxvcnJkNC8yAC95bG9ycmQ0LzMAL3lsb3JyZDQvNAAveWxvcnJkNS8xAC95bG9ycmQ1LzIAL3lsb3JyZDUvMwAveWxvcnJkNS80AC95bG9ycmQ1LzUAL3lsb3JyZDYvMQAveWxvcnJkNi8yAC95bG9ycmQ2LzMAL3lsb3JyZDYvNAAveWxvcnJkNi81AC95bG9ycmQ2LzYAL3lsb3JyZDcvMQAveWxvcnJkNy8yAC95bG9ycmQ3LzMAL3lsb3JyZDcvNAAveWxvcnJkNy81AC95bG9ycmQ3LzYAL3lsb3JyZDcvNwAveWxvcnJkOC8xAC95bG9ycmQ4LzIAL3lsb3JyZDgvMwAveWxvcnJkOC80AC95bG9ycmQ4LzUAL3lsb3JyZDgvNgAveWxvcnJkOC83AC95bG9ycmQ4LzgAL3lsb3JyZDkvMQAveWxvcnJkOS8yAC95bG9ycmQ5LzMAL3lsb3JyZDkvNAAveWxvcnJkOS81AC95bG9ycmQ5LzYAL3lsb3JyZDkvNwAveWxvcnJkOS84AC95bG9ycmQ5LzkAYWxpY2VibHVlAGFudGlxdWV3aGl0ZQBhbnRpcXVld2hpdGUxAGFudGlxdWV3aGl0ZTIAYW50aXF1ZXdoaXRlMwBhbnRpcXVld2hpdGU0AGFxdWFtYXJpbmUAYXF1YW1hcmluZTEAYXF1YW1hcmluZTIAYXF1YW1hcmluZTMAYXF1YW1hcmluZTQAYXp1cmUAYXp1cmUxAGF6dXJlMgBhenVyZTMAYXp1cmU0AGJlaWdlAGJpc3F1ZQBiaXNxdWUxAGJpc3F1ZTIAYmlzcXVlMwBiaXNxdWU0AGJsYW5jaGVkYWxtb25kAGJsdWUAYmx1ZTEAYmx1ZTIAYmx1ZTMAYmx1ZTQAYmx1ZXZpb2xldABicm93bgBicm93bjEAYnJvd24yAGJyb3duMwBicm93bjQAYnVybHl3b29kAGJ1cmx5d29vZDEAYnVybHl3b29kMgBidXJseXdvb2QzAGJ1cmx5d29vZDQAY2FkZXRibHVlAGNhZGV0Ymx1ZTEAY2FkZXRibHVlMgBjYWRldGJsdWUzAGNhZGV0Ymx1ZTQAY2hhcnRyZXVzZQBjaGFydHJldXNlMQBjaGFydHJldXNlMgBjaGFydHJldXNlMwBjaGFydHJldXNlNABjaG9jb2xhdGUAY2hvY29sYXRlMQBjaG9jb2xhdGUyAGNob2NvbGF0ZTMAY2hvY29sYXRlNABjb3JhbABjb3JhbDEAY29yYWwyAGNvcmFsMwBjb3JhbDQAY29ybmZsb3dlcmJsdWUAY29ybnNpbGsAY29ybnNpbGsxAGNvcm5zaWxrMgBjb3Juc2lsazMAY29ybnNpbGs0AGNyaW1zb24AY3lhbgBjeWFuMQBjeWFuMgBjeWFuMwBjeWFuNABkYXJrZ29sZGVucm9kAGRhcmtnb2xkZW5yb2QxAGRhcmtnb2xkZW5yb2QyAGRhcmtnb2xkZW5yb2QzAGRhcmtnb2xkZW5yb2Q0AGRhcmtncmVlbgBkYXJra2hha2kAZGFya29saXZlZ3JlZW4AZGFya29saXZlZ3JlZW4xAGRhcmtvbGl2ZWdyZWVuMgBkYXJrb2xpdmVncmVlbjMAZGFya29saXZlZ3JlZW40AGRhcmtvcmFuZ2UAZGFya29yYW5nZTEAZGFya29yYW5nZTIAZGFya29yYW5nZTMAZGFya29yYW5nZTQAZGFya29yY2hpZABkYXJrb3JjaGlkMQBkYXJrb3JjaGlkMgBkYXJrb3JjaGlkMwBkYXJrb3JjaGlkNABkYXJrc2FsbW9uAGRhcmtzZWFncmVlbgBkYXJrc2VhZ3JlZW4xAGRhcmtzZWFncmVlbjIAZGFya3NlYWdyZWVuMwBkYXJrc2VhZ3JlZW40AGRhcmtzbGF0ZWJsdWUAZGFya3NsYXRlZ3JheQBkYXJrc2xhdGVncmF5MQBkYXJrc2xhdGVncmF5MgBkYXJrc2xhdGVncmF5MwBkYXJrc2xhdGVncmF5NABkYXJrc2xhdGVncmV5AGRhcmt0dXJxdW9pc2UAZGFya3Zpb2xldABkZWVwcGluawBkZWVwcGluazEAZGVlcHBpbmsyAGRlZXBwaW5rMwBkZWVwcGluazQAZGVlcHNreWJsdWUAZGVlcHNreWJsdWUxAGRlZXBza3libHVlMgBkZWVwc2t5Ymx1ZTMAZGVlcHNreWJsdWU0AGRpbWdyYXkAZGltZ3JleQBkb2RnZXJibHVlAGRvZGdlcmJsdWUxAGRvZGdlcmJsdWUyAGRvZGdlcmJsdWUzAGRvZGdlcmJsdWU0AGZpcmVicmljawBmaXJlYnJpY2sxAGZpcmVicmljazIAZmlyZWJyaWNrMwBmaXJlYnJpY2s0AGZsb3JhbHdoaXRlAGZvcmVzdGdyZWVuAGdhaW5zYm9ybwBnaG9zdHdoaXRlAGdvbGQAZ29sZDEAZ29sZDIAZ29sZDMAZ29sZDQAZ29sZGVucm9kAGdvbGRlbnJvZDEAZ29sZGVucm9kMgBnb2xkZW5yb2QzAGdvbGRlbnJvZDQAZ3JheQBncmF5MABncmF5MQBncmF5MTAAZ3JheTEwMABncmF5MTEAZ3JheTEyAGdyYXkxMwBncmF5MTQAZ3JheTE1AGdyYXkxNgBncmF5MTcAZ3JheTE4AGdyYXkxOQBncmF5MgBncmF5MjAAZ3JheTIxAGdyYXkyMgBncmF5MjMAZ3JheTI0AGdyYXkyNQBncmF5MjYAZ3JheTI3AGdyYXkyOABncmF5MjkAZ3JheTMAZ3JheTMwAGdyYXkzMQBncmF5MzIAZ3JheTMzAGdyYXkzNABncmF5MzUAZ3JheTM2AGdyYXkzNwBncmF5MzgAZ3JheTM5AGdyYXk0AGdyYXk0MABncmF5NDEAZ3JheTQyAGdyYXk0MwBncmF5NDQAZ3JheTQ1AGdyYXk0NgBncmF5NDcAZ3JheTQ4AGdyYXk0OQBncmF5NQBncmF5NTAAZ3JheTUxAGdyYXk1MgBncmF5NTMAZ3JheTU0AGdyYXk1NQBncmF5NTYAZ3JheTU3AGdyYXk1OABncmF5NTkAZ3JheTYAZ3JheTYwAGdyYXk2MQBncmF5NjIAZ3JheTYzAGdyYXk2NABncmF5NjUAZ3JheTY2AGdyYXk2NwBncmF5NjgAZ3JheTY5AGdyYXk3AGdyYXk3MABncmF5NzEAZ3JheTcyAGdyYXk3MwBncmF5NzQAZ3JheTc1AGdyYXk3NgBncmF5NzcAZ3JheTc4AGdyYXk3OQBncmF5OABncmF5ODAAZ3JheTgxAGdyYXk4MgBncmF5ODMAZ3JheTg0AGdyYXk4NQBncmF5ODYAZ3JheTg3AGdyYXk4OABncmF5ODkAZ3JheTkAZ3JheTkwAGdyYXk5MQBncmF5OTIAZ3JheTkzAGdyYXk5NABncmF5OTUAZ3JheTk2AGdyYXk5NwBncmF5OTgAZ3JheTk5AGdyZWVuAGdyZWVuMQBncmVlbjIAZ3JlZW4zAGdyZWVuNABncmVlbnllbGxvdwBncmV5AGdyZXkwAGdyZXkxAGdyZXkxMABncmV5MTAwAGdyZXkxMQBncmV5MTIAZ3JleTEzAGdyZXkxNABncmV5MTUAZ3JleTE2AGdyZXkxNwBncmV5MTgAZ3JleTE5AGdyZXkyAGdyZXkyMABncmV5MjEAZ3JleTIyAGdyZXkyMwBncmV5MjQAZ3JleTI1AGdyZXkyNgBncmV5MjcAZ3JleTI4AGdyZXkyOQBncmV5MwBncmV5MzAAZ3JleTMxAGdyZXkzMgBncmV5MzMAZ3JleTM0AGdyZXkzNQBncmV5MzYAZ3JleTM3AGdyZXkzOABncmV5MzkAZ3JleTQAZ3JleTQwAGdyZXk0MQBncmV5NDIAZ3JleTQzAGdyZXk0NABncmV5NDUAZ3JleTQ2AGdyZXk0NwBncmV5NDgAZ3JleTQ5AGdyZXk1AGdyZXk1MABncmV5NTEAZ3JleTUyAGdyZXk1MwBncmV5NTQAZ3JleTU1AGdyZXk1NgBncmV5NTcAZ3JleTU4AGdyZXk1OQBncmV5NgBncmV5NjAAZ3JleTYxAGdyZXk2MgBncmV5NjMAZ3JleTY0AGdyZXk2NQBncmV5NjYAZ3JleTY3AGdyZXk2OABncmV5NjkAZ3JleTcAZ3JleTcwAGdyZXk3MQBncmV5NzIAZ3JleTczAGdyZXk3NABncmV5NzUAZ3JleTc2AGdyZXk3NwBncmV5NzgAZ3JleTc5AGdyZXk4AGdyZXk4MABncmV5ODEAZ3JleTgyAGdyZXk4MwBncmV5ODQAZ3JleTg1AGdyZXk4NgBncmV5ODcAZ3JleTg4AGdyZXk4OQBncmV5OQBncmV5OTAAZ3JleTkxAGdyZXk5MgBncmV5OTMAZ3JleTk0AGdyZXk5NQBncmV5OTYAZ3JleTk3AGdyZXk5OABncmV5OTkAaG9uZXlkZXcAaG9uZXlkZXcxAGhvbmV5ZGV3MgBob25leWRldzMAaG9uZXlkZXc0AGhvdHBpbmsAaG90cGluazEAaG90cGluazIAaG90cGluazMAaG90cGluazQAaW5kaWFucmVkAGluZGlhbnJlZDEAaW5kaWFucmVkMgBpbmRpYW5yZWQzAGluZGlhbnJlZDQAaW5kaWdvAGludmlzAGl2b3J5AGl2b3J5MQBpdm9yeTIAaXZvcnkzAGl2b3J5NABraGFraQBraGFraTEAa2hha2kyAGtoYWtpMwBraGFraTQAbGF2ZW5kZXIAbGF2ZW5kZXJibHVzaABsYXZlbmRlcmJsdXNoMQBsYXZlbmRlcmJsdXNoMgBsYXZlbmRlcmJsdXNoMwBsYXZlbmRlcmJsdXNoNABsYXduZ3JlZW4AbGVtb25jaGlmZm9uAGxlbW9uY2hpZmZvbjEAbGVtb25jaGlmZm9uMgBsZW1vbmNoaWZmb24zAGxlbW9uY2hpZmZvbjQAbGlnaHRibHVlAGxpZ2h0Ymx1ZTEAbGlnaHRibHVlMgBsaWdodGJsdWUzAGxpZ2h0Ymx1ZTQAbGlnaHRjb3JhbABsaWdodGN5YW4AbGlnaHRjeWFuMQBsaWdodGN5YW4yAGxpZ2h0Y3lhbjMAbGlnaHRjeWFuNABsaWdodGdvbGRlbnJvZABsaWdodGdvbGRlbnJvZDEAbGlnaHRnb2xkZW5yb2QyAGxpZ2h0Z29sZGVucm9kMwBsaWdodGdvbGRlbnJvZDQAbGlnaHRnb2xkZW5yb2R5ZWxsb3cAbGlnaHRncmF5AGxpZ2h0Z3JleQBsaWdodHBpbmsAbGlnaHRwaW5rMQBsaWdodHBpbmsyAGxpZ2h0cGluazMAbGlnaHRwaW5rNABsaWdodHNhbG1vbgBsaWdodHNhbG1vbjEAbGlnaHRzYWxtb24yAGxpZ2h0c2FsbW9uMwBsaWdodHNhbG1vbjQAbGlnaHRzZWFncmVlbgBsaWdodHNreWJsdWUAbGlnaHRza3libHVlMQBsaWdodHNreWJsdWUyAGxpZ2h0c2t5Ymx1ZTMAbGlnaHRza3libHVlNABsaWdodHNsYXRlYmx1ZQBsaWdodHNsYXRlZ3JheQBsaWdodHNsYXRlZ3JleQBsaWdodHN0ZWVsYmx1ZQBsaWdodHN0ZWVsYmx1ZTEAbGlnaHRzdGVlbGJsdWUyAGxpZ2h0c3RlZWxibHVlMwBsaWdodHN0ZWVsYmx1ZTQAbGlnaHR5ZWxsb3cAbGlnaHR5ZWxsb3cxAGxpZ2h0eWVsbG93MgBsaWdodHllbGxvdzMAbGlnaHR5ZWxsb3c0AGxpbWVncmVlbgBsaW5lbgBtYWdlbnRhAG1hZ2VudGExAG1hZ2VudGEyAG1hZ2VudGEzAG1hZ2VudGE0AG1hcm9vbgBtYXJvb24xAG1hcm9vbjIAbWFyb29uMwBtYXJvb240AG1lZGl1bWFxdWFtYXJpbmUAbWVkaXVtYmx1ZQBtZWRpdW1vcmNoaWQAbWVkaXVtb3JjaGlkMQBtZWRpdW1vcmNoaWQyAG1lZGl1bW9yY2hpZDMAbWVkaXVtb3JjaGlkNABtZWRpdW1wdXJwbGUAbWVkaXVtcHVycGxlMQBtZWRpdW1wdXJwbGUyAG1lZGl1bXB1cnBsZTMAbWVkaXVtcHVycGxlNABtZWRpdW1zZWFncmVlbgBtZWRpdW1zbGF0ZWJsdWUAbWVkaXVtc3ByaW5nZ3JlZW4AbWVkaXVtdHVycXVvaXNlAG1lZGl1bXZpb2xldHJlZABtaWRuaWdodGJsdWUAbWludGNyZWFtAG1pc3R5cm9zZQBtaXN0eXJvc2UxAG1pc3R5cm9zZTIAbWlzdHlyb3NlMwBtaXN0eXJvc2U0AG1vY2Nhc2luAG5hdmFqb3doaXRlAG5hdmFqb3doaXRlMQBuYXZham93aGl0ZTIAbmF2YWpvd2hpdGUzAG5hdmFqb3doaXRlNABuYXZ5AG5hdnlibHVlAG5vbmUAb2xkbGFjZQBvbGl2ZWRyYWIAb2xpdmVkcmFiMQBvbGl2ZWRyYWIyAG9saXZlZHJhYjMAb2xpdmVkcmFiNABvcmFuZ2UAb3JhbmdlMQBvcmFuZ2UyAG9yYW5nZTMAb3JhbmdlNABvcmFuZ2VyZWQAb3JhbmdlcmVkMQBvcmFuZ2VyZWQyAG9yYW5nZXJlZDMAb3JhbmdlcmVkNABvcmNoaWQAb3JjaGlkMQBvcmNoaWQyAG9yY2hpZDMAb3JjaGlkNABwYWxlZ29sZGVucm9kAHBhbGVncmVlbgBwYWxlZ3JlZW4xAHBhbGVncmVlbjIAcGFsZWdyZWVuMwBwYWxlZ3JlZW40AHBhbGV0dXJxdW9pc2UAcGFsZXR1cnF1b2lzZTEAcGFsZXR1cnF1b2lzZTIAcGFsZXR1cnF1b2lzZTMAcGFsZXR1cnF1b2lzZTQAcGFsZXZpb2xldHJlZABwYWxldmlvbGV0cmVkMQBwYWxldmlvbGV0cmVkMgBwYWxldmlvbGV0cmVkMwBwYWxldmlvbGV0cmVkNABwYXBheWF3aGlwAHBlYWNocHVmZgBwZWFjaHB1ZmYxAHBlYWNocHVmZjIAcGVhY2hwdWZmMwBwZWFjaHB1ZmY0AHBlcnUAcGluawBwaW5rMQBwaW5rMgBwaW5rMwBwaW5rNABwbHVtAHBsdW0xAHBsdW0yAHBsdW0zAHBsdW00AHBvd2RlcmJsdWUAcHVycGxlAHB1cnBsZTEAcHVycGxlMgBwdXJwbGUzAHB1cnBsZTQAcmVkAHJlZDEAcmVkMgByZWQzAHJlZDQAcm9zeWJyb3duAHJvc3licm93bjEAcm9zeWJyb3duMgByb3N5YnJvd24zAHJvc3licm93bjQAcm95YWxibHVlAHJveWFsYmx1ZTEAcm95YWxibHVlMgByb3lhbGJsdWUzAHJveWFsYmx1ZTQAc2FkZGxlYnJvd24Ac2FsbW9uAHNhbG1vbjEAc2FsbW9uMgBzYWxtb24zAHNhbG1vbjQAc2FuZHlicm93bgBzZWFncmVlbgBzZWFncmVlbjEAc2VhZ3JlZW4yAHNlYWdyZWVuMwBzZWFncmVlbjQAc2Vhc2hlbGwAc2Vhc2hlbGwxAHNlYXNoZWxsMgBzZWFzaGVsbDMAc2Vhc2hlbGw0AHNpZW5uYQBzaWVubmExAHNpZW5uYTIAc2llbm5hMwBzaWVubmE0AHNreWJsdWUAc2t5Ymx1ZTEAc2t5Ymx1ZTIAc2t5Ymx1ZTMAc2t5Ymx1ZTQAc2xhdGVibHVlAHNsYXRlYmx1ZTEAc2xhdGVibHVlMgBzbGF0ZWJsdWUzAHNsYXRlYmx1ZTQAc2xhdGVncmF5AHNsYXRlZ3JheTEAc2xhdGVncmF5MgBzbGF0ZWdyYXkzAHNsYXRlZ3JheTQAc2xhdGVncmV5AHNub3cAc25vdzEAc25vdzIAc25vdzMAc25vdzQAc3ByaW5nZ3JlZW4Ac3ByaW5nZ3JlZW4xAHNwcmluZ2dyZWVuMgBzcHJpbmdncmVlbjMAc3ByaW5nZ3JlZW40AHN0ZWVsYmx1ZQBzdGVlbGJsdWUxAHN0ZWVsYmx1ZTIAc3RlZWxibHVlMwBzdGVlbGJsdWU0AHRhbgB0YW4xAHRhbjIAdGFuMwB0YW40AHRoaXN0bGUAdGhpc3RsZTEAdGhpc3RsZTIAdGhpc3RsZTMAdGhpc3RsZTQAdG9tYXRvAHRvbWF0bzEAdG9tYXRvMgB0b21hdG8zAHRvbWF0bzQAdHVycXVvaXNlAHR1cnF1b2lzZTEAdHVycXVvaXNlMgB0dXJxdW9pc2UzAHR1cnF1b2lzZTQAdmlvbGV0AHZpb2xldHJlZAB2aW9sZXRyZWQxAHZpb2xldHJlZDIAdmlvbGV0cmVkMwB2aW9sZXRyZWQ0AHdoZWF0AHdoZWF0MQB3aGVhdDIAd2hlYXQzAHdoZWF0NAB3aGl0ZQB3aGl0ZXNtb2tlAHllbGxvdwB5ZWxsb3cxAHllbGxvdzIAeWVsbG93MwB5ZWxsb3c0AHllbGxvd2dyZWVuAGxhY2sAaGl0ZQBpZ2h0Z3JleQBYMTEvAC8lcy8lcwBpbWFnZXNjYWxlAGZhbHNlAGJsYWNrAGRvdHRlZABkYXNoZWQAY3AtPnNyYwBodG1sdGFibGUuYwBlbWl0X2h0bWxfaW1nAGNwLT5zcmNbMF0AdHJhbnNwYXJlbnQAXyVkACVkADEAMgAzADQANQA2ADcAOAA5ADEwADExADEyADEzADE0ADE1ADE2ADE3ADE4ADE5ADIwAEFnbm9kZWluZm9fdABBZ2VkZ2VpbmZvX3QAcm93ZwBjb2xnAEFncmFwaGluZm9fdAA8VEFCTEU+AGRlbHggPj0gMABwb3NfaHRtbF90YmwAZGVseSA+PSAwAHRhYmxlIHNpemUgdG9vIHNtYWxsIGZvciBjb250ZW50CgBmaXhlZCB0YWJsZSBzaXplIHdpdGggdW5zcGVjaWZpZWQgd2lkdGggb3IgaGVpZ2h0CgBjZWxsIHNpemUgdG9vIHNtYWxsIGZvciBjb250ZW50CgBmaXhlZCBjZWxsIHNpemUgd2l0aCB1bnNwZWNpZmllZCB3aWR0aCBvciBoZWlnaHQKAE5vIG9yIGltcHJvcGVyIGltYWdlIGZpbGU9IiVzIgoAcGVuY29sb3IAY29sb3IALT4ALS0AZlBRLmMAUFFjaGVjawBIZWFwIG92ZXJmbG93CgAlIVBTLUFkb2JlLTIuMAovbm9kZSB7CiAgL1kgZXhjaCBkZWYKICAvWCBleGNoIGRlZgogIC95IGV4Y2ggZGVmCiAgL3ggZXhjaCBkZWYKICBuZXdwYXRoCiAgeCB5IG1vdmV0bwogIHggWSBsaW5ldG8KICBYIFkgbGluZXRvCiAgWCB5IGxpbmV0bwogIGNsb3NlcGF0aCBmaWxsCn0gZGVmCi9jZWxsIHsKICAvWSBleGNoIGRlZgogIC9YIGV4Y2ggZGVmCiAgL3kgZXhjaCBkZWYKICAveCBleGNoIGRlZgogIG5ld3BhdGgKICB4IHkgbW92ZXRvCiAgeCBZIGxpbmV0bwogIFggWSBsaW5ldG8KICBYIHkgbGluZXRvCiAgY2xvc2VwYXRoIHN0cm9rZQp9IGRlZgoAc2hvd3BhZ2UKAGZhaWxlZCBhdCBub2RlICVkWzBdCgBucC0+Y2VsbHNbMF0AbWF6ZS5jAGNoa1NncmFwaABmYWlsZWQgYXQgbm9kZSAlZFsxXQoAbnAtPmNlbGxzWzFdAGRpdGVtcwBmaW5kU1ZlcnQAJSUlJVBhZ2U6IDEgMQolJSUlUGFnZUJvdW5kaW5nQm94OiAlZCAlZCAlZCAlZAoAJWYgJWYgdHJhbnNsYXRlCgAwIDAgMSBzZXRyZ2Jjb2xvcgoAJWYgJWYgJWYgJWYgbm9kZQoAMCAwIDAgc2V0cmdiY29sb3IKACVmICVmICVmICVmIGNlbGwKADEgMCAwIHNldHJnYmNvbG9yCgB1bmV4cGVjdGVkIGNhc2UgaW4gbG9jYXRlX2VuZHBvaW50CgAwAHRyYXBlem9pZC5jAGxvY2F0ZV9lbmRwb2ludABhZGRfc2VnbWVudDogZXJyb3IKAG5ld25vZGU6IFF1ZXJ5LXRhYmxlIG92ZXJmbG93CgBuZXdub2RlAG5ld3RyYXA6IFRyYXBlem9pZC10YWJsZSBvdmVyZmxvdyAlZAoAbmV3dHJhcABpbmRleC5jAFJUcmVlU2VhcmNoAG4tPmxldmVsID49IDAAUlRyZWVJbnNlcnQAbGV2ZWwgPj0gMCAmJiBsZXZlbCA8PSAoKm4pLT5sZXZlbAByLT5ib3VuZGFyeVtpXSA8PSByLT5ib3VuZGFyeVtOVU1ESU1TICsgaV0AciAmJiBuICYmIG5ldwBSVHJlZUluc2VydDIAbGV2ZWwgPj0gMCAmJiBsZXZlbCA8PSBuLT5sZXZlbABGQUxTRQBub2RlLmMATm9kZUNvdmVyAHIgJiYgbgBQaWNrQnJhbmNoAEFkZEJyYW5jaABpIDwgTk9ERUNBUkQAbmV3AG4gJiYgaSA+PSAwICYmIGkgPCBOT0RFQ0FSRABEaXNjb25CcmFuY2gAcgByZWN0YW5nbGUuYwBSZWN0QXJlYQByICYmIHJyAENvbWJpbmVSZWN0AHIgJiYgcwBPdmVybGFwAG4Ac3BsaXQucS5jAFNwbGl0Tm9kZQBiAG4tPmNvdW50ICsgKCpubiktPmNvdW50ID09IE5PREVDQVJEICsgMQBMb2FkTm9kZXMAcQBwAHJ0cC0+c3BsaXQuUGFydGl0aW9uc1swXS5wYXJ0aXRpb25baV0gPT0gMCB8fCBydHAtPnNwbGl0LlBhcnRpdGlvbnNbMF0ucGFydGl0aW9uW2ldID09IDEAcnRwLT5zcGxpdC5QYXJ0aXRpb25zWzBdLmNvdW50WzBdICsgcnRwLT5zcGxpdC5QYXJ0aXRpb25zWzBdLmNvdW50WzFdID09IE5PREVDQVJEICsgMQBNZXRob2RaZXJvAHJ0cC0+c3BsaXQuUGFydGl0aW9uc1swXS5jb3VudFswXSA+PSBydHAtPk1pbkZpbGwgJiYgcnRwLT5zcGxpdC5QYXJ0aXRpb25zWzBdLmNvdW50WzFdID49IHJ0cC0+TWluRmlsbAAhcnRwLT5zcGxpdC5QYXJ0aXRpb25zWzBdLnRha2VuW2ldAENsYXNzaWZ5AEdldEJyYW5jaGVzAG4tPmJyYW5jaFtpXS5jaGlsZAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKAICAgICAhAMWQEAH1AIAwcSExRXFhcIC2kMHwoFDA4pESsPLRAvMCAyBjQ1GxwdHgsMISIjJCUmJygMGBkXBAobHBogKgohIiMkJSYnKAwKDlMKLFgxWFhYWFhYDBscDy5YMyEiIyQlJicoGxz/U///ISIjJCUmJygM//8F////CRT//////wwbHP8QFRYhIiMkJSYnKBsc/////yEiIyQlJicoDP8SExQRFhf///////8MGxz///8SISIjJCUmJygbHP////8hIiMkJSYnKAz///////8T////////DBsc/////yEiIyQlJicoGxz/////ISIjJCUmJygSExQVFhcYGf///////////yMkJSYnGxITFBYXIjZoAR84ViEgAhsbG14bGzc5cDbSwk8EPCJHIj8iRCIiWCJlIiIFBl9gOQQHCAkKCwwNDgRmZ11qbQUGb1g7cQcICQoLDA0OBHI8W3M+YUYbEhMUFhcEBQY/QWJJBwgJCgsMDQ4FBgBcAAAHCAkKCwwNDgQAAE8AAABTQgAAAAAABAUGAERUVQcICQoLDA0OBQYAAAAABwgJCgsMDQ4EACosLkcxMwAAAAAAAAQFBgAAAEoHCAkKCwwNDgUGAAAAAAcICQoLDA0OBAAAAAAAAEwAAAAAAAAEBQYAAAAABwgJCgsMDQ4FBgAAAAAHCAkKCwwNDikrLS8wMjQ1AAAAAAAAAAAAKSstMDIABC8AJCMAEhQWGhweIBgABQcvLy8ALy8AAAkIKAAAASICBgAAAAAACAAAAAAAAAAAAAAAAAAlAyYTCikVCyoXDi0ZERsMKx0NLB8PIRAAMwAwAC9DADEALwA1LidCMkEAOjgAPDRFADYAQAAAPwBENzs5PQACAwMBAQIBAQEDAwMDAwMDAwEBAQEBAQEBAQEBAQEBAQECAQECAAYBAwMDAwMBAAECAwAEAQIDAAQABAAEAAMCAQIBAgFTeW50YXggZXJyb3I6IG5vbi1zcGFjZSBzdHJpbmcgdXNlZCBiZWZvcmUgPFRBQkxFPgBTeW50YXggZXJyb3I6IG5vbi1zcGFjZSBzdHJpbmcgdXNlZCBhZnRlciA8L1RBQkxFPgAAKSoqKissLC0tLS0tLS0tLS0uLzAxMjM0NTY3ODk6Ozw9Pj4/P0FAQkJCQkJCQ0NERERGRUdHR0lISkhLSExITU1OTk9P/wMPEBEjOiQ9JUAVQyZFJ0gYSxlNGigcTh0eUFFSWVpsa25jZFdpc3ludGF4IGVycm9yAG1lbW9yeSBleGhhdXN0ZWQAJXMgaW4gbGluZSAlZCAKAE5vdCBidWlsdCB3aXRoIGxpYmV4cGF0LiBUYWJsZSBmb3JtYXR0aW5nIGlzIG5vdCBhdmFpbGFibGUuCgByb3V0ZS5jAGxpYnBhdGgvJXM6JWQ6ICVzCgBzaG9ydGVzdC5jAHNvdXJjZSBwb2ludCBub3QgaW4gYW55IHRyaWFuZ2xlAGRlc3RpbmF0aW9uIHBvaW50IG5vdCBpbiBhbnkgdHJpYW5nbGUAY2Fubm90IGZpbmQgdHJpYW5nbGUgcGF0aABjYW5ub3QgbWFsbG9jIG9wcwBjYW5ub3QgcmVhbGxvYyBvcHMAdHJpYW5ndWxhdGlvbiBmYWlsZWQAY2Fubm90IG1hbGxvYyB0cmlzAGNhbm5vdCByZWFsbG9jIHRyaXMAY2Fubm90IG1hbGxvYyBkcS5wbmxzAGNhbm5vdCByZWFsbG9jIGRxLnBubHMAY2Fubm90IG1hbGxvYyBwbmxzAGNhbm5vdCBtYWxsb2MgcG5scHMAY2Fubm90IHJlYWxsb2MgcG5scwBjYW5ub3QgcmVhbGxvYyBwbmxwcwBUISIZDQECAxFLHAwQBAsdEh4naG5vcHFiIAUGDxMUFRoIFgcoJBcYCQoOGx8lI4OCfSYqKzw9Pj9DR0pNWFlaW1xdXl9gYWNkZWZnaWprbHJzdHl6e3wASWxsZWdhbCBieXRlIHNlcXVlbmNlAERvbWFpbiBlcnJvcgBSZXN1bHQgbm90IHJlcHJlc2VudGFibGUATm90IGEgdHR5AFBlcm1pc3Npb24gZGVuaWVkAE9wZXJhdGlvbiBub3QgcGVybWl0dGVkAE5vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnkATm8gc3VjaCBwcm9jZXNzAEZpbGUgZXhpc3RzAFZhbHVlIHRvbyBsYXJnZSBmb3IgZGF0YSB0eXBlAE5vIHNwYWNlIGxlZnQgb24gZGV2aWNlAE91dCBvZiBtZW1vcnkAUmVzb3VyY2UgYnVzeQBJbnRlcnJ1cHRlZCBzeXN0ZW0gY2FsbABSZXNvdXJjZSB0ZW1wb3JhcmlseSB1bmF2YWlsYWJsZQBJbnZhbGlkIHNlZWsAQ3Jvc3MtZGV2aWNlIGxpbmsAUmVhZC1vbmx5IGZpbGUgc3lzdGVtAERpcmVjdG9yeSBub3QgZW1wdHkAQ29ubmVjdGlvbiByZXNldCBieSBwZWVyAE9wZXJhdGlvbiB0aW1lZCBvdXQAQ29ubmVjdGlvbiByZWZ1c2VkAEhvc3QgaXMgZG93bgBIb3N0IGlzIHVucmVhY2hhYmxlAEFkZHJlc3MgaW4gdXNlAEJyb2tlbiBwaXBlAEkvTyBlcnJvcgBObyBzdWNoIGRldmljZSBvciBhZGRyZXNzAEJsb2NrIGRldmljZSByZXF1aXJlZABObyBzdWNoIGRldmljZQBOb3QgYSBkaXJlY3RvcnkASXMgYSBkaXJlY3RvcnkAVGV4dCBmaWxlIGJ1c3kARXhlYyBmb3JtYXQgZXJyb3IASW52YWxpZCBhcmd1bWVudABBcmd1bWVudCBsaXN0IHRvbyBsb25nAFN5bWJvbGljIGxpbmsgbG9vcABGaWxlbmFtZSB0b28gbG9uZwBUb28gbWFueSBvcGVuIGZpbGVzIGluIHN5c3RlbQBObyBmaWxlIGRlc2NyaXB0b3JzIGF2YWlsYWJsZQBCYWQgZmlsZSBkZXNjcmlwdG9yAE5vIGNoaWxkIHByb2Nlc3MAQmFkIGFkZHJlc3MARmlsZSB0b28gbGFyZ2UAVG9vIG1hbnkgbGlua3MATm8gbG9ja3MgYXZhaWxhYmxlAFJlc291cmNlIGRlYWRsb2NrIHdvdWxkIG9jY3VyAFN0YXRlIG5vdCByZWNvdmVyYWJsZQBQcmV2aW91cyBvd25lciBkaWVkAE9wZXJhdGlvbiBjYW5jZWxlZABGdW5jdGlvbiBub3QgaW1wbGVtZW50ZWQATm8gbWVzc2FnZSBvZiBkZXNpcmVkIHR5cGUASWRlbnRpZmllciByZW1vdmVkAERldmljZSBub3QgYSBzdHJlYW0ATm8gZGF0YSBhdmFpbGFibGUARGV2aWNlIHRpbWVvdXQAT3V0IG9mIHN0cmVhbXMgcmVzb3VyY2VzAExpbmsgaGFzIGJlZW4gc2V2ZXJlZABQcm90b2NvbCBlcnJvcgBCYWQgbWVzc2FnZQBGaWxlIGRlc2NyaXB0b3IgaW4gYmFkIHN0YXRlAE5vdCBhIHNvY2tldABEZXN0aW5hdGlvbiBhZGRyZXNzIHJlcXVpcmVkAE1lc3NhZ2UgdG9vIGxhcmdlAFByb3RvY29sIHdyb25nIHR5cGUgZm9yIHNvY2tldABQcm90b2NvbCBub3QgYXZhaWxhYmxlAFByb3RvY29sIG5vdCBzdXBwb3J0ZWQAU29ja2V0IHR5cGUgbm90IHN1cHBvcnRlZABOb3Qgc3VwcG9ydGVkAFByb3RvY29sIGZhbWlseSBub3Qgc3VwcG9ydGVkAEFkZHJlc3MgZmFtaWx5IG5vdCBzdXBwb3J0ZWQgYnkgcHJvdG9jb2wAQWRkcmVzcyBub3QgYXZhaWxhYmxlAE5ldHdvcmsgaXMgZG93bgBOZXR3b3JrIHVucmVhY2hhYmxlAENvbm5lY3Rpb24gcmVzZXQgYnkgbmV0d29yawBDb25uZWN0aW9uIGFib3J0ZWQATm8gYnVmZmVyIHNwYWNlIGF2YWlsYWJsZQBTb2NrZXQgaXMgY29ubmVjdGVkAFNvY2tldCBub3QgY29ubmVjdGVkAENhbm5vdCBzZW5kIGFmdGVyIHNvY2tldCBzaHV0ZG93bgBPcGVyYXRpb24gYWxyZWFkeSBpbiBwcm9ncmVzcwBPcGVyYXRpb24gaW4gcHJvZ3Jlc3MAU3RhbGUgZmlsZSBoYW5kbGUAUmVtb3RlIEkvTyBlcnJvcgBRdW90YSBleGNlZWRlZABObyBtZWRpdW0gZm91bmQAV3JvbmcgbWVkaXVtIHR5cGUATm8gZXJyb3IgaW5mb3JtYXRpb24AABIQExQVFhcYGRobHB0eHyAhEBAiIxAkJSYnKCkqKxAsLS4RLzARETEREREyMzQ1Njc4OREQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQOhAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQOxA8PT4/QEEQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQQhAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQQxAQRBBFRkcQSBBJEBAQEEpLTE0QEE4QT1AQEBAQURAQEBAQEBAQEBAQEBBSEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBTEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQVFVWVxAQWFkQEBAQEBAQEBAQEBAQEBAQEBAQEBAQWhBbXF1eX2BhYhAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////////////////////////////wAAAAD+/wD8AQAA+AEAAHgAAAAA//vf+wAAgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAD8/+Cv/////////////9///////yBAsAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAD8AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8AAAAAACG/v///wBASQAAAAAAGADf/wDIAAAAAAAAAAEAPAAAAAAAAAAAAAAAABDgAR4AYP+/AAAAAAAA/wcAAAAAAAAAAAAAAAAAAAAAAAAA+M8DAAAAAwAg/38AAABOAAAAAAAAAAAAAAAAAAAAAAD8AAAAAAAAAAAAEAAgHgAwAAEAAAAAAAAAABAAIAAAAAD8DwAAAAAAAAAQACAAAAAAAAAAAAAAAAAAEAAgAAAAAAMAAAAAAAAAABAAIAAAAAD9AAAAAAAAAAAAACAAAAAA/wcAAAAAAAAAAAAgAAAAAAD/AAAAAAAAABAAIAAAAAAAAAAAAAAAAAAAACAAAAAAPwIAAAAAAAAAAAAEAAAAABAAAAAAAACAAIDA3wAMAAAAAAAAAAAAAAAAAB8AAAAAAAD+////APz//wAAAAAAAAAA/AAAAAAAAMD/3/8HAAAAAAAAAAAAAIAGAPwAABg+AACAvwDMAAAAAAAAAAAAAAAIAAAAAAAAAAAAAABg////HwAA/wMAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAABAAAYAAAAAAAAAAAAOAAAAAAQAAAAcAAAAAAAAAAAAAAAAAAAADAAAP5/LwAA/wP/fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOMQAAAAAAAAAAAAAAAAAAAAAAAMT/////AAAAwAAAAAAAAAAAAQDgnwAAAAB/PwAAAAAAAAAAAAAAAAAAAAAQABAAAPz///8fAAAAAAAMAAAAAAAAQAAM8AAAAAAAAMD4AAAAAAAAAMAAAAAAAAAAAP8A////IRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////38AAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAD4ADgAOAAYID4/////P//////fx/88X//fwAA////AwAA/////wEAewPQwa9CAAwfvP//AAAAAAAC//////////////////////////////////////////////////////////8PAP////9/AAAA/wcAAP////////////8/AAAAAAAA/P///v////////////////////////////////////////////////////8f/wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADghwP+AAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAD//////3//DwAAAAAAAAAA////+/////////////8PAP//////////////////////////////////PwAAAP8PHv///wH8weAAAAAAAAAAAAAAAB4BAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAD//wAAAAD/////DwAAAP///3////////////////////////////////////9/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAD///////9/AAAAAAAAwADgAAAAAAAAAAAAAACAD3AAAAAAAAAAAAAAAAAAAP8A//9/AAMAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAABECAAAAA//AwAAAAAAAPAAAAAAAAAAAAAQwAAA//8DBwAAAAAA+AAAAAAIgAAAAAAAAAAAAAAIAP8/AMAAAAAAAAAAAAAAAAAAAADwAACACwAAAAAAAACAAgAAwAAAQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA/P8DAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw////A38A//////f/fw8AAAAAAAAAAAAAAAAAAAAAAID+/wD8AQAA+AEAAPg/AAAAAAAAAAAAAAAAAAAAf38AMIf//////4//AAAAAAAA4P//B/8PAAAAAAAA//////8/AAAAAA8AAAAAAAAAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwI8AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIf/AP8BAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAP/z/PwAAAAMAAAAAAAD+AwAAAAAAAAAAAAAAAAAYAA8AAAAAAAAAAAAAAAAAAADhAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAHAAAAAAAAAAAAAAAAAP///////////////////////////////////////z8A/////3/+////////////////////////////PwAAAAD//////////z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////9/AP//AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAACAAAAAgAACAAAAAgAACAAAAAgAAAAAIAAAACAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA//////8P////////////////DwD/f/5//v/+/wAAAAD/B////3//////////D///////BwAAAAAAAAAAwP///wcA//////8H/wEDAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wEAv///////////H///DwD/////3wcAAP//AQD/////////f/3/////////////////////////////Hv////////8/DwD///8AAAAAAAAAAAAAAAAAAAAAAAD4///////////h/wAAAAAAAP//////////PwAAAAAAAAD//////////////////w8AAAAAAAAAAAAAAAAAAAAAAP////////////////////////////////////////////////////////////////8AAQIDBAUGBwgJ/////////woLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj////////CgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAECBAcDBgUAEhETFBUWFxgZGhscHR4fICERIiMkESUmJygpKissES0uLxAQMBAQEBAQEBAxMjMQNDUQEBERERERERERERERERERERERERERERERERE2ERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERNxERERE4ETk6Ozw9PhERERERERERERERERERERERERERERERERERERERERERERERERERERERERE/EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEUBBEUJDREVGR0hJEBAQSktMTU4QEBBPUBAQEBBREBAQEBAQEBAQERERUlMQEBAQEBAQEBAQEBERERFUEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQERFVEBAQEFYQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQVxAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQWFlaWxAQEBAQEBAQEBAQEBAQEBAQEBAQEBBcEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////////////////////////////////AAAAAAAAAAD+//8H/v//BwAAAAAABCAE//9/////f//////////////////////////////////D/wMAH1AAAAAAAAAAAAAAIAAAAAAA3zxA1///+////////////7///////////////////////wP8/////////////////////////wD+////fwL+/////wAAAAAA/7+2AP///wcHAAAA/wf//////////v/D////////////////7x/+4f+fAAD///////8A4P///////////////wMA//////8HMAT////8/x8AAP///wEAAAAAAAAAAP0fAAAAAAAA8AP/f//////////v/9/h/8///v7un/n///3F459ZgLDP/wMA7of5///9bcOHGQJewP8/AO6/+////e3jvxsBAM//AADun/n///3t458ZwLDP/wIA7Mc91hjH/8PHHYEAwP8AAO7f/f///e/j3x1gA8//AADs3/3///3v498dYEDP/wYA7N/9/////+ffXYAAz/8A/Oz/f/z///svf4Bf/wAADAD+/////3//Bz8g/wMAAAAAliXw/q7s/ztfIP/zAAAAAAEAAAD/AwAA//7///8f/v8D///+////HwAAAAAAAAAA////////f/n/A///58H//39A/zP/////vyD///////f///////////89fz3//////z3/////PX89/3//////////Pf//////////hwAAAAD//wAA/////////////x8A/v//////////////////////////////////////////////////////////n////v//B////////////8cBAP/fDwD//w8A//8PAP/fDQD////////P//8BgBD/AwAAAAD/A///////////////AP//////B///////////PwD///8f/w//AcD/////Px8A//////8P////A/8DAAAAAP///w//////////f/7/HwD/A/8DgAAAAAAAAAAAAAAA////////7//vD/8DAAAAAP//////8////////7//AwD///////8/AP/j//////8/AAAAAAAAAAAAAAAAAN5vAP///////////////////////////////wAAAAAAAAAA//8/P/////8/P/+q////P////////99f3B/PD/8f3B8AAAAAAAAAAAAAAAAAAAKAAAD/HwAAAAAAAAAAAAAAAIT8Lz5Qvf/z4EMAAP//////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMD///////8DAAD//////3///////3//////////////////////H3gMAP////+/IP////////+AAAD//38Af39/f39/f3//////AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAA/gM+H/7///////////9/4P7/////////////9+D/////P/7/////////////fwAA////BwAAAAAAAP///////////////////////////////z8AAAAAAAAAAAD/////////////////////////////////HwAAAAAAAP//////////////////////HwAAAAAAAAAA//////8//x////8PAAD//////3/wj////4D/////////////AAAAAID//P///////////////3kPAP8HAAAAAAAAAAAA/7v3////AAAA////////DwD//////////w8A/wMAAPwI//////8H/////wcA////H/////////f/AID/AwAAAAD///////9/AP8//wP//38E/////////38FAAA4//88AH5+fgB/fwAAAAAAAAAAAAAAAAAAAAAAAP//////B/8D//////////////////////////8PAP//f/j//////w//////////////////P/////////////////8DAAAAAH8A+OD//X9f2/////////////////8DAAAA+P///////////////z8AAP///////////P///////wAAAAAA/w8AAAAAAAAAAAAAAAAAAN//////////////////////HwAA/wP+//8H/v//B8D/////////////f/z8/BwAAAAA/+///3///7f/P/8/AAAAAP///////////////////wcAAAAAAAAAAP///////x8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8f////////AQAAAAAA////fwAA////BwAAAAAAAP///z//////D/8+AAAAAAD/////////////////////////P/8DAAAAAAAAAAAAAD/9/////7+R//8/AAAAAAAAAAAAAAAAAAAAAAAAAAAA//8/AP///wMAAAAAAAAAAP/////////AAAAAAAAAAABv8O/+//8PAAAAAAD///8fAAAAAAAAAAAAAAAAAAAAAP///////z8A//8/AP//BwAAAAAAAAAAAAAAAAAAAAAA////////////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////z8AAADA/wAA/P///////wEAAP///wH/A////////8f/AAAAAAAAAAD//////////x4A/wMAAAAAAAAAAAAAAAAAAAAAAAAAAP///////z8A/wMAAAAAAAD/////////////////fwAAAAAAAAAAAAAAAAAAAAAAAP///////////////wcAAAAAAAAAAAAAAAAAAAAAAAAA//////9/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////HwD//////38AAPj/AAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////3///////////32Te/+vv/////////7/n39////97X/z9//////////////////////////////////////////////////////8//////f//9/////f//9/////f//9/////f/////3////9///3z////////+////+W/vcKhOqWqpb3917/+/8P7vv/DwAAAAAAAAAATENfQUxMAExDX0NUWVBFAAAAAExDX05VTUVSSUMAAExDX1RJTUUAAAAAAExDX0NPTExBVEUAAExDX01PTkVUQVJZAExDX01FU1NBR0VTAExBTkcAQy5VVEYtOABQT1NJWABNVVNMX0xPQ1BBVEgAEQAKABEREQAAAAAFAAAAAAAACQAAAAALAAAAAAAAAAARAA8KERERAwoHAAETCQsLAAAJBgsAAAsABhEAAAAREREAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAEQAKChEREQAKAAACAAkLAAAACQALAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAADAAAAAAJDAAAAAAADAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAANAAAABA0AAAAACQ4AAAAAAA4AAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAADwAAAAAPAAAAAAkQAAAAAAAQAAAQAAASAAAAEhISAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAASEhIAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAKAAAAAAoAAAAACQsAAAAAAAsAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAMAAAAAAkMAAAAAAAMAAAMAAAtKyAgIDBYMHgAKG51bGwpAC0wWCswWCAwWC0weCsweCAweABpbmYASU5GAE5BTgAwMTIzNDU2Nzg5QUJDREVGLgBhbG51bQBhbHBoYQBibGFuawBjbnRybABkaWdpdABncmFwaABsb3dlcgBwcmludABwdW5jdABzcGFjZQB1cHBlcgB4ZGlnaXQAQy5VVEYtOAAAAAAAAAAAAEMAL3Byb2Mvc2VsZi9mZC8AcndhAGluZmluaXR5AG5hbgAJAAoADQAMAAcAGwBbWzphbG51bTpdX10AW15bOmFsbnVtOl1fXQBbWzpzcGFjZTpdXQBbXls6c3BhY2U6XV0AW1s6ZGlnaXQ6XV0AW15bOmRpZ2l0Ol1dAC90bXAvdG1wZmlsZV9YWFhYWFgAdys=";var tempDoublePtr=STATICTOP;STATICTOP+=16;function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+Pointer_stringify(condition)+", at: "+[filename?Pointer_stringify(filename):"unknown filename",line,func?Pointer_stringify(func):"unknown function"])}function _emscripten_get_now(){abort()}function _emscripten_get_now_is_monotonic(){return ENVIRONMENT_IS_NODE||typeof dateNow!=="undefined"||(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&self["performance"]&&self["performance"]["now"]}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()}else if(clk_id===1&&_emscripten_get_now_is_monotonic()){now=_emscripten_get_now()}else{___setErrNo(ERRNO_CODES.EINVAL);return-1}HEAP32[tp>>2]=now/1e3|0;HEAP32[tp+4>>2]=now%1e3*1e3*1e3|0;return 0}function ___clock_gettime(){return _clock_gettime.apply(null,arguments)}function ___lock(){}function ___map_file(pathname,size){___setErrNo(ERRNO_CODES.EPERM);return-1}var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"};var PATH={splitPath:(function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)}),normalizeArray:(function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts}),normalize:(function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter((function(p){return!!p})),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path}),dirname:(function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir}),basename:(function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)}),extname:(function(path){return PATH.splitPath(path)[3]}),join:(function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))}),join2:(function(l,r){return PATH.normalize(l+"/"+r)}),resolve:(function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter((function(p){return!!p})),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."}),relative:(function(from,to){from=PATH.resolve(from).substr(1);to=PATH.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()}),put_char:(function(tty,val){if(val===null||val===10){Module["print"](UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}}),flush:(function(tty){if(tty.output&&tty.output.length>0){Module["print"](UTF8ArrayToString(tty.output,0));tty.output=[]}})},default_tty1_ops:{put_char:(function(tty,val){if(val===null||val===10){Module["printErr"](UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}}),flush:(function(tty){if(tty.output&&tty.output.length>0){Module["printErr"](UTF8ArrayToString(tty.output,0));tty.output=[]}})}};var MEMFS={ops_table:null,mount:(function(mount){return MEMFS.createNode(null,"/",16384|511,0)}),createNode:(function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node}return node}),getFileDataAsRegularArray:(function(node){if(node.contents&&node.contents.subarray){var arr=[];for(var i=0;inode.contents.length){node.contents=MEMFS.getFileDataAsRegularArray(node);node.usedBytes=node.contents.length}if(!node.contents||node.contents.subarray){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return}if(!node.contents&&newCapacity>0)node.contents=[];while(node.contents.lengthnewSize)node.contents.length=newSize;else while(node.contents.length=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+lengthe2.timestamp){create.push(key);total++}}));var remove=[];Object.keys(dst.entries).forEach((function(key){var e=dst.entries[key];var e2=src.entries[key];if(!e2){remove.push(key);total++}}));if(!total){return callback(null)}var completed=0;var db=src.type==="remote"?src.db:dst.db;var transaction=db.transaction([IDBFS.DB_STORE_NAME],"readwrite");var store=transaction.objectStore(IDBFS.DB_STORE_NAME);function done(err){if(err){if(!done.errored){done.errored=true;return callback(err)}return}if(++completed>=total){return callback(null)}}transaction.onerror=(function(e){done(this.error);e.preventDefault()});create.sort().forEach((function(path){if(dst.type==="local"){IDBFS.loadRemoteEntry(store,path,(function(err,entry){if(err)return done(err);IDBFS.storeLocalEntry(path,entry,done)}))}else{IDBFS.loadLocalEntry(path,(function(err,entry){if(err)return done(err);IDBFS.storeRemoteEntry(store,path,entry,done)}))}}));remove.sort().reverse().forEach((function(path){if(dst.type==="local"){IDBFS.removeLocalEntry(path,done)}else{IDBFS.removeRemoteEntry(store,path,done)}}))})};var NODEFS={isWindows:false,staticInit:(function(){NODEFS.isWindows=!!process.platform.match(/^win/);var flags=process["binding"]("constants");if(flags["fs"]){flags=flags["fs"]}NODEFS.flagsForNodeMap={"1024":flags["O_APPEND"],"64":flags["O_CREAT"],"128":flags["O_EXCL"],"0":flags["O_RDONLY"],"2":flags["O_RDWR"],"4096":flags["O_SYNC"],"512":flags["O_TRUNC"],"1":flags["O_WRONLY"]}}),bufferFrom:(function(arrayBuffer){return Buffer.alloc?Buffer.from(arrayBuffer):new Buffer(arrayBuffer)}),mount:(function(mount){assert(ENVIRONMENT_IS_NODE);return NODEFS.createNode(null,"/",NODEFS.getMode(mount.opts.root),0)}),createNode:(function(parent,name,mode,dev){if(!FS.isDir(mode)&&!FS.isFile(mode)&&!FS.isLink(mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node=FS.createNode(parent,name,mode);node.node_ops=NODEFS.node_ops;node.stream_ops=NODEFS.stream_ops;return node}),getMode:(function(path){var stat;try{stat=fs.lstatSync(path);if(NODEFS.isWindows){stat.mode=stat.mode|(stat.mode&292)>>2}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return stat.mode}),realPath:(function(node){var parts=[];while(node.parent!==node){parts.push(node.name);node=node.parent}parts.push(node.mount.opts.root);parts.reverse();return PATH.join.apply(null,parts)}),flagsForNode:(function(flags){flags&=~2097152;flags&=~2048;flags&=~32768;flags&=~524288;var newFlags=0;for(var k in NODEFS.flagsForNodeMap){if(flags&k){newFlags|=NODEFS.flagsForNodeMap[k];flags^=k}}if(!flags){return newFlags}else{throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}}),node_ops:{getattr:(function(node){var path=NODEFS.realPath(node);var stat;try{stat=fs.lstatSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}if(NODEFS.isWindows&&!stat.blksize){stat.blksize=4096}if(NODEFS.isWindows&&!stat.blocks){stat.blocks=(stat.size+stat.blksize-1)/stat.blksize|0}return{dev:stat.dev,ino:stat.ino,mode:stat.mode,nlink:stat.nlink,uid:stat.uid,gid:stat.gid,rdev:stat.rdev,size:stat.size,atime:stat.atime,mtime:stat.mtime,ctime:stat.ctime,blksize:stat.blksize,blocks:stat.blocks}}),setattr:(function(node,attr){var path=NODEFS.realPath(node);try{if(attr.mode!==undefined){fs.chmodSync(path,attr.mode);node.mode=attr.mode}if(attr.timestamp!==undefined){var date=new Date(attr.timestamp);fs.utimesSync(path,date,date)}if(attr.size!==undefined){fs.truncateSync(path,attr.size)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),lookup:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);var mode=NODEFS.getMode(path);return NODEFS.createNode(parent,name,mode)}),mknod:(function(parent,name,mode,dev){var node=NODEFS.createNode(parent,name,mode,dev);var path=NODEFS.realPath(node);try{if(FS.isDir(node.mode)){fs.mkdirSync(path,node.mode)}else{fs.writeFileSync(path,"",{mode:node.mode})}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return node}),rename:(function(oldNode,newDir,newName){var oldPath=NODEFS.realPath(oldNode);var newPath=PATH.join2(NODEFS.realPath(newDir),newName);try{fs.renameSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),unlink:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.unlinkSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),rmdir:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.rmdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),readdir:(function(node){var path=NODEFS.realPath(node);try{return fs.readdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),symlink:(function(parent,newName,oldPath){var newPath=PATH.join2(NODEFS.realPath(parent),newName);try{fs.symlinkSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),readlink:(function(node){var path=NODEFS.realPath(node);try{path=fs.readlinkSync(path);path=NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root),path);return path}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}})},stream_ops:{open:(function(stream){var path=NODEFS.realPath(stream.node);try{if(FS.isFile(stream.node.mode)){stream.nfd=fs.openSync(path,NODEFS.flagsForNode(stream.flags))}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),close:(function(stream){try{if(FS.isFile(stream.node.mode)&&stream.nfd){fs.closeSync(stream.nfd)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),read:(function(stream,buffer,offset,length,position){if(length===0)return 0;try{return fs.readSync(stream.nfd,NODEFS.bufferFrom(buffer.buffer),offset,length,position)}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),write:(function(stream,buffer,offset,length,position){try{return fs.writeSync(stream.nfd,NODEFS.bufferFrom(buffer.buffer),offset,length,position)}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){try{var stat=fs.fstatSync(stream.nfd);position+=stat.size}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position})}};var WORKERFS={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:(function(mount){assert(ENVIRONMENT_IS_WORKER);if(!WORKERFS.reader)WORKERFS.reader=new FileReaderSync;var root=WORKERFS.createNode(null,"/",WORKERFS.DIR_MODE,0);var createdParents={};function ensureParent(path){var parts=path.split("/");var parent=root;for(var i=0;i=stream.node.size)return 0;var chunk=stream.node.contents.slice(position,position+length);var ab=WORKERFS.reader.readAsArrayBuffer(chunk);buffer.set(new Uint8Array(ab),offset);return chunk.size}),write:(function(stream,buffer,offset,length,position){throw new FS.ErrnoError(ERRNO_CODES.EIO)}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.size}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position})}};STATICTOP+=16;STATICTOP+=16;STATICTOP+=16;var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:(function(e){if(!(e instanceof FS.ErrnoError))throw e+" : "+stackTrace();return ___setErrNo(e.errno)}),lookupPath:(function(path,opts){path=PATH.resolve(FS.cwd(),path);opts=opts||{};if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};for(var key in defaults){if(opts[key]===undefined){opts[key]=defaults[key]}}if(opts.recurse_count>8){throw new FS.ErrnoError(ERRNO_CODES.ELOOP)}var parts=PATH.normalizeArray(path.split("/").filter((function(p){return!!p})),false);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(ERRNO_CODES.ELOOP)}}}}return{path:current_path,node:current}}),getPath:(function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}}),hashName:(function(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length}),hashAddNode:(function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node}),hashRemoveNode:(function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}}),lookupNode:(function(parent,name){var err=FS.mayLookup(parent);if(err){throw new FS.ErrnoError(err,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)}),createNode:(function(parent,name,mode,rdev){if(!FS.FSNode){FS.FSNode=(function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev});FS.FSNode.prototype={};var readMode=292|73;var writeMode=146;Object.defineProperties(FS.FSNode.prototype,{read:{get:(function(){return(this.mode&readMode)===readMode}),set:(function(val){val?this.mode|=readMode:this.mode&=~readMode})},write:{get:(function(){return(this.mode&writeMode)===writeMode}),set:(function(val){val?this.mode|=writeMode:this.mode&=~writeMode})},isFolder:{get:(function(){return FS.isDir(this.mode)})},isDevice:{get:(function(){return FS.isChrdev(this.mode)})}})}var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node}),destroyNode:(function(node){FS.hashRemoveNode(node)}),isRoot:(function(node){return node===node.parent}),isMountpoint:(function(node){return!!node.mounted}),isFile:(function(mode){return(mode&61440)===32768}),isDir:(function(mode){return(mode&61440)===16384}),isLink:(function(mode){return(mode&61440)===40960}),isChrdev:(function(mode){return(mode&61440)===8192}),isBlkdev:(function(mode){return(mode&61440)===24576}),isFIFO:(function(mode){return(mode&61440)===4096}),isSocket:(function(mode){return(mode&49152)===49152}),flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:(function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags}),flagsToPermissionString:(function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms}),nodePermissions:(function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return ERRNO_CODES.EACCES}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return ERRNO_CODES.EACCES}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return ERRNO_CODES.EACCES}return 0}),mayLookup:(function(dir){var err=FS.nodePermissions(dir,"x");if(err)return err;if(!dir.node_ops.lookup)return ERRNO_CODES.EACCES;return 0}),mayCreate:(function(dir,name){try{var node=FS.lookupNode(dir,name);return ERRNO_CODES.EEXIST}catch(e){}return FS.nodePermissions(dir,"wx")}),mayDelete:(function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var err=FS.nodePermissions(dir,"wx");if(err){return err}if(isdir){if(!FS.isDir(node.mode)){return ERRNO_CODES.ENOTDIR}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return ERRNO_CODES.EBUSY}}else{if(FS.isDir(node.mode)){return ERRNO_CODES.EISDIR}}return 0}),mayOpen:(function(node,flags){if(!node){return ERRNO_CODES.ENOENT}if(FS.isLink(node.mode)){return ERRNO_CODES.ELOOP}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return ERRNO_CODES.EISDIR}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))}),MAX_OPEN_FDS:4096,nextfd:(function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(ERRNO_CODES.EMFILE)}),getStream:(function(fd){return FS.streams[fd]}),createStream:(function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=(function(){});FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:(function(){return this.node}),set:(function(val){this.node=val})},isRead:{get:(function(){return(this.flags&2097155)!==1})},isWrite:{get:(function(){return(this.flags&2097155)!==0})},isAppend:{get:(function(){return this.flags&1024})}})}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream}),closeStream:(function(fd){FS.streams[fd]=null}),chrdev_stream_ops:{open:(function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}}),llseek:(function(){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)})},major:(function(dev){return dev>>8}),minor:(function(dev){return dev&255}),makedev:(function(ma,mi){return ma<<8|mi}),registerDevice:(function(dev,ops){FS.devices[dev]={stream_ops:ops}}),getDevice:(function(dev){return FS.devices[dev]}),getMounts:(function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts}),syncfs:(function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){console.log("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(err){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(err)}function done(err){if(err){if(!done.errored){done.errored=true;return doCallback(err)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach((function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)}))}),mount:(function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot}),unmount:(function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach((function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}}));node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)}),lookup:(function(parent,name){return parent.node_ops.lookup(parent,name)}),mknod:(function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var err=FS.mayCreate(parent,name);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}return parent.node_ops.mknod(parent,name,mode,dev)}),create:(function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)}),mkdir:(function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)}),mkdirTree:(function(path,mode){var dirs=path.split("/");var d="";for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}});var lazyArray=this;lazyArray.setDataGetter((function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]}));if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;console.log("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:(function(){if(!this.lengthKnown){this.cacheLength()}return this._length})},chunkSize:{get:(function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize})}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:(function(){return this.contents.length})}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach((function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(ERRNO_CODES.EIO)}return fn.apply(null,arguments)}}));stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(ERRNO_CODES.EIO)}var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;HEAP32[buf+36>>2]=stat.size;HEAP32[buf+40>>2]=4096;HEAP32[buf+44>>2]=stat.blocks;HEAP32[buf+48>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+52>>2]=0;HEAP32[buf+56>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ino;return 0}),doMsync:(function(addr,stream,len,flags){var buffer=new Uint8Array(HEAPU8.subarray(addr,addr+len));FS.msync(stream,buffer,0,len,flags)}),doMkdir:(function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}),doMknod:(function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-ERRNO_CODES.EINVAL}FS.mknod(path,mode,dev);return 0}),doReadlink:(function(path,buf,bufsize){if(bufsize<=0)return-ERRNO_CODES.EINVAL;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}),doAccess:(function(path,amode){if(amode&~7){return-ERRNO_CODES.EINVAL}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-ERRNO_CODES.EACCES}return 0}),doDup:(function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd}),doReadv:(function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret}),varargs:0,get:(function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret}),getStr:(function(){var ret=Pointer_stringify(SYSCALLS.get());return ret}),getStreamFromFD:(function(){var stream=FS.getStream(SYSCALLS.get());if(!stream)throw new FS.ErrnoError(ERRNO_CODES.EBADF);return stream}),getSocketFromFD:(function(){var socket=SOCKFS.getSocket(SYSCALLS.get());if(!socket)throw new FS.ErrnoError(ERRNO_CODES.EBADF);return socket}),getSocketAddress:(function(allowNull){var addrp=SYSCALLS.get(),addrlen=SYSCALLS.get();if(allowNull&&addrp===0)return null;var info=__read_sockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info}),get64:(function(){var low=SYSCALLS.get(),high=SYSCALLS.get();if(low>=0)assert(high===0);else assert(high===-1);return low}),getZero:(function(){assert(SYSCALLS.get()===0)})};function ___syscall10(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr();FS.unlink(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall140(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),offset_high=SYSCALLS.get(),offset_low=SYSCALLS.get(),result=SYSCALLS.get(),whence=SYSCALLS.get();var offset=offset_low;FS.llseek(stream,offset,whence);HEAP32[result>>2]=stream.position;if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall145(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();return SYSCALLS.doReadv(stream,iov,iovcnt)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall146(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();return SYSCALLS.doWritev(stream,iov,iovcnt)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall192(which,varargs){SYSCALLS.varargs=varargs;try{var addr=SYSCALLS.get(),len=SYSCALLS.get(),prot=SYSCALLS.get(),flags=SYSCALLS.get(),fd=SYSCALLS.get(),off=SYSCALLS.get();off<<=12;var ptr;var allocated=false;if(fd===-1){ptr=_memalign(PAGE_SIZE,len);if(!ptr)return-ERRNO_CODES.ENOMEM;_memset(ptr,0,len);allocated=true}else{var info=FS.getStream(fd);if(!info)return-ERRNO_CODES.EBADF;var res=FS.mmap(info,HEAPU8,addr,len,off,prot,flags);ptr=res.ptr;allocated=res.allocated}SYSCALLS.mappings[ptr]={malloc:ptr,len:len,allocated:allocated,fd:fd,flags:flags};return ptr}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall195(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),buf=SYSCALLS.get();return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall197(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),buf=SYSCALLS.get();return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall221(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),cmd=SYSCALLS.get();switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-ERRNO_CODES.EINVAL}var newStream;newStream=FS.open(stream.path,stream.flags,0,arg);return newStream.fd};case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0};case 12:case 12:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0};case 13:case 14:case 13:case 14:return 0;case 16:case 8:return-ERRNO_CODES.EINVAL;case 9:___setErrNo(ERRNO_CODES.EINVAL);return-1;default:{return-ERRNO_CODES.EINVAL}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall33(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),amode=SYSCALLS.get();return SYSCALLS.doAccess(path,amode)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall5(which,varargs){SYSCALLS.varargs=varargs;try{var pathname=SYSCALLS.getStr(),flags=SYSCALLS.get(),mode=SYSCALLS.get();var stream=FS.open(pathname,flags,mode);return stream.fd}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall54(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),op=SYSCALLS.get();switch(op){case 21509:case 21505:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};case 21519:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0};case 21520:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return-ERRNO_CODES.EINVAL};case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)};case 21523:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};default:abort("bad ioctl syscall "+op)}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall6(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD();FS.close(stream);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall91(which,varargs){SYSCALLS.varargs=varargs;try{var addr=SYSCALLS.get(),len=SYSCALLS.get();var info=SYSCALLS.mappings[addr];if(!info)return 0;if(len===info.len){var stream=FS.getStream(info.fd);SYSCALLS.doMsync(addr,stream,len,info.flags);FS.munmap(stream);SYSCALLS.mappings[addr]=null;if(info.allocated){_free(info.malloc)}}return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_STATIC);function ___unlock(){}function __exit(status){Module["exit"](status)}function _exit(status){__exit(status)}var _environ=STATICTOP;STATICTOP+=16;function ___buildEnvironment(env){var MAX_ENV_VALUES=64;var TOTAL_ENV_SIZE=1024;var poolPtr;var envPtr;if(!___buildEnvironment.called){___buildEnvironment.called=true;ENV["USER"]=ENV["LOGNAME"]="web_user";ENV["PATH"]="/";ENV["PWD"]="/";ENV["HOME"]="/home/web_user";ENV["LANG"]="C.UTF-8";ENV["_"]=Module["thisProgram"];poolPtr=staticAlloc(TOTAL_ENV_SIZE);envPtr=staticAlloc(MAX_ENV_VALUES*4);HEAP32[envPtr>>2]=poolPtr;HEAP32[_environ>>2]=envPtr}else{envPtr=HEAP32[_environ>>2];poolPtr=HEAP32[envPtr>>2]}var strings=[];var totalSize=0;for(var key in env){if(typeof env[key]==="string"){var line=key+"="+env[key];strings.push(line);totalSize+=line.length}}if(totalSize>TOTAL_ENV_SIZE){throw new Error("Environment size exceeded TOTAL_ENV_SIZE!")}var ptrSize=4;for(var i=0;i>2]=poolPtr;poolPtr+=line.length+1}HEAP32[envPtr+strings.length*ptrSize>>2]=0}var ENV={};function _getenv(name){if(name===0)return 0;name=Pointer_stringify(name);if(!ENV.hasOwnProperty(name))return 0;if(_getenv.ret)_free(_getenv.ret);_getenv.ret=allocateUTF8(ENV[name]);return _getenv.ret}var _llvm_ceil_f64=Math_ceil;var _llvm_fabs_f64=Math_abs;var _llvm_floor_f64=Math_floor;var _llvm_pow_f64=Math_pow;var _llvm_sqrt_f64=Math_sqrt;function _llvm_trap(){abort("trap!")}function _longjmp(env,value){Module["setThrew"](env,value||1);throw"longjmp"}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}function _setenv(envname,envval,overwrite){if(envname===0){___setErrNo(ERRNO_CODES.EINVAL);return-1}var name=Pointer_stringify(envname);var val=Pointer_stringify(envval);if(name===""||name.indexOf("=")!==-1){___setErrNo(ERRNO_CODES.EINVAL);return-1}if(ENV.hasOwnProperty(name)&&!overwrite)return 0;ENV[name]=val;___buildEnvironment(ENV);return 0}function _times(buffer){if(buffer!==0){_memset(buffer,0,16)}return 0}if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function _emscripten_get_now_actual(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else if(typeof self==="object"&&self["performance"]&&typeof self["performance"]["now"]==="function"){_emscripten_get_now=(function(){return self["performance"]["now"]()})}else if(typeof performance==="object"&&typeof performance["now"]==="function"){_emscripten_get_now=(function(){return performance["now"]()})}else{_emscripten_get_now=Date.now}FS.staticInit();__ATINIT__.unshift((function(){if(!Module["noFSInit"]&&!FS.init.initialized)FS.init()}));__ATMAIN__.push((function(){FS.ignorePermissions=false}));__ATEXIT__.push((function(){FS.quit()}));__ATINIT__.unshift((function(){TTY.init()}));__ATEXIT__.push((function(){TTY.shutdown()}));if(ENVIRONMENT_IS_NODE){var fs=require("fs");var NODEJS_PATH=require("path");NODEFS.staticInit()}___buildEnvironment(ENV);DYNAMICTOP_PTR=staticAlloc(4);STACK_BASE=STACKTOP=alignMemory(STATICTOP);STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=alignMemory(STACK_MAX);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;staticSealed=true;var ASSERTIONS=false;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}function intArrayToString(array){var ret=[];for(var i=0;i255){if(ASSERTIONS){assert(false,"Character code "+chr+" ("+String.fromCharCode(chr)+") at offset "+i+" not in 0x00-0xFF.")}chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}var decodeBase64=typeof atob==="function"?atob:(function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i>2]=0;h=ls()|0;qs(h,10904);qs(h,17148);_l(1)|0;Zl(16)|0;fp(1);while(1){a=Tn(a)|0;e=c[f>>2]|0;if(!a)break;if(!e){ms(h,a,d)|0;ps(h,a,b,f,g)|0;ir(h,a)|0}mn(a)|0;a=174185}l=i;return e|0}function Ab(a){a=a|0;var d=0,e=0,f=0,g=0;g=l;l=l+16|0;d=g+4|0;e=g;f=c[(c[a+16>>2]|0)+8>>2]|0;a=a+64|0;switch(c[a>>2]|0){case 0:{wx(f);break}case 1:{if(b[(c[f+16>>2]|0)+136>>1]&1)oB(f);break}case 4:case 5:case 6:{tx(f,e,d);Db(f,c[e>>2]|0,c[d>>2]|0,c[a>>2]|0);break}default:{}}l=g;return}function Bb(a){a=a|0;var b=0,d=0,e=0,f=0;d=c[(c[a+16>>2]|0)+8>>2]|0;if(!(c[41841]|0)){c[41841]=c[4442];c[41842]=9;c[41843]=17}e=d+64|0;f=(c[e>>2]|0)+8|0;b=c[f>>2]|0;c[f>>2]=167364;switch(c[a+64>>2]|0){case 2:{jx(a,d,a,0);break}case 3:{jx(a,d,a,1);break}case 1:case 0:{if(!(c[a+152>>2]&134217728))$p(d,a)|0;break}case 6:case 5:case 4:{Cb(d);if(!(c[a+152>>2]&134217728))$p(d,a)|0;break}default:{}}c[(c[e>>2]|0)+8>>2]=b;return}function Cb(b){b=b|0;var d=0,e=0;d=c[41845]|0;if((d|0)!=(c[41844]|0)){e=c[c[41876]>>2]|0;if(!e){e=uB(b,0,84827,174185)|0;c[c[41876]>>2]=e;d=c[41845]|0}if(d>>>0>=(c[41846]|0)>>>0){em(167376,1)|0;d=c[41845]|0}a[d>>0]=0;d=c[41844]|0;c[41845]=d;Dm(b,e,d)|0}if(c[(c[b+16>>2]|0)+12>>2]|0){e=c[(c[41876]|0)+4>>2]|0;d=c[41861]|0;if(d>>>0>=(c[41862]|0)>>>0){em(167440,1)|0;d=c[41861]|0}a[d>>0]=0;d=c[41860]|0;c[41861]=d;Dm(b,e,d)|0}Mm(b,59577,c[(c[41876]|0)+8236>>2]|0,174185)|0;d=0;while(1){if((d|0)==8)break;hm(167376+(d<<4)|0);d=d+1|0}$I(c[41876]|0);h[1]=1.0;h[5]=1.0;c[41877]=0;c[41881]=0;return}function Db(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0;i=_I(8240)|0;c[41876]=i;a:do switch(g|0){case 6:{b[i+8232>>1]=14;g=59593;break}case 5:{b[i+8232>>1]=12;g=59597;break}default:{g=Jm(d,59577)|0;if((g|0?a[g>>0]|0:0)?(h=Eb(g)|0,(h&65535)>10):0){i=c[41876]|0;b[i+8232>>1]=h;break a}g=Eb(59589)|0;i=c[41876]|0;b[i+8232>>1]=g;g=59589}}while(0);c[i+8236>>2]=g;j=d+16|0;g=c[j>>2]|0;if(!(c[g+180>>2]|0))h=0;else{h=uB(d,0,84827,174185)|0;i=c[41876]|0;g=c[j>>2]|0}c[i>>2]=h;if(!(a[g+113>>0]&8))g=0;else g=uB(d,0,59601,174185)|0;c[(c[41876]|0)+4>>2]=g;i=uB(d,1,84827,174185)|0;c[(c[41876]|0)+8>>2]=i;i=uB(d,1,59601,174185)|0;c[(c[41876]|0)+12>>2]=i;i=uB(d,2,84827,174185)|0;g=c[41876]|0;c[g+16>>2]=i;if(!f)h=0;else{h=uB(d,2,59609,174185)|0;g=c[41876]|0}c[g+20>>2]=h;if(!e)h=0;else{h=uB(d,2,59617,174185)|0;g=c[41876]|0}c[g+24>>2]=h;h=a[(c[j>>2]|0)+113>>0]|0;if(!(h&33))i=0;else{i=uB(d,2,59601,174185)|0;g=c[41876]|0;h=a[(c[j>>2]|0)+113>>0]|0}c[g+28>>2]=i;if(!(h&2))i=0;else{i=uB(d,2,59625,174185)|0;g=c[41876]|0;h=a[(c[j>>2]|0)+113>>0]|0}c[g+32>>2]=i;if(!(h&4))h=0;else{h=uB(d,2,59634,174185)|0;g=c[41876]|0}c[g+36>>2]=h;g=0;while(1){if((g|0)==8)break;dm(167376+(g<<4)|0,1024,(c[41876]|0)+40+(g<<10)|0);g=g+1|0}return}function Eb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+1040|0;h=j;g=j+8|0;f=0;d=b;a:while(1){do{e=d;d=d+1|0;e=a[e>>0]|0;if(!(e<<24>>24))break a}while(((e<<24>>24)+-48|0)>>>0>=10);if((f|0)>=1023){i=7;break}a[g+f>>0]=e;f=f+1|0}if((i|0)==7){c[h>>2]=b;$l(0,59643,h)|0}a[g+f>>0]=0;i=(sM(g)|0)&65535;l=j;return i|0}function Fb(b){b=b|0;var d=0,e=0;e=c[(c[b+16>>2]|0)+8>>2]|0;d=c[c[41876]>>2]|0;b=c[41849]|0;if(b>>>0>=(c[41850]|0)>>>0){em(167392,1)|0;b=c[41849]|0}a[b>>0]=0;b=c[41848]|0;c[41849]=b;Dm(e,d,b)|0;if(c[(c[e+16>>2]|0)+12>>2]|0){d=c[(c[41876]|0)+4>>2]|0;b=c[41865]|0;if(b>>>0>=(c[41866]|0)>>>0){em(167456,1)|0;b=c[41865]|0}a[b>>0]=0;b=c[41864]|0;c[41865]=b;Dm(e,d,b)|0}h[2]=1.0;h[6]=1.0;c[41878]=0;c[41882]=0;return}function Gb(b){b=b|0;var d=0,e=0;e=c[(c[b+16>>2]|0)+8>>2]|0;b=c[41849]|0;if((c[41848]|0)!=(b|0)){d=c[(c[41876]|0)+8>>2]|0;if(b>>>0>=(c[41850]|0)>>>0){em(167392,1)|0;b=c[41849]|0}a[b>>0]=0;b=c[41848]|0;c[41849]=b;Dm(e,d,b)|0}b=c[41865]|0;if((c[41864]|0)!=(b|0)){d=c[(c[41876]|0)+12>>2]|0;if(b>>>0>=(c[41866]|0)>>>0){em(167456,1)|0;b=c[41865]|0}a[b>>0]=0;b=c[41864]|0;c[41865]=b;Dm(e,d,b)|0}h[9]=1.0;h[11]=1.0;c[41885]=0;c[41887]=0;return}function Hb(b){b=b|0;var d=0,e=0;e=c[(c[b+16>>2]|0)+8>>2]|0;b=c[41849]|0;if((c[41848]|0)!=(b|0)){d=c[(c[41876]|0)+16>>2]|0;if(b>>>0>=(c[41850]|0)>>>0){em(167392,1)|0;b=c[41849]|0}a[b>>0]=0;b=c[41848]|0;c[41849]=b;Dm(e,d,b)|0}b=c[41853]|0;if((c[41852]|0)!=(b|0)){d=c[(c[41876]|0)+24>>2]|0;if(b>>>0>=(c[41854]|0)>>>0){em(167408,1)|0;b=c[41853]|0}a[b>>0]=0;b=c[41852]|0;c[41853]=b;Dm(e,d,b)|0}b=c[41857]|0;if((c[41856]|0)!=(b|0)){d=c[(c[41876]|0)+20>>2]|0;if(b>>>0>=(c[41858]|0)>>>0){em(167424,1)|0;b=c[41857]|0}a[b>>0]=0;b=c[41856]|0;c[41857]=b;Dm(e,d,b)|0}b=c[41865]|0;if((c[41864]|0)!=(b|0)){d=c[(c[41876]|0)+28>>2]|0;if(b>>>0>=(c[41866]|0)>>>0){em(167456,1)|0;b=c[41865]|0}a[b>>0]=0;b=c[41864]|0;c[41865]=b;Dm(e,d,b)|0}b=c[41869]|0;if((c[41868]|0)!=(b|0)){d=c[(c[41876]|0)+36>>2]|0;if(b>>>0>=(c[41870]|0)>>>0){em(167472,1)|0;b=c[41869]|0}a[b>>0]=0;b=c[41868]|0;c[41869]=b;Dm(e,d,b)|0}b=c[41873]|0;if((c[41872]|0)!=(b|0)){d=c[(c[41876]|0)+32>>2]|0;if(b>>>0>=(c[41874]|0)>>>0){em(167488,1)|0;b=c[41873]|0}a[b>>0]=0;b=c[41872]|0;c[41873]=b;Dm(e,d,b)|0}h[10]=1.0;h[12]=1.0;h[3]=1.0;h[4]=1.0;h[7]=1.0;h[8]=1.0;c[41886]=0;c[41888]=0;c[41879]=0;c[41880]=0;c[41883]=0;c[41884]=0;return}function Ib(d,e,f){d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=l;l=l+1056|0;j=t+16|0;s=t+8|0;r=t;k=t+32|0;o=c[(c[d+16>>2]|0)+12>>2]|0;p=c[11344+(o<<2)>>2]|0;gm(p,59746)|0;g=f+4|0;Rb(k,+h[(c[g>>2]|0)+16>>3]);gm(p,k)|0;Ub(d,174185,c[c[g>>2]>>2]|0);Ob(d);q=a[f+48>>0]|0;q=q<<24>>24==108?-1:q<<24>>24==114&1;g=c[g>>2]|0;if(!g)g=0;else g=c[g+24>>2]&127;i=b[(c[41876]|0)+8232>>1]|0;if((i&65535)>14?(m=c[11392+((i&65535)+-15<<2)>>2]&g,n=167508+(o<<2)|0,(c[n>>2]|0)!=(m|0)):0){c[r>>2]=m;qL(k,59749,r)|0;gm(p,k)|0;c[n>>2]=m}r=e+8|0;h[r>>3]=+h[r>>3]+ +h[f+24>>3];gm(p,59755)|0;c[j>>2]=c[e>>2];c[j+4>>2]=c[e+4>>2];c[j+8>>2]=c[e+8>>2];c[j+12>>2]=c[e+12>>2];Qb(p,j);c[s>>2]=q;qL(k,87254,s)|0;gm(p,k)|0;Rb(k,+h[f+32>>3]);gm(p,k)|0;Ub(d,174185,c[f>>2]|0);l=t;return}function Jb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0;i=l;l=l+1040|0;f=i;g=i+16|0;e=c[(c[a+16>>2]|0)+12>>2]|0;Nb(a);Ob(a);if(!d){a=c[11344+(e<<2)>>2]|0;gm(a,59743)|0}else{if((d|1|0)==3)Wb(a,d,b,2);else Xb(a);a=c[11344+(e<<2)>>2]|0;gm(a,59740)|0};c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];Qb(a,f);Rb(g,+h[b+16>>3]-+h[b>>3]);gm(a,g)|0;Rb(g,+h[b+24>>3]-+h[b+8>>3]);gm(a,g)|0;l=i;return}function Kb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Nb(a);Ob(a);if(!d)Pb(a,112,b,c);else{if((d|1|0)==3)Wb(a,d,b,c);else Xb(a);Pb(a,80,b,c)}return}function Lb(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Nb(a);Ob(a);if(!f)Pb(a,66,b,c);else{if((f|1|0)==3)Wb(a,f,b,c);else Xb(a);Pb(a,98,b,c)}return}function Mb(a,b,c){a=a|0;b=b|0;c=c|0;Nb(a);Ob(a);Pb(a,76,b,c);return}function Nb(b){b=b|0;var d=0,e=0,f=0,g=0.0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+1184|0;i=n;f=n+24|0;m=n+8|0;dm(m,1024,n+152|0);j=b+16|0;d=c[j>>2]|0;g=+h[d+152>>3];e=8+(c[d+12>>2]<<3)|0;if(g!=+h[e>>3]){h[e>>3]=g;gm(m,59706)|0;h[i>>3]=+h[(c[j>>2]|0)+152>>3];qL(f,59720,i)|0;Sb(f,0);gm(m,f)|0;f=m+4|0;d=c[f>>2]|0;e=m+8|0;if(d>>>0>=(c[e>>2]|0)>>>0){em(m,1)|0;d=c[f>>2]|0}c[f>>2]=d+1;a[d>>0]=41;d=c[f>>2]|0;if(d>>>0>=(c[e>>2]|0)>>>0){em(m,1)|0;d=c[f>>2]|0}a[d>>0]=0;d=c[m>>2]|0;c[f>>2]=d;Ub(b,59725,d);d=c[j>>2]|0}d=c[d+160>>2]|0;if(d|0){j=m+4|0;k=m+8|0;a:while(1){i=d+4|0;d=c[d>>2]|0;if(!d)break;switch(a[d>>0]|0){case 102:{if(!(yJ(d,95923)|0)){d=i;continue a}break}case 98:{if(!(yJ(d,95905)|0)){d=i;continue a}break}case 115:{if(!(yJ(d,95910)|0)){d=i;continue a}break}default:{}}gm(m,d)|0;do{f=d;d=d+1|0}while((a[f>>0]|0)!=0);if(a[d>>0]|0){e=c[j>>2]|0;if(e>>>0>=(c[k>>2]|0)>>>0){em(m,1)|0;e=c[j>>2]|0}c[j>>2]=e+1;a[e>>0]=40;f=0;while(1){if(!(a[d>>0]|0))break;if(f|0){e=c[j>>2]|0;if(e>>>0>=(c[k>>2]|0)>>>0){em(m,1)|0;e=c[j>>2]|0}c[j>>2]=e+1;a[e>>0]=44}gm(m,d)|0;do{e=d;d=d+1|0}while((a[e>>0]|0)!=0);f=f+1|0}d=c[j>>2]|0;if(d>>>0>=(c[k>>2]|0)>>>0){em(m,1)|0;d=c[j>>2]|0}c[j>>2]=d+1;a[d>>0]=41}d=c[j>>2]|0;if(d>>>0>=(c[k>>2]|0)>>>0){em(m,1)|0;d=c[j>>2]|0}a[d>>0]=0;d=c[m>>2]|0;c[j>>2]=d;Ub(b,59725,d);d=i}hm(m)}l=n;return}function Ob(a){a=a|0;Tb((c[a+16>>2]|0)+16|0);Ub(a,68667,173886);return}function Pb(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0;k=l;l=l+1040|0;j=k;i=k+16|0;h=c[11344+(c[(c[b+16>>2]|0)+12>>2]<<2)>>2]|0;g=h+4|0;b=c[g>>2]|0;if(b>>>0>=(c[h+8>>2]|0)>>>0){em(h,1)|0;b=c[g>>2]|0}c[g>>2]=b+1;a[b>>0]=d;c[j>>2]=f;qL(i,59670,j)|0;gm(h,i)|0;b=0;while(1){if((b|0)>=(f|0))break;i=e+(b<<4)|0;c[j>>2]=c[i>>2];c[j+4>>2]=c[i+4>>2];c[j+8>>2]=c[i+8>>2];c[j+12>>2]=c[i+12>>2];Qb(h,j);b=b+1|0}l=k;return}function Qb(a,b){a=a|0;b=b|0;var c=0,d=0;c=l;l=l+1024|0;d=c;Rb(d,+h[b>>3]);gm(a,d)|0;Rb(d,+ix(+h[b+8>>3]));gm(a,d)|0;l=c;return}function Rb(a,b){a=a|0;b=+b;var c=0,d=0;c=l;l=l+16|0;d=c;h[d>>3]=b>-1.0e-08&b<1.0e-08?0.0:b;qL(a,59675,d)|0;Sb(a,1);l=c;return}function Sb(b,c){b=b|0;c=c|0;var d=0,e=0;d=XJ(b,46)|0;if(!d){if(c|0){d=b+(sJ(b)|0)|0;e=10}}else{while(1){b=d+1|0;if(!(a[b>>0]|0))break;else d=b}a:while(1){switch(a[d>>0]|0){case 46:{e=5;break a}case 48:break;default:{e=6;break a}}a[d>>0]=0;d=d+-1|0}if((e|0)==5)a[d>>0]=0;else if((e|0)==6)d=d+1|0;if(c|0)e=10}if((e|0)==10){a[d>>0]=32;a[d+1>>0]=0}return}function Tb(b){b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+32|0;i=j+16|0;h=j;e=a[b+3>>0]|0;f=d[b>>0]|0;g=d[b+1>>0]|0;b=d[b+2>>0]|0;if(e<<24>>24==-1){c[h>>2]=f;c[h+4>>2]=g;c[h+8>>2]=b;qL(173886,68547,h)|0}else{c[i>>2]=f;c[i+4>>2]=g;c[i+8>>2]=b;c[i+12>>2]=e&255;qL(173886,59688,i)|0}l=j;return}function Ub(a,b,d){a=a|0;b=b|0;d=d|0;Vb(c[11344+(c[(c[a+16>>2]|0)+12>>2]<<2)>>2]|0,b,d);return}function Vb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=l;l=l+1040|0;h=f;g=f+8|0;i=sJ(e)|0;c[h>>2]=d;c[h+4>>2]=i;qL(g,59681,h)|0;gm(b,g)|0;gm(b,e)|0;e=b+4|0;d=c[e>>2]|0;if(d>>>0>=(c[b+8>>2]|0)>>>0){em(b,1)|0;d=c[e>>2]|0}c[e>>2]=d+1;a[d>>0]=32;l=f;return}function Wb(b,d,f,i){b=b|0;d=d|0;f=f|0;i=i|0;var j=0.0,k=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0;x=l;l=l+1120|0;t=x+64|0;w=x+80|0;k=x+32|0;r=x+16|0;s=x;u=c[b+16>>2]|0;j=+(c[u+136>>2]|0)*.017453292519943295;if((e[(c[41876]|0)+8232>>1]|0)<14)Xb(b);else{dm(w,1024,x+96|0);v=(d|0)==2;if(v){KB(f,k,i,j,2);f=w+4|0;d=c[f>>2]|0;if(d>>>0>=(c[w+8>>2]|0)>>>0){em(w,1)|0;d=c[f>>2]|0}c[f>>2]=d+1;a[d>>0]=91;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[t+8>>2]=c[k+8>>2];c[t+12>>2]=c[k+12>>2];Qb(w,t);s=k+16|0;c[t>>2]=c[s>>2];c[t+4>>2]=c[s+4>>2];c[t+8>>2]=c[s+8>>2];c[t+12>>2]=c[s+12>>2];Qb(w,t)}else{KB(f,k,i,0.0,3);q=+h[k+24>>3];o=+h[k>>3];if(j==0.0){n=+h[k+8>>3];p=q*.25;j=n;m=o}else{p=q*.25;y=p;m=+E(+j)*y+o;n=+h[k+8>>3];j=+F(+j)*y+n}h[r>>3]=m;h[r+8>>3]=j;h[s>>3]=o;h[s+8>>3]=n;f=w+4|0;d=c[f>>2]|0;if(d>>>0>=(c[w+8>>2]|0)>>>0){em(w,1)|0;d=c[f>>2]|0}c[f>>2]=d+1;a[d>>0]=40;c[t>>2]=c[r>>2];c[t+4>>2]=c[r+4>>2];c[t+8>>2]=c[r+8>>2];c[t+12>>2]=c[r+12>>2];Qb(w,t);Yb(w,p);c[t>>2]=c[s>>2];c[t+4>>2]=c[s+4>>2];c[t+8>>2]=c[s+8>>2];c[t+12>>2]=c[s+12>>2];Qb(w,t);Yb(w,q)}gm(w,59731)|0;d=u+140|0;j=+g[d>>2];f=u+56|0;if(j>0.0){Zb(w,j,f);Zb(w,+g[d>>2],u+96|0)}else{Zb(w,0.0,f);Zb(w,1.0,u+96|0)}im(w)|0;k=w+4|0;d=c[k>>2]|0;i=w+8|0;f=d>>>0>=(c[i>>2]|0)>>>0;if(v){if(f){em(w,1)|0;d=c[k>>2]|0}c[k>>2]=d+1;a[d>>0]=93}else{if(f){em(w,1)|0;d=c[k>>2]|0}c[k>>2]=d+1;a[d>>0]=41}d=c[k>>2]|0;if(d>>>0>=(c[i>>2]|0)>>>0){em(w,1)|0;d=c[k>>2]|0}a[d>>0]=0;v=c[w>>2]|0;c[k>>2]=v;Ub(b,59728,v);hm(w)}l=x;return}function Xb(a){a=a|0;Tb((c[a+16>>2]|0)+56|0);Ub(a,59728,173886);return}function Yb(a,b){a=a|0;b=+b;var c=0,d=0;c=l;l=l+1024|0;d=c;Rb(d,b);gm(a,d)|0;l=c;return}function Zb(a,b,c){a=a|0;b=+b;c=c|0;var d=0,e=0,f=0;d=l;l=l+1040|0;f=d;e=d+8|0;h[f>>3]=b;qL(e,59734,f)|0;Sb(e,1);Tb(c);Vb(a,e,173886);l=d;return}function _b(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0;e=l;l=l+1040|0;i=e;f=e+16|0;g=c[11344+(c[(c[a+16>>2]|0)+12>>2]<<2)>>2]|0;gm(g,59843)|0;c[i>>2]=c[d>>2];c[i+4>>2]=c[d+4>>2];c[i+8>>2]=c[d+8>>2];c[i+12>>2]=c[d+12>>2];Qb(g,i);Rb(f,+h[d+16>>3]-+h[d>>3]);gm(g,f)|0;Rb(f,+h[d+24>>3]-+h[d+8>>3]);gm(g,f)|0;Ub(a,174185,c[b+8>>2]|0);l=e;return}function $b(a){a=a|0;var b=0;switch(c[a+64>>2]|0){case 0:{b=zr(c[a>>2]|0)|0;ns(b,c[(c[a+16>>2]|0)+8>>2]|0,60630,0)|0;Ar(b);break}case 1:{wx(c[(c[a>>2]|0)+168>>2]|0);break}default:{}}return}function ac(b){b=b|0;var d=0,e=0,f=0,g=0;f=l;l=l+16|0;d=f;e=c[(c[b+16>>2]|0)+8>>2]|0;if(!(c[41889]|0)){c[41889]=c[4442];c[41890]=9;c[41891]=17}c[(c[e+64>>2]|0)+8>>2]=167556;bc(e,1);c[d>>2]=0;a[d+4>>0]=(a[(c[e+16>>2]|0)+115>>0]|0)==1&1;g=c[b+64>>2]|0;a[d+5>>0]=((g|0)==0|(g|0)==3)&1;a[d+6>>0]=0;cc(e,b,1,d);l=f;return}function bc(a,b){a=a|0;b=b|0;var d=0;c[a>>2]=c[a>>2]&-9;d=Kp(a)|0;while(1){if(!d)break;bc(d,0);d=Lp(d)|0}a:do if(b|0){b=eo(a)|0;while(1){if(!b)break a;c[b>>2]=c[b>>2]&-9;d=Qm(a,b)|0;while(1){if(!d)break;c[d>>2]=c[d>>2]&-9;d=Sm(a,d)|0}b=fo(a,b)|0}}while(0);return}function cc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;q=l;l=l+16|0;p=q+8|0;o=q;n=(d|0)!=0;if(n){m=Rl(11764,c[4345]|0)|0;To(a,1,86799,12,0);To(a,2,86799,12,0);To(a,0,86799,-12,0);f=dc(a,0,m)|0;j=eo(a)|0;i=0;g=0;while(1){if(!j)break;if(!(WJ(En(j)|0,93039,7)|0)){k=g;g=ec(m,En(j)|0)|0}else{k=g+1|0;g=g+f|0}c[(Mo(j,86799,0)|0)+8>>2]=g;h=Qm(a,j)|0;g=i;while(1){if(!h)break;c[(Mo(h,86799,0)|0)+8>>2]=g;h=Sm(a,h)|0;g=g+1|0}j=fo(a,j)|0;i=g;g=k}Ll(m)|0}else f=0;m=c[e>>2]|0;c[e>>2]=m+1;fc(b,m);nr(b,82337)|0;gc(a,b,d,e);hc(a,b,e);nr(b,82308)|0;fc(b,c[e>>2]|0);if(n){c[o>>2]=f;tr(b,59846,o)}else{c[p>>2]=c[(Mo(a,86799,0)|0)+8>>2];tr(b,59866,p)}jc(a,b,d,ic(a,b,d,e)|0,e);kc(a,b,d,e);nr(b,134901)|0;p=(c[e>>2]|0)+-1|0;c[e>>2]=p;fc(b,p);if(n)nr(b,95830)|0;else nr(b,68190)|0;l=q;return}function dc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;if((to(a)|0)!=(a|0)){e=b+1|0;c[(Mo(a,86799,0)|0)+8>>2]=b;if(!(WJ(En(a)|0,93039,7)|0)){b=En(a)|0;wc(d,b,c[(Mo(a,86799,0)|0)+8>>2]|0);b=e}else b=e}e=Kp(a)|0;while(1){if(!e)break;a=dc(e,b,d)|0;e=Lp(e)|0;b=a}return b|0}function ec(a,b){a=a|0;b=b|0;a=bb[c[a>>2]&31](a,b,512)|0;if(!a)a=-1;else a=c[a+12>>2]|0;return a|0}function fc(a,b){a=a|0;b=b|0;while(1){if((b|0)<=0)break;nr(a,60598)|0;b=b+-1|0}return}function gc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;h=l;l=l+32|0;g=h+16|0;f=h+8|0;i=h;j=En(a)|0;fc(b,c[e>>2]|0);c[i>>2]=nc(j,e)|0;tr(b,59954,i);if(d|0){nr(b,82308)|0;fc(b,c[e>>2]|0);j=(rn(a)|0)!=0;c[f>>2]=j?92685:122100;tr(b,60568,f);fc(b,c[e>>2]|0);j=(tn(a)|0)!=0;c[g>>2]=j?92685:122100;tr(b,60585,g)}l=h;return}function hc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;n=o+8|0;m=o;i=to(b)|0;j=c[b>>2]&3;f=Em(i,j,0)|0;a:do if(f|0){k=e+5|0;while(1){if(!f)break a;g=Km(b,f)|0;do if(g|0){h=f+8|0;if(!(a[g>>0]|0)){g=c[h>>2]|0;if((a[g>>0]|0)!=108)break;if(yJ(g,86240)|0)break}nr(d,82308)|0;fc(d,c[e>>2]|0);c[m>>2]=nc(c[h>>2]|0,e)|0;tr(d,60004,m);if(a[k>>0]|0?pc(c[h>>2]|0)|0:0){qc(Km(b,f)|0,d,e);break}c[n>>2]=nc(Km(b,f)|0,e)|0;tr(d,60011,n)}while(0);f=Em(i,j,f)|0}}while(0);l=o;return}function ic(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;f=Kp(a)|0;if(f){nr(b,82308)|0;g=c[e>>2]|0;c[e>>2]=g+1;fc(b,g);g=(d|0)!=0;if(g){nr(b,59928)|0;a=0;d=f}else{nr(b,59988)|0;fc(b,c[e>>2]|0);a=0;d=f}while(1){if(!d)break;if(!a)a=1;else nr(b,82308)|0;if(g)oc(d,b,e);else{c[h>>2]=c[(Mo(d,86799,0)|0)+8>>2];tr(b,122187,h)}d=Lp(d)|0}if(g)a=1;else{c[e>>2]=(c[e>>2]|0)+-1;nr(b,134901)|0;fc(b,c[e>>2]|0);nr(b,82303)|0;a=1}}else a=0;l=i;return a|0}function jc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;g=eo(a)|0;if(!g){if((d|0)!=0&(e|0)!=0){c[f>>2]=(c[f>>2]|0)+-1;nr(b,134901)|0;fc(b,c[f>>2]|0);nr(b,82303)|0}}else{nr(b,82308)|0;h=(d|0)!=0;if(h)if(!e){e=c[f>>2]|0;c[f>>2]=e+1;fc(b,e);nr(b,59928)|0;e=0}else e=0;else{e=c[f>>2]|0;c[f>>2]=e+1;fc(b,e);nr(b,59942)|0;fc(b,c[f>>2]|0);e=0}while(1){if(!g)break;if(WJ(En(g)|0,93039,7)|0){do if(e)if(h){nr(b,82308)|0;break}else{nr(b,86030)|0;break}else e=1;while(0);mc(g,b,d,f)}g=fo(a,g)|0}c[f>>2]=(c[f>>2]|0)+-1;nr(b,134901)|0;fc(b,c[f>>2]|0);nr(b,82303)|0}return}function kc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=eo(a)|0;a:do if(f|0){while(1){if(!f)break a;if(Qm(a,f)|0)break;f=fo(a,f)|0}nr(b,82308)|0;i=c[e>>2]|0;c[e>>2]=i+1;fc(b,i);nr(b,59878)|0;i=(d|0)!=0;if(i)g=0;else{fc(b,c[e>>2]|0);g=0}while(1){if(!f)break;h=Qm(a,f)|0;while(1){if(!h)break;do if(g)if(i){nr(b,82308)|0;break}else{nr(b,86030)|0;break}else g=1;while(0);lc(h,b,d,e);h=Sm(a,h)|0}f=fo(a,f)|0}c[e>>2]=(c[e>>2]|0)+-1;nr(b,134901)|0;fc(b,c[e>>2]|0);nr(b,82303)|0}while(0);return}function lc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;j=l;l=l+32|0;i=j+24|0;h=j+16|0;g=j+8|0;f=j;if(!d){c[i>>2]=c[(Mo(a,86799,0)|0)+8>>2];tr(b,122187,i)}else{i=c[e>>2]|0;c[e>>2]=i+1;fc(b,i);nr(b,82337)|0;fc(b,c[e>>2]|0);c[f>>2]=c[(Mo(a,86799,0)|0)+8>>2];tr(b,59890,f);fc(b,c[e>>2]|0);c[g>>2]=c[(Mo(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0,86799,0)|0)+8>>2];tr(b,59904,g);fc(b,c[e>>2]|0);c[h>>2]=c[(Mo(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0,86799,0)|0)+8>>2];tr(b,59917,h);hc(a,b,e);nr(b,134901)|0;i=(c[e>>2]|0)+-1|0;c[e>>2]=i;fc(b,i);nr(b,68190)|0}l=j;return}function mc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=l;l=l+32|0;h=i+16|0;g=i+8|0;f=i;if(!d){c[h>>2]=c[(Mo(a,86799,0)|0)+8>>2];tr(b,122187,h)}else{h=c[e>>2]|0;c[e>>2]=h+1;fc(b,h);nr(b,82337)|0;fc(b,c[e>>2]|0);c[f>>2]=c[(Mo(a,86799,0)|0)+8>>2];tr(b,59890,f);fc(b,c[e>>2]|0);c[g>>2]=nc(En(a)|0,e)|0;tr(b,59954,g);hc(a,b,e);nr(b,134901)|0;h=(c[e>>2]|0)+-1|0;c[e>>2]=h;fc(b,h);nr(b,68190)|0}l=i;return}function nc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;g=d+4|0;if(a[g>>0]|0)b=zB(b)|0;if(!(c[41892]|0)){dm(167568,1024,0);e=b}else e=b;a:while(1){f=a[e>>0]|0;switch(f<<24>>24){case 0:break a;case 34:{gm(167568,59967)|0;break}case 92:{gm(167568,81579)|0;break}case 47:{gm(167568,59970)|0;break}case 8:{gm(167568,59973)|0;break}case 12:{gm(167568,59976)|0;break}case 10:{gm(167568,59979)|0;break}case 13:{gm(167568,59982)|0;break}case 9:{gm(167568,59985)|0;break}default:{d=c[41893]|0;if(d>>>0>=(c[41894]|0)>>>0){em(167568,1)|0;d=c[41893]|0}c[41893]=d+1;a[d>>0]=f}}e=e+1|0}d=c[41893]|0;if(d>>>0>=(c[41894]|0)>>>0){em(167568,1)|0;d=c[41893]|0}a[d>>0]=0;d=c[41892]|0;c[41893]=d;if(a[g>>0]|0)$I(b);return d|0}function oc(a,b,c){a=a|0;b=b|0;c=c|0;cc(a,b,0,c);a=Kp(a)|0;while(1){if(!a)break;nr(b,82308)|0;oc(a,b,c);a=Lp(a)|0}return}function pc(b){b=b|0;var c=0;c=b+1|0;a:do if((a[b>>0]|0)==95){b=(a[c>>0]|0)+-100<<24>>24;switch(((b&255)>>>2|b<<6&255)<<24>>24){case 0:{if(!(yJ(c,60525)|0)){b=1;break a}break}case 2:{if(!(yJ(c,60531)|0)){b=1;break a}break}case 1:{if(!(yJ(c,60538)|0)){b=1;break a}return (yJ(c,60552)|0)==0|0}case 4:{if(!(yJ(c,60545)|0)){b=1;break a}b=(yJ(c,60560)|0)==0&1;break a}default:{b=0;break a}}b=0}else b=0;while(0);return b|0}function qc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=l;l=l+16|0;f=i;do if(b|0?a[b>>0]|0:0){h=xt(b)|0;if(!h){c[f>>2]=b;$l(0,60016,f)|0;break}nr(d,134901)|0;g=c[e>>2]|0;c[e>>2]=g+1;fc(d,g);nr(d,60043)|0;g=h+8|0;b=0;f=0;while(1){if((f|0)>=(c[h>>2]|0))break;if(!b)b=1;else nr(d,82308)|0;rc((c[g>>2]|0)+(f*80|0)|0,d,e);f=f+1|0}c[e>>2]=(c[e>>2]|0)+-1;nr(d,134901)|0;fc(d,c[e>>2]|0);nr(d,82303)|0;yt(h)}while(0);l=i;return}function rc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0.0;A=l;l=l+240|0;y=A+224|0;x=A+216|0;w=A+208|0;v=A+200|0;u=A+192|0;t=A+184|0;s=A+176|0;r=A+152|0;q=A+136|0;p=A+128|0;o=A+112|0;n=A+104|0;m=A+96|0;k=A+88|0;j=A+72|0;i=A+48|0;z=A+40|0;g=A+8|0;f=A;e=c[d>>2]|0;c[d>>2]=e+1;fc(b,e);nr(b,82337)|0;fc(b,c[d>>2]|0);e=c[a>>2]|0;a:do switch(e|0){case 1:case 0:{c[f>>2]=(e|0)==0?69:101;tr(b,60046,f);fc(b,c[d>>2]|0);D=+h[a+16>>3];C=+h[a+24>>3];B=+h[a+32>>3];h[g>>3]=+h[a+8>>3];h[g+8>>3]=D;h[g+16>>3]=C;h[g+24>>3]=B;tr(b,60059,g);break}case 3:case 2:{c[z>>2]=(e|0)==2?80:112;tr(b,60046,z);fc(b,c[d>>2]|0);sc(b,a+8|0);break}case 5:case 4:{c[i>>2]=(e|0)==4?66:98;tr(b,60046,i);fc(b,c[d>>2]|0);sc(b,a+8|0);break}case 6:{tr(b,60094,A+56|0);fc(b,c[d>>2]|0);sc(b,a+8|0);break}case 7:{tr(b,60106,A+64|0);fc(b,c[d>>2]|0);D=+h[a+16>>3];h[j>>3]=+h[a+8>>3];h[j+8>>3]=D;tr(b,60118,j);fc(b,c[d>>2]|0);z=c[a+24>>2]|0;c[k>>2]=(z|0)==0?108:(z|0)==1?99:114;tr(b,60140,k);fc(b,c[d>>2]|0);h[m>>3]=+h[a+32>>3];tr(b,60156,m);fc(b,c[d>>2]|0);c[n>>2]=nc(c[a+40>>2]|0,d)|0;tr(b,60173,n);break}case 9:case 8:{c[o>>2]=(e|0)==8?67:99;tr(b,60046,o);fc(b,c[d>>2]|0);tr(b,60187,A+120|0);fc(b,c[d>>2]|0);c[p>>2]=nc(c[a+8>>2]|0,d)|0;tr(b,60204,p);break}case 13:case 14:{c[q>>2]=(e|0)==13?67:99;tr(b,60046,q);fc(b,c[d>>2]|0);switch(c[a+8>>2]|0){case 0:{tr(b,60187,A+144|0);fc(b,c[d>>2]|0);c[r>>2]=nc(c[a+16>>2]|0,d)|0;tr(b,60204,r);break a}case 1:{tr(b,60219,A+160|0);fc(b,c[d>>2]|0);tc(b,a+16|0,d);break a}default:{tr(b,60238,A+168|0);fc(b,c[d>>2]|0);uc(b,a+16|0,d);break a}}}case 10:{tr(b,60257,s);fc(b,c[d>>2]|0);h[t>>3]=+h[a+8>>3];tr(b,60269,t);fc(b,c[d>>2]|0);c[u>>2]=nc(c[a+16>>2]|0,d)|0;tr(b,60285,u);break}case 11:{tr(b,60299,v);fc(b,c[d>>2]|0);c[w>>2]=nc(c[a+8>>2]|0,d)|0;tr(b,60311,w);break}case 15:{tr(b,60326,x);fc(b,c[d>>2]|0);c[y>>2]=c[a+8>>2];tr(b,60338,y);break}default:{}}while(0);z=(c[d>>2]|0)+-1|0;c[d>>2]=z;fc(b,z);nr(b,68190)|0;l=A;return}function sc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0.0;j=l;l=l+48|0;i=j+32|0;g=j+16|0;f=j+8|0;e=c[b>>2]|0;d=c[b+4>>2]|0;tr(a,60499,j);b=0;while(1){if((b|0)>=(e|0))break;if((b|0)>0)tr(a,86030,f);k=+h[d+(b*24|0)+8>>3];h[g>>3]=+h[d+(b*24|0)>>3];h[g+8>>3]=k;tr(a,60511,g);b=b+1|0}tr(a,60452,i);l=j;return}function tc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0;e=l;l=l+32|0;f=e+16|0;i=e;fc(a,c[d>>2]|0);g=+h[b+8>>3];h[i>>3]=+h[b>>3];h[i+8>>3]=g;tr(a,60455,i);fc(a,c[d>>2]|0);g=+h[b+24>>3];h[f>>3]=+h[b+16>>3];h[f+8>>3]=g;tr(a,60477,f);fc(a,c[d>>2]|0);vc(a,c[b+32>>2]|0,c[b+36>>2]|0,d);l=e;return}function uc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0;e=l;l=l+48|0;f=e+24|0;j=e;fc(a,c[d>>2]|0);g=+h[b+8>>3];i=+h[b+16>>3];h[j>>3]=+h[b>>3];h[j+8>>3]=g;h[j+16>>3]=i;tr(a,60354,j);fc(a,c[d>>2]|0);i=+h[b+32>>3];g=+h[b+40>>3];h[f>>3]=+h[b+24>>3];h[f+8>>3]=i;h[f+16>>3]=g;tr(a,60382,f);fc(a,c[d>>2]|0);vc(a,c[b+48>>2]|0,c[b+52>>2]|0,d);l=e;return}function vc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,i=0,j=0,k=0,m=0,n=0,o=0.0;m=l;l=l+48|0;k=m+32|0;j=m+16|0;i=m+8|0;tr(a,60410,m);f=0;while(1){if((f|0)>=(b|0))break;if((f|0)>0)tr(a,86030,i);o=+g[d+(f<<3)>>2];n=nc(c[d+(f<<3)+4>>2]|0,e)|0;h[j>>3]=o;c[j+8>>2]=n;tr(a,60421,j);f=f+1|0}tr(a,60452,k);l=m;return}function wc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;g=l;l=l+16|0;f=g;e=bb[c[a>>2]&31](a,b,512)|0;if(e){if((c[e+12>>2]|0)!=(d|0)){c[f>>2]=b;$l(0,60601,f)|0}}else{f=aJ(1,16)|0;c[f+8>>2]=HL(b)|0;c[f+12>>2]=d;bb[c[a>>2]&31](a,f,1)|0}l=g;return}function xc(a,b,d){a=a|0;b=b|0;d=d|0;$I(c[b+8>>2]|0);$I(b);return}function yc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;b=l;l=l+32|0;d=b+24|0;e=b+16|0;g=b;f=c[a+16>>2]|0;nr(a,61456)|0;j=c[c[a+12>>2]>>2]|0;i=c[j+4>>2]|0;h=c[j+8>>2]|0;c[g>>2]=c[j>>2];c[g+4>>2]=i;c[g+8>>2]=h;tr(a,61466,g);c[e>>2]=En(c[f+8>>2]|0)|0;tr(a,61501,e);c[d>>2]=O(c[a+168>>2]|0,c[a+164>>2]|0)|0;tr(a,61514,d);nr(a,61527)|0;nr(a,61537)|0;nr(a,61545)|0;nr(a,61553)|0;nr(a,61561)|0;nr(a,61569)|0;nr(a,61577)|0;nr(a,61581)|0;nr(a,61586)|0;l=b;return}function zc(a){a=a|0;nr(a,61437)|0;return}function Ac(a){a=a|0;c[41896]=2;return}function Bc(a){a=a|0;c[41896]=1;return}function Cc(a){a=a|0;c[41896]=2;return}function Dc(a){a=a|0;c[41896]=0;return}function Ec(a){a=a|0;c[41896]=2;return}function Fc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0,k=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0;p=l;l=l+80|0;o=p;m=c[(c[b+16>>2]|0)+16>>2]|0;n=c[41896]|0;f=c[e+4>>2]|0;g=+h[b+352>>3]*+h[f+16>>3];i=c[b+360>>2]|0?1.5707963267948966:0.0;j=c[e>>2]|0;k=g*.3333333333333333*+((sJ(j)|0)>>>0);f=c[f+8>>2]|0;if(!f)f=-1;else f=c[f+20>>2]|0;s=a[e+48>>0]|0;r=+h[d>>3];q=+h[d+8>>3];e=Pc(j)|0;c[o>>2]=4;c[o+4>>2]=s<<24>>24==108?0:s<<24>>24==114?2:1;c[o+8>>2]=m;c[o+12>>2]=n;c[o+16>>2]=0;c[o+20>>2]=f;h[o+24>>3]=g;h[o+32>>3]=i;c[o+40>>2]=6;h[o+48>>3]=g;h[o+56>>3]=k;c[o+64>>2]=~~(r+(r>=0.0?.5:-.5));c[o+68>>2]=~~(q+(q+-72.0>=0.0?-71.5:-72.5));c[o+72>>2]=e;tr(b,61382,o);l=p;return}function Gc(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;n=l;l=l+32|0;j=n;i=n+20|0;m=e+32|0;a:do switch(c[m>>2]|0){case 5:{f=0;while(1){g=c[12652+(f<<2)>>2]|0;if((f|0)==8)break a;h=c[e>>2]|0;if((a[g>>0]|0)==(a[h>>0]|0)?(yJ(g,h)|0)==0:0){k=10;break a}f=f+1|0}}case 1:{g=e+1|0;h=e+2|0;f=(Oc(i,d[e>>0]|0,d[g>>0]|0,d[h>>0]|0)|0)+32|0;if(!(c[i>>2]|0))k=10;else{o=d[e>>0]|0;i=d[g>>0]|0;k=d[h>>0]|0;c[j>>2]=0;c[j+4>>2]=f;c[j+8>>2]=o;c[j+12>>2]=i;c[j+16>>2]=k;tr(b,61325,j);k=10}break}default:ma(123205,60722,163,60753)}while(0);if((k|0)==10)c[e>>2]=f;c[m>>2]=6;l=n;return}function Hc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0,k=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0;e=l;l=l+112|0;f=e+8|0;u=e+104|0;t=e;k=c[a+16>>2]|0;s=~~+h[k+152>>3];r=c[k+16>>2]|0;q=c[k+56>>2]|0;p=c[41896]|0;Mc(k,u,t);n=+h[b>>3];k=~~(n+(n>=0.0?.5:-.5));m=+h[b+8>>3];j=~~(m+(m>=0.0?.5:-.5));i=+h[b+16>>3];n=i-n;g=+h[b+24>>3];m=g-m;b=c[u>>2]|0;o=+h[t>>3];c[f>>2]=1;c[f+4>>2]=1;c[f+8>>2]=b;c[f+12>>2]=s;c[f+16>>2]=r;c[f+20>>2]=q;c[f+24>>2]=p;c[f+28>>2]=0;c[f+32>>2]=d|0?20:-1;h[f+40>>3]=o;c[f+48>>2]=0;h[f+56>>3]=0.0;c[f+64>>2]=k;c[f+68>>2]=j;c[f+72>>2]=~~(n+(n>=0.0?.5:-.5));c[f+76>>2]=~~(m+(m>=0.0?.5:-.5));c[f+80>>2]=k;c[f+84>>2]=j;c[f+88>>2]=~~(i+(i>=0.0?.5:-.5));c[f+92>>2]=~~(g+(g>=0.0?.5:-.5));tr(a,61260,f);l=e;return}function Ic(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;f=l;l=l+96|0;g=f+8|0;o=f+80|0;p=f;q=c[a+16>>2]|0;n=~~+h[q+152>>3];m=c[q+16>>2]|0;k=c[q+56>>2]|0;j=c[41896]|0;Mc(q,o,p);o=c[o>>2]|0;i=+h[p>>3];c[g>>2]=2;c[g+4>>2]=3;c[g+8>>2]=o;c[g+12>>2]=n;c[g+16>>2]=m;c[g+20>>2]=k;c[g+24>>2]=j;c[g+28>>2]=0;c[g+32>>2]=e|0?20:-1;h[g+40>>3]=i;c[g+48>>2]=0;c[g+52>>2]=0;c[g+56>>2]=0;c[g+60>>2]=0;c[g+64>>2]=0;c[g+68>>2]=d+1;tr(a,61164,g);Nc(a,b,d,1);l=f;return}function Jc(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0;C=l;l=l+192|0;B=C+176|0;z=C+168|0;A=C+104|0;y=C+96|0;i=C+88|0;u=C+180|0;v=C+80|0;w=C+16|0;x=C;f=a+16|0;e=c[f>>2]|0;q=~~+h[e+152>>3];r=c[e+16>>2]|0;s=c[41896]|0;if((d|0)<=3)ma(60715,60722,360,60742);t=_I((d*140|0)+140|0)|0;Mc(e,u,v);if(!g){o=4;j=0;k=-1}else{o=5;j=c[(c[f>>2]|0)+56>>2]|0;k=20}E=+h[b>>3];n=w+48|0;h[n>>3]=E;D=+h[b+8>>3];h[w+56>>3]=D;c[i>>2]=~~(E+(E>=0.0?.5:-.5));c[i+4>>2]=~~(D+(D>=0.0?.5:-.5));m=x+8|0;e=t+(qL(t,73932,i)|0)|0;p=1;g=0;while(1){i=g+3|0;if((i|0)>=(d|0))break;c[w>>2]=c[n>>2];c[w+4>>2]=c[n+4>>2];c[w+8>>2]=c[n+8>>2];c[w+12>>2]=c[n+12>>2];f=1;while(1){if((f|0)==4){f=1;break}F=f+g|0;h[w+(f<<4)>>3]=+h[b+(F<<4)>>3];h[w+(f<<4)+8>>3]=+h[b+(F<<4)+8>>3];f=f+1|0}while(1){if((f|0)==7)break;QA(x,w,3,+(f|0)*.16666666666666666,0,0);D=+h[x>>3];E=+h[m>>3];c[y>>2]=~~(D+(D>=0.0?.5:-.5));c[y+4>>2]=~~(E+(E>=0.0?.5:-.5));f=f+1|0;e=e+(qL(e,73932,y)|0)|0}p=p+6|0;g=i}f=c[u>>2]|0;E=+h[v>>3];c[A>>2]=3;c[A+4>>2]=o;c[A+8>>2]=f;c[A+12>>2]=q;c[A+16>>2]=r;c[A+20>>2]=j;c[A+24>>2]=s;c[A+28>>2]=0;c[A+32>>2]=k;h[A+40>>3]=E;c[A+48>>2]=0;c[A+52>>2]=0;c[A+56>>2]=0;c[A+60>>2]=p;tr(a,61215,A);c[z>>2]=t;tr(a,73939,z);$I(t);f=p+-1|0;e=0;while(1){if((e|0)>=(p|0))break;c[B>>2]=((e|0)%(f|0)|0|0)!=0&1;tr(a,73944,B);e=e+1|0}nr(a,134901)|0;l=C;return}function Kc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0,j=0,k=0,m=0,n=0,o=0;e=l;l=l+96|0;f=e+8|0;m=e+80|0;n=e;o=c[a+16>>2]|0;k=~~+h[o+152>>3];j=c[o+16>>2]|0;i=c[41896]|0;Mc(o,m,n);m=c[m>>2]|0;g=+h[n>>3];c[f>>2]=2;c[f+4>>2]=1;c[f+8>>2]=m;c[f+12>>2]=k;c[f+16>>2]=j;c[f+20>>2]=0;c[f+24>>2]=i;c[f+28>>2]=0;c[f+32>>2]=0;h[f+40>>3]=g;c[f+48>>2]=0;c[f+52>>2]=0;c[f+56>>2]=0;c[f+60>>2]=0;c[f+64>>2]=0;c[f+68>>2]=d;tr(a,61164,f);Nc(a,b,d,0);l=e;return}function Lc(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=b;tr(a,61158,e);l=d;return}function Mc(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0;switch(c[a+144>>2]|0){case 1:{e=10.0;a=1;break}case 2:{e=10.0;a=2;break}default:{e=0.0;a=0}}c[b>>2]=a;h[d>>3]=e;return}function Nc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0,m=0.0;j=l;l=l+16|0;i=j+8|0;g=j;f=0;while(1){if((f|0)>=(d|0))break;m=+h[b+(f<<4)>>3];k=+h[b+(f<<4)+8>>3];c[g>>2]=~~(m+(m>=0.0?.5:-.5));c[g+4>>2]=~~(k+(k>=0.0?.5:-.5));tr(a,73932,g);f=f+1|0}if(e|0){k=+h[b>>3];m=+h[b+8>>3];c[i>>2]=~~(k+(k>=0.0?.5:-.5));c[i+4>>2]=~~(m+(m>=0.0?.5:-.5));tr(a,73932,i)}nr(a,134901)|0;l=j;return}function Oc(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;c[a>>2]=0;k=c[41897]|0;h=195075;g=0;i=-1;while(1){if((g|0)>=(k|0)){l=6;break}m=(b[170808+(g<<1)>>1]|0)-d|0;n=(b[171320+(g<<1)>>1]|0)-e|0;j=(b[171832+(g<<1)>>1]|0)-f|0;j=(O(n,n)|0)+(O(m,m)|0)+(O(j,j)|0)|0;if((j|0)<(h|0))if(!j)break;else{h=j;i=g}g=g+1|0}if((l|0)==6){c[41897]=k+1;if((k|0)==256)g=i;else{b[170808+(g<<1)>>1]=d;b[171320+(g<<1)>>1]=e;b[171832+(g<<1)>>1]=f;c[a>>2]=1}}return g|0}function Pc(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;d=c[41898]|0;if(!d){c[41899]=64;d=_I(64)|0;c[41898]=d;e=0}else e=0;while(1){g=b+1|0;f=a[b>>0]|0;if(!(f<<24>>24))break;b=c[41899]|0;if((e|0)>(b+-8|0)){d=b<<1;c[41899]=d;d=bJ(c[41898]|0,d)|0;c[41898]=d;d=d+e|0}if(f<<24>>24<=-1){a[d>>0]=92;c[h>>2]=f&255;qL(d+1|0,74057,h)|0;b=g;d=d+4|0;e=e+4|0;continue}if(f<<24>>24==92){a[d>>0]=92;e=e+1|0;d=d+1|0}a[d>>0]=f;b=g;d=d+1|0;e=e+1|0}a[d>>0]=0;l=i;return c[41898]|0}function Qc(b){b=b|0;var d=0,e=0,f=0;e=c[b+16>>2]|0;switch(c[b+64>>2]|0){case 0:{nr(b,61053)|0;d=e+208|0;e=c[d>>2]|0;if(e|0?a[e>>0]|0:0){nr(b,61067)|0;nr(b,sw(c[d>>2]|0)|0)|0;nr(b,134901)|0}break}case 1:{d=e+208|0;f=c[d>>2]|0;if(f|0?a[f>>0]|0:0){nr(b,61067)|0;nr(b,sw(c[d>>2]|0)|0)|0;nr(b,87638)|0;nr(b,sw(En(c[e+8>>2]|0)|0)|0)|0;nr(b,134901)|0}break}case 3:{f=sw(En(c[e+8>>2]|0)|0)|0;nr(b,61076)|0;nr(b,f)|0;nr(b,61086)|0;nr(b,f)|0;nr(b,61041)|0;break}default:{}}return}function Rc(a){a=a|0;var b=0;b=c[a+16>>2]|0;switch(c[a+64>>2]|0){case 2:{Tc(a,c[b+264>>2]|0,c[b+272>>2]|0,c[b+268>>2]|0,c[b+208>>2]|0,c[b+228>>2]|0,c[b+244>>2]|0,c[b+212>>2]|0);break}case 3:{Tc(a,c[b+264>>2]|0,c[b+272>>2]|0,c[b+268>>2]|0,c[b+208>>2]|0,c[b+228>>2]|0,c[b+244>>2]|0,c[b+212>>2]|0);nr(a,61045)|0;break}default:{}}return}function Sc(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0;g=c[a+16>>2]|0;Tc(a,c[g+264>>2]|0,c[g+272>>2]|0,c[g+268>>2]|0,b,d,e,f);return}function Tc(b,d,e,f,g,i,j,k){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;k=k|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0;y=l;l=l+128|0;x=y+120|0;u=y+112|0;t=y+96|0;s=y+80|0;r=y+56|0;w=y+48|0;q=y+40|0;v=y+24|0;p=y;a:do if((e|0)!=0&(f|0)!=0){m=f+10|0;if((c[41900]|0)<(f|0)){c[41900]=m;o=bJ(c[41901]|0,m<<3)|0;c[41901]=o}else o=c[41901]|0;m=0;while(1){if((m|0)>=(f|0))break;z=+h[e+(m<<4)>>3];c[o+(m<<3)>>2]=~~(z+(z>=0.0?.5:-.5));z=+h[e+(m<<4)+8>>3];c[o+(m<<3)+4>>2]=~~(z+(z>=0.0?.5:-.5));m=m+1|0}n=b+64|0;m=c[n>>2]|0;e=(g|0)!=0;if(e&(m|0)==0){if(!(a[g>>0]|0))break;switch(d|0){case 0:{v=c[o>>2]|0;w=c[o+12>>2]|0;x=c[o+8>>2]|0;f=c[o+4>>2]|0;c[p>>2]=g;c[p+4>>2]=v;c[p+8>>2]=w;c[p+12>>2]=x;c[p+16>>2]=f;tr(b,60787,p);break a}case 1:{w=c[o>>2]|0;x=c[o+4>>2]|0;f=(c[o+8>>2]|0)-w|0;c[v>>2]=g;c[v+4>>2]=w;c[v+8>>2]=x;c[v+12>>2]=f;tr(b,60808,v);break a}case 2:{c[q>>2]=g;tr(b,60828,q);m=0;while(1){if((m|0)>=(f|0))break;v=c[41901]|0;x=c[v+(m<<3)+4>>2]|0;c[w>>2]=c[v+(m<<3)>>2];c[w+4>>2]=x;tr(b,60836,w);m=m+1|0}nr(b,134901)|0;break a}default:ma(123205,60843,63,60863)}}if(e&(m|0)==1){if(!(a[g>>0]|0))break;if(!d){w=c[o+12>>2]|0;x=c[o+8>>2]|0;f=c[o+4>>2]|0;c[r>>2]=c[o>>2];c[r+4>>2]=w;c[r+8>>2]=x;c[r+12>>2]=f;c[r+16>>2]=g;c[r+20>>2]=i;tr(b,60880,r);break}else ma(123205,60843,75,60863)}if((m&-2|0)==2){switch(d|0){case 1:{nr(b,60913)|0;break}case 0:{nr(b,60934)|0;break}case 2:{nr(b,60953)|0;break}default:ma(123205,60843,91,60863)}if(k|0?a[k>>0]|0:0){nr(b,66433)|0;nr(b,vw(k)|0)|0;nr(b,83714)|0}if(e?a[g>>0]|0:0){nr(b,60972)|0;nr(b,vw(g)|0)|0;nr(b,83714)|0}if(j|0?a[j>>0]|0:0){nr(b,67392)|0;nr(b,sw(j)|0)|0;nr(b,83714)|0}if(i|0?a[i>>0]|0:0){nr(b,60980)|0;nr(b,sw(i)|0)|0;nr(b,83714)|0}nr(b,60989)|0;nr(b,60997)|0;b:do switch(d|0){case 1:{f=c[41901]|0;w=c[f>>2]|0;x=c[f+4>>2]|0;f=(c[f+8>>2]|0)-w|0;c[s>>2]=w;c[s+4>>2]=x;c[s+8>>2]=f;tr(b,61007,s);break}case 0:{v=c[41901]|0;w=c[v+12>>2]|0;x=c[v+8>>2]|0;f=c[v+4>>2]|0;c[t>>2]=c[v>>2];c[t+4>>2]=w;c[t+8>>2]=x;c[t+12>>2]=f;tr(b,61016,t);break}case 2:{w=c[41901]|0;m=c[w+4>>2]|0;c[u>>2]=c[w>>2];c[u+4>>2]=m;tr(b,61028,u);m=1;while(1){if((m|0)>=(f|0))break b;v=c[41901]|0;w=c[v+(m<<3)+4>>2]|0;c[x>>2]=c[v+(m<<3)>>2];c[x+4>>2]=w;tr(b,61034,x);m=m+1|0}}default:{}}while(0);if((c[n>>2]|0)==3){nr(b,66257)|0;break}else{nr(b,61041)|0;break}}}while(0);l=y;return}function Uc(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;b=l;l=l+32|0;d=b+24|0;e=b+16|0;g=b;f=c[a+16>>2]|0;nr(a,61456)|0;j=c[c[a+12>>2]>>2]|0;i=c[j+4>>2]|0;h=c[j+8>>2]|0;c[g>>2]=c[j>>2];c[g+4>>2]=i;c[g+8>>2]=h;tr(a,61466,g);c[e>>2]=En(c[f+8>>2]|0)|0;tr(a,61501,e);c[d>>2]=O(c[a+168>>2]|0,c[a+164>>2]|0)|0;tr(a,61514,d);nr(a,61527)|0;nr(a,61537)|0;nr(a,61545)|0;nr(a,61553)|0;nr(a,61561)|0;nr(a,61569)|0;nr(a,61577)|0;nr(a,61581)|0;nr(a,61586)|0;l=b;return}function Vc(a){a=a|0;nr(a,61437)|0;return}function Wc(a){a=a|0;c[41902]=2;return}function Xc(a){a=a|0;c[41902]=1;return}function Yc(a){a=a|0;c[41902]=2;return}function Zc(a){a=a|0;c[41902]=0;return}function _c(a){a=a|0;c[41902]=2;return}function $c(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0,k=0,m=0,n=0,o=0.0,p=0.0,q=0;n=l;l=l+80|0;m=n;j=c[(c[b+16>>2]|0)+16>>2]|0;k=c[41902]|0;f=c[e+4>>2]|0;g=+h[b+352>>3]*+h[f+16>>3];i=c[b+360>>2]|0?1.5707963267948966:0.0;f=c[f+8>>2]|0;if(!f)f=-1;else f=c[f+20>>2]|0;q=a[e+48>>0]|0;p=+h[d>>3];o=+h[d+8>>3];e=jd(c[e>>2]|0)|0;c[m>>2]=4;c[m+4>>2]=q<<24>>24==108?0:q<<24>>24==114?2:1;c[m+8>>2]=j;c[m+12>>2]=k;c[m+16>>2]=0;c[m+20>>2]=f;h[m+24>>3]=g;h[m+32>>3]=i;c[m+40>>2]=4;h[m+48>>3]=0.0;h[m+56>>3]=0.0;c[m+64>>2]=~~(p+(p>=0.0?.5:-.5));c[m+68>>2]=~~(o+(o>=0.0?.5:-.5));c[m+72>>2]=e;tr(b,61382,m);l=n;return}function ad(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;n=l;l=l+32|0;j=n;i=n+20|0;m=e+32|0;a:do switch(c[m>>2]|0){case 5:{f=0;while(1){g=c[12652+(f<<2)>>2]|0;if((f|0)==8)break a;h=c[e>>2]|0;if((a[g>>0]|0)==(a[h>>0]|0)?(yJ(g,h)|0)==0:0){k=10;break a}f=f+1|0}}case 1:{g=e+1|0;h=e+2|0;f=(id(i,d[e>>0]|0,d[g>>0]|0,d[h>>0]|0)|0)+32|0;if(!(c[i>>2]|0))k=10;else{o=d[e>>0]|0;i=d[g>>0]|0;k=d[h>>0]|0;c[j>>2]=0;c[j+4>>2]=f;c[j+8>>2]=o;c[j+12>>2]=i;c[j+16>>2]=k;tr(b,61325,j);k=10}break}case 0:{f=0;k=10;break}default:ma(123205,61346,168,61365)}while(0);if((k|0)==10)c[e>>2]=f;c[m>>2]=6;l=n;return}function bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0,k=0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0;e=l;l=l+112|0;f=e+8|0;u=e+104|0;t=e;k=c[a+16>>2]|0;s=~~+h[k+152>>3];r=c[k+16>>2]|0;q=c[k+56>>2]|0;p=c[41902]|0;gd(k,u,t);n=+h[b>>3];k=~~(n+(n>=0.0?.5:-.5));m=+h[b+8>>3];j=~~(m+(m>=0.0?.5:-.5));i=+h[b+16>>3];n=i-n;g=+h[b+24>>3];m=g-m;b=c[u>>2]|0;o=+h[t>>3];c[f>>2]=1;c[f+4>>2]=1;c[f+8>>2]=b;c[f+12>>2]=s;c[f+16>>2]=r;c[f+20>>2]=q;c[f+24>>2]=p;c[f+28>>2]=0;c[f+32>>2]=d|0?20:-1;h[f+40>>3]=o;c[f+48>>2]=0;h[f+56>>3]=0.0;c[f+64>>2]=k;c[f+68>>2]=j;c[f+72>>2]=~~(n+(n>=0.0?.5:-.5));c[f+76>>2]=~~(m+(m>=0.0?.5:-.5));c[f+80>>2]=k;c[f+84>>2]=j;c[f+88>>2]=~~(i+(i>=0.0?.5:-.5));c[f+92>>2]=~~(g+(g>=0.0?.5:-.5));tr(a,61260,f);l=e;return}function cd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;f=l;l=l+96|0;g=f+8|0;o=f+80|0;p=f;q=c[a+16>>2]|0;n=~~+h[q+152>>3];m=c[q+16>>2]|0;k=c[q+56>>2]|0;j=c[41902]|0;gd(q,o,p);o=c[o>>2]|0;i=+h[p>>3];c[g>>2]=2;c[g+4>>2]=3;c[g+8>>2]=o;c[g+12>>2]=n;c[g+16>>2]=m;c[g+20>>2]=k;c[g+24>>2]=j;c[g+28>>2]=0;c[g+32>>2]=e|0?20:-1;h[g+40>>3]=i;c[g+48>>2]=0;c[g+52>>2]=0;c[g+56>>2]=0;c[g+60>>2]=0;c[g+64>>2]=0;c[g+68>>2]=d+1;tr(a,61164,g);hd(a,b,d,1);l=f;return}function dd(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0,F=0;C=l;l=l+192|0;B=C+176|0;z=C+168|0;A=C+104|0;y=C+96|0;f=C+88|0;u=C+180|0;v=C+80|0;w=C+16|0;x=C;e=a+16|0;p=c[e>>2]|0;q=~~+h[p+152>>3];r=c[p+16>>2]|0;s=c[41902]|0;t=_I((d*140|0)+140|0)|0;gd(p,u,v);if(!g){o=4;j=0;k=-1}else{o=5;j=c[(c[e>>2]|0)+56>>2]|0;k=20}E=+h[b>>3];n=w+48|0;h[n>>3]=E;D=+h[b+8>>3];h[w+56>>3]=D;c[f>>2]=~~(E+(E>=0.0?.5:-.5));c[f+4>>2]=~~(D+(D>=0.0?.5:-.5));m=x+8|0;e=t+(qL(t,73932,f)|0)|0;p=1;g=0;while(1){i=g+3|0;if((i|0)>=(d|0))break;c[w>>2]=c[n>>2];c[w+4>>2]=c[n+4>>2];c[w+8>>2]=c[n+8>>2];c[w+12>>2]=c[n+12>>2];f=1;while(1){if((f|0)==4){f=1;break}F=f+g|0;h[w+(f<<4)>>3]=+h[b+(F<<4)>>3];h[w+(f<<4)+8>>3]=+h[b+(F<<4)+8>>3];f=f+1|0}while(1){if((f|0)==7)break;QA(x,w,3,+(f|0)*.16666666666666666,0,0);D=+h[x>>3];E=+h[m>>3];c[y>>2]=~~(D+(D>=0.0?.5:-.5));c[y+4>>2]=~~(E+(E>=0.0?.5:-.5));f=f+1|0;e=e+(qL(e,73932,y)|0)|0}p=p+6|0;g=i}f=c[u>>2]|0;E=+h[v>>3];c[A>>2]=3;c[A+4>>2]=o;c[A+8>>2]=f;c[A+12>>2]=q;c[A+16>>2]=r;c[A+20>>2]=j;c[A+24>>2]=s;c[A+28>>2]=0;c[A+32>>2]=k;h[A+40>>3]=E;c[A+48>>2]=0;c[A+52>>2]=0;c[A+56>>2]=0;c[A+60>>2]=p;tr(a,61215,A);c[z>>2]=t;tr(a,73939,z);$I(t);f=p+-1|0;e=0;while(1){if((e|0)>=(p|0))break;c[B>>2]=((e|0)%(f|0)|0|0)!=0&1;tr(a,73944,B);e=e+1|0}nr(a,134901)|0;l=C;return}function ed(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0,j=0,k=0,m=0,n=0,o=0;e=l;l=l+96|0;f=e+8|0;m=e+80|0;n=e;o=c[a+16>>2]|0;k=~~+h[o+152>>3];j=c[o+16>>2]|0;i=c[41902]|0;gd(o,m,n);m=c[m>>2]|0;g=+h[n>>3];c[f>>2]=2;c[f+4>>2]=1;c[f+8>>2]=m;c[f+12>>2]=k;c[f+16>>2]=j;c[f+20>>2]=0;c[f+24>>2]=i;c[f+28>>2]=0;c[f+32>>2]=0;h[f+40>>3]=g;c[f+48>>2]=0;c[f+52>>2]=0;c[f+56>>2]=0;c[f+60>>2]=0;c[f+64>>2]=0;c[f+68>>2]=d;tr(a,61164,f);hd(a,b,d,0);l=e;return}function fd(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=b;tr(a,61158,e);l=d;return}function gd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0;switch(c[a+144>>2]|0){case 1:{e=10.0;a=1;break}case 2:{e=10.0;a=2;break}default:{e=0.0;a=0}}c[b>>2]=a;h[d>>3]=e;return}function hd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0,m=0.0;j=l;l=l+16|0;i=j+8|0;g=j;f=0;while(1){if((f|0)>=(d|0))break;m=+h[b+(f<<4)>>3];k=+h[b+(f<<4)+8>>3];c[g>>2]=~~(m+(m>=0.0?.5:-.5));c[g+4>>2]=~~(k+(k>=0.0?.5:-.5));tr(a,73932,g);f=f+1|0}if(e|0){k=+h[b>>3];m=+h[b+8>>3];c[i>>2]=~~(k+(k>=0.0?.5:-.5));c[i+4>>2]=~~(m+(m>=0.0?.5:-.5));tr(a,73932,i)}nr(a,134901)|0;l=j;return}function id(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;c[a>>2]=0;k=c[41903]|0;h=195075;g=0;i=-1;while(1){if((g|0)>=(k|0)){l=6;break}m=(b[172344+(g<<1)>>1]|0)-d|0;n=(b[172856+(g<<1)>>1]|0)-e|0;j=(b[173368+(g<<1)>>1]|0)-f|0;j=(O(n,n)|0)+(O(m,m)|0)+(O(j,j)|0)|0;if((j|0)<(h|0))if(!j)break;else{h=j;i=g}g=g+1|0}if((l|0)==6){c[41903]=k+1;if((k|0)==256)g=i;else{b[172344+(g<<1)>>1]=d;b[172856+(g<<1)>>1]=e;b[173368+(g<<1)>>1]=f;c[a>>2]=1}}return g|0}function jd(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;d=c[41904]|0;if(!d){c[41905]=64;d=_I(64)|0;c[41904]=d;e=0}else e=0;while(1){g=b+1|0;f=a[b>>0]|0;if(!(f<<24>>24))break;b=c[41905]|0;if((e|0)>(b+-8|0)){d=b<<1;c[41905]=d;d=bJ(c[41904]|0,d)|0;c[41904]=d;d=d+e|0}if(f<<24>>24<=-1){a[d>>0]=92;c[h>>2]=f&255;qL(d+1|0,74057,h)|0;b=g;d=d+4|0;e=e+4|0;continue}if(f<<24>>24==92){a[d>>0]=92;e=e+1|0;d=d+1|0}a[d>>0]=f;b=g;d=d+1|0;e=e+1|0}a[d>>0]=0;l=i;return c[41904]|0}function kd(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;d=l;l=l+16|0;b=d;nr(a,66165)|0;if((c[a+64>>2]|0)==2)nr(a,66180)|0;else nr(a,134901)|0;g=c[c[a+12>>2]>>2]|0;f=c[g+4>>2]|0;e=c[g+8>>2]|0;c[b>>2]=c[g>>2];c[b+4>>2]=f;c[b+8>>2]=e;tr(a,66191,b);l=d;return}function ld(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;g=l;l=l+32|0;f=g+8|0;e=g;nr(a,66119)|0;d=a+64|0;b=a+12|0;if((c[d>>2]|0)!=2){c[e>>2]=c[(c[b>>2]|0)+28>>2];tr(a,66130,e)}if((c[(c[b>>2]|0)+20>>2]|0)==0?(c[d>>2]|0)!=2:0){b=c[a+476>>2]|0;d=c[a+480>>2]|0;e=c[a+484>>2]|0;c[f>>2]=c[a+472>>2];c[f+4>>2]=b;c[f+8>>2]=d;c[f+12>>2]=e;tr(a,62499,f)}nr(a,66145)|0;nr(a,66158)|0;l=g;return}function md(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;k=l;l=l+32|0;j=k+24|0;f=k+8|0;i=k;g=c[b+16>>2]|0;a[173896]=0;e=b+12|0;h=g+8|0;if(!(c[(c[e>>2]|0)+28>>2]|0)){c[i>>2]=En(c[h>>2]|0)|0;tr(b,62430,i);d=b+64|0;if((c[d>>2]|0)==2)nr(b,62463)|0;else nr(b,62445)|0;do if(!(c[(c[e>>2]|0)+20>>2]|0))if((c[d>>2]|0)==2){n=c[b+460>>2]|0;m=c[b+464>>2]|0;d=c[b+468>>2]|0;c[f>>2]=c[b+456>>2];c[f+4>>2]=n;c[f+8>>2]=m;c[f+12>>2]=d;tr(b,62499,f);break}else{nr(b,62475)|0;break}while(0);nr(b,62529)|0;fy(b,c[(c[e>>2]|0)+24>>2]|0,12928);hy(b);d=c[(c[e>>2]|0)+20>>2]|0;if(d|0){c[i>>2]=c[d>>2];c[i+4>>2]=0;fy(b,0,i)}}c[41906]=(a[(c[(c[h>>2]|0)+16>>2]|0)+115>>0]|0)==1?1:-1;if(!(a[173896]|0)){nr(b,62549)|0;a[173896]=1}d=c[g+208>>2]|0;if(d|0){c[j>>2]=iy(d,c[41906]|0)|0;tr(b,62562,j)}l=k;return}function nd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;b=l;l=l+16|0;f=b;c[f>>2]=d;c[f+4>>2]=e;tr(a,62414,f);l=b;return}function od(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0.0;s=l;l=l+144|0;r=s+128|0;q=s+112|0;p=s+72|0;o=s+56|0;n=s+40|0;m=s+32|0;e=s+24|0;b=s+8|0;d=s;f=c[a+456>>2]|0;j=c[a+460>>2]|0;g=c[a+464>>2]|0;i=c[a+468>>2]|0;k=a+12|0;t=(c[(c[k>>2]|0)+28>>2]|0)+1|0;c[d>>2]=t;c[d+4>>2]=t;tr(a,62041,d);if(!(c[(c[k>>2]|0)+20>>2]|0)){c[b>>2]=f;c[b+4>>2]=j;c[b+8>>2]=g;c[b+12>>2]=i;tr(a,62058,b)}d=a+360|0;c[e>>2]=c[d>>2]|0?62092:62102;tr(a,62111,e);b=a+64|0;if((c[b>>2]|0)==1){c[m>>2]=g;c[m+4>>2]=i;tr(a,62136,m)}m=c[a+200>>2]|0;t=c[a+204>>2]|0;c[n>>2]=c[a+196>>2];c[n+4>>2]=m;c[n+8>>2]=t;tr(a,62175,n);if(!(c[(c[k>>2]|0)+20>>2]|0)){c[o>>2]=f;c[o+4>>2]=j;c[o+8>>2]=g-f;c[o+12>>2]=i-j;tr(a,62195,o)}w=+h[a+496>>3];t=c[d>>2]|0;v=+h[a+504>>3];u=+h[a+512>>3];h[p>>3]=+h[a+488>>3];h[p+8>>3]=w;c[p+16>>2]=t;h[p+24>>3]=v;h[p+32>>3]=u;tr(a,62235,p);if((c[b>>2]|0)==1){if((g|0)>14399|(i|0)>14399){t=c[(c[k>>2]|0)+16>>2]|0;c[q>>2]=g;c[q+4>>2]=i;c[q+8>>2]=14400;hb[t&31](62278,q)}c[r>>2]=f;c[r+4>>2]=j;c[r+8>>2]=g;c[r+12>>2]=i;tr(a,62373,r)}l=s;return}function pd(a){a=a|0;var b=0,d=0,e=0;e=l;l=l+16|0;d=e;b=a+12|0;if(c[(c[b>>2]|0)+20>>2]|0){nr(a,61965)|0;fy(a,0,(c[(c[b>>2]|0)+20>>2]|0)+4|0)}nr(a,61982)|0;nr(a,62009)|0;c[d>>2]=c[(c[b>>2]|0)+28>>2];tr(a,62024,d);l=e;return}function qd(a){a=a|0;var b=0,d=0;b=l;l=l+16|0;d=b;c[d>>2]=En(c[(c[a+16>>2]|0)+8>>2]|0)|0;tr(a,61958,d);nr(a,61951)|0;l=b;return}function rd(a){a=a|0;nr(a,77394)|0;return}function sd(a){a=a|0;nr(a,61951)|0;return}function td(a){a=a|0;nr(a,77394)|0;return}function ud(a){a=a|0;nr(a,61951)|0;return}function vd(a){a=a|0;nr(a,77394)|0;return}function wd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0;e=l;l=l+16|0;d=e;if(b|0?(g=(c[a+16>>2]|0)+272|0,c[g>>2]|0):0){nr(a,61847)|0;xr(a,c[g>>2]|0,2);nr(a,61858)|0;c[d>>2]=iy(b,c[41906]|0)|0;tr(a,61862,d)}l=e;return}function xd(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0,j=0,k=0,m=0,n=0;m=l;l=l+32|0;j=m+8|0;k=m;f=c[b+16>>2]|0;if(!(+h[f+40>>3]<.5)){Ed(b,f+16|0);i=e+4|0;ur(b,+h[(c[i>>2]|0)+16>>3]);c[j>>2]=c[c[i>>2]>>2];tr(b,61806,j);i=iy(c[e>>2]|0,c[41906]|0)|0;switch(a[e+48>>0]|0){case 114:{n=e+32|0;f=n;g=+h[n>>3];break}case 108:{f=e+32|0;g=0.0;break}default:{n=e+32|0;f=n;g=+h[n>>3]*.5}}h[d>>3]=+h[d>>3]-g;n=d+8|0;h[n>>3]=+h[n>>3]+ +h[e+24>>3];c[j>>2]=c[d>>2];c[j+4>>2]=c[d+4>>2];c[j+8>>2]=c[d+8>>2];c[j+12>>2]=c[d+12>>2];wr(b,j);nr(b,61821)|0;ur(b,+h[f>>3]);c[k>>2]=i;tr(b,61830,k)}l=m;return}function yd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;g=l;l=l+32|0;f=g;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];h[f+16>>3]=+h[b+16>>3]-+h[b>>3];h[f+24>>3]=+h[b+24>>3]-+h[b+8>>3];b=a+16|0;if(d|0?(e=c[b>>2]|0,+h[e+80>>3]>.5):0){Ed(a,e+56|0);xr(a,f,2);nr(a,61764)|0}if(+h[(c[b>>2]|0)+40>>3]>.5){Fd(a);Ed(a,(c[b>>2]|0)+16|0);xr(a,f,2);nr(a,61784)|0}l=g;return}function zd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0;j=l;l=l+16|0;i=j;g=a+16|0;if(e|0?(f=c[g>>2]|0,+h[f+80>>3]>.5):0){Ed(a,f+56|0);nr(a,61685)|0;c[i>>2]=c[b>>2];c[i+4>>2]=c[b+4>>2];c[i+8>>2]=c[b+8>>2];c[i+12>>2]=c[b+12>>2];wr(a,i);nr(a,61694)|0;e=1;while(1){if((e|0)>=(d|0))break;f=b+(e<<4)|0;c[i>>2]=c[f>>2];c[i+4>>2]=c[f+4>>2];c[i+8>>2]=c[f+8>>2];c[i+12>>2]=c[f+12>>2];wr(a,i);nr(a,61703)|0;e=e+1|0}nr(a,61730)|0}if(+h[(c[g>>2]|0)+40>>3]>.5){Fd(a);Ed(a,(c[g>>2]|0)+16|0);nr(a,61685)|0;c[i>>2]=c[b>>2];c[i+4>>2]=c[b+4>>2];c[i+8>>2]=c[b+8>>2];c[i+12>>2]=c[b+12>>2];wr(a,i);nr(a,61694)|0;e=1;while(1){if((e|0)>=(d|0))break;g=b+(e<<4)|0;c[i>>2]=c[g>>2];c[i+4>>2]=c[g+4>>2];c[i+8>>2]=c[g+8>>2];c[i+12>>2]=c[g+12>>2];wr(a,i);nr(a,61703)|0;e=e+1|0}nr(a,61746)|0}l=j;return}function Ad(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0;k=l;l=l+16|0;f=k;i=a+16|0;if(g|0?(j=c[i>>2]|0,+h[j+80>>3]>.5):0){Ed(a,j+56|0);nr(a,61685)|0;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];wr(a,f);nr(a,61694)|0;e=1;while(1){if((e|0)>=(d|0))break;xr(a,b+(e<<4)|0,3);nr(a,61720)|0;e=e+3|0}nr(a,61730)|0}if(+h[(c[i>>2]|0)+40>>3]>.5){Fd(a);Ed(a,(c[i>>2]|0)+16|0);nr(a,61685)|0;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];wr(a,f);nr(a,61694)|0;e=1;while(1){if((e|0)>=(d|0))break;xr(a,b+(e<<4)|0,3);nr(a,61720)|0;e=e+3|0}nr(a,61712)|0}l=k;return}function Bd(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0;g=l;l=l+16|0;f=g;e=a+16|0;if(+h[(c[e>>2]|0)+40>>3]>.5){Fd(a);Ed(a,(c[e>>2]|0)+16|0);nr(a,61685)|0;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];wr(a,f);nr(a,61694)|0;e=1;while(1){if((e|0)>=(d|0))break;i=b+(e<<4)|0;c[f>>2]=c[i>>2];c[f+4>>2]=c[i+4>>2];c[f+8>>2]=c[i+8>>2];c[f+12>>2]=c[i+12>>2];wr(a,f);nr(a,61703)|0;e=e+1|0}nr(a,61712)|0}l=g;return}function Cd(a,b){a=a|0;b=b|0;nr(a,61682)|0;nr(a,b)|0;nr(a,134901)|0;return}function Dd(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+32|0;g=n+16|0;m=n+8|0;k=n;i=a+16|0;if(f|0?(j=c[i>>2]|0,+h[j+80>>3]>.5):0){Ed(a,j+56|0);nr(a,77289)|0;xr(a,d,e);nr(a,87638)|0;c[g>>2]=c[d>>2];c[g+4>>2]=c[d+4>>2];c[g+8>>2]=c[d+8>>2];c[g+12>>2]=c[d+12>>2];wr(a,g);c[k>>2]=e;c[k+4>>2]=b;tr(a,61599,k)}if(+h[(c[i>>2]|0)+40>>3]>.5){Fd(a);Ed(a,(c[i>>2]|0)+16|0);nr(a,77289)|0;xr(a,d,e);nr(a,87638)|0;c[g>>2]=c[d>>2];c[g+4>>2]=c[d+4>>2];c[g+8>>2]=c[d+8>>2];c[g+12>>2]=c[d+12>>2];wr(a,g);c[m>>2]=e;c[m+4>>2]=b;tr(a,61615,m)}l=n;return}function Ed(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0.0,i=0.0;f=l;l=l+32|0;e=f;if(b|0){switch(c[(c[a+16>>2]|0)+4>>2]|0){case 1:case 0:{d=96286;break}case 2:{d=96273;break}case 3:{d=96237;break}default:d=61651}i=+h[b+8>>3];g=+h[b+16>>3];h[e>>3]=+h[b>>3];h[e+8>>3]=i;h[e+16>>3]=g;c[e+24>>2]=d;tr(a,61658,e)}l=f;return}function Fd(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0;m=l;l=l+16|0;k=m+8|0;j=m;g=b+16|0;i=c[g>>2]|0;d=c[i+160>>2]|0;ur(b,+h[i+152>>3]);nr(b,61632)|0;while(1){if(!d)break;i=d+4|0;f=c[d>>2]|0;if(!f)break;if(!(yJ(f,95910)|0)){d=i;continue}else e=f;while(1){d=e+1|0;if(!(a[e>>0]|0))break;else e=d}a:while(1){if(!(a[d>>0]|0))break;c[j>>2]=d;tr(b,61647,j);while(1){e=d+1|0;if(!(a[d>>0]|0)){d=e;continue a}else d=e}}if(!(yJ(f,119127)|0))h[(c[g>>2]|0)+152>>3]=0.0;c[k>>2]=f;tr(b,81633,k);d=i}l=m;return}function Gd(b){b=b|0;var d=0;nr(b,67671)|0;d=Jm(c[(c[b>>2]|0)+168>>2]|0,67727)|0;if(d|0?a[d>>0]|0:0){nr(b,67738)|0;nr(b,d)|0;nr(b,67762)|0}nr(b,67783)|0;nr(b,67831)|0;nr(b,67885)|0;d=b+12|0;nr(b,sw(c[c[c[d>>2]>>2]>>2]|0)|0)|0;nr(b,71014)|0;nr(b,sw(c[(c[c[d>>2]>>2]|0)+4>>2]|0)|0)|0;nr(b,71024)|0;nr(b,sw(c[(c[c[d>>2]>>2]|0)+8>>2]|0)|0)|0;nr(b,68267)|0;nr(b,68291)|0;return}function Hd(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0.0,k=0.0,m=0.0;i=l;l=l+48|0;g=i+16|0;f=i+8|0;e=i;d=c[b+16>>2]|0;nr(b,67506)|0;d=d+8|0;if(a[(En(c[d>>2]|0)|0)>>0]|0){nr(b,68230)|0;nr(b,sw(En(c[d>>2]|0)|0)|0)|0}c[e>>2]=O(c[b+168>>2]|0,c[b+164>>2]|0)|0;tr(b,67511,e);e=c[b+452>>2]|0;c[f>>2]=c[b+448>>2];c[f+4>>2]=e;tr(b,67527,f);m=+h[b+392>>3];k=+h[b+400>>3];j=+h[b+408>>3];h[g>>3]=+h[b+384>>3];h[g+8>>3]=m;h[g+16>>3]=k;h[g+24>>3]=j;tr(b,67560,g);nr(b,67591)|0;nr(b,67627)|0;nr(b,69221)|0;l=i;return}function Id(a){a=a|0;nr(a,67498)|0;return}function Jd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;ee(a,b,0,86583,c[(c[a+16>>2]|0)+8>>2]|0);nr(a,69221)|0;return}function Kd(a){a=a|0;nr(a,67346)|0;return}function Ld(b){b=b|0;var d=0,e=0,f=0,g=0;e=l;l=l+16|0;f=e;g=c[b+16>>2]|0;d=g+8|0;ee(b,c[g+212>>2]|0,0,96286,c[d>>2]|0);nr(b,67450)|0;ur(b,+h[b+488>>3]);nr(b,87638)|0;ur(b,+h[b+496>>3]);c[f>>2]=0-(c[b+360>>2]|0);tr(b,67469,f);ur(b,+h[b+504>>3]);nr(b,87638)|0;ur(b,-+h[b+512>>3]);nr(b,67493)|0;if(a[(En(c[d>>2]|0)|0)>>0]|0){nr(b,67402)|0;nr(b,sw(En(c[d>>2]|0)|0)|0)|0;nr(b,67410)|0}l=e;return}function Md(a){a=a|0;nr(a,67346)|0;return}function Nd(a){a=a|0;var b=0,d=0;d=c[a+16>>2]|0;b=d+8|0;ee(a,c[d+212>>2]|0,0,93039,c[b>>2]|0);nr(a,69221)|0;nr(a,67402)|0;nr(a,sw(En(c[b>>2]|0)|0)|0)|0;nr(a,67410)|0;return}function Od(a){a=a|0;nr(a,67346)|0;return}function Pd(a){a=a|0;var b=0,d=0,e=0;d=c[a+16>>2]|0;b=c[a+160>>2]|0;if((b|0)>1)b=c[(c[(c[a>>2]|0)+308>>2]|0)+(b<<2)>>2]|0;else b=0;e=d+8|0;ee(a,c[d+212>>2]|0,b,96273,c[e>>2]|0);nr(a,69221)|0;nr(a,67402)|0;nr(a,sw(En(c[e>>2]|0)|0)|0)|0;nr(a,67410)|0;return}function Qd(a){a=a|0;nr(a,67346)|0;return}function Rd(a){a=a|0;var b=0,d=0;d=c[a+16>>2]|0;b=d+8|0;ee(a,c[d+212>>2]|0,0,96237,c[b>>2]|0);nr(a,69221)|0;nr(a,67402)|0;b=rw(87129,c[b>>2]|0)|0;nr(a,sw(b)|0)|0;$I(b);nr(a,67410)|0;return}function Sd(a){a=a|0;nr(a,67346)|0;return}function Td(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;nr(b,67352)|0;if(f|0){nr(b,67355)|0;nr(b,sw(f)|0)|0;nr(b,83714)|0}nr(b,67245)|0;nr(b,69182)|0;if(c|0?a[c>>0]|0:0){nr(b,67363)|0;nr(b,c)|0;nr(b,83714)|0}if(d|0?a[d>>0]|0:0){nr(b,67377)|0;nr(b,tw(d,1)|0)|0;nr(b,83714)|0}if(e|0?a[e>>0]|0:0){nr(b,67392)|0;nr(b,sw(e)|0)|0;nr(b,83714)|0}nr(b,69221)|0;return}function Ud(a){a=a|0;nr(a,69176)|0;nr(a,67346)|0;return}function Vd(e,f,g){e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0.0,H=0,I=0,J=0,K=0,L=0,M=0;M=l;l=l+176|0;L=M+160|0;K=M+152|0;F=M+136|0;J=M+128|0;E=M+120|0;D=M+112|0;C=M+104|0;B=M+96|0;A=M+88|0;y=M+80|0;w=M+72|0;v=M+64|0;u=M+56|0;t=M+48|0;i=M+40|0;q=M+32|0;s=M+24|0;r=M+16|0;p=M+8|0;o=M;I=c[e+16>>2]|0;nr(e,66877)|0;switch(a[g+48>>0]|0){case 108:{nr(e,66883)|0;break}case 114:{nr(e,66904)|0;break}default:nr(e,66923)|0}H=f+8|0;G=+h[H>>3]+ +h[g+24>>3];h[H>>3]=G;H=I+260|0;if(!(b[H>>1]&512)){nr(e,66945)|0;ur(e,+h[f>>3]);nr(e,66950)|0;ur(e,-G);nr(e,83714)|0}x=g+4|0;f=c[x>>2]|0;n=c[f+8>>2]|0;if(n){switch(c[(c[(c[(c[e>>2]|0)+168>>2]|0)+16>>2]|0)+244>>2]|0){case 1:{m=n;f=n+16|0;i=n+8|0;break}case 2:{m=n+24|0;f=n+32|0;i=n+28|0;break}default:{m=n+4|0;f=n+16|0;i=n+8|0}}j=c[f>>2]|0;f=c[i>>2]|0;k=c[n+12>>2]|0;c[o>>2]=c[m>>2];tr(e,66956,o);i=c[n+24>>2]|0;if(i|0){c[p>>2]=i;tr(e,66973,p)}nr(e,83714)|0;if(f|0){c[r>>2]=f;tr(e,66977,r)}if(k|0){c[s>>2]=k;tr(e,66995,s)}if(!j)j=0;else{c[q>>2]=j;tr(e,67014,q)}}else{c[i>>2]=c[f>>2];tr(e,67031,i);j=0;f=0}i=c[x>>2]|0;if(i|0?(z=c[i+24>>2]|0,z&127|0):0){if(!((f|0)!=0|(z&1|0)==0))tr(e,67049,t);if(!((j|0)!=0|(z&2|0)==0))tr(e,67069,u);if(z&100|0){tr(e,67090,v);if(!(z&4))f=0;else{tr(e,91030,w);f=1}if(z&64){c[y>>2]=f|0?86030:174185;tr(e,67109,y);f=1}if(z&32|0){c[A>>2]=f|0?86030:174185;tr(e,67120,A)}tr(e,83714,B)}if(z&8|0)tr(e,67135,C);if(z&16|0)tr(e,67159,D)}h[E>>3]=+h[(c[x>>2]|0)+16>>3];tr(e,67181,E);f=I+16|0;switch(c[I+48>>2]|0){case 5:{f=c[f>>2]|0;if(jK(f,122106)|0){c[J>>2]=f;tr(e,67199,J)}break}case 1:{E=d[f+1>>0]|0;J=d[f+2>>0]|0;c[F>>2]=d[f>>0];c[F+4>>2]=E;c[F+8>>2]=J;tr(e,67210,F);break}default:ma(123205,66391,486,67232)}nr(e,67245)|0;if(b[H>>1]&512){c[K>>2]=sw(c[I+212>>2]|0)|0;tr(e,67247,K);nr(e,67296)|0;ur(e,-G);nr(e,67314)|0}nr(e,tw(c[g>>2]|0,1)|0)|0;if(b[H>>1]&512)tr(e,67317,L);nr(e,67337)|0;l=M;return}function Wd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;switch(c|0){case 2:{d=be(a,b,2)|0;break}case 3:{d=ce(a)|0;break}default:d=0}nr(a,66841)|0;$d(a,c,d);nr(a,66850)|0;ur(a,+h[b>>3]);nr(a,66856)|0;c=b+8|0;ur(a,-+h[c>>3]);nr(a,66863)|0;ur(a,+h[b+16>>3]-+h[b>>3]);nr(a,66870)|0;ur(a,+h[b+24>>3]-+h[c>>3]);nr(a,66257)|0;return}function Xd(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;switch(d|0){case 2:{e=be(a,b,c)|0;break}case 3:{e=ce(a)|0;break}default:e=0}nr(a,66832)|0;$d(a,d,e);nr(a,66247)|0;e=0;while(1){if((e|0)>=(c|0))break;ur(a,+h[b+(e<<4)>>3]);nr(a,86030)|0;ur(a,-+h[b+(e<<4)+8>>3]);nr(a,87638)|0;e=e+1|0}ur(a,+h[b>>3]);nr(a,86030)|0;ur(a,-+h[b+8>>3]);nr(a,66257)|0;return}function Yd(a,d,e,f,g,h){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;g=c[a+16>>2]|0;switch(h|0){case 2:{f=be(a,d,e)|0;break}case 3:{f=ce(a)|0;break}default:f=0}nr(a,66427)|0;if(b[g+260>>1]&512){nr(a,66433)|0;nr(a,sw(c[g+212>>2]|0)|0)|0;nr(a,66439)|0}$d(a,h,f);nr(a,66444)|0;de(a,d,e);nr(a,66257)|0;return}function Zd(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;nr(a,66237)|0;$d(a,0,0);nr(a,66247)|0;d=0;while(1){if((d|0)>=(c|0))break;ur(a,+h[b+(d<<4)>>3]);nr(a,86030)|0;ur(a,-+h[b+(d<<4)+8>>3]);nr(a,87638)|0;d=d+1|0}nr(a,66257)|0;return}function _d(a,b){a=a|0;b=b|0;nr(a,66231)|0;nr(a,sw(b)|0)|0;nr(a,68291)|0;return}function $d(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;q=l;l=l+96|0;k=q+48|0;p=q+40|0;n=q+32|0;o=q+24|0;j=q+16|0;g=q+8|0;f=q;m=c[b+16>>2]|0;nr(b,66262)|0;a:do switch(d|0){case 2:{c[f>>2]=e;tr(b,66270,f);break}case 3:{c[g>>2]=e;tr(b,66281,g);break}case 0:{nr(b,120501)|0;break}default:{d=m+56|0;f=k;g=d;i=f+40|0;do{c[f>>2]=c[g>>2];f=f+4|0;g=g+4|0}while((f|0)<(i|0));ae(b,k);if((c[m+88>>2]|0)==1){d=a[d+3>>0]|0;switch(d<<24>>24){case -1:case 0:break a;default:{}}h[j>>3]=+(d&255)*.00392156862745098;tr(b,66292,j)}}}while(0);nr(b,66311)|0;e=m+16|0;f=k;g=e;i=f+40|0;do{c[f>>2]=c[g>>2];f=f+4|0;g=g+4|0}while((f|0)<(i|0));ae(b,k);d=m+152|0;if(+h[d>>3]!=1.0){nr(b,66322)|0;ur(b,+h[d>>3])}switch(c[m+144>>2]|0){case 1:{c[o>>2]=66362;tr(b,66339,o);break}case 2:{c[n>>2]=66366;tr(b,66339,n);break}default:{}}b:do if((c[m+48>>2]|0)==1){d=a[e+3>>0]|0;switch(d<<24>>24){case -1:case 0:break b;default:{}}h[p>>3]=+(d&255)*.00392156862745098;tr(b,66370,p)}while(0);nr(b,83714)|0;l=q;return}function ae(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0;g=l;l=l+16|0;f=g;a:do switch(c[e+32>>2]|0){case 5:{nr(b,c[e>>2]|0)|0;break}case 1:if(!(a[e+3>>0]|0)){nr(b,122171)|0;break a}else{i=d[e+1>>0]|0;h=d[e+2>>0]|0;c[f>>2]=d[e>>0];c[f+4>>2]=i;c[f+8>>2]=h;tr(b,68547,f);break a}default:ma(123205,66391,117,66411)}while(0);l=g;return}function be(b,d,e){b=b|0;d=d|0;e=e|0;var f=0.0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=l;l=l+112|0;o=t+64|0;r=t+56|0;n=t+48|0;m=t+40|0;i=t+32|0;k=t;q=c[41908]|0;c[41908]=q+1;p=c[b+16>>2]|0;f=+(c[p+136>>2]|0)*.017453292519943295;c[k>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;c[k+16>>2]=0;c[k+20>>2]=0;c[k+24>>2]=0;c[k+28>>2]=0;KB(d,k,e,f,0);c[o>>2]=q;tr(b,66664,o);nr(b,66729)|0;ur(b,+h[k>>3]);nr(b,66734)|0;ur(b,+h[k+8>>3]);nr(b,66741)|0;ur(b,+h[k+16>>3]);nr(b,66748)|0;ur(b,+h[k+24>>3]);nr(b,66755)|0;k=p+140|0;f=+g[k>>2];if(f>0.0){h[i>>3]=f+-.001;tr(b,66760,i)}else nr(b,66536)|0;d=p+56|0;e=o;i=d;j=e+40|0;do{c[e>>2]=c[i>>2];e=e+4|0;i=i+4|0}while((e|0)<(j|0));ae(b,o);nr(b,66572)|0;a:do if((c[p+88>>2]|0)==1){d=a[d+3>>0]|0;switch(d<<24>>24){case -1:case 0:{s=7;break a}default:{}}h[m>>3]=+(d&255)*.00392156862745098;tr(b,84631,m)}else s=7;while(0);if((s|0)==7)nr(b,66587)|0;nr(b,66590)|0;f=+g[k>>2];if(f>0.0){h[n>>3]=f;tr(b,66760,n)}else nr(b,66596)|0;d=p+96|0;e=o;i=d;j=e+40|0;do{c[e>>2]=c[i>>2];e=e+4|0;i=i+4|0}while((e|0)<(j|0));ae(b,o);nr(b,66572)|0;b:do if((c[p+128>>2]|0)==1){d=a[d+3>>0]|0;switch(d<<24>>24){case -1:case 0:{s=14;break b}default:{}}h[r>>3]=+(d&255)*.00392156862745098;tr(b,84631,r)}else s=14;while(0);if((s|0)==14)nr(b,66587)|0;nr(b,66800)|0;l=t;return q|0}function ce(b){b=b|0;var d=0,e=0.0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0;q=l;l=l+64|0;k=q+16|0;o=q+8|0;j=q;n=c[41907]|0;c[41907]=n+1;m=c[b+16>>2]|0;r=+(c[m+136>>2]|0)*.017453292519943295;e=r;if(r==0.0){f=50;d=50}else{f=~~((+E(+e)+1.0)*50.0);d=~~((1.0-+F(+e))*50.0)}c[k>>2]=n;c[k+4>>2]=f;c[k+8>>2]=d;tr(b,66452,k);nr(b,66536)|0;d=m+56|0;f=k;g=d;i=f+40|0;do{c[f>>2]=c[g>>2];f=f+4|0;g=g+4|0}while((f|0)<(i|0));ae(b,k);nr(b,66572)|0;a:do if((c[m+88>>2]|0)==1){d=a[d+3>>0]|0;switch(d<<24>>24){case -1:case 0:{p=6;break a}default:{}}h[j>>3]=+(d&255)*.00392156862745098;tr(b,84631,j)}else p=6;while(0);if((p|0)==6)nr(b,66587)|0;nr(b,66590)|0;nr(b,66596)|0;d=m+96|0;f=k;g=d;i=f+40|0;do{c[f>>2]=c[g>>2];f=f+4|0;g=g+4|0}while((f|0)<(i|0));ae(b,k);nr(b,66572)|0;b:do if((c[m+128>>2]|0)==1){d=a[d+3>>0]|0;switch(d<<24>>24){case -1:case 0:{p=10;break b}default:{}}h[o>>3]=+(d&255)*.00392156862745098;tr(b,84631,o)}else p=10;while(0);if((p|0)==10)nr(b,66587)|0;nr(b,66632)|0;l=q;return n|0}function de(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0;i=l;l=l+16|0;g=i;e=77;f=0;while(1){if((f|0)>=(d|0))break;c[g>>2]=e;tr(a,66449,g);ur(a,+h[b+(f<<4)>>3]);nr(a,86030)|0;ur(a,-+h[b+(f<<4)+8>>3]);e=(f|0)==0?67:32;f=f+1|0}l=i;return}function ee(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0;j=l;l=l+16|0;i=j+8|0;h=j;nr(b,67420)|0;nr(b,sw(d)|0)|0;if(e|0){c[h>>2]=sw(e)|0;tr(b,67428,h)}c[i>>2]=f;tr(b,67432,i);d=Jm(g,67444)|0;if(d|0?a[d>>0]|0:0){nr(b,87638)|0;nr(b,sw(d)|0)|0}nr(b,83714)|0;l=j;return}function fe(a){a=a|0;var b=0;nr(a,68251)|0;b=a+12|0;nr(a,pe(c[c[c[b>>2]>>2]>>2]|0)|0)|0;nr(a,71014)|0;nr(a,pe(c[(c[c[b>>2]>>2]|0)+4>>2]|0)|0)|0;nr(a,71024)|0;nr(a,pe(c[(c[c[b>>2]>>2]|0)+8>>2]|0)|0)|0;nr(a,68267)|0;return}function ge(b){b=b|0;var d=0,e=0,f=0;f=l;l=l+16|0;e=f;d=c[b+16>>2]|0;nr(b,68228)|0;d=d+8|0;if(a[(En(c[d>>2]|0)|0)>>0]|0){nr(b,68230)|0;nr(b,pe(En(c[d>>2]|0)|0)|0)|0}c[e>>2]=O(c[b+168>>2]|0,c[b+164>>2]|0)|0;tr(b,68239,e);c[41909]=0;l=f;return}function he(a){a=a|0;c[41909]=1;return}function ie(a){a=a|0;c[41909]=-1;return}function je(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+48|0;i=n+8|0;m=n;f=c[b+16>>2]|0;if(c[f+144>>2]|0?(k=e+4|0,j=~~(+h[b+352>>3]*+h[(c[k>>2]|0)+16>>3]),j|0):0){qe(b);nr(b,68167)|0;g=d+8|0;h[g>>3]=+h[g>>3]-+(j|0)*.55;c[i>>2]=c[d>>2];c[i+4>>2]=c[d+4>>2];c[i+8>>2]=c[d+8>>2];c[i+12>>2]=c[d+12>>2];wr(b,i);nr(b,68181)|0;nr(b,c[e>>2]|0)|0;nr(b,68190)|0;nr(b,67988)|0;g=i;d=f+16|0;f=g+40|0;do{c[g>>2]=c[d>>2];g=g+4|0;d=d+4|0}while((g|0)<(f|0));re(b,i);nr(b,68192)|0;i=c[k>>2]|0;k=c[i+8>>2]|0;k=c[((k|0)==0?i:k+4|0)>>2]|0;nr(b,83714)|0;nr(b,k)|0;nr(b,83714)|0;c[m>>2]=j;tr(b,68201,m);switch(a[e+48>>0]|0){case 108:{nr(b,68206)|0;break}case 114:{nr(b,68217)|0;break}default:{}}se(b);nr(b,134901)|0}l=n;return}function ke(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0.0,m=0.0,n=0.0;j=l;l=l+48|0;f=j;g=c[a+16>>2]|0;i=g+144|0;if(c[i>>2]|0){n=+h[b>>3];m=+h[b+24>>3];e=b+8|0;k=+h[e>>3];h[b>>3]=n-+h[b+16>>3]+n;h[e>>3]=k-m+k;qe(a);nr(a,68153)|0;xr(a,b,2);nr(a,67988)|0;do if(!d)if(!(c[41909]|0)){nr(a,82272)|0;break}else{nr(a,121990)|0;break}else{b=f;d=g+56|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));re(a,f)}while(0);if((c[41909]|0)==1)c[41909]=0;nr(a,68099)|0;ur(a,+h[g+152>>3]);nr(a,68142)|0;b=f;d=g+16|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));re(a,f);b=c[i>>2]|0;if((b|0)==1){nr(a,67996)|0;b=c[i>>2]|0}if((b|0)==2)nr(a,68005)|0;se(a);nr(a,134901)|0}l=j;return}function le(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0;j=l;l=l+48|0;f=j;g=c[a+16>>2]|0;i=g+144|0;if(c[i>>2]|0){qe(a);nr(a,68125)|0;xr(a,b,d);nr(a,67988)|0;do if(!e)if(!(c[41909]|0)){nr(a,82272)|0;break}else{nr(a,121990)|0;break}else{b=f;d=g+56|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));re(a,f)}while(0);if((c[41909]|0)==1)c[41909]=0;nr(a,68099)|0;ur(a,+h[g+152>>3]);nr(a,68142)|0;b=f;d=g+16|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));re(a,f);b=c[i>>2]|0;if((b|0)==1){nr(a,67996)|0;b=c[i>>2]|0}if((b|0)==2)nr(a,68005)|0;se(a);nr(a,134901)|0}l=j;return}function me(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0;m=l;l=l+48|0;i=m;j=c[a+16>>2]|0;k=j+144|0;if(c[k>>2]|0){qe(a);nr(a,67974)|0;xr(a,b,d);nr(a,67988)|0;e=i;f=j+16|0;g=e+40|0;do{c[e>>2]=c[f>>2];e=e+4|0;f=f+4|0}while((e|0)<(g|0));re(a,i);nr(a,68099)|0;ur(a,+h[j+152>>3]);e=c[k>>2]|0;if((e|0)==1){nr(a,67996)|0;e=c[k>>2]|0}if((e|0)==2)nr(a,68005)|0;nr(a,68108)|0;se(a);nr(a,134901)|0}l=m;return}function ne(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=l;l=l+48|0;g=i;e=c[a+16>>2]|0;h=e+144|0;if(c[h>>2]|0){qe(a);nr(a,67974)|0;xr(a,b,d);nr(a,67988)|0;f=g;b=e+16|0;d=f+40|0;do{c[f>>2]=c[b>>2];f=f+4|0;b=b+4|0}while((f|0)<(d|0));re(a,g);b=c[h>>2]|0;if((b|0)==1){nr(a,67996)|0;b=c[h>>2]|0}if((b|0)==2)nr(a,68005)|0;se(a);nr(a,134901)|0}l=i;return}function oe(a,b){a=a|0;b=b|0;nr(a,67971)|0;nr(a,pe(b)|0)|0;nr(a,134901)|0;return}function pe(a){a=a|0;return a|0}function qe(b){b=b|0;if(!(a[b+144>>0]|0))nr(b,68096)|0;else nr(b,c[b+148>>2]|0)|0;return}function re(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0;g=l;l=l+16|0;f=g;a:do switch(c[e+32>>2]|0){case 5:{nr(b,c[e>>2]|0)|0;break}case 1:if(!(a[e+3>>0]|0)){nr(b,82272)|0;break a}else{i=d[e+1>>0]|0;h=d[e+2>>0]|0;c[f>>2]=d[e>>0];c[f+4>>2]=i;c[f+8>>2]=h;tr(b,68547,f);break a}default:ma(123205,68014,49,68078)}while(0);l=g;return}function se(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;g=h;f=c[a+16>>2]|0;switch(c[f+12>>2]|0){case 8:{b=1;d=96273;e=f+8|0;break}case 10:{b=0;d=96273;e=f+8|0;break}case 3:case 2:case 9:{b=1;d=96237;e=f+8|0;break}case 7:case 6:case 11:{b=0;d=96237;e=f+8|0;break}case 0:{b=1;d=96286;e=f+8|0;break}case 4:{b=0;d=68050;e=f+8|0;break}case 1:{b=1;d=96286;e=f+8|0;break}case 5:{b=0;d=96286;e=f+8|0;break}default:ma(123205,68014,106,68033)}f=c[(c[e>>2]|0)+8>>2]|0;c[g>>2]=b;c[g+4>>2]=d;c[g+8>>2]=f;tr(a,68062,g);l=h;return}function te(a){a=a|0;var b=0;nr(a,70986)|0;nr(a,70994)|0;b=a+12|0;nr(a,Ee(c[c[c[b>>2]>>2]>>2]|0)|0)|0;nr(a,71014)|0;nr(a,Ee(c[(c[c[b>>2]>>2]|0)+4>>2]|0)|0)|0;nr(a,71024)|0;nr(a,Ee(c[(c[c[b>>2]>>2]|0)+8>>2]|0)|0)|0;nr(a,71027)|0;return}function ue(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0;j=l;l=l+32|0;i=j+24|0;g=j+16|0;f=j+8|0;e=j;d=c[b+16>>2]|0;c[41913]=~~(+h[b+232>>3]-+h[b+216>>3]);c[41912]=~~(+h[b+224>>3]-+h[b+208>>3]);nr(b,69673)|0;nr(b,69680)|0;d=En(c[d+8>>2]|0)|0;if(a[d>>0]|0){nr(b,69749)|0;nr(b,Ee(d)|0)|0;nr(b,69757)|0}c[e>>2]=O(c[b+168>>2]|0,c[b+164>>2]|0)|0;tr(b,69766,e);nr(b,69786)|0;nr(b,69821)|0;nr(b,69849)|0;nr(b,69855)|0;nr(b,69898)|0;nr(b,69939)|0;nr(b,69958)|0;nr(b,69975)|0;nr(b,70023)|0;nr(b,70076)|0;nr(b,70152)|0;nr(b,70228)|0;nr(b,70237)|0;nr(b,70260)|0;nr(b,70287)|0;nr(b,70340)|0;nr(b,70362)|0;nr(b,70407)|0;nr(b,70419)|0;nr(b,70429)|0;nr(b,70455)|0;nr(b,70340)|0;nr(b,70507)|0;nr(b,70407)|0;nr(b,70419)|0;nr(b,70551)|0;nr(b,70260)|0;nr(b,70287)|0;nr(b,70340)|0;nr(b,70507)|0;nr(b,70407)|0;nr(b,70419)|0;nr(b,70429)|0;nr(b,70455)|0;nr(b,70340)|0;nr(b,70362)|0;nr(b,70407)|0;nr(b,70419)|0;nr(b,70564)|0;nr(b,70572)|0;nr(b,70578)|0;nr(b,70592)|0;nr(b,70600)|0;nr(b,70633)|0;e=(c[41913]|0)+10|0;c[f>>2]=c[41912];c[f+4>>2]=e;tr(b,70710,f);nr(b,70740)|0;nr(b,70749)|0;nr(b,70807)|0;nr(b,70817)|0;nr(b,70882)|0;f=c[41913]|0;c[g>>2]=c[41912];c[g+4>>2]=f;tr(b,70919,g);g=c[41913]|0;c[i>>2]=c[41912];c[i+4>>2]=g;tr(b,70947,i);l=j;return}function ve(a){a=a|0;nr(a,69224)|0;nr(a,69236)|0;nr(a,69244)|0;nr(a,69307)|0;nr(a,69236)|0;nr(a,69352)|0;nr(a,69401)|0;nr(a,69455)|0;nr(a,69236)|0;nr(a,69555)|0;nr(a,69604)|0;nr(a,69236)|0;nr(a,69656)|0;return}function we(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0;j=l;l=l+32|0;i=j+16|0;h=j+8|0;g=j;nr(b,69182)|0;if(d|0?a[d>>0]|0:0){c[g>>2]=Ee(d)|0;tr(b,69185,g)}if(e|0?a[e>>0]|0:0){c[h>>2]=Ee(e)|0;tr(b,69196,h)}if(f|0?a[f>>0]|0:0){c[i>>2]=Ee(f)|0;tr(b,69208,i)}nr(b,69221)|0;l=j;return}function xe(a){a=a|0;nr(a,69176)|0;return}function ye(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,i=0.0,j=0.0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0;A=l;l=l+112|0;y=A+96|0;z=A+88|0;w=A+80|0;q=A+72|0;v=A+64|0;t=A+56|0;s=A+48|0;r=A+40|0;p=A+24|0;o=A+8|0;n=A;x=c[b+16>>2]|0;switch(a[f+48>>0]|0){case 108:{j=+h[e>>3];m=+h[f+32>>3];break}case 114:{m=+h[f+32>>3];j=+h[e>>3]-m;break}default:{m=+h[f+32>>3];j=+h[e>>3]-m*.5}}g=f+40|0;i=+h[g>>3];u=f+4|0;k=+h[(c[u>>2]|0)+16>>3];if(i>3]=i}B=j+-8.0;k=+((c[41913]|0)>>>0)-+h[e+8>>3]-i+k*.2+(k<12.0?1.4:2.0);tr(b,68838,n);h[o>>3]=B;h[o+8>>3]=k;tr(b,68775,o);h[p>>3]=j+8.0+m-B;h[p+8>>3]=i;tr(b,68799,p);nr(b,68873)|0;nr(b,68907)|0;g=c[u>>2]|0;e=c[g+8>>2]|0;if(e){c[r>>2]=c[e+4>>2];tr(b,68997,r);g=c[e+8>>2]|0;if(g|0){c[s>>2]=g;tr(b,69016,s)}g=c[e+12>>2]|0;if(g|0){c[t>>2]=g;tr(b,69033,t)}g=c[e+16>>2]|0;if(g|0){c[v>>2]=g;tr(b,69051,v)}}else{c[q>>2]=c[g>>2];tr(b,68997,q)}h[w>>3]=+h[(c[u>>2]|0)+16>>3];tr(b,69067,w);g=x+16|0;switch(c[x+48>>2]|0){case 5:{g=c[g>>2]|0;if(jK(g,122106)|0){c[z>>2]=g;tr(b,69087,z)}break}case 1:{x=d[g+1>>0]|0;z=d[g+2>>0]|0;c[y>>2]=d[g>>0];c[y+4>>2]=x;c[y+8>>2]=z;tr(b,69097,y);break}default:ma(123205,68561,438,69118)}nr(b,69131)|0;nr(b,Ee(c[f>>2]|0)|0)|0;nr(b,69142)|0;nr(b,69165)|0;l=A;return}function ze(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0,k=0.0,m=0.0;e=l;l=l+32|0;f=e+16|0;j=e;nr(a,68739)|0;m=+h[b>>3];i=+h[b+16>>3]-m;k=+h[b+24>>3];g=k-+h[b+8>>3];k=+((c[41913]|0)>>>0)-k;h[j>>3]=m-i;h[j+8>>3]=k;tr(a,68775,j);h[f>>3]=i*2.0;h[f+8>>3]=g*2.0;tr(a,68799,f);Ie(a,d);nr(a,68621)|0;Ge(a);nr(a,68827)|0;l=e;return}function Ae(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0,i=0.0,j=0,k=0,m=0,n=0;m=l;l=l+48|0;k=m+24|0;j=m+8|0;g=m;nr(a,68344)|0;n=c[41913]|0;c[g>>2]=c[41912];c[g+4>>2]=n;tr(a,68597,g);Ie(a,e);nr(a,68621)|0;Ge(a);nr(a,68624)|0;g=d+-1|0;e=0;while(1){if((e|0)>=(d|0))break;i=+h[b+(e<<4)>>3];f=+((c[41913]|0)>>>0)-+h[b+(e<<4)+8>>3];if(!e){nr(a,68651)|0;h[j>>3]=i;h[j+8>>3]=f;tr(a,68717,j);nr(a,68728)|0}else{h[k>>3]=i;h[k+8>>3]=f;tr(a,68717,k)}if((e|0)==(g|0))nr(a,68731)|0;e=e+1|0}nr(a,68460)|0;l=m;return}function Be(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;f=l;l=l+16|0;e=f;nr(a,68344)|0;h=c[41913]|0;c[e>>2]=c[41912];c[e+4>>2]=h;tr(a,68597,e);Ie(a,g);nr(a,68621)|0;Ge(a);nr(a,68624)|0;Je(a,b,d);nr(a,68637)|0;l=f;return}function Ce(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0.0;k=l;l=l+48|0;j=k+24|0;i=k+8|0;f=k;nr(a,68344)|0;g=c[41913]|0;c[f>>2]=c[41912];c[f+4>>2]=g;tr(a,68381,f);nr(a,68421)|0;f=d+-1|0;g=b+8|0;e=0;while(1){if((e|0)>=(d|0))break;if(!e){nr(a,68433)|0;m=+((c[41913]|0)>>>0)-+h[g>>3];h[i>>3]=+h[b>>3];h[i+8>>3]=m;tr(a,68437,i);nr(a,68448)|0}else{m=+((c[41913]|0)>>>0)-+h[b+(e<<4)+8>>3];h[j>>3]=+h[b+(e<<4)>>3];h[j+8>>3]=m;tr(a,68437,j)}if((e|0)==(f|0))nr(a,68452)|0;e=e+1|0}nr(a,68456)|0;Ge(a);nr(a,68460)|0;l=k;return}function De(a,b){a=a|0;b=b|0;nr(a,68279)|0;nr(a,Ee(b)|0)|0;nr(a,68291)|0;return}function Ee(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+16|0;e=u;d=c[41910]|0;if(!d){c[41911]=64;d=xw(64)|0;c[41910]=d}s=e+15|0;r=e+14|0;g=0;q=0;o=0;e=0;f=0;a:while(1){n=(o|0)!=0;k=g;p=b;j=e;b:while(1){if(!p){t=32;break a}e=a[p>>0]|0;if(!(e<<24>>24)){t=32;break a}b=c[41911]|0;if((q|0)>(b+-8|0)){d=b<<1;c[41911]=d;d=zw(c[41910]|0,d)|0;c[41910]=d;d=d+q|0;e=a[p>>0]|0}switch(e<<24>>24){case 60:{e=4;b=87187;t=26;break b}case 62:{e=4;b=87170;t=27;break b}case 38:{t=10;break b}case 45:{e=5;b=87181;i=j;break b}default:{}}if(n&e<<24>>24==32){t=12;break}switch(e<<24>>24){case 34:{e=6;b=87150;t=26;break b}case 39:{e=5;b=87175;t=27;break b}default:{}}if(e<<24>>24<0){i=127;b=0}else{e=1;b=p;t=26;break}while(1){g=i&255;h=e&255;if(g>>>0>=h>>>0)break;e=i&h&255;i=g>>>1;b=b+1|0}if((b|0)<=1){g=PN(j|0,f|0,6)|0;g=IN(g|0,z|0,e&255|0,0)|0;f=z;m=k+-1|0;if((k|0)>1){b=m;e=g}else{t=21;break}}else{b=b+-1|0;e=e&255;f=0}k=b;p=p+1|0;j=e}if((t|0)==10){t=0;b=(Fe(p)|0)==0;e=b?5:1;b=b?87164:p;i=j}else if((t|0)==12){t=0;b=(a[o>>0]|0)==32;e=b?6:1;b=b?87157:p;i=j}else if((t|0)==21){t=0;a[s>>0]=59;e=3;h=r;i=g;j=f;while(1){b=NN(i|0,j|0,10,0)|0;g=h+-1|0;a[h>>0]=b|48;b=i;i=MN(i|0,j|0,10,0)|0;f=j;j=z;o=e;e=e+1|0;if((o|0)>11){t=23;break a}if(!(f>>>0>0|(f|0)==0&b>>>0>9))break;else h=g}b=h+-2|0;a[g>>0]=35;a[b>>0]=38;k=m;f=j}else if((t|0)==26){t=0;i=j}else if((t|0)==27){t=0;i=j}h=d+e|0;g=e;while(1){if(!g)break;a[d>>0]=a[b>>0]|0;g=g+-1|0;b=b+1|0;d=d+1|0}g=k;b=p+1|0;q=e+q|0;o=p;d=h;e=i}if((t|0)==23){YL(68297,46,1,c[13918]|0)|0;Ma(1)}else if((t|0)==32){a[d>>0]=0;l=u;return c[41910]|0}return 0}function Fe(b){b=b|0;var c=0,d=0;d=b+1|0;c=a[d>>0]|0;a:do if(c<<24>>24==35){d=b+2|0;c=a[d>>0]|0;switch(c<<24>>24){case 88:case 120:break;default:{b=d;while(1){d=b+1|0;if((c+-48&255)>=10)break a;b=d;c=a[d>>0]|0}}}d=b+3|0;while(1){c=a[d>>0]|0;if((c+-48&255)>=10)switch(c<<24>>24){case 65:case 66:case 67:case 68:case 69:case 70:case 97:case 98:case 99:case 100:case 101:case 102:break;default:break a}d=d+1|0}}else while(1){b=d+1|0;if(((c&-33)+-65&255)>=26)break a;d=b;c=a[b>>0]|0}while(0);return c<<24>>24==59|0}function Ge(a){a=a|0;var b=0.0,d=0,e=0,f=0,g=0,i=0,j=0,k=0;k=l;l=l+48|0;d=k+8|0;j=k;i=c[a+16>>2]|0;nr(a,68472)|0;e=d;f=i+16|0;g=e+40|0;do{c[e>>2]=c[f>>2];e=e+4|0;f=f+4|0}while((e|0)<(g|0));He(a,d);b=+h[i+152>>3];if(b!=1.0){h[j>>3]=b;tr(a,68490,j)}switch(c[i+144>>2]|0){case 1:{nr(a,68507)|0;break}case 2:{nr(a,68525)|0;break}default:{}}nr(a,68542)|0;l=k;return}function He(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0;g=l;l=l+16|0;f=g;a:do switch(c[e+32>>2]|0){case 5:{nr(b,c[e>>2]|0)|0;break}case 1:if(!(a[e+3>>0]|0)){nr(b,120501)|0;break a}else{i=d[e+1>>0]|0;h=d[e+2>>0]|0;c[f>>2]=d[e>>0];c[f+4>>2]=i;c[f+8>>2]=h;tr(b,68547,f);break a}default:ma(123205,68561,94,68581)}while(0);l=g;return}function Ie(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=l;l=l+48|0;f=g;if(!b)nr(a,68700)|0;else{d=c[a+16>>2]|0;nr(a,68670)|0;b=f;d=d+56|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));He(a,f);nr(a,68697)|0}l=g;return}function Je(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0.0,k=0.0;i=l;l=l+32|0;g=i;e=68651;f=0;while(1){if((f|0)>=(d|0))break;k=+h[b+(f<<4)>>3];j=+((c[41913]|0)>>>0)-+h[b+(f<<4)+8>>3];c[g>>2]=e;h[g+8>>3]=k;h[g+16>>3]=j;tr(a,68654,g);e=(f|0)==0?68667:174185;f=f+1|0}nr(a,83714)|0;l=i;return}function Ke(a){a=a|0;var b=0,d=0,e=0;b=l;l=l+16|0;d=b+8|0;e=b;nr(a,73284)|0;nr(a,73299)|0;nr(a,73338)|0;nr(a,73387)|0;c[e>>2]=122106;c[e+4>>2]=73475;tr(a,73456,e);c[d>>2]=121990;c[d+4>>2]=73481;tr(a,73456,d);l=b;return}function Le(a){a=a|0;var b=0,d=0,e=0.0,f=0.0,g=0.0,i=0.0,j=0;b=l;l=l+64|0;d=b+8|0;j=b;c[j>>2]=En(c[(c[a+16>>2]|0)+8>>2]|0)|0;tr(a,72237,j);i=+h[a+368>>3]*.5*+h[a+488>>3];g=+h[a+376>>3]*.5*+h[a+496>>3];f=+J(+(i*2.0000000949949026e-03))*180.0*.6366197723675814;e=+J(+(g*2.0000000949949026e-03))*180.0*.6366197723675814;h[d>>3]=i;h[d+8>>3]=g;h[d+16>>3]=-500.0;h[d+24>>3]=i;h[d+32>>3]=g;h[d+40>>3]=0.0;h[d+48>>3]=(f>e?f:e)*1.2;tr(a,72259,d);nr(a,72406)|0;nr(a,73236)|0;l=b;return}function Me(a){a=a|0;nr(a,72220)|0;return}function Ne(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0;f=l;l=l+16|0;h=f;c[h>>2]=b;c[h+4>>2]=d;c[h+8>>2]=e;tr(a,72190,h);g[41914]=+(O(d,-10)|0);l=f;return}function Oe(a){a=a|0;nr(a,72173)|0;return}function Pe(a){a=a|0;nr(a,72155)|0;return}function Qe(a){a=a|0;nr(a,72139)|0;return}function Re(a){a=a|0;nr(a,72118)|0;g[41914]=+g[41914]+-2.0;return}function Se(a){a=a|0;nr(a,72099)|0;return}function Te(a){a=a|0;var b=0,d=0;b=l;l=l+16|0;d=b;c[d>>2]=En(c[(c[a+16>>2]|0)+8>>2]|0)|0;tr(a,72077,d);l=b;return}function Ue(a){a=a|0;nr(a,72061)|0;return}function Ve(a){a=a|0;nr(a,72043)|0;g[41914]=+g[41914]+-5.0;return}function We(a){a=a|0;nr(a,72027)|0;g[41914]=+g[41914]+5.0;return}function Xe(b,d,e){b=b|0;d=d|0;e=e|0;var f=0.0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0,u=0.0;r=l;l=l+144|0;o=r+104|0;q=r+56|0;m=r+32|0;j=r+24|0;n=r;p=e+4|0;i=c[p>>2]|0;f=+h[i+16>>3];i=c[i>>2]|0;c[n>>2]=c[e>>2];h[n+8>>3]=f;c[n+16>>2]=i;tr(b,71873,n);g[41915]=+g[41914]+-9.0;switch(a[e+48>>0]|0){case 108:{f=+h[d>>3];break}case 114:{i=d;f=+h[d>>3]-+h[e+32>>3];k=5;break}default:{i=d;f=+h[d>>3]-+h[e+32>>3]*.5;k=5}}if((k|0)==5)h[i>>3]=f;u=+h[b+488>>3];t=(+h[b+504>>3]+f)*u;s=(+h[b+512>>3]+ +h[d+8>>3])*+h[b+496>>3];h[j>>3]=+h[(c[p>>2]|0)+16>>3]*u;n=bf(b,71925,j)|0;f=+(c[b+360>>2]|0);h[m>>3]=0.0;h[m+8>>3]=0.0;h[m+16>>3]=f;i=bf(b,71142,m)|0;f=+g[41915];h[o>>3]=t;h[o+8>>3]=s;h[o+16>>3]=f;d=bf(b,71174,o)|0;j=o;k=(c[b+16>>2]|0)+16|0;m=j+40|0;do{c[j>>2]=c[k>>2];j=j+4|0;k=k+4|0}while((j|0)<(m|0));o=cf(b,o,0.0)|0;e=c[e>>2]|0;c[q>>2]=c[c[p>>2]>>2];h[q+8>>3]=.25;h[q+16>>3]=0.0;c[q+24>>2]=e;c[q+28>>2]=72012;c[q+32>>2]=n;c[q+36>>2]=i;c[q+40>>2]=d;c[q+44>>2]=o;q=bf(b,71937,q)|0;nr(b,q)|0;$I(q);$I(i);$I(o);$I(d);$I(n);l=r;return}function Ye(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,i=0.0,j=0.0,k=0.0,m=0,n=0,o=0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0;z=l;l=l+240|0;x=z+192|0;y=z+152|0;t=z+128|0;r=z+104|0;o=z+80|0;n=z+48|0;e=z+24|0;m=z;nr(a,71750)|0;g[41915]=+g[41914]+-6.0;i=+h[b>>3];j=+h[a+488>>3];p=(+h[a+504>>3]+i)*j;A=+h[b+8>>3];k=+h[a+496>>3];q=(+h[a+512>>3]+A)*k;j=(+h[b+16>>3]-i)*j;k=(+h[b+24>>3]-A)*k;s=a+16|0;A=k+j;i=+h[(c[s>>2]|0)+152>>3]/A*2.5;h[m>>3]=j;h[m+8>>3]=A*.25;h[m+16>>3]=k;b=bf(a,71110,m)|0;m=a+360|0;A=+(c[m>>2]|0);h[e>>3]=90.0;h[e+8>>3]=0.0;h[e+16>>3]=A;e=bf(a,71142,e)|0;A=+g[41915];h[x>>3]=p;h[x+8>>3]=q;h[x+16>>3]=A;f=bf(a,71174,x)|0;u=x;v=(c[s>>2]|0)+16|0;w=u+40|0;do{c[u>>2]=c[v>>2];u=u+4|0;v=v+4|0}while((u|0)<(w|0));v=cf(a,x,0.0)|0;h[n>>3]=1.0;h[n+8>>3]=i;c[n+16>>2]=b;c[n+20>>2]=e;c[n+24>>2]=f;c[n+28>>2]=v;w=bf(a,71765,n)|0;nr(a,w)|0;$I(b);$I(e);$I(f);$I(v);$I(w);if(d|0){h[o>>3]=j;h[o+8>>3]=k;h[o+16>>3]=1.0;f=bf(a,71110,o)|0;A=+(c[m>>2]|0);h[r>>3]=0.0;h[r+8>>3]=0.0;h[r+16>>3]=A;e=bf(a,71142,r)|0;A=+g[41915];h[t>>3]=p;h[t+8>>3]=q;h[t+16>>3]=A;b=bf(a,71174,t)|0;u=x;v=(c[s>>2]|0)+56|0;w=u+40|0;do{c[u>>2]=c[v>>2];u=u+4|0;v=v+4|0}while((u|0)<(w|0));x=cf(a,x,0.0)|0;h[y>>3]=0.0;h[y+8>>3]=0.0;h[y+16>>3]=0.0;c[y+24>>2]=f;c[y+28>>2]=e;c[y+32>>2]=b;c[y+36>>2]=x;y=bf(a,71811,y)|0;nr(a,y)|0;$I(f);$I(e);$I(b);$I(x);$I(y)}l=z;return}function Ze(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0.0,M=0,N=0.0;K=l;l=l+336|0;B=K+296|0;J=K+288|0;I=K+272|0;H=K+264|0;G=K+240|0;D=K+232|0;A=K+208|0;z=K+184|0;w=K+160|0;v=K+152|0;u=K+136|0;t=K+128|0;s=K+96|0;r=K+88|0;q=K+56|0;f=K+48|0;m=K+24|0;k=K;nr(a,71615)|0;g[41915]=+g[41914]+-2.0;o=a+488|0;p=a+496|0;L=+h[p>>3];h[k>>3]=+h[o>>3];h[k+8>>3]=L;h[k+16>>3]=1.0;k=bf(a,71110,k)|0;y=a+360|0;L=+(c[y>>2]|0);h[m>>3]=0.0;h[m+8>>3]=0.0;h[m+16>>3]=L;m=bf(a,71142,m)|0;L=+g[41915]+-2.0;h[B>>3]=0.0;h[B+8>>3]=0.0;h[B+16>>3]=L;n=bf(a,71174,B)|0;C=a+16|0;i=B;j=(c[C>>2]|0)+16|0;x=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(x|0));j=cf(a,B,0.0)|0;c[f>>2]=71237;c[f+4>>2]=d+1;E=a+504|0;F=a+512|0;i=0;f=bf(a,71206,f)|0;while(1){if((i|0)>=(d|0))break;N=+h[F>>3]+ +h[b+(i<<4)+8>>3];L=+h[(c[C>>2]|0)+152>>3];h[q>>3]=+h[E>>3]+ +h[b+(i<<4)>>3];h[q+8>>3]=N;h[q+16>>3]=0.0;h[q+24>>3]=L;M=bf(a,71251,q)|0;c[r>>2]=f;c[r+4>>2]=M;x=bf(a,71280,r)|0;$I(M);$I(f);i=i+1|0;f=x}L=+h[F>>3]+ +h[b+8>>3];N=+h[(c[C>>2]|0)+152>>3];h[s>>3]=+h[E>>3]+ +h[b>>3];h[s+8>>3]=L;h[s+16>>3]=0.0;h[s+24>>3]=N;x=bf(a,71251,s)|0;c[t>>2]=f;c[t+4>>2]=x;M=bf(a,71280,t)|0;$I(x);$I(f);c[u>>2]=k;c[u+4>>2]=m;c[u+8>>2]=n;c[u+12>>2]=j;x=bf(a,71630,u)|0;c[v>>2]=M;c[v+4>>2]=x;M=bf(a,71335,v)|0;$I(x);nr(a,M)|0;$I(k);$I(m);$I(n);$I(j);$I(M);if(e|0){N=+h[p>>3];h[w>>3]=+h[o>>3];h[w+8>>3]=N;h[w+16>>3]=1.0;n=bf(a,71110,w)|0;N=+(c[y>>2]|0);h[z>>3]=0.0;h[z+8>>3]=0.0;h[z+16>>3]=N;m=bf(a,71142,z)|0;N=+g[41915]+-2.0;h[A>>3]=0.0;h[A+8>>3]=0.0;h[A+16>>3]=N;k=bf(a,71174,A)|0;i=B;j=(c[C>>2]|0)+56|0;x=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(x|0));j=cf(a,B,.25)|0;c[D>>2]=d;i=0;f=bf(a,71675,D)|0;while(1){if((i|0)>=(d|0))break;N=+h[F>>3]+ +h[b+(i<<4)+8>>3];h[G>>3]=+h[E>>3]+ +h[b+(i<<4)>>3];h[G+8>>3]=N;h[G+16>>3]=0.0;D=bf(a,71690,G)|0;c[H>>2]=f;c[H+4>>2]=D;M=bf(a,71712,H)|0;$I(D);$I(f);i=i+1|0;f=M}c[I>>2]=n;c[I+4>>2]=m;c[I+8>>2]=k;c[I+12>>2]=j;I=bf(a,71722,I)|0;c[J>>2]=f;c[J+4>>2]=I;M=bf(a,71335,J)|0;$I(I);nr(a,M)|0;$I(n);$I(m);$I(k);$I(j);$I(M)}l=K;return}function _e(a,b,d,e,f,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0;B=l;l=l+208|0;e=B+160|0;A=B+152|0;z=B+136|0;y=B+128|0;x=B+96|0;w=B+88|0;v=B+56|0;k=B+48|0;s=B+24|0;r=B;nr(a,71542)|0;g[41915]=+g[41914]+-4.0;C=+h[a+496>>3];h[r>>3]=+h[a+488>>3];h[r+8>>3]=C;h[r+16>>3]=1.0;r=bf(a,71110,r)|0;C=+(c[a+360>>2]|0);h[s>>3]=0.0;h[s+8>>3]=0.0;h[s+16>>3]=C;s=bf(a,71142,s)|0;C=+g[41915]+-2.0;h[e>>3]=0.0;h[e+8>>3]=0.0;h[e+16>>3]=C;t=bf(a,71174,e)|0;u=a+16|0;f=e;i=(c[u>>2]|0)+56|0;j=f+40|0;do{c[f>>2]=c[i>>2];f=f+4|0;i=i+4|0}while((f|0)<(j|0));n=cf(a,e,0.0)|0;c[k>>2]=71556;c[k+4>>2]=d+2;o=a+504|0;p=a+512|0;q=d+-1|0;m=0;e=bf(a,71206,k)|0;while(1){if((m|0)>=(d|0))break;f=b+(m<<4)|0;i=b+(m<<4)+8|0;D=+h[p>>3]+ +h[i>>3];C=+h[(c[u>>2]|0)+152>>3];h[v>>3]=+h[o>>3]+ +h[f>>3];h[v+8>>3]=D;h[v+16>>3]=0.0;h[v+24>>3]=C;k=bf(a,71251,v)|0;c[w>>2]=e;c[w+4>>2]=k;j=bf(a,71280,w)|0;$I(k);$I(e);if((m|0)==0|(m|0)==(q|0)){C=+h[p>>3]+ +h[i>>3];D=+h[(c[u>>2]|0)+152>>3];h[x>>3]=+h[o>>3]+ +h[f>>3];h[x+8>>3]=C;h[x+16>>3]=0.0;h[x+24>>3]=D;k=bf(a,71251,x)|0;c[y>>2]=j;c[y+4>>2]=k;e=bf(a,71280,y)|0;$I(k);$I(j)}else e=j;m=m+1|0}c[z>>2]=r;c[z+4>>2]=s;c[z+8>>2]=t;c[z+12>>2]=n;b=bf(a,71565,z)|0;c[A>>2]=e;c[A+4>>2]=b;d=bf(a,71335,A)|0;$I(b);nr(a,d)|0;$I(r);$I(s);$I(t);$I(n);$I(d);l=B;return}function $e(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0,y=0.0;v=l;l=l+160|0;e=v+120|0;u=v+112|0;t=v+96|0;s=v+88|0;r=v+56|0;m=v+48|0;n=v+24|0;q=v;nr(a,71094)|0;g[41915]=+g[41914]+-6.0;w=+h[a+496>>3];h[q>>3]=+h[a+488>>3];h[q+8>>3]=w;h[q+16>>3]=1.0;q=bf(a,71110,q)|0;w=+(c[a+360>>2]|0);h[n>>3]=0.0;h[n+8>>3]=0.0;h[n+16>>3]=w;n=bf(a,71142,n)|0;w=+g[41915];h[e>>3]=0.0;h[e+8>>3]=0.0;h[e+16>>3]=w;o=bf(a,71174,e)|0;p=a+16|0;f=e;i=(c[p>>2]|0)+16|0;j=f+40|0;do{c[f>>2]=c[i>>2];f=f+4|0;i=i+4|0}while((f|0)<(j|0));i=cf(a,e,0.0)|0;c[m>>2]=71237;c[m+4>>2]=d;j=a+504|0;k=a+512|0;f=0;e=bf(a,71206,m)|0;while(1){if((f|0)>=(d|0))break;y=+h[k>>3]+ +h[b+(f<<4)+8>>3];w=+h[(c[p>>2]|0)+152>>3];h[r>>3]=+h[j>>3]+ +h[b+(f<<4)>>3];h[r+8>>3]=y;h[r+16>>3]=0.0;h[r+24>>3]=w;x=bf(a,71251,r)|0;c[s>>2]=e;c[s+4>>2]=x;m=bf(a,71280,s)|0;$I(x);$I(e);f=f+1|0;e=m}c[t>>2]=q;c[t+4>>2]=n;c[t+8>>2]=o;c[t+12>>2]=i;t=bf(a,71289,t)|0;c[u>>2]=e;c[u+4>>2]=t;x=bf(a,71335,u)|0;$I(t);nr(a,x)|0;$I(q);$I(n);$I(o);$I(i);$I(x);l=v;return}function af(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=b;tr(a,71075,e);l=d;return}function bf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=l;l=l+1056|0;h=i;e=i+24|0;f=i+8|0;c[f>>2]=d;g=MK(e,1024,b,f)|0;do if((g|0)>=0)if((g|0)>1023){a=_I(g+1|0)|0;c[f>>2]=d;rL(a,b,f)|0;break}else{a=HL(e)|0;break}else{a=c[(c[a+12>>2]|0)+16>>2]|0;c[h>>2]=zJ(c[(kJ()|0)>>2]|0)|0;hb[a&31](71520,h);a=HL(174185)|0}while(0);l=i;return a|0}function cf(a,b,e){a=a|0;b=b|0;e=+e;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0;q=l;l=l+112|0;o=q+104|0;j=q+96|0;i=q+64|0;n=q+48|0;p=q+32|0;m=q+16|0;k=q;g=c[b+32>>2]|0;a:do switch(g|0){case 5:{f=c[b>>2]|0;if(!(yJ(f,121094)|0)){c[k>>2]=71357;h[k+8>>3]=e;f=bf(a,71340,k)|0;break a}if(!(yJ(f,118224)|0)){c[m>>2]=71361;h[m+8>>3]=e;f=bf(a,71340,m)|0;break a}if(!(yJ(f,116223)|0)){c[p>>2]=71367;h[p+8>>3]=e;f=bf(a,71340,p)|0;break a}else{c[n>>2]=f;h[n+8>>3]=e;f=bf(a,71340,n)|0;break a}}case 1:{s=+(d[b+1>>0]|0)*.00390625;r=+(d[b+2>>0]|0)*.00390625;h[i>>3]=+(d[b>>0]|0)*.00390625;h[i+8>>3]=s;h[i+16>>3]=r;h[i+24>>3]=e;f=bf(a,71372,i)|0;break}default:{p=c[13918]|0;n=c[b>>2]|0;c[j>>2]=g;c[j+4>>2]=n;AL(p,71411,j)|0;ma(123205,71461,436,71481)}}while(0);c[o>>2]=f;p=bf(a,71498,o)|0;$I(f);l=q;return p|0}function df(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;b=l;l=l+32|0;d=b+24|0;e=b+16|0;g=b;f=c[a+16>>2]|0;h=c[c[a+12>>2]>>2]|0;j=c[h>>2]|0;i=c[h+4>>2]|0;h=c[h+8>>2]|0;c[g>>2]=73927;c[g+4>>2]=j;c[g+8>>2]=i;c[g+12>>2]=h;tr(a,76546,g);f=En(c[f+8>>2]|0)|0;c[e>>2]=73927;c[e+4>>2]=f;tr(a,76578,e);c[d>>2]=73927;tr(a,76592,d);l=b;return}function ef(a){a=a|0;var b=0,d=0;b=l;l=l+16|0;d=b;c[d>>2]=73927;tr(a,76494,d);l=b;return}function ff(a){a=a|0;var b=0.0,d=0.0,e=0.0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;W=l;l=l+304|0;V=W+296|0;U=W+288|0;T=W+272|0;R=W+264|0;Q=W+256|0;P=W+248|0;O=W+240|0;N=W+232|0;M=W+224|0;L=W+216|0;K=W+208|0;J=W+200|0;I=W+192|0;H=W+184|0;G=W+176|0;F=W+168|0;E=W+160|0;C=W+152|0;A=W+144|0;z=W+136|0;y=W+128|0;x=W+120|0;w=W+112|0;v=W+104|0;u=W+96|0;t=W+88|0;s=W+80|0;r=W+72|0;q=W+64|0;p=W+56|0;o=W+48|0;S=W+40|0;B=W+24|0;n=W+16|0;m=W;g=c[a+456>>2]|0;i=c[a+460>>2]|0;j=c[a+464>>2]|0;k=c[a+468>>2]|0;f=a+360|0;a:do if(c[4007]|0){switch(c[f>>2]|0){case 90:case 0:break a;default:{}}sf();c[4007]=0}while(0);e=(+(k|0)-+(i|0))*.013888888888888888;b=(+(j|0)-+(g|0))*.013888888888888888;k=(c[f>>2]|0)==90;d=k?e:b;e=k?b:e;h[m>>3]=d;h[m+8>>3]=e;tr(a,74114,m);c[n>>2]=73927;tr(a,74129,n);if(d>0.0){b=+GJ(d);h[16877]=b;b=b+3.0-+(~~b|0)}else b=3.0;b=+D(10.0,+b);h[16877]=b;h[B>>3]=b;h[B+8>>3]=b;tr(a,74298,B);c[S>>2]=73927;tr(a,74333,S);c[o>>2]=73927;tr(a,74391,o);c[p>>2]=73927;tr(a,74451,p);c[q>>2]=73927;tr(a,74500,q);c[r>>2]=73927;tr(a,74539,r);c[s>>2]=73927;tr(a,74590,s);c[t>>2]=73927;tr(a,74652,t);c[u>>2]=73927;tr(a,74762,u);c[v>>2]=73927;tr(a,74853,v);c[w>>2]=73927;tr(a,74907,w);c[x>>2]=73927;tr(a,74976,x);tr(a,75012,y);c[z>>2]=73927;tr(a,75137,z);c[A>>2]=73927;tr(a,75166,A);tr(a,75206,C);c[E>>2]=73927;tr(a,75299,E);c[F>>2]=73927;tr(a,75358,F);c[G>>2]=73927;tr(a,75439,G);tr(a,75509,H);c[I>>2]=73927;tr(a,75598,I);c[J>>2]=73927;tr(a,75703,J);c[K>>2]=73927;tr(a,75779,K);c[L>>2]=73927;tr(a,75818,L);c[M>>2]=73927;tr(a,75917,M);c[N>>2]=73927;tr(a,75963,N);tr(a,76052,O);c[P>>2]=73927;tr(a,76093,P);c[Q>>2]=73927;tr(a,76176,Q);c[R>>2]=73927;tr(a,76277,R);h[T>>3]=e;h[T+8>>3]=d;tr(a,76341,T);tr(a,76369,U);tr(a,76377,V);l=W;return}function gf(a){a=a|0;var b=0;b=l;l=l+16|0;tr(a,74107,b);l=b;return}function hf(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0.0,k=0,m=0,n=0.0,o=0,p=0,q=0,r=0;r=l;l=l+48|0;q=r+24|0;p=r+8|0;o=r;switch(a[e+48>>0]|0){case 108:{k=d;i=+h[e+32>>3];j=+h[d>>3];break}case 114:{i=+h[e+32>>3];g=i;f=5;break}default:{i=+h[e+32>>3];g=i*.5;f=5}}if((f|0)==5){j=+h[d>>3]-g;h[d>>3]=j;k=d}m=e+4|0;f=c[m>>2]|0;g=+h[f+16>>3];d=d+8|0;n=+h[d>>3]+g*.004629629629629629;h[d>>3]=n;i=j+i*.006944444444444444;h[k>>3]=i;f=c[f>>2]|0;do if(f){d=c[41916]|0;if(d|0?(yJ(d,f)|0)==0:0)break;c[o>>2]=qf(f)|0;tr(b,74006,o);o=c[m>>2]|0;c[41916]=c[o>>2];g=+h[o+16>>3]}while(0);f=~~g;f=(f|0)>1?f:1;if((f|0)!=(c[41917]|0)){j=+h[16877];c[p>>2]=f;h[p+8>>3]=j;tr(b,74014,p);c[41917]=f}c[q>>2]=rf(c[e>>2]|0)|0;h[q+8>>3]=i;h[q+16>>3]=n;tr(b,74035,q);l=r;return}function jf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0.0,k=0.0;e=l;l=l+48|0;f=e;i=+h[b>>3];k=(+h[b+16>>3]-i)*.027777777777777776;g=+h[b+8>>3];j=(+h[b+24>>3]-g)*.027777777777777776;c[f>>2]=1;c[f+4>>2]=d|0?73948:174185;h[f+8>>3]=k;h[f+16>>3]=j;h[f+24>>3]=i*.013888888888888888;h[f+32>>3]=g*.013888888888888888;tr(a,73954,f);l=e;return}function kf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;e=l;l=l+16|0;of(c[a+16>>2]|0,e+8|0,e);pf(a,b,d,1);l=e;return}function lf(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0.0,w=0;t=l;l=l+128|0;s=t+112|0;q=t+104|0;p=t+96|0;e=t+88|0;n=t+16|0;o=t;k=c[a+16>>2]|0;j=_I((d*140|0)+140|0)|0;of(k,t+116|0,t+80|0);v=+h[b>>3];k=n+48|0;h[k>>3]=v;u=+h[b+8>>3];h[n+56>>3]=u;c[e>>2]=~~(v+(v>=0.0?.5:-.5));c[e+4>>2]=~~(u+(u>=0.0?.5:-.5));i=o+8|0;e=j+(qL(j,73932,e)|0)|0;r=1;g=0;while(1){m=g+3|0;if((m|0)>=(d|0))break;c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];c[n+8>>2]=c[k+8>>2];c[n+12>>2]=c[k+12>>2];f=1;while(1){if((f|0)==4){f=1;break}w=f+g|0;h[n+(f<<4)>>3]=+h[b+(w<<4)>>3];h[n+(f<<4)+8>>3]=+h[b+(w<<4)+8>>3];f=f+1|0}while(1){if((f|0)==7)break;QA(o,n,3,+(f|0)*.16666666666666666,0,0);u=+h[o>>3];v=+h[i>>3];c[p>>2]=~~(u+(u>=0.0?.5:-.5));c[p+4>>2]=~~(v+(v>=0.0?.5:-.5));f=f+1|0;e=e+(qL(e,73932,p)|0)|0}r=r+6|0;g=m}c[q>>2]=j;tr(a,73939,q);$I(j);f=r+-1|0;e=0;while(1){if((e|0)>=(r|0))break;c[s>>2]=((e|0)%(f|0)|0|0)!=0&1;tr(a,73944,s);e=e+1|0}nr(a,134901)|0;l=t;return}function mf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=l;l=l+16|0;of(c[a+16>>2]|0,e+8|0,e);pf(a,b,d,0);l=e;return}function nf(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=73927;c[e+4>>2]=b;tr(a,73920,e);l=d;return}function of(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0;switch(c[a+144>>2]|0){case 1:{e=10.0;a=1;break}case 2:{e=10.0;a=2;break}default:{e=0.0;a=0}}c[b>>2]=a;h[d>>3]=e;return}function pf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0,m=0.0;j=l;l=l+16|0;i=j+8|0;g=j;f=0;while(1){if((f|0)>=(d|0))break;m=+h[b+(f<<4)>>3];k=+h[b+(f<<4)+8>>3];c[g>>2]=~~(m+(m>=0.0?.5:-.5));c[g+4>>2]=~~(k+(k>=0.0?.5:-.5));tr(a,73932,g);f=f+1|0}if(e|0){k=+h[b>>3];m=+h[b+8>>3];c[i>>2]=~~(k+(k>=0.0?.5:-.5));c[i+4>>2]=~~(m+(m>=0.0?.5:-.5));tr(a,73932,i)}nr(a,134901)|0;l=j;return}function qf(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;f=h;a:while(1){d=15756;while(1){e=c[d+4>>2]|0;if(!e)break;if(!(yJ(e,b)|0)){g=6;break a}d=d+8|0}c[f>>2]=74088;c[f+4>>2]=b;$l(1,74062,f)|0;d=IL(b,45)|0;if(!d){d=74105;break}a[d>>0]=0}l=h;return d|0}function rf(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;d=c[41918]|0;if(!d){c[41919]=64;d=_I(64)|0;c[41918]=d;e=0}else e=0;while(1){g=b+1|0;f=a[b>>0]|0;if(!(f<<24>>24))break;b=c[41919]|0;if((e|0)>(b+-8|0)){d=b<<1;c[41919]=d;d=bJ(c[41918]|0,d)|0;c[41918]=d;d=d+e|0}if(f<<24>>24<=-1){a[d>>0]=92;c[h>>2]=f&255;qL(d+1|0,74057,h)|0;b=g;d=d+4|0;e=e+4|0;continue}if(f<<24>>24==92){a[d>>0]=92;e=e+1|0;d=d+1|0}a[d>>0]=f;b=g;d=d+1|0;e=e+1|0}a[d>>0]=0;l=i;return c[41918]|0}function sf(){var a=0,b=0;a=l;l=l+16|0;b=a;c[b>>2]=74088;c[b+4>>2]=76485;$l(0,76467,b)|0;l=a;return}function tf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0,k=0;e=l;l=l+32|0;f=e+8|0;j=e;b=b+8|0;k=c[b>>2]|0;c[j>>2]=k;c[j+4>>2]=k;tr(a,77065,j);i=(+h[d>>3]+ +h[d+16>>3])*.5;g=(+h[d+8>>3]+ +h[d+24>>3])*.5;c[f>>2]=c[b>>2];h[f+8>>3]=i;h[f+16>>3]=g;tr(a,77107,f);l=e;return}function uf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0.0,k=0.0;e=l;l=l+48|0;f=e;i=+h[d>>3];k=+h[d+16>>3]-i;g=+h[d+24>>3];j=g-+h[d+8>>3];g=+(~~(+h[a+232>>3]-+h[a+216>>3])>>>0)-g;c[f>>2]=c[b+8>>2];h[f+8>>3]=k;h[f+16>>3]=j;h[f+24>>3]=i;h[f+32>>3]=g;tr(a,77152,f);nr(a,77244)|0;l=e;return}function vf(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return}function wf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0;t=l;l=l+160|0;s=t+152|0;r=t+136|0;q=t+120|0;k=t+112|0;n=t+104|0;m=t+88|0;j=t+72|0;i=t+64|0;o=t;if(!a)ma(96061,77249,212,77268);if(!b)ma(96091,77249,213,77268);p=b+8|0;if(!(c[p>>2]|0))ma(96094,77249,214,77268);if(c[b+52>>2]|0){c[o>>2]=c[d>>2];c[o+4>>2]=c[d+4>>2];c[o+8>>2]=c[d+8>>2];c[o+12>>2]=c[d+12>>2];b=o+32|0;d=d+16|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];f=+h[o>>3];h[o+16>>3]=f;h[o+24>>3]=+h[o+40>>3];h[o+48>>3]=+h[b>>3];g=+h[o+8>>3];h[o+56>>3]=g;if(e<<24>>24){tr(a,77289,i);b=0;while(1){if((b|0)==4)break;u=+h[o+(b<<4)+8>>3];h[j>>3]=+h[o+(b<<4)>>3];h[j+8>>3]=u;tr(a,77292,j);b=b+1|0}h[m>>3]=f;h[m+8>>3]=g;tr(a,77292,m);m=c[p>>2]|0;c[n>>2]=4;c[n+4>>2]=m;tr(a,77299,n)}tr(a,77289,k);b=0;while(1){if((b|0)==4)break;u=+h[o+(b<<4)+8>>3];h[q>>3]=+h[o+(b<<4)>>3];h[q+8>>3]=u;tr(a,77292,q);b=b+1|0}h[r>>3]=f;h[r+8>>3]=g;tr(a,77292,r);r=c[p>>2]|0;c[s>>2]=4;c[s+4>>2]=r;tr(a,77314,s)}l=t;return}function xf(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0.0;o=l;l=l+112|0;n=o+24|0;m=o+16|0;k=o;i=o+28|0;if(!b)ma(96061,77249,153,77330);if(!d)ma(96091,77249,154,77330);if(!(c[d+8>>2]|0))ma(96094,77249,155,77330);j=d+52|0;if(c[j>>2]|0){f=d+60|0;g=c[f>>2]|0;if((g|0)==84)g=18;else{gb[g&127](d);c[j>>2]=0;c[f>>2]=0;c[d+56>>2]=0;g=10}}else g=10;do if((g|0)==10){if(!((Nr(d)|0)<<24>>24))break;f=AN(c[d+20>>2]|0)|0;if((c[d+24>>2]&-2|0)==6){$L(f,i)|0;i=c[i+36>>2]|0;c[d+56>>2]=i;f=qJ(0,i,1,1,f,0)|0;c[j>>2]=f;a[d+16>>0]=1}else f=c[j>>2]|0;if(f|0)c[d+60>>2]=84;Or(d);if(c[j>>2]|0)g=18}while(0);if((g|0)==18){p=+h[e+8>>3]-+(c[d+36>>2]|0);h[k>>3]=+h[e>>3]-+(c[d+32>>2]|0);h[k+8>>3]=p;tr(b,77348,k);if(!(a[d+16>>0]|0)){c[m>>2]=c[d+12>>2];tr(b,77379,m)}else gy(b,d);tr(b,77394,n)}l=o;return}function yf(a){a=a|0;oJ(c[a+52>>2]|0,c[a+56>>2]|0)|0;return}function zf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;g=l;l=l+80|0;f=g+48|0;if(!a)ma(96061,77249,121,77404);e=c[a+16>>2]|0;if(!e)ma(84921,77249,123,77404);if(!b)ma(96091,77249,124,77404);d=b+8|0;if(!(c[d>>2]|0))ma(96094,77249,125,77404);if(!(c[e+8>>2]|0))ma(123690,77249,128,77404);else{tr(a,77424,g);tr(a,77433,g+8|0);tr(a,77460,g+16|0);tr(a,77485,g+24|0);tr(a,77514,g+32|0);tr(a,77542,g+40|0);c[f>>2]=c[d>>2];tr(a,77549,f);tr(a,77588,g+56|0);tr(a,95830,g+64|0);l=g;return}}function Af(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0.0;i=l;l=l+128|0;g=i+80|0;f=i;if(!a)ma(96061,77249,97,77593);if(!b)ma(96091,77249,98,77593);e=c[b+8>>2]|0;if(!e)ma(96094,77249,99,77593);else{m=+h[d>>3];j=~~(m+(m>=0.0?.5:-.5));m=+h[d+8>>3];b=~~(m+(m>=0.0?.5:-.5));m=+h[d+16>>3];k=~~(m+(m>=0.0?.5:-.5));m=+h[d+24>>3];d=~~(m+(m>=0.0?.5:-.5));c[f>>2]=2;c[f+4>>2]=5;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=-1;c[f+24>>2]=1;c[f+28>>2]=-1;c[f+32>>2]=0;h[f+40>>3]=0.0;c[f+48>>2]=0;c[f+52>>2]=0;c[f+56>>2]=0;c[f+60>>2]=0;c[f+64>>2]=0;c[f+68>>2]=5;c[f+72>>2]=0;c[f+76>>2]=e;tr(a,77612,f);c[g>>2]=j;c[g+4>>2]=b;c[g+8>>2]=j;c[g+12>>2]=d;c[g+16>>2]=k;c[g+20>>2]=d;c[g+24>>2]=k;c[g+28>>2]=b;c[g+32>>2]=j;c[g+36>>2]=b;tr(a,77670,g);l=i;return}}function Bf(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0.0,k=0,m=0,n=0,o=0;o=l;l=l+96|0;n=o+56|0;m=o+32|0;k=o;i=+h[d>>3];j=+h[d+16>>3]-i;f=+h[d+24>>3];g=f-+h[d+8>>3];if(!a)ma(96061,77249,53,77702);if(!b)ma(96091,77249,54,77702);e=b+8|0;if(!(c[e>>2]|0))ma(96094,77249,55,77702);nr(a,77721)|0;nr(a,c[e>>2]|0)|0;e=a+360|0;f=-f;if(!(c[e>>2]|0)){h[n>>3]=j;h[n+8>>3]=g;h[n+16>>3]=i;h[n+24>>3]=f;tr(a,77850,n)}else{h[k>>3]=g;h[k+8>>3]=j;h[k+16>>3]=i;h[k+24>>3]=f;tr(a,77741,k);c[m>>2]=c[e>>2];h[m+8>>3]=i;h[m+16>>3]=f;tr(a,77820,m)}nr(a,77929)|0;l=o;return}function Cf(a){a=a|0;var b=0,c=0;b=eo(a)|0;while(1){if(!b)break;Df(b);b=fo(a,b)|0}c=eo(a)|0;while(1){if(!c)break;b=Qm(a,c)|0;while(1){if(!b)break;Ef(b);b=Sm(a,b)|0}c=fo(a,c)|0}return}function Df(a){a=a|0;var b=0,d=0;Oo(a,122241,304,1)|0;XA(a);LB(a,c[(c[(so(a)|0)+16>>2]|0)+116>>2]&1);a=a+16|0;c[(c[a>>2]|0)+176>>2]=0;b=ww(20)|0;d=c[a>>2]|0;c[d+172>>2]=b;c[d+184>>2]=0;d=ww(20)|0;b=c[a>>2]|0;c[b+180>>2]=d;c[b+200>>2]=0;b=ww(12)|0;d=c[a>>2]|0;c[d+196>>2]=b;c[d+192>>2]=0;d=ww(12)|0;b=c[a>>2]|0;c[b+188>>2]=d;c[b+208>>2]=0;b=ww(12)|0;a=c[a>>2]|0;c[a+204>>2]=b;c[a+216>>2]=1;return}function Ef(d){d=d|0;var e=0,f=0,g=0,h=0,i=0;Oo(d,122254,176,1)|0;YA(d)|0;h=EA(d,c[42219]|0,1,0)|0;g=d+16|0;c[(c[g>>2]|0)+156>>2]=h;h=GA(c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0,c[42213]|0,174185)|0;i=GA(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0,c[42213]|0,174185)|0;e=c[g>>2]|0;f=e+154|0;b[f>>1]=1;b[e+168>>1]=1;if((h|0)==(i|0)&(a[h>>0]|0)!=0){b[f>>1]=1e3;i=e+156|0;c[i>>2]=(c[i>>2]|0)*100}if(Ak(d)|0){i=c[g>>2]|0;b[i+154>>1]=0;c[i+156>>2]=0}i=(EA(d,c[42232]|0,0,0)|0)&255;a[(c[g>>2]|0)+152>>0]=i;i=(EA(d,c[42220]|0,1,0)|0)&65535;b[(c[g>>2]|0)+170>>1]=i;return}function Ff(a){a=a|0;var b=0,d=0;Gf(c[(c[a+16>>2]|0)+192>>2]|0);d=eo(a)|0;while(1){if(!d)break;b=Qm(a,d)|0;while(1){if(!b)break;sB(b);b=Sm(a,b)|0}Hf(d);d=fo(a,d)|0}If(a);return}function Gf(b){b=b|0;var d=0,e=0,f=0,g=0;while(1){if(!b)break;f=b+16|0;g=c[(c[f>>2]|0)+164>>2]|0;Jf(b);d=c[f>>2]|0;if((a[d+156>>0]|0)!=1){b=g;continue}e=c[d+180>>2]|0;if(e){$I(e);d=c[f>>2]|0}e=c[d+172>>2]|0;if(e){$I(e);d=c[f>>2]|0}$I(d);$I(b);b=g}return}function Hf(a){a=a|0;var b=0,d=0,e=0;e=a+16|0;b=c[e>>2]|0;d=c[b+172>>2]|0;if(d){$I(d);b=c[e>>2]|0}d=c[b+180>>2]|0;if(d){$I(d);b=c[e>>2]|0}d=c[b+188>>2]|0;if(d){$I(d);b=c[e>>2]|0}d=c[b+196>>2]|0;if(d){$I(d);b=c[e>>2]|0}d=c[b+204>>2]|0;if(d){$I(d);b=c[e>>2]|0}pw(c[b+104>>2]|0);pw(c[(c[e>>2]|0)+108>>2]|0);b=c[(c[e>>2]|0)+8>>2]|0;if(b|0)gb[c[(c[b+4>>2]|0)+4>>2]&127](a);Qo(a,122241)|0;return}function If(a){a=a|0;var d=0,e=0,f=0;d=Kp(a)|0;while(1){if(!d)break;If(d);d=Lp(d)|0}if(Oo(a,122277,0,1)|0){f=a+16|0;d=c[f>>2]|0;e=c[d+184>>2]|0;if(e){$I(e);d=c[f>>2]|0}e=c[d+268>>2]|0;if(e){$I(e);d=c[f>>2]|0}e=c[d+216>>2]|0;if(e){$I(e);d=c[f>>2]|0}do if(c[d+196>>2]|0){e=b[d+236>>1]|0;while(1){if((e|0)>(b[d+238>>1]|0))break;$I(c[(c[d+196>>2]|0)+(e<<6)+12>>2]|0);e=e+1|0;d=c[f>>2]|0}e=c[d+196>>2]|0;if((b[d+236>>1]|0)==-1){$I(e+-64|0);break}else{$I(e);break}}while(0);if((to(a)|0)!=(a|0)){pw(c[(c[f>>2]|0)+12>>2]|0);Qo(a,122277)|0}}return}function Jf(a){a=a|0;var b=0,d=0,e=0;e=a+16|0;d=c[e>>2]|0;b=c[d+176>>2]|0;while(1){a=b+-1|0;if((b|0)<=0)break;b=c[(c[d+172>>2]|0)+(a<<2)>>2]|0;Yg(b);$I(c[b+16>>2]|0);$I(b);b=a;d=c[e>>2]|0}b=c[d+184>>2]|0;while(1){a=b+-1|0;if((b|0)<=0)break;b=c[(c[(c[e>>2]|0)+180>>2]|0)+(a<<2)>>2]|0;Yg(b);$I(c[b+16>>2]|0);$I(b);b=a}return}function Kf(a){a=a|0;if(nn(a)|0)Lf(a);ay(a);return}function Lf(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;h=l;l=l+48|0;g=h+32|0;f=h;b=ft(a,-1,8)|0;d=gt(a,0,f)|0;et(a,2,8,f)|0;d=(d|0)==0;e=(b|0)<0;if(e&d)Mf(a);else{if(d)c[f+16>>2]=3;else b=e?8:b;c[f+8>>2]=b;c[f+20>>2]=0;e=Cs(a,g,0)|0;b=c[g>>2]|0;do if((b|0)==1){Mf(a);b=0}else{if(c[(c[(c[a+16>>2]|0)+8>>2]|0)+84>>2]|0){Mf(a);b=0;break}c[f+12>>2]=1;d=0;while(1){if((d|0)>=(b|0))break;b=c[e+(d<<2)>>2]|0;Nf(b,a);Mf(b);d=d+1|0;b=c[g>>2]|0}Of(a);dt(c[g>>2]|0,e,a,f)|0;Pf(a);Qf(c[g>>2]|0,e,a);b=0}while(0);while(1){if((b|0)>=(c[g>>2]|0))break;f=e+(b<<2)|0;$I(c[(c[(c[f>>2]|0)+16>>2]|0)+8>>2]|0);If(c[f>>2]|0);ro(a,c[f>>2]|0)|0;b=b+1|0}$I(e)}l=h;return}function Mf(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;m=l;l=l+48|0;k=m+40|0;e=m;i=EA(a,zm(a,0,77944,0)|0,-1,1)|0;JB(a,10);d=zk(a,e)|0;Sf(a,a);Cf(a);f=(i|0)==1;g=e+32|0;h=(i|0)==2;i=(i|0)==3;j=e+28|0;e=e+24|0;while(1){lj(a,d);if(f){d=3;break}if(c[g>>2]|0){$l(0,77950,k)|0;c[e>>2]=0;d=0}vh(a,(d|0)!=0&1);if(h){d=7;break}yi(a,d);if(i){d=9;break}n=(c[j>>2]|0)+-1|0;c[j>>2]=n;if(!((n|0)!=0&(c[e>>2]|0)!=0)){d=11;break}}if((d|0)==3)Tf(a,1);else if((d|0)==7)Tf(a,2);else if((d|0)==9)Tf(a,2);else if((d|0)==11){if(b[(c[a+16>>2]|0)+136>>1]&16)Uf(a);fk(a);Yf(a);if((JA(Jm(a,78041)|0)|0)<<24>>24)$k(a)}l=m;return}function Nf(b,d){b=b|0;d=d|0;var e=0,f=0;Oo(b,122277,280,1)|0;e=ww(96)|0;b=c[b+16>>2]|0;c[b+8>>2]=e;d=c[d+16>>2]|0;f=c[d+8>>2]|0;h[e>>3]=+h[f>>3];h[e+24>>3]=+h[f+24>>3];c[b+144>>2]=c[d+144>>2];a[b+115>>0]=a[d+115>>0]|0;c[b+116>>2]=c[d+116>>2];c[b+248>>2]=c[d+248>>2];c[b+252>>2]=c[d+252>>2];c[b+244>>2]=c[d+244>>2];return}function Of(a){a=a|0;var b=0,d=0,e=0;b=ww((nn(a)|0)<<4)|0;d=eo(a)|0;while(1){if(!d)break;e=c[d+16>>2]|0;c[e+132>>2]=b;h[b>>3]=+h[e+16>>3]*.013888888888888888;h[b+8>>3]=+h[e+24>>3]*.013888888888888888;b=b+16|0;d=fo(a,d)|0}return}function Pf(a){a=a|0;var b=0,d=0,e=0,f=0;e=c[(c[(eo(a)|0)+16>>2]|0)+132>>2]|0;b=e;d=eo(a)|0;while(1){if(!d)break;f=c[d+16>>2]|0;c[f+132>>2]=0;h[f+16>>3]=+h[b>>3]*72.0;h[f+24>>3]=+h[b+8>>3]*72.0;b=b+16|0;d=fo(a,d)|0}$I(e);return}function Qf(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=0;f=0;while(1){if((e|0)>=(a|0))break;i=(c[(c[(c[b+(e<<2)>>2]|0)+16>>2]|0)+180>>2]|0)+f|0;e=e+1|0;f=i}i=d+16|0;c[(c[i>>2]|0)+180>>2]=f;g=ww((f<<2)+4|0)|0;c[(c[i>>2]|0)+184>>2]=g;g=0;e=1;while(1){if((g|0)>=(a|0))break;h=(c[b+(g<<2)>>2]|0)+16|0;f=1;while(1){d=c[h>>2]|0;if((f|0)>(c[d+180>>2]|0))break;d=Bs(c[(c[d+184>>2]|0)+(f<<2)>>2]|0)|0;c[(c[(c[i>>2]|0)+184>>2]|0)+(e<<2)>>2]=d;Rf(c[(c[(c[h>>2]|0)+184>>2]|0)+(f<<2)>>2]|0,d);f=f+1|0;e=e+1|0}g=g+1|0}return}function Rf(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;Oo(d,122277,280,1)|0;g=d+16|0;d=(c[g>>2]|0)+16|0;f=b+16|0;b=(c[f>>2]|0)+16|0;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];c[d+16>>2]=c[b+16>>2];c[d+20>>2]=c[b+20>>2];c[d+24>>2]=c[b+24>>2];c[d+28>>2]=c[b+28>>2];b=c[f>>2]|0;d=c[g>>2]|0;a[d+275>>0]=a[b+275>>0]|0;d=d+48|0;b=b+48|0;e=d+64|0;do{c[d>>2]=c[b>>2];d=d+4|0;b=b+4|0}while((d|0)<(e|0));b=c[(c[f>>2]|0)+180>>2]|0;c[(c[g>>2]|0)+180>>2]=b;d=ww((b<<2)+4|0)|0;c[(c[g>>2]|0)+184>>2]=d;d=1;while(1){e=c[f>>2]|0;if((d|0)>(b|0))break;e=Bs(c[(c[e+184>>2]|0)+(d<<2)>>2]|0)|0;c[(c[(c[g>>2]|0)+184>>2]|0)+(d<<2)>>2]=e;Rf(c[(c[(c[f>>2]|0)+184>>2]|0)+(d<<2)>>2]|0,e);d=d+1|0}f=e+12|0;c[(c[g>>2]|0)+12>>2]=c[f>>2];c[f>>2]=0;return}function Sf(a,b){a=a|0;b=b|0;if((to(a)|0)!=(a|0))Oo(a,122277,280,1)|0;if((a|0)==(b|0))c[(c[(to(a)|0)+16>>2]|0)+188>>2]=a;a=Kp(a)|0;while(1){if(!a)break;Sf(a,b);a=Lp(a)|0}return}function Tf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+1040|0;k=m+8|0;j=m;e=m+16|0;f=zm(a,1,80018,174185)|0;g=zm(a,1,78084,174185)|0;h=(b|0)>0;d=(b|0)==1;b=eo(a)|0;while(1){if(!b)break;if(h?(i=b+16|0,c[j>>2]=c[(c[i>>2]|0)+232>>2],qL(e,122187,j)|0,Dm(b,f,e)|0,!d):0){c[k>>2]=c[(c[i>>2]|0)+236>>2];qL(e,122187,k)|0;Dm(b,g,e)|0}b=fo(a,b)|0}l=m;return}function Uf(a){a=a|0;var b=0,c=0,d=0;c=Jp(a,79522,0)|0;if(c|0){b=eo(c)|0;while(1){if(!b)break;d=fo(c,b)|0;eh(a,b);Vf(a,b);Hf(b);qo(a,b)|0;b=d}Np(a,c)|0}return}function Vf(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;j=c[(c[b+16>>2]|0)+232>>2]|0;i=a+16|0;a=c[(c[i>>2]|0)+196>>2]|0;d=c[a+(j<<6)>>2]|0;h=a+(j<<6)+4|0;g=0;e=0;while(1){if((e|0)>=(d|0)){f=7;break}f=c[(c[h>>2]|0)+(e<<2)>>2]|0;e=e+1|0;if((f|0)==(b|0)){f=4;break}else g=f}if((f|0)==4){while(1){if((e|0)>=(d|0))break;f=c[a+(j<<6)+4>>2]|0;c[f+(e+-1<<2)>>2]=c[f+(e<<2)>>2];f=c[(c[i>>2]|0)+196>>2]|0;e=e+1|0;d=c[f+(j<<6)>>2]|0;a=f;f=4}c[a+(j<<6)>>2]=d+-1}else if((f|0)==7?(g|0)!=(b|0):0)ma(78050,78057,248,78067);return}function Wf(a){a=a|0;return c[(c[(to(a)|0)+16>>2]|0)+188>>2]|0}function Xf(b,c){b=b|0;c=c|0;var d=0;d=a[b+28>>0]|0;if(a[c+28>>0]|0)if(d<<24>>24){d=~~(+h[b>>3]-+h[c>>3]);if(!d)d=~~(+h[b+8>>3]-+h[c+8>>3])}else d=-1;else d=d<<24>>24!=0&1;return d|0}function Yf(a){a=a|0;Zf(a,1);return}function Zf(d,e){d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0.0;Z=l;l=l+656|0;O=Z+592|0;N=Z+552|0;f=Z+544|0;T=Z+96|0;U=Z;Y=Z+632|0;V=d+16|0;X=b[(c[V>>2]|0)+136>>1]&14;P=X&65535;Q=T+16|0;c[Q>>2]=Z+368;R=U+16|0;c[R>>2]=Z+192;do if(X<<16>>16){S=X<<16>>16==4;do if(S){_f(d);if(!(a[(c[(c[d+60>>2]|0)+16>>2]|0)+113>>0]&1))A=9;else{$l(0,78090,f)|0;A=9}}else if(X<<16>>16==8){_f(d);if(!(a[(c[(c[d+60>>2]|0)+16>>2]|0)+113>>0]&1)){MB(d,0);n=0;m=0;k=0;break}else{$f(d);MB(d,1);n=0;m=0;k=0;break}}else A=9;while(0);if((A|0)==9){Zk(d);if(my()|0)break;W=ww(96)|0;K=c[(c[V>>2]|0)+248>>2]|0;c[Y+8>>2]=(K|0)/4|0;c[Y+12>>2]=K;k=ww(512)|0;F=Y+4|0;c[F>>2]=0;c[Y>>2]=0;j=c[V>>2]|0;C=b[j+236>>1]|0;D=0;L=0;M=k;E=k;m=k;n=k;o=k;H=0;I=0;a:while(1){if((C|0)>(b[j+238>>1]|0))break;p=c[j+196>>2]|0;i=c[p+(C<<6)>>2]|0;G=i+D|0;g=c[p+(C<<6)+4>>2]|0;f=c[g>>2]|0;if(!f)f=H;else{_=+(H|0);f=c[f+16>>2]|0;y=+h[f+16>>3]-+h[f+88>>3];f=~~(y>_?_:y)}if((i|0)!=0?(J=c[g+(i+-1<<2)>>2]|0,(J|0)!=0):0){y=+(I|0);g=c[J+16>>2]|0;_=+h[g+96>>3]+ +h[g+16>>3];g=~~(_=(i|0))break;k=c[(c[f+(C<<6)+4>>2]|0)+(x<<2)>>2]|0;w=k+16|0;f=c[w>>2]|0;i=c[f+112>>2]|0;if(i){i=i+16|0;j=c[(c[i>>2]|0)+96>>2]|0;if(!j){A=21;break a}s=j+56|0;f=f+16|0;c[s>>2]=c[f>>2];c[s+4>>2]=c[f+4>>2];c[s+8>>2]=c[f+8>>2];c[s+12>>2]=c[f+12>>2];a[(c[(c[i>>2]|0)+96>>2]|0)+81>>0]=1;f=c[w>>2]|0}if((a[f+156>>0]|0)!=0?($a[c[17228>>2]&31](k)|0)<<24>>24==0:0){q=t;f=r;j=u;k=v;i=o}else{s=0;q=t;j=u;k=v;A=25}b:do if((A|0)==25){while(1){A=0;p=c[w>>2]|0;i=c[(c[p+180>>2]|0)+(s<<2)>>2]|0;if(!i)break;switch(a[(c[i+16>>2]|0)+112>>0]|0){case 6:case 4:{f=q;i=r;break}default:{ag(i,1,16,64);f=q+1|0;c[r+(q<<2)>>2]=i;if(!(f&127)){g=zw(g,(q<<2)+516|0)|0;i=g;j=g;k=g;n=g;o=g}else i=r}}s=s+1|0;q=f;r=i;A=25}f=c[p+188>>2]|0;c:do if(!f)i=o;else{s=0;i=o;while(1){f=c[f+(s<<2)>>2]|0;if(!f)break c;ag(f,2,0,128);o=q+1|0;c[r+(q<<2)>>2]=f;if(!(o&127)){g=zw(i,(q<<2)+516|0)|0;f=g;j=g;k=g;n=g;i=g}else f=r;p=c[w>>2]|0;s=s+1|0;q=o;r=f;f=c[p+188>>2]|0}}while(0);f=c[p+204>>2]|0;if(!f)f=r;else{if(!(a[p+156>>0]|0)){v=p+96|0;_=+h[v>>3];s=p+240|0;h[v>>3]=+h[s>>3];h[s>>3]=_;s=0;p=r}else{s=0;p=r}while(1){f=c[f+(s<<2)>>2]|0;if(!f){f=p;break b}ag(f,0,0,128);o=q+1|0;c[p+(q<<2)>>2]=f;if(!(o&127)){g=zw(n,(q<<2)+516|0)|0;f=g;j=g;k=g;n=g;i=g}else f=p;s=s+1|0;q=o;p=f;f=c[(c[w>>2]|0)+204>>2]|0}}}while(0);u=c[V>>2]|0;w=c[u+196>>2]|0;x=x+1|0;t=q;r=f;q=u;u=j;v=k;o=i;i=c[w+(C<<6)>>2]|0;f=w}C=C+1|0;D=G;L=t;M=r;E=u;j=q;m=v;k=g;H=B;I=z}if((A|0)==21)ma(78158,78171,313,78184);c[Y>>2]=H;c[F>>2]=I;sL(E,L,4,10);c[W+84>>2]=ww((D<<5)+11520|0)|0;c[Y+16>>2]=ww(C<<5)|0;d:do if(X<<16>>16==2){f=(c[V>>2]|0)+192|0;while(1){g=c[f>>2]|0;if(!g)break d;i=g+16|0;f=c[i>>2]|0;if((a[f+156>>0]|0)==1?(c[f+104>>2]|0)!=0:0){cg(g);f=c[i>>2]|0}f=f+164|0}}while(0);z=U+48|0;A=U+-48|0;B=T+48|0;C=T+-48|0;y=+(K|0);x=0;e:while(1){if((x|0)>=(L|0))break;v=M+(x<<2)|0;r=c[v>>2]|0;s=dg(r)|0;t=r+16|0;g=c[t>>2]|0;if(!(a[g+44>>0]|0)){g=(a[g+84>>0]|0)==0?s:r;f=g;g=c[g+16>>2]|0}else f=r;i=f+16|0;if(c[g+164>>2]&32){g=c[Q>>2]|0;UN(g|0,c[i>>2]|0,176)|0;n=T;o=f;p=n+48|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));c[Q>>2]=g;o=c[f>>2]&3;n=c[T>>2]&3;c[((n|0)==3?T:B)+40>>2]=c[((o|0)==2?f:f+-48|0)+40>>2];c[((n|0)==2?T:C)+40>>2]=c[((o|0)==3?f:f+48|0)+40>>2];n=g+16|0;o=(c[i>>2]|0)+56|0;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));n=g+56|0;o=(c[i>>2]|0)+16|0;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));a[g+112>>0]=1;c[g+116>>2]=f;f=T}q=f+16|0;w=1;f=x;while(1){u=f+1|0;if((u|0)>=(L|0))break;j=M+(u<<2)|0;f=c[j>>2]|0;if((s|0)!=(dg(f)|0))break;if(!(a[(c[t>>2]|0)+113>>0]|0)){k=f+16|0;g=c[k>>2]|0;if(!(a[g+44>>0]|0)){g=(a[g+84>>0]|0)==0?s:f;f=g;g=c[g+16>>2]|0}i=f+16|0;if(c[g+164>>2]&32){g=c[R>>2]|0;UN(g|0,c[i>>2]|0,176)|0;n=U;o=f;p=n+48|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));c[R>>2]=g;o=c[f>>2]&3;n=c[U>>2]&3;c[((n|0)==3?U:z)+40>>2]=c[((o|0)==2?f:f+-48|0)+40>>2];c[((n|0)==2?U:A)+40>>2]=c[((o|0)==3?f:f+48|0)+40>>2];n=g+16|0;o=(c[i>>2]|0)+56|0;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));n=g+56|0;o=(c[i>>2]|0)+16|0;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));a[g+112>>0]=1;c[g+116>>2]=f}i=c[q>>2]|0;f=g+16|0;n=N;o=i+16|0;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));n=O;o=f;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));if(Xf(N,O)|0)break;f=g+56|0;n=N;o=i+56|0;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));n=O;o=f;p=n+40|0;do{c[n>>2]=c[o>>2];n=n+4|0;o=o+4|0}while((n|0)<(p|0));if(Xf(N,O)|0)break;K=c[t>>2]|0;if((c[K+164>>2]&15|0)==2?(c[K+96>>2]|0)!=(c[(c[k>>2]|0)+96>>2]|0):0)break;if(c[(c[(c[j>>2]|0)+16>>2]|0)+164>>2]&64|0)break}w=w+1|0;f=u}if(S){if((w|0)==1)f=O;else f=ww(w<<2)|0;c[f>>2]=dg(c[v>>2]|0)|0;g=1;while(1){if((g|0)>=(w|0))break;c[f+(g<<2)>>2]=c[v+(g<<2)>>2];g=g+1|0}vy(d,f,w,P,17224);if((w|0)>1)$I(f);x=u;continue}f=c[r>>2]&3;K=c[((f|0)==3?r:r+48|0)+40>>2]|0;f=c[((f|0)==2?r:r+-48|0)+40>>2]|0;g=c[K+16>>2]|0;i=c[g+232>>2]|0;if((K|0)!=(f|0))if((i|0)==(c[(c[f+16>>2]|0)+232>>2]|0)){eg(d,Y,W,M,x,w,P);x=u;continue}else{fg(d,Y,W,M,x,w,P);x=u;continue}f=c[V>>2]|0;do if((i|0)==(b[f+238>>1]|0))if((i|0)>0){f=~~(+h[(c[(c[c[(c[f+196>>2]|0)+(i+-1<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]-+h[g+24>>3]);break}else{f=~~+h[g+80>>3];break}else if((i|0)==(b[f+236>>1]|0)){f=~~(+h[g+24>>3]-+h[(c[(c[c[(c[f+196>>2]|0)+(i+1<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]);break}else{f=c[f+196>>2]|0;_=+h[g+24>>3];K=~~(+h[(c[(c[c[f+(i+-1<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]-_);f=~~(_-+h[(c[(c[c[f+(i+1<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]);f=(K|0)<(f|0)?K:f;break}while(0);Sz(W,M,x,w,y,+((f|0)/2|0|0),17224);f=0;while(1){if((f|0)>=(w|0)){x=u;continue e}g=c[(c[(c[M+(f+x<<2)>>2]|0)+16>>2]|0)+96>>2]|0;if(g|0)cB(d,g);f=f+1|0}}f=(c[V>>2]|0)+192|0;while(1){g=c[f>>2]|0;if(!g)break;i=g+16|0;f=c[i>>2]|0;if((a[f+156>>0]|0)==1?(c[f+104>>2]|0)!=0:0){cg(g);cB(d,c[(c[i>>2]|0)+104>>2]|0);f=c[i>>2]|0}f=f+164|0}if(!e){n=W;k=W}else{gg(d);n=W;k=W}}f:do if((c[42242]|0)!=0|(c[42243]|0)!=0?(c[42248]|0)!=0|(c[42247]|0)!=0:0){j=eo(d)|0;while(1){if(!j)break f;g:do if(c[42242]|0){f=Tm(d,j)|0;while(1){if(!f)break g;g=f+-48|0;i=(c[f>>2]&3|0)==2?f:g;if(c[(c[i+16>>2]|0)+100>>2]|0){_z(i,1)|0;cB(d,c[(c[((c[f>>2]&3|0)==2?f:g)+16>>2]|0)+100>>2]|0)}f=Um(d,f)|0}}while(0);h:do if(c[42243]|0){f=Qm(d,j)|0;while(1){if(!f)break h;g=f+16|0;if(c[(c[g>>2]|0)+104>>2]|0?_z(f,0)|0:0)cB(d,c[(c[g>>2]|0)+104>>2]|0);f=Sm(d,f)|0}}while(0);j=fo(d,j)|0}}while(0);switch(X&15){case 4:case 8:break;default:{$I(m);$I(c[n+84>>2]|0);$I(k);$I(c[Y+16>>2]|0);ny()}}c[42182]=1;c[42183]=1}while(0);l=Z;return}function _f(a){a=a|0;var b=0,d=0,e=0.0,f=0;b=eo(a)|0;while(1){if(!b)break;d=c[b+16>>2]|0;if(c[d+204>>2]|0){f=d+96|0;e=+h[f>>3];d=d+240|0;h[f>>3]=+h[d>>3];h[d>>3]=e}b=fo(a,b)|0}return}function $f(b){b=b|0;var d=0,e=0,f=0,g=0;d=(c[b+16>>2]|0)+192|0;a:while(1){f=c[d>>2]|0;if(!f){d=12;break}g=f+16|0;d=c[g>>2]|0;do if((a[d+156>>0]|0)==1){e=c[d+112>>2]|0;if(!e){e=c[d+104>>2]|0;if(!e)break;cg(f);d=e}else{e=c[(c[e+16>>2]|0)+96>>2]|0;if(!e){d=6;break a}f=e+56|0;d=d+16|0;c[f>>2]=c[d>>2];c[f+4>>2]=c[d+4>>2];c[f+8>>2]=c[d+8>>2];c[f+12>>2]=c[d+12>>2];a[e+81>>0]=1;d=e}cB(b,d);d=c[g>>2]|0}while(0);d=d+164|0}if((d|0)==6)ma(78358,78171,234,78377);else if((d|0)==12)return}function ag(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0;do if(!d){g=c[b>>2]&3;d=c[((g|0)==3?b:b+48|0)+40>>2]|0;g=c[((g|0)==2?b:b+-48|0)+40>>2]|0;if((d|0)!=(g|0)){d=(c[(c[d+16>>2]|0)+232>>2]|0)==(c[(c[g+16>>2]|0)+232>>2]|0)?2:1;break}d=c[b+16>>2]|0;if(!(a[d+44>>0]|0))d=(a[d+84>>0]|0)==0?8:4;else d=4}while(0);a:do if(!e)switch(d|0){case 1:{e=c[b>>2]&3;e=(c[(c[(c[((e|0)==3?b:b+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)<(c[(c[(c[((e|0)==2?b:b+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)?16:32;break a}case 2:{e=c[b>>2]&3;e=(c[(c[(c[((e|0)==3?b:b+48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)<(c[(c[(c[((e|0)==2?b:b+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)?16:32;break a}default:{e=16;break a}}while(0);c[(c[b+16>>2]|0)+164>>2]=d|f|e;return}function bg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;D=l;l=l+624|0;z=D+584|0;y=D+544|0;s=D+368|0;e=D+192|0;t=D+96|0;v=D;u=t+16|0;c[u>>2]=s;w=v+16|0;c[w>>2]=e;C=c[b>>2]|0;B=c[d>>2]|0;x=C+16|0;q=c[x>>2]|0;d=c[q+164>>2]|0;f=d&15;A=B+16|0;b=c[A>>2]|0;g=c[b+164>>2]&15;do if((g|0)==(f|0)){p=dg(C)|0;r=dg(B)|0;n=c[p>>2]|0;g=n&3;f=c[(c[((g|0)==3?p:p+48|0)+40>>2]|0)+16>>2]|0;g=c[(c[((g|0)==2?p:p+-48|0)+40>>2]|0)+16>>2]|0;i=(c[f+232>>2]|0)-(c[g+232>>2]|0)|0;o=c[r>>2]|0;m=o&3;k=c[(c[((m|0)==3?r:r+48|0)+40>>2]|0)+16>>2]|0;m=c[(c[((m|0)==2?r:r+-48|0)+40>>2]|0)+16>>2]|0;j=(c[k+232>>2]|0)-(c[m+232>>2]|0)|0;i=(i|0)>-1?i:0-i|0;j=(j|0)>-1?j:0-j|0;if((i|0)!=(j|0)){b=i-j|0;break}g=~~(+h[f+16>>3]-+h[g+16>>3]);g=(g|0)>-1?g:0-g|0;f=~~(+h[k+16>>3]-+h[m+16>>3]);f=(f|0)>-1?f:0-f|0;if((g|0)!=(f|0)){b=g-f|0;break}g=n>>>4;f=o>>>4;if((g|0)!=(f|0)){b=g-f|0;break}if(!(a[q+44>>0]|0)){d=(a[q+84>>0]|0)==0?p:C;g=d;d=c[(c[d+16>>2]|0)+164>>2]|0}else g=C;f=g+16|0;if(d&32){UN(s|0,c[f>>2]|0,176)|0;i=t;j=g;k=i+48|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));c[u>>2]=s;j=c[g>>2]&3;i=c[t>>2]&3;c[((i|0)==3?t:t+48|0)+40>>2]=c[((j|0)==2?g:g+-48|0)+40>>2];c[((i|0)==2?t:t+-48|0)+40>>2]=c[((j|0)==3?g:g+48|0)+40>>2];i=s+16|0;j=(c[f>>2]|0)+56|0;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));i=s+56|0;j=(c[f>>2]|0)+16|0;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));a[s+112>>0]=1;c[s+116>>2]=g;g=t;b=c[A>>2]|0}if(!(a[b+44>>0]|0)){b=(a[b+84>>0]|0)==0?r:B;f=b;b=c[b+16>>2]|0}else f=B;d=f+16|0;if(!(c[b+164>>2]&32))e=b;else{UN(e|0,c[d>>2]|0,176)|0;i=v;j=f;k=i+48|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));c[w>>2]=e;j=c[f>>2]&3;i=c[v>>2]&3;c[((i|0)==3?v:v+48|0)+40>>2]=c[((j|0)==2?f:f+-48|0)+40>>2];c[((i|0)==2?v:v+-48|0)+40>>2]=c[((j|0)==3?f:f+48|0)+40>>2];i=e+16|0;j=(c[d>>2]|0)+56|0;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));i=e+56|0;j=(c[d>>2]|0)+16|0;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));a[e+112>>0]=1;c[e+116>>2]=f}d=c[g+16>>2]|0;b=e+16|0;i=y;j=d+16|0;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));i=z;j=b;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));b=Xf(y,z)|0;if(!b){b=e+56|0;i=y;j=d+56|0;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));i=z;j=b;k=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(k|0));b=Xf(y,z)|0;if(!b){d=c[(c[x>>2]|0)+164>>2]&192;b=c[(c[A>>2]|0)+164>>2]&192;if((d|0)==(b|0)){b=((c[C>>2]|0)>>>4)-((c[B>>2]|0)>>>4)|0;break}else{b=d-b|0;break}}}}else b=g-f|0;while(0);l=D;return b|0}function cg(b){b=b|0;var d=0,e=0,f=0,g=0.0,i=0.0;f=b+16|0;d=c[f>>2]|0;if(c[d+176>>2]|0){d=c[d+180>>2]|0;while(1){d=(c[d>>2]|0)+16|0;e=c[d>>2]|0;if(!(a[e+112>>0]|0))break;else d=e+116|0}e=c[e+96>>2]|0;g=+h[e+24>>3];i=+h[e+32>>3];e=(c[(c[(so(b)|0)+16>>2]|0)+116>>2]&1|0)!=0;b=c[f>>2]|0;f=c[(c[d>>2]|0)+96>>2]|0;h[f+56>>3]=(e?i:g)*.5+ +h[b+16>>3];h[f+64>>3]=+h[b+24>>3];a[f+81>>0]=1}return}function dg(a){a=a|0;var b=0,d=0;while(1){b=c[a+16>>2]|0;d=c[b+172>>2]|0;if(!d)break;else a=d}while(1){b=c[b+116>>2]|0;if(!b)break;a=b;b=c[b+16>>2]|0}return a|0}function eg(b,d,e,f,g,i,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;var k=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0,x=0,y=0,z=0,A=0,B=0,C=0.0,D=0.0,E=0.0,F=0.0,G=0.0;B=l;l=l+1712|0;x=B+1664|0;s=B+1488|0;t=B+1392|0;A=B+1696|0;y=B+696|0;z=B;p=t+16|0;c[p>>2]=s;q=c[f+(g<<2)>>2]|0;r=q+16|0;k=c[r>>2]|0;u=a[k+113>>0]|0;if(c[k+164>>2]&32){UN(s|0,k|0,176)|0;k=t;n=q;o=k+48|0;do{c[k>>2]=c[n>>2];k=k+4|0;n=n+4|0}while((k|0)<(o|0));c[p>>2]=s;k=c[t>>2]&3;c[((k|0)==3?t:t+48|0)+40>>2]=c[((c[q>>2]&3|0)==2?q:q+-48|0)+40>>2];c[((k|0)==2?t:t+-48|0)+40>>2]=c[((c[q>>2]&3|0)==3?q:q+48|0)+40>>2];k=s+16|0;n=(c[r>>2]|0)+56|0;o=k+40|0;do{c[k>>2]=c[n>>2];k=k+4|0;n=n+4|0}while((k|0)<(o|0));k=s+56|0;n=(c[r>>2]|0)+16|0;o=k+40|0;do{c[k>>2]=c[n>>2];k=k+4|0;n=n+4|0}while((k|0)<(o|0));a[s+112>>0]=1;c[s+116>>2]=q;q=t}k=1;while(1){if((k|0)>=(i|0)){w=6;break}if(!(a[(c[(c[f+(k+g<<2)>>2]|0)+16>>2]|0)+113>>0]|0))k=k+1|0;else{w=7;break}}a:do if((w|0)==6)if(!(u<<24>>24)){k=c[q+16>>2]|0;if(c[k+96>>2]|0){Eg(b,d,e,q,j);break}if((j|0)==2){A=c[q>>2]&3;Fg(c[((A|0)==3?q:q+48|0)+40>>2]|0,c[((A|0)==2?q:q+-48|0)+40>>2]|0,f,g,i,2);break}t=a[k+49>>0]|0;u=a[k+89>>0]|0;if(!(t<<24>>24==1&u<<24>>24!=4)?!(t<<24>>24!=4&u<<24>>24==1):0){p=c[q>>2]&3;o=c[((p|0)==3?q:q+48|0)+40>>2]|0;p=c[((p|0)==2?q:q+-48|0)+40>>2]|0;k=c[o+16>>2]|0;n=c[k+232>>2]|0;if((n|0)>0){u=c[(c[b+16>>2]|0)+196>>2]|0;t=n+~(a[(c[(c[b+60>>2]|0)+16>>2]|0)+113>>0]&1)|0;m=+h[(c[(c[c[u+(t<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]-+h[u+(t<<6)+16>>3]-+h[k+24>>3]-+h[u+(n<<6)+24>>3]}else m=+(c[(c[b+16>>2]|0)+252>>2]|0);C=+(i+1|0);v=+(c[d+12>>2]|0)/C;m=m/C;Hg(b,d,e,o,q,y,1);Hg(b,d,e,p,q,z,0);s=y+52|0;t=z+52|0;p=(j|0)==10;q=e+80|0;k=0;while(1){if((k|0)>=(i|0))break a;r=c[f+(k+g<<2)>>2]|0;o=c[s>>2]|0;n=o+-1|0;G=+h[y+56+(n<<5)>>3];F=+h[y+56+(n<<5)+16>>3];E=+h[y+56+(n<<5)+24>>3];h[16878]=G;h[16879]=E;k=k+1|0;C=+(k|0);D=v*C;h[16880]=F+D;C=E+m*C;h[16881]=C;h[16882]=G;h[16883]=C;n=(c[t>>2]|0)+-1|0;G=+h[z+56+(n<<5)+16>>3];h[16884]=G;h[16885]=C+m;E=+h[z+56+(n<<5)>>3];F=+h[z+56+(n<<5)+24>>3];h[16888]=G;h[16887]=F;h[16886]=E-D;h[16889]=C;n=0;while(1){if((n|0)>=(o|0)){n=0;break}o=y+56+(n<<5)|0;c[x>>2]=c[o>>2];c[x+4>>2]=c[o+4>>2];c[x+8>>2]=c[o+8>>2];c[x+12>>2]=c[o+12>>2];c[x+16>>2]=c[o+16>>2];c[x+20>>2]=c[o+20>>2];c[x+24>>2]=c[o+24>>2];c[x+28>>2]=c[o+28>>2];Mz(e,x);n=n+1|0;o=c[s>>2]|0}while(1){if((n|0)==3)break;j=135024+(n<<5)|0;c[x>>2]=c[j>>2];c[x+4>>2]=c[j+4>>2];c[x+8>>2]=c[j+8>>2];c[x+12>>2]=c[j+12>>2];c[x+16>>2]=c[j+16>>2];c[x+20>>2]=c[j+20>>2];c[x+24>>2]=c[j+24>>2];c[x+28>>2]=c[j+28>>2];Mz(e,x);n=n+1|0}o=c[t>>2]|0;while(1){n=o+-1|0;if((o|0)<=0)break;o=z+56+(n<<5)|0;c[x>>2]=c[o>>2];c[x+4>>2]=c[o+4>>2];c[x+8>>2]=c[o+8>>2];c[x+12>>2]=c[o+12>>2];c[x+16>>2]=c[o+16>>2];c[x+20>>2]=c[o+20>>2];c[x+24>>2]=c[o+24>>2];c[x+28>>2]=c[o+28>>2];Mz(e,x);o=n}if(p)n=oy(e,A)|0;else n=uy(e,A)|0;o=c[A>>2]|0;if(!o)break a;Kz(r,c[((c[r>>2]&3|0)==2?r:r+-48|0)+40>>2]|0,n,o,17224);c[q>>2]=0}}Gg(b,d,e,f,g,i,q,(j|0)==10&1)}else w=7;while(0);if((w|0)==7)Dg(b,f,g,i,q,j);l=B;return}function fg(b,d,e,f,g,i,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;var k=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0;ba=l;l=l+2576|0;S=ba+2528|0;_=ba+2568|0;k=ba+2352|0;n=ba+2176|0;t=ba+1904|0;Y=ba+1808|0;$=ba+1712|0;T=ba+1016|0;U=ba+320|0;V=ba+256|0;X=ba+2564|0;Z=ba+2560|0;z=ba+288|0;A=ba+224|0;L=ba+192|0;M=ba+160|0;N=ba+128|0;P=ba+96|0;Q=ba+64|0;R=ba+32|0;W=ba;s=t+16|0;c[s>>2]=k;o=Y+16|0;c[o>>2]=n;aa=$+16|0;c[aa>>2]=ba+2e3;if(!(c[41920]|0)){c[41920]=xw(32e3)|0;c[41921]=xw(32e3)|0;c[41922]=2e3;c[41923]=2e3}u=c[f+(g<<2)>>2]|0;K=c[u>>2]&3;p=u+48|0;q=u+-48|0;K=(c[(c[(c[((K|0)==3?u:p)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((K|0)==2?u:q)+40>>2]|0)+16>>2]|0)+232>>2]|0)|0;r=u+16|0;if((((K|0)>-1?K:0-K|0)|0)<=1){k=c[r>>2]|0;if(!(c[k+164>>2]&32)){K=u;n=0}else{n=c[s>>2]|0;UN(n|0,k|0,176)|0;w=t;x=u;y=w+48|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));c[s>>2]=n;w=c[t>>2]&3;c[((w|0)==3?t:t+48|0)+40>>2]=c[((c[u>>2]&3|0)==2?u:q)+40>>2];c[((w|0)==2?t:t+-48|0)+40>>2]=c[((c[u>>2]&3|0)==3?u:p)+40>>2];w=n+16|0;x=(c[r>>2]|0)+56|0;y=w+40|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));k=c[s>>2]|0;w=k+56|0;x=(c[r>>2]|0)+16|0;y=w+40|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));a[k+112>>0]=1;n=0;J=12}}else{UN(k|0,c[r>>2]|0,176)|0;w=t;x=u;y=w+48|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));w=t+48|0;x=p;y=w+48|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));c[s>>2]=k;k=c[r>>2]|0;if(!(c[k+164>>2]&32)){UN(n|0,k|0,176)|0;w=Y;x=u;y=w+48|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));c[o>>2]=n;o=c[t>>2]|0;c[((o&3|0)==3?t:t+48|0)+40>>2]=c[((c[u>>2]&3|0)==3?u:p)+40>>2];w=Y+48|0;x=p;y=w+48|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0))}else{n=c[o>>2]|0;UN(n|0,k|0,176)|0;w=Y;x=u;y=w+48|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));c[o>>2]=n;w=c[Y>>2]&3;c[((w|0)==3?Y:Y+48|0)+40>>2]=c[((c[u>>2]&3|0)==2?u:q)+40>>2];c[((w|0)==2?Y:Y+-48|0)+40>>2]=c[((c[u>>2]&3|0)==3?u:p)+40>>2];w=n+16|0;x=(c[r>>2]|0)+56|0;y=w+40|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));k=c[o>>2]|0;w=k+56|0;x=(c[r>>2]|0)+16|0;y=w+40|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));a[k+112>>0]=1;c[k+116>>2]=u;o=c[t>>2]|0;c[((o&3|0)==3?t:t+48|0)+40>>2]=c[((c[u>>2]&3|0)==2?u:q)+40>>2];w=(c[s>>2]|0)+16|0;x=(c[r>>2]|0)+56|0;y=w+40|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0))}k=dg(u)|0;while(1){n=c[(c[k+16>>2]|0)+172>>2]|0;if(!n)break;else k=n}c[((o&3|0)==2?t:t+-48|0)+40>>2]=c[((c[k>>2]&3|0)==2?k:k+-48|0)+40>>2];k=c[s>>2]|0;a[k+84>>0]=0;a[k+112>>0]=1;n=k+56|0;c[n>>2]=0;c[n+4>>2]=0;c[n+8>>2]=0;c[n+12>>2]=0;n=1;J=12}if((J|0)==12){c[k+116>>2]=u;K=t}H=(j|0)==2;if(H?(v=jg(b,K,c[41920]|0,_)|0,c[Z>>2]=v,(v|0)!=0):0)J=63;else J=15;a:do if((J|0)==15){G=(j|0)==10;c[Z>>2]=0;o=c[K>>2]&3;k=c[((o|0)==3?K:K+48|0)+40>>2]|0;o=c[((o|0)==2?K:K+-48|0)+40>>2]|0;c[_>>2]=o;kg(z,b,d,k,0,K);c[T>>2]=c[z>>2];c[T+4>>2]=c[z+4>>2];c[T+8>>2]=c[z+8>>2];c[T+12>>2]=c[z+12>>2];c[T+16>>2]=c[z+16>>2];c[T+20>>2]=c[z+20>>2];c[T+24>>2]=c[z+24>>2];c[T+28>>2]=c[z+28>>2];c[V>>2]=c[z>>2];c[V+4>>2]=c[z+4>>2];c[V+8>>2]=c[z+8>>2];c[V+12>>2]=c[z+12>>2];c[V+16>>2]=c[z+16>>2];c[V+20>>2]=c[z+20>>2];Nz(e,K,1,T,lg(k)|0);B=T+52|0;I=(c[B>>2]|0)+-1|0;D=V+24|0;h[D>>3]=+h[T+56+(I<<5)+24>>3];E=V+8|0;h[E>>3]=+h[T+56+(I<<5)+8>>3];I=c[k+16>>2]|0;F=b+16|0;m=+h[I+24>>3]-+h[(c[(c[F>>2]|0)+196>>2]|0)+(c[I+232>>2]<<6)+16>>3];c[S>>2]=c[V>>2];c[S+4>>2]=c[V+4>>2];c[S+8>>2]=c[V+8>>2];c[S+12>>2]=c[V+12>>2];c[S+16>>2]=c[V+16>>2];c[S+20>>2]=c[V+20>>2];c[S+24>>2]=c[V+24>>2];c[S+28>>2]=c[V+28>>2];mg(A,S,1,m);c[V>>2]=c[A>>2];c[V+4>>2]=c[A+4>>2];c[V+8>>2]=c[A+8>>2];c[V+12>>2]=c[A+12>>2];c[V+16>>2]=c[A+16>>2];c[V+20>>2]=c[A+20>>2];c[V+24>>2]=c[A+24>>2];c[V+28>>2]=c[A+28>>2];A=V+16|0;if(+h[V>>3]<+h[A>>3]?+h[E>>3]<+h[D>>3]:0){I=c[B>>2]|0;c[B>>2]=I+1;I=T+56+(I<<5)|0;c[I>>2]=c[V>>2];c[I+4>>2]=c[V+4>>2];c[I+8>>2]=c[V+8>>2];c[I+12>>2]=c[V+12>>2];c[I+16>>2]=c[V+16>>2];c[I+20>>2]=c[V+20>>2];c[I+24>>2]=c[V+24>>2];c[I+28>>2]=c[V+28>>2]}w=b+60|0;C=U+52|0;x=e+56|0;y=e+69|0;j=e+16|0;z=e+29|0;I=K;q=0;r=-1;b:while(1){s=k;t=0;k=0;u=I;while(1){p=o;v=o;if((a[(c[p+16>>2]|0)+156>>0]|0)!=1)break b;if(($a[c[17228>>2]&31](p)|0)<<24>>24)break b;o=t|1;ca=135024+(t<<5)|0;ng(L,d,b,c[(c[s+16>>2]|0)+232>>2]|0);c[ca>>2]=c[L>>2];c[ca+4>>2]=c[L+4>>2];c[ca+8>>2]=c[L+8>>2];c[ca+12>>2]=c[L+12>>2];c[ca+16>>2]=c[L+16>>2];c[ca+20>>2]=c[L+20>>2];c[ca+24>>2]=c[L+24>>2];c[ca+28>>2]=c[L+28>>2];if(!k){q=og(p)|0;k=(q|0)<((a[(c[(c[w>>2]|0)+16>>2]|0)+113>>0]<<1&2)+3&255|0);q=k?q:q+-2|0;r=k?r:1;k=(k^1)&1}if(!((k|0)==0|(r|0)>0))break;ca=135024+(o<<5)|0;kg(M,b,d,p,u,c[c[(c[p+16>>2]|0)+180>>2]>>2]|0);c[ca>>2]=c[M>>2];c[ca+4>>2]=c[M+4>>2];c[ca+8>>2]=c[M+8>>2];c[ca+12>>2]=c[M+12>>2];c[ca+16>>2]=c[M+16>>2];c[ca+20>>2]=c[M+20>>2];c[ca+24>>2]=c[M+24>>2];c[ca+28>>2]=c[M+28>>2];ca=c[c[(c[v+16>>2]|0)+180>>2]>>2]|0;o=c[ca>>2]&3;s=c[((o|0)==3?ca:ca+48|0)+40>>2]|0;o=c[((o|0)==2?ca:ca+-48|0)+40>>2]|0;c[_>>2]=o;t=t+2|0;r=r+-1|0;u=ca}kg(N,b,d,p,u,c[c[(c[p+16>>2]|0)+180>>2]>>2]|0);c[U>>2]=c[N>>2];c[U+4>>2]=c[N+4>>2];c[U+8>>2]=c[N+8>>2];c[U+12>>2]=c[N+12>>2];c[U+16>>2]=c[N+16>>2];c[U+20>>2]=c[N+20>>2];c[U+24>>2]=c[N+24>>2];c[U+28>>2]=c[N+28>>2];Qz(e,u,1,U,lg(c[((c[u>>2]&3|0)==2?u:u+-48|0)+40>>2]|0)|0);ca=U+56+((c[C>>2]|0)+-1<<5)|0;t=c[v+16>>2]|0;m=+h[(c[(c[F>>2]|0)+196>>2]|0)+(c[t+232>>2]<<6)+24>>3]+ +h[t+24>>3];c[S>>2]=c[ca>>2];c[S+4>>2]=c[ca+4>>2];c[S+8>>2]=c[ca+8>>2];c[S+12>>2]=c[ca+12>>2];c[S+16>>2]=c[ca+16>>2];c[S+20>>2]=c[ca+20>>2];c[S+24>>2]=c[ca+24>>2];c[S+28>>2]=c[ca+28>>2];mg(V,S,4,m);if(+h[V>>3]<+h[A>>3]?+h[E>>3]<+h[D>>3]:0){ca=c[C>>2]|0;c[C>>2]=ca+1;ca=U+56+(ca<<5)|0;c[ca>>2]=c[V>>2];c[ca+4>>2]=c[V+4>>2];c[ca+8>>2]=c[V+8>>2];c[ca+12>>2]=c[V+12>>2];c[ca+16>>2]=c[V+16>>2];c[ca+20>>2]=c[V+20>>2];c[ca+24>>2]=c[V+24>>2];c[ca+28>>2]=c[V+28>>2]}h[x>>3]=1.5707963267948966;a[y>>0]=1;pg(e,I,u,T,U,o);if(!G){k=uy(e,X)|0;o=c[X>>2]|0;if(H&(o|0)>4){ca=k+16|0;c[ca>>2]=c[k>>2];c[ca+4>>2]=c[k+4>>2];c[ca+8>>2]=c[k+8>>2];c[ca+12>>2]=c[k+12>>2];ca=k+32|0;o=k+(o+-1<<4)|0;c[ca>>2]=c[o>>2];c[ca+4>>2]=c[o+4>>2];c[ca+8>>2]=c[o+8>>2];c[ca+12>>2]=c[o+12>>2];VN(k+48|0,o|0,16)|0;c[X>>2]=4;o=4}else J=33}else{k=oy(e,X)|0;o=c[X>>2]|0;J=33}if((J|0)==33){J=0;if(!o)break a}u=c[Z>>2]|0;p=u+o|0;if((p|0)>(c[41922]|0)){c[41922]=p<<1;t=zw(c[41920]|0,p<<5)|0;c[41920]=t;o=c[X>>2]|0}else t=c[41920]|0;s=0;p=u;while(1){if((s|0)>=(o|0))break;ca=t+(p<<4)|0;u=k+(s<<4)|0;c[ca>>2]=c[u>>2];c[ca+4>>2]=c[u+4>>2];c[ca+8>>2]=c[u+8>>2];c[ca+12>>2]=c[u+12>>2];s=s+1|0;p=p+1|0}c[Z>>2]=p;o=qg(c[c[(c[v+16>>2]|0)+180>>2]>>2]|0,q,t,Z)|0;rg(I,e);p=c[o>>2]&3;k=c[((p|0)==3?o:o+48|0)+40>>2]|0;p=c[((p|0)==2?o:o+-48|0)+40>>2]|0;c[_>>2]=p;I=k+16|0;kg(P,b,d,k,c[c[(c[I>>2]|0)+172>>2]>>2]|0,o);c[T>>2]=c[P>>2];c[T+4>>2]=c[P+4>>2];c[T+8>>2]=c[P+8>>2];c[T+12>>2]=c[P+12>>2];c[T+16>>2]=c[P+16>>2];c[T+20>>2]=c[P+20>>2];c[T+24>>2]=c[P+24>>2];c[T+28>>2]=c[P+28>>2];Nz(e,o,1,T,lg(k)|0);ca=T+56+((c[B>>2]|0)+-1<<5)|0;I=c[I>>2]|0;m=+h[I+24>>3]-+h[(c[(c[F>>2]|0)+196>>2]|0)+(c[I+232>>2]<<6)+16>>3];c[S>>2]=c[ca>>2];c[S+4>>2]=c[ca+4>>2];c[S+8>>2]=c[ca+8>>2];c[S+12>>2]=c[ca+12>>2];c[S+16>>2]=c[ca+16>>2];c[S+20>>2]=c[ca+20>>2];c[S+24>>2]=c[ca+24>>2];c[S+28>>2]=c[ca+28>>2];mg(V,S,1,m);if(+h[V>>3]<+h[A>>3]?+h[E>>3]<+h[D>>3]:0){ca=c[B>>2]|0;c[B>>2]=ca+1;ca=T+56+(ca<<5)|0;c[ca>>2]=c[V>>2];c[ca+4>>2]=c[V+4>>2];c[ca+8>>2]=c[V+8>>2];c[ca+12>>2]=c[V+12>>2];c[ca+16>>2]=c[V+16>>2];c[ca+20>>2]=c[V+20>>2];c[ca+24>>2]=c[V+24>>2];c[ca+28>>2]=c[V+28>>2]}h[j>>3]=-1.5707963267948966;a[z>>0]=1;I=o;o=p}k=t|1;r=135024+(t<<5)|0;ng(Q,d,b,c[(c[s+16>>2]|0)+232>>2]|0);c[r>>2]=c[Q>>2];c[r+4>>2]=c[Q+4>>2];c[r+8>>2]=c[Q+8>>2];c[r+12>>2]=c[Q+12>>2];c[r+16>>2]=c[Q+16>>2];c[r+20>>2]=c[Q+20>>2];c[r+24>>2]=c[Q+24>>2];c[r+28>>2]=c[Q+28>>2];kg(R,b,d,p,u,0);c[U>>2]=c[R>>2];c[U+4>>2]=c[R+4>>2];c[U+8>>2]=c[R+8>>2];c[U+12>>2]=c[R+12>>2];c[U+16>>2]=c[R+16>>2];c[U+20>>2]=c[R+20>>2];c[U+24>>2]=c[R+24>>2];c[U+28>>2]=c[R+28>>2];c[V>>2]=c[R>>2];c[V+4>>2]=c[R+4>>2];c[V+8>>2]=c[R+8>>2];c[V+12>>2]=c[R+12>>2];c[V+16>>2]=c[R+16>>2];c[V+20>>2]=c[R+20>>2];c[V+24>>2]=c[R+24>>2];c[V+28>>2]=c[R+28>>2];r=(n|0)!=0;s=u+-48|0;Qz(e,r?Y:u,1,U,lg(c[((c[u>>2]&3|0)==2?u:s)+40>>2]|0)|0);ca=(c[C>>2]|0)+-1|0;h[D>>3]=+h[U+56+(ca<<5)+24>>3];h[E>>3]=+h[U+56+(ca<<5)+8>>3];ca=c[v+16>>2]|0;m=+h[(c[(c[F>>2]|0)+196>>2]|0)+(c[ca+232>>2]<<6)+24>>3]+ +h[ca+24>>3];c[S>>2]=c[V>>2];c[S+4>>2]=c[V+4>>2];c[S+8>>2]=c[V+8>>2];c[S+12>>2]=c[V+12>>2];c[S+16>>2]=c[V+16>>2];c[S+20>>2]=c[V+20>>2];c[S+24>>2]=c[V+24>>2];c[S+28>>2]=c[V+28>>2];mg(W,S,4,m);c[V>>2]=c[W>>2];c[V+4>>2]=c[W+4>>2];c[V+8>>2]=c[W+8>>2];c[V+12>>2]=c[W+12>>2];c[V+16>>2]=c[W+16>>2];c[V+20>>2]=c[W+20>>2];c[V+24>>2]=c[W+24>>2];c[V+28>>2]=c[W+28>>2];if(+h[V>>3]<+h[A>>3]?+h[E>>3]<+h[D>>3]:0){ca=c[C>>2]|0;c[C>>2]=ca+1;ca=U+56+(ca<<5)|0;c[ca>>2]=c[V>>2];c[ca+4>>2]=c[V+4>>2];c[ca+8>>2]=c[V+8>>2];c[ca+12>>2]=c[V+12>>2];c[ca+16>>2]=c[V+16>>2];c[ca+20>>2]=c[V+20>>2];c[ca+24>>2]=c[V+24>>2];c[ca+28>>2]=c[V+28>>2]}pg(e,I,u,T,U,k);if(G)q=oy(e,X)|0;else q=uy(e,X)|0;k=c[X>>2]|0;if(!(H&(k|0)>4)){if(!k)break}else{ca=q+16|0;c[ca>>2]=c[q>>2];c[ca+4>>2]=c[q+4>>2];c[ca+8>>2]=c[q+8>>2];c[ca+12>>2]=c[q+12>>2];ca=q+32|0;k=q+(k+-1<<4)|0;c[ca>>2]=c[k>>2];c[ca+4>>2]=c[k+4>>2];c[ca+8>>2]=c[k+8>>2];c[ca+12>>2]=c[k+12>>2];VN(q+48|0,k|0,16)|0;c[X>>2]=4;k=4}o=c[Z>>2]|0;n=o+k|0;if((n|0)>(c[41922]|0)){c[41922]=n<<1;p=zw(c[41920]|0,n<<5)|0;c[41920]=p;k=c[X>>2]|0}else p=c[41920]|0;n=0;while(1){if((n|0)>=(k|0))break;ca=p+(o<<4)|0;X=q+(n<<4)|0;c[ca>>2]=c[X>>2];c[ca+4>>2]=c[X+4>>2];c[ca+8>>2]=c[X+8>>2];c[ca+12>>2]=c[X+12>>2];n=n+1|0;o=o+1|0}c[Z>>2]=o;rg(I,e);if(r)k=(c[Y>>2]&3|0)==2?Y:Y+-48|0;else k=(c[u>>2]&3|0)==2?u:s;c[_>>2]=c[k+40>>2];v=o;J=63}while(0);c:do if((J|0)==63){if((i|0)==1){Kz(K,c[_>>2]|0,c[41920]|0,v,17224);break}t=d+12|0;u=v+-1|0;m=+((O(c[t>>2]|0,i+-1|0)|0)/2|0|0);n=c[41920]|0;k=1;while(1){if((k|0)>=(u|0))break;ca=n+(k<<4)|0;h[ca>>3]=+h[ca>>3]-m;k=k+1|0}k=c[41922]|0;if((k|0)>(c[41923]|0)){c[41923]=k;o=zw(c[41921]|0,k<<4)|0;c[41921]=o;n=c[41920]|0}else o=c[41921]|0;k=0;while(1){if((k|0)>=(v|0))break;ca=o+(k<<4)|0;d=n+(k<<4)|0;c[ca>>2]=c[d>>2];c[ca+4>>2]=c[d+4>>2];c[ca+8>>2]=c[d+8>>2];c[ca+12>>2]=c[d+12>>2];k=k+1|0}Kz(K,c[_>>2]|0,o,v,17224);r=$+48|0;s=$+-48|0;q=1;while(1){if((q|0)>=(i|0))break c;o=c[f+(q+g<<2)>>2]|0;p=o+16|0;k=c[p>>2]|0;if(c[k+164>>2]&32){n=c[aa>>2]|0;UN(n|0,k|0,176)|0;w=$;x=o;y=w+48|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));c[aa>>2]=n;w=c[$>>2]&3;c[((w|0)==3?$:r)+40>>2]=c[((c[o>>2]&3|0)==2?o:o+-48|0)+40>>2];c[((w|0)==2?$:s)+40>>2]=c[((c[o>>2]&3|0)==3?o:o+48|0)+40>>2];w=n+16|0;x=(c[p>>2]|0)+56|0;y=w+40|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));k=c[aa>>2]|0;w=k+56|0;x=(c[p>>2]|0)+16|0;y=w+40|0;do{c[w>>2]=c[x>>2];w=w+4|0;x=x+4|0}while((w|0)<(y|0));a[k+112>>0]=1;c[k+116>>2]=o;o=$}p=c[41920]|0;k=1;while(1){if((k|0)>=(u|0))break;ca=p+(k<<4)|0;h[ca>>3]=+h[ca>>3]+ +(c[t>>2]|0);k=k+1|0}n=c[41921]|0;k=0;while(1){if((k|0)>=(v|0))break;ca=n+(k<<4)|0;_=p+(k<<4)|0;c[ca>>2]=c[_>>2];c[ca+4>>2]=c[_+4>>2];c[ca+8>>2]=c[_+8>>2];c[ca+12>>2]=c[_+12>>2];k=k+1|0}Kz(o,c[((c[o>>2]&3|0)==2?o:o+-48|0)+40>>2]|0,n,v,17224);q=q+1|0}}while(0);l=ba;return}function gg(a){a=a|0;var b=0,d=0,e=0;b=eo(a)|0;while(1){if(!b)break;d=Qm(a,b)|0;while(1){if(!d)break;if(($a[c[4306]&31](d)|0)<<24>>24?(e=c[(c[d+16>>2]|0)+8>>2]|0,e|0):0)hg(e);d=Sm(a,d)|0}b=fo(a,b)|0}return}function hg(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;f=c[a+4>>2]|0;g=xw(f*48|0)|0;b=g;d=0;e=(c[a>>2]|0)+((f+-1|0)*48|0)|0;while(1){if((d|0)>=(f|0)){b=0;break}ig(e,b);b=b+48|0;d=d+1|0;e=e+-48|0}while(1){d=c[a>>2]|0;if((b|0)>=(f|0))break;$I(c[d+(b*48|0)>>2]|0);b=b+1|0}$I(d);c[a>>2]=g;return}function ig(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;g=c[a+4>>2]|0;h=xw(g<<4)|0;d=h;e=0;f=(c[a>>2]|0)+(g+-1<<4)|0;while(1){if((e|0)>=(g|0))break;c[d>>2]=c[f>>2];c[d+4>>2]=c[f+4>>2];c[d+8>>2]=c[f+8>>2];c[d+12>>2]=c[f+12>>2];d=d+16|0;e=e+1|0;f=f+-16|0}c[b>>2]=h;c[b+4>>2]=g;c[b+8>>2]=c[a+12>>2];c[b+12>>2]=c[a+8>>2];h=b+16|0;g=a+32|0;c[h>>2]=c[g>>2];c[h+4>>2]=c[g+4>>2];c[h+8>>2]=c[g+8>>2];c[h+12>>2]=c[g+12>>2];h=b+32|0;g=a+16|0;c[h>>2]=c[g>>2];c[h+4>>2]=c[g+4>>2];c[h+8>>2]=c[g+8>>2];c[h+12>>2]=c[g+12>>2];return}function jg(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0.0,j=0.0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;x=l;l=l+96|0;q=x+80|0;s=x+64|0;r=x+48|0;u=x+32|0;v=x+16|0;w=x;m=d;while(1){t=m+16|0;g=c[t>>2]|0;if(!(a[g+112>>0]|0))break;m=c[g+116>>2]|0}g=c[m>>2]&3;o=c[((g|0)==2?m:m+-48|0)+40>>2]|0;g=c[((g|0)==3?m:m+48|0)+40>>2]|0;m=o+16|0;n=g+16|0;y=(c[(c[m>>2]|0)+232>>2]|0)-(c[(c[n>>2]|0)+232>>2]|0)|0;switch(((y|0)>-1?y:0-y|0)|0){case 1:{g=0;break}case 2:{if(!(a[(c[(c[b+60>>2]|0)+16>>2]|0)+113>>0]&1))p=6;else g=0;break}default:p=6}do if((p|0)==6){if((c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0)==(g|0)){c[f>>2]=o;y=(c[n>>2]|0)+16|0;p=(c[t>>2]|0)+16|0;c[s>>2]=c[y>>2];c[s+4>>2]=c[y+4>>2];c[s+8>>2]=c[y+8>>2];c[s+12>>2]=c[y+12>>2];c[q>>2]=c[p>>2];c[q+4>>2]=c[p+4>>2];c[q+8>>2]=c[p+8>>2];c[q+12>>2]=c[p+12>>2];Bg(u,s,q);p=(c[m>>2]|0)+16|0;y=(c[t>>2]|0)+56|0;c[s>>2]=c[p>>2];c[s+4>>2]=c[p+4>>2];c[s+8>>2]=c[p+8>>2];c[s+12>>2]=c[p+12>>2];c[q>>2]=c[y>>2];c[q+4>>2]=c[y+4>>2];c[q+8>>2]=c[y+8>>2];c[q+12>>2]=c[y+12>>2];Bg(v,s,q)}else{c[f>>2]=g;y=(c[m>>2]|0)+16|0;p=(c[t>>2]|0)+56|0;c[s>>2]=c[y>>2];c[s+4>>2]=c[y+4>>2];c[s+8>>2]=c[y+8>>2];c[s+12>>2]=c[y+12>>2];c[q>>2]=c[p>>2];c[q+4>>2]=c[p+4>>2];c[q+8>>2]=c[p+8>>2];c[q+12>>2]=c[p+12>>2];Bg(u,s,q);p=(c[n>>2]|0)+16|0;y=(c[t>>2]|0)+16|0;c[s>>2]=c[p>>2];c[s+4>>2]=c[p+4>>2];c[s+8>>2]=c[p+8>>2];c[s+12>>2]=c[p+12>>2];c[q>>2]=c[y>>2];c[q+4>>2]=c[y+4>>2];c[q+8>>2]=c[y+8>>2];c[q+12>>2]=c[y+12>>2];Bg(v,s,q)}g=c[(c[t>>2]|0)+96>>2]|0;if(!g){g=e+16|0;c[e>>2]=c[u>>2];c[e+4>>2]=c[u+4>>2];c[e+8>>2]=c[u+8>>2];c[e+12>>2]=c[u+12>>2];c[g>>2]=c[u>>2];c[g+4>>2]=c[u+4>>2];c[g+8>>2]=c[u+8>>2];c[g+12>>2]=c[u+12>>2];g=e+48|0;y=e+32|0;c[y>>2]=c[v>>2];c[y+4>>2]=c[v+4>>2];c[y+8>>2]=c[v+8>>2];c[y+12>>2]=c[v+12>>2];c[g>>2]=c[v>>2];c[g+4>>2]=c[v+4>>2];c[g+8>>2]=c[v+8>>2];c[g+12>>2]=c[v+12>>2];g=4;break}j=+h[g+24>>3];i=+h[g+32>>3];p=(c[(c[(so(o)|0)+16>>2]|0)+116>>2]&1|0)==0;k=p?i:j;y=(c[(c[t>>2]|0)+96>>2]|0)+56|0;c[w>>2]=c[y>>2];c[w+4>>2]=c[y+4>>2];c[w+8>>2]=c[y+8>>2];c[w+12>>2]=c[y+12>>2];c[r>>2]=c[v>>2];c[r+4>>2]=c[v+4>>2];c[r+8>>2]=c[v+8>>2];c[r+12>>2]=c[v+12>>2];c[s>>2]=c[u>>2];c[s+4>>2]=c[u+4>>2];c[s+8>>2]=c[u+8>>2];c[s+12>>2]=c[u+12>>2];c[q>>2]=c[y>>2];c[q+4>>2]=c[y+4>>2];c[q+8>>2]=c[y+8>>2];c[q+12>>2]=c[y+12>>2];y=(Cg(r,s,q)|0)==0;i=(p?j:i)*.5;j=+h[w>>3];if(y){h[w>>3]=j-i;y=w+8|0;h[y>>3]=+h[y>>3]+k*.5}else{h[w>>3]=j+i;y=w+8|0;h[y>>3]=+h[y>>3]-k*.5}g=e+16|0;c[e>>2]=c[u>>2];c[e+4>>2]=c[u+4>>2];c[e+8>>2]=c[u+8>>2];c[e+12>>2]=c[u+12>>2];c[g>>2]=c[u>>2];c[g+4>>2]=c[u+4>>2];c[g+8>>2]=c[u+8>>2];c[g+12>>2]=c[u+12>>2];g=e+32|0;y=e+48|0;u=e+64|0;c[u>>2]=c[w>>2];c[u+4>>2]=c[w+4>>2];c[u+8>>2]=c[w+8>>2];c[u+12>>2]=c[w+12>>2];c[y>>2]=c[w>>2];c[y+4>>2]=c[w+4>>2];c[y+8>>2]=c[w+8>>2];c[y+12>>2]=c[w+12>>2];c[g>>2]=c[w>>2];c[g+4>>2]=c[w+4>>2];c[g+8>>2]=c[w+8>>2];c[g+12>>2]=c[w+12>>2];g=e+80|0;y=e+96|0;c[y>>2]=c[v>>2];c[y+4>>2]=c[v+4>>2];c[y+8>>2]=c[v+8>>2];c[y+12>>2]=c[v+12>>2];c[g>>2]=c[v>>2];c[g+4>>2]=c[v+4>>2];c[g+8>>2]=c[v+8>>2];c[g+12>>2]=c[v+12>>2];g=7}while(0);l=x;return g|0}function kg(b,d,e,f,g,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0.0,k=0,l=0,m=0.0,n=0,o=0.0,p=0.0,q=0;q=c[f+16>>2]|0;p=+h[q+16>>3];j=p-+h[q+88>>3];m=j+-4.0;l=xg(d,f,g,i,-1)|0;if(!l){n=~~(j+(m>=0.0?-3.5:-4.5));k=c[e>>2]|0;k=(k|0)>(n|0)?n:k}else{k=yg(d,f,l)|0;do if(!k){n=c[l+16>>2]|0;j=+h[n+240>>3]+ +h[n+16>>3];if(!(a[n+156>>0]|0)){j=+(c[(c[d+16>>2]|0)+248>>2]|0)*.5+j;break}else{j=j+ +(c[e+8>>2]|0);break}}else j=+h[(c[k+16>>2]|0)+32>>3]+ +(c[e+8>>2]|0);while(0);o=j=0.0?.5:-.5))}o=+(k|0);n=(a[q+156>>0]|0)==1;if(n?(c[q+104>>2]|0)!=0:0)m=p+10.0;else m=p+4.0+ +h[q+96>>3];l=xg(d,f,g,i,1)|0;if(!l){f=~~(m+(m>=0.0?.5:-.5));k=c[e+4>>2]|0;k=(k|0)<(f|0)?f:k}else{k=yg(d,f,l)|0;do if(!k){f=c[l+16>>2]|0;j=+h[f+16>>3]-+h[f+88>>3];if(!(a[f+156>>0]|0)){j=j-+(c[(c[d+16>>2]|0)+248>>2]|0)*.5;break}else{j=j-+(c[e+8>>2]|0);break}}else j=+h[(c[k+16>>2]|0)+16>>3]-+(c[e+8>>2]|0);while(0);m=j>m?j:m;k=~~(m+(m>=0.0?.5:-.5))}j=+(k|0);if(n?(c[q+104>>2]|0)!=0:0){j=j-+h[q+96>>3];if(j>3];d=c[(c[d+16>>2]|0)+196>>2]|0;q=c[q+232>>2]|0;m=p-+h[d+(q<<6)+16>>3];p=+h[d+(q<<6)+24>>3]+p;h[b>>3]=o;h[b+8>>3]=m;h[b+16>>3]=j;h[b+24>>3]=p;return}function lg(b){b=b|0;b=c[b+16>>2]|0;if((a[b+156>>0]|0)==1)if((c[b+176>>2]|0)>1)b=1;else b=(c[b+184>>2]|0)>1&1;else b=0;return b|0}function mg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=+e;var f=0,g=0;g=l;l=l+32|0;f=g;switch(d|0){case 1:{wg(f,+h[b>>3],e,+h[b+16>>3],+h[b+8>>3]);break}case 4:{wg(f,+h[b>>3],+h[b+24>>3],+h[b+16>>3],e);break}default:{}}c[a>>2]=c[f>>2];c[a+4>>2]=c[f+4>>2];c[a+8>>2]=c[f+8>>2];c[a+12>>2]=c[f+12>>2];c[a+16>>2]=c[f+16>>2];c[a+20>>2]=c[f+20>>2];c[a+24>>2]=c[f+24>>2];c[a+28>>2]=c[f+28>>2];l=g;return}function ng(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0.0,k=0,l=0,m=0,n=0,o=0;l=c[b+16>>2]|0;k=l+(e<<5)|0;j=+h[k>>3];m=l+(e<<5)+8|0;g=+h[m>>3];n=l+(e<<5)+16|0;f=+h[n>>3];l=l+(e<<5)+24|0;i=+h[l>>3];if(j==f){d=c[(c[d+16>>2]|0)+196>>2]|0;o=e+1|0;j=+(c[b>>2]|0);g=+h[d+(o<<6)+24>>3]+ +h[(c[(c[c[d+(o<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3];f=+(c[b+4>>2]|0);i=+h[(c[(c[c[d+(e<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]-+h[d+(e<<6)+16>>3];h[k>>3]=j;h[m>>3]=g;h[n>>3]=f;h[l>>3]=i}h[a>>3]=j;h[a+8>>3]=g;h[a+16>>3]=f;h[a+24>>3]=i;return}function og(b){b=b|0;var d=0,e=0;b=c[b+16>>2]|0;e=b+16|0;d=0;while(1){b=c[c[b+180>>2]>>2]|0;b=c[(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)+16>>2]|0;if((a[b+156>>0]|0)!=1)break;if((c[b+184>>2]|0)!=1)break;if((c[b+176>>2]|0)!=1)break;if(+h[b+16>>3]!=+h[e>>3])break;d=d+1|0}return d|0}function pg(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;k=l;l=l+32|0;j=k;h=tg(b,-1)|0;b=tg(b,1)|0;if(!((h|0)!=0?!($z(h)|0):0))i=3;do if((i|0)==3){if(b|0?($z(b)|0)==0:0)break;h=ug(d,-1)|0;b=ug(d,1)|0;if(h|0?($z(h)|0)==0:0)break;if(b|0?($z(b)|0)==0:0)break;h=e+52|0;b=0;while(1){if((b|0)>=(c[h>>2]|0))break;d=e+56+(b<<5)|0;c[j>>2]=c[d>>2];c[j+4>>2]=c[d+4>>2];c[j+8>>2]=c[d+8>>2];c[j+12>>2]=c[d+12>>2];c[j+16>>2]=c[d+16>>2];c[j+20>>2]=c[d+20>>2];c[j+24>>2]=c[d+24>>2];c[j+28>>2]=c[d+28>>2];Mz(a,j);b=b+1|0}h=c[a+80>>2]|0;i=g+-3|0;b=0;while(1){if((b|0)>=(g|0))break;e=135024+(b<<5)|0;c[j>>2]=c[e>>2];c[j+4>>2]=c[e+4>>2];c[j+8>>2]=c[e+8>>2];c[j+12>>2]=c[e+12>>2];c[j+16>>2]=c[e+16>>2];c[j+20>>2]=c[e+20>>2];c[j+24>>2]=c[e+24>>2];c[j+28>>2]=c[e+28>>2];Mz(a,j);b=b+1|0}d=h+1|0;i=i+d|0;h=c[f+52>>2]|0;while(1){b=h+-1|0;if((h|0)<=0)break;h=f+56+(b<<5)|0;c[j>>2]=c[h>>2];c[j+4>>2]=c[h+4>>2];c[j+8>>2]=c[h+8>>2];c[j+12>>2]=c[h+12>>2];c[j+16>>2]=c[h+16>>2];c[j+20>>2]=c[h+20>>2];c[j+24>>2]=c[h+24>>2];c[j+28>>2]=c[h+28>>2];Mz(a,j);h=b}vg(a,d,i)}while(0);l=k;return}function qg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=c[e>>2]|0;while(1){if(!b)break;a=c[c[(c[(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+180>>2]>>2]|0;b=b+-1|0}c[e>>2]=f+1;g=d+(f<<4)|0;b=d+(f+-1<<4)|0;c[g>>2]=c[b>>2];c[g+4>>2]=c[b+4>>2];c[g+8>>2]=c[b+8>>2];c[g+12>>2]=c[b+12>>2];f=c[e>>2]|0;c[e>>2]=f+1;f=d+(f<<4)|0;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];f=d+(c[e>>2]<<4)|0;e=(c[(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+16|0;c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2];return a|0}function rg(b,d){b=b|0;d=d|0;var e=0,f=0.0,g=0.0,i=0,j=0,k=0,l=0,m=0;m=d+84|0;l=d+80|0;e=0;d=b;a:while(1){j=c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0;k=j+16|0;if((a[(c[k>>2]|0)+156>>0]|0)!=1)break;if(($a[c[17228>>2]&31](j)|0)<<24>>24)break;d=c[l>>2]|0;while(1){if((e|0)>=(d|0))break a;if(!(+h[(c[m>>2]|0)+(e<<5)+8>>3]>+h[(c[k>>2]|0)+24>>3]))break;e=e+1|0}d=c[m>>2]|0;b=c[k>>2]|0;do if(!(+h[d+(e<<5)+24>>3]<+h[b+24>>3])){g=+h[d+(e<<5)>>3];i=~~g;f=+h[d+(e<<5)+16>>3];if(!(c[b+104>>2]|0)){sg(j,i,~~((f+g)*.5),~~f);break}else{sg(j,i,~~f,~~(+h[b+96>>3]+f));break}}while(0);d=c[c[(c[k>>2]|0)+180>>2]>>2]|0}return}function sg(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=c[a+16>>2]|0;h[a+16>>3]=+(d|0);h[a+88>>3]=+(d-b|0);h[a+96>>3]=+(e-d|0);return}function tg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=c[a>>2]&3;i=c[(c[(c[((h|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+180>>2]|0;h=((h|0)==2?a:a+-48|0)+40|0;g=0;a=0;while(1){e=c[i+(g<<2)>>2]|0;if(!e)break;f=c[(c[(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;do if((O(f-(c[(c[(c[h>>2]|0)+16>>2]|0)+236>>2]|0)|0,b)|0)>=1){d=c[e+16>>2]|0;if(!(c[d+8>>2]|0)){d=c[d+116>>2]|0;if(!d)break;if(!(c[(c[d+16>>2]|0)+8>>2]|0))break}if(a|0?(O((c[(c[(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)-f|0,b)|0)<=0:0)break;a=e}while(0);g=g+1|0}return a|0}function ug(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=c[a>>2]&3;i=c[(c[(c[((h|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+172>>2]|0;h=((h|0)==3?a:a+48|0)+40|0;g=0;a=0;while(1){e=c[i+(g<<2)>>2]|0;if(!e)break;f=c[(c[(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;do if((O(f-(c[(c[(c[h>>2]|0)+16>>2]|0)+236>>2]|0)|0,b)|0)>=1){d=c[e+16>>2]|0;if(!(c[d+8>>2]|0)){d=c[d+116>>2]|0;if(!d)break;if(!(c[(c[d+16>>2]|0)+8>>2]|0))break}if(a|0?(O((c[(c[(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)-f|0,b)|0)<=0:0)break;a=e}while(0);g=g+1|0}return a|0}function vg(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0,g=0,i=0,j=0,k=0,l=0,m=0.0;l=a+84|0;i=b+-1|0;while(1){if((i|0)>(d|0))break;f=c[l>>2]|0;j=f+(i<<5)|0;e=+h[j>>3];if(!(i-b&1)){f=f+(i<<5)+16|0;m=+h[f>>3];g=~~((m+e)*.5);if(e>=m){h[j>>3]=+(g+-8|0);h[f>>3]=+(g+8|0)}}else{f=f+(i<<5)+16|0;m=+h[f>>3];g=~~((m+e)*.5);if(e+16.0>m){h[j>>3]=+(g+-8|0);h[f>>3]=+(g+8|0)}}i=i+1|0}k=(c[a+80>>2]|0)+-1|0;g=0;while(1){if((g|0)>=(k|0))break;i=c[l>>2]|0;f=i+(g<<5)|0;j=g+1|0;a=i+(j<<5)|0;if(!((g|0)<(b|0)|(g|0)>(d|0))?(g-b&1|0)==0:0){e=+h[f>>3]+16.0;f=i+(j<<5)+16|0;if(e>+h[f>>3])h[f>>3]=e;e=+h[i+(g<<5)+16>>3]+-16.0;if(!(e<+h[a>>3])){g=j;continue}h[a>>3]=e;g=j;continue}if(!((g|0)<(d|0)&(j|0)>=(b|0))){g=j;continue}if(j-b&1|0){g=j;continue}e=+h[i+(j<<5)+16>>3];if(+h[f>>3]+16.0>e)h[f>>3]=e+-16.0;f=i+(g<<5)+16|0;e=+h[a>>3];if(!(+h[f>>3]+-16.0>3]=e+16.0;g=j}return}function wg(a,b,c,d,e){a=a|0;b=+b;c=+c;d=+d;e=+e;h[a>>3]=b;h[a+8>>3]=c;h[a+16>>3]=d;h[a+24>>3]=e;return}function xg(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;k=c[(c[b+16>>2]|0)+196>>2]|0;h=c[d+16>>2]|0;j=c[h+232>>2]|0;i=k+(j<<6)|0;j=k+(j<<6)+4|0;h=c[h+236>>2]|0;a:do{h=h+g|0;if((h|0)<=-1){b=0;break}if((h|0)>=(c[i>>2]|0)){b=0;break}b=c[(c[j>>2]|0)+(h<<2)>>2]|0;k=c[b+16>>2]|0;switch(a[k+156>>0]|0){case 0:break a;case 1:{if(c[k+104>>2]|0)break a;break}default:{}}}while((Ag(b,d,e,f)|0)<<24>>24!=0);return b|0}function yg(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;d=c[d+16>>2]|0;if(!(a[d+156>>0]|0)){i=c[d+212>>2]|0;h=i}else{i=c[(c[(c[c[d+180>>2]>>2]|0)+16>>2]|0)+116>>2]|0;g=c[i>>2]&3;h=c[(c[(c[((g|0)==2?i:i+-48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0;i=c[(c[(c[((g|0)==3?i:i+48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0}d=c[e+16>>2]|0;if(!(a[d+156>>0]|0)){e=c[d+212>>2]|0;e=(e|0)==(b|0)?0:e;return ((e|0)==(h|0)|((e|0)==0|(e|0)==(i|0))?0:e)|0}f=c[(c[(c[c[d+180>>2]>>2]|0)+16>>2]|0)+116>>2]|0;g=c[f>>2]&3;d=c[(c[(c[((g|0)==3?f:f+48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0;d=(d|0)==(b|0)?0:d;if(!(!((d|0)==(h|0)|((d|0)==0|(d|0)==(i|0)))?(zg(d,e)|0)!=0:0)){d=c[(c[(c[((g|0)==2?f:f+-48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0;d=(d|0)==(b|0)?0:d;if((d|0)==(h|0)|((d|0)==0|(d|0)==(i|0)))d=0;else{e=(zg(d,e)|0)==0;return (e?0:d)|0}}return d|0}function zg(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0.0;d=c[a+16>>2]|0;a=c[b+16>>2]|0;f=+h[a+16>>3];if((+h[d+16>>3]<=f?f<=+h[d+32>>3]:0)?(e=+h[a+24>>3],+h[d+24>>3]<=e):0)a=e<=+h[d+40>>3]&1;else a=0;return a|0}function Ag(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;i=c[b+16>>2]|0;j=(c[i+236>>2]|0)>(c[(c[d+16>>2]|0)+236>>2]|0);a:do if((c[i+184>>2]|0)==1){b:do if(f|0){h=0;b=c[c[i+180>>2]>>2]|0;while(1){if((h|0)>=2)break b;b=c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0;d=c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0;if((b|0)==(d|0))break b;g=c[b+16>>2]|0;b=c[d+16>>2]|0;if(j^(c[g+236>>2]|0)>(c[b+236>>2]|0)){b=1;break a}if((c[g+184>>2]|0)!=1)break b;if(!(a[g+156>>0]|0))break b;if((c[b+184>>2]|0)!=1)break b;if(!(a[b+156>>0]|0))break b;h=h+1|0;f=c[c[b+180>>2]>>2]|0;b=c[c[g+180>>2]>>2]|0}}while(0);if(e|0?(c[i+176>>2]|0)==1:0){g=0;d=e;b=c[c[i+172>>2]>>2]|0;while(1){if((g|0)>=2){b=0;break a}b=c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0;d=c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0;if((b|0)==(d|0)){b=0;break a}f=c[b+16>>2]|0;b=c[d+16>>2]|0;if(j^(c[f+236>>2]|0)>(c[b+236>>2]|0)){b=1;break a}if((c[f+176>>2]|0)!=1){b=0;break a}if(!(a[f+156>>0]|0)){b=0;break a}if((c[b+176>>2]|0)!=1){b=0;break a}if(!(a[b+156>>0]|0)){b=0;break a}g=g+1|0;d=c[c[b+172>>2]>>2]|0;b=c[c[f+172>>2]>>2]|0}}else b=0}else b=0;while(0);return b|0}function Bg(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=+h[c+8>>3]+ +h[b+8>>3];h[a>>3]=+h[c>>3]+ +h[b>>3];h[a+8>>3]=d;return}function Cg(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0;d=+h[b+8>>3];e=+h[b>>3];return (~~((+h[c>>3]-e)*(+h[a+8>>3]-d)-(+h[a>>3]-e)*(+h[c+8>>3]-d))|0)>0|0}function Dg(b,d,e,f,g,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0,u=0,v=0.0,w=0.0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0;R=l;l=l+256|0;D=R+232|0;C=R+216|0;P=R+88|0;O=R+80|0;K=R+64|0;L=R+200|0;M=R+184|0;N=R;E=R+168|0;F=R+152|0;G=R+136|0;H=R+120|0;I=R+104|0;B=c[g>>2]&3;J=c[((B|0)==3?g:g+48|0)+40>>2]|0;B=c[((B|0)==2?g:g+-48|0)+40>>2]|0;do if((Cy(J)|0)!=2?(Cy(B)|0)!=2:0){g=0;j=0;k=0;while(1){if((k|0)>=(f|0))break;A=c[(c[d+(k+e<<2)>>2]|0)+16>>2]|0;g=g+((c[A+96>>2]|0)!=0&1)|0;if(!((a[A+44>>0]|0)==0?(a[A+84>>0]|0)==0:0))j=1;k=k+1|0}if(!j)if(!g){Fg(J,B,d,e,f,i);break}else{Kg(J,B,d,e,f,i,g);break}y=ww(156)|0;z=Lg(b,y)|0;t=Jp(z,78320,1)|0;Oo(t,122277,280,1)|0;Lm(t,80018,80032)|0;m=+h[(c[B+16>>2]|0)+16>>3];s=+h[(c[J+16>>2]|0)+16>>3];A=b+16|0;q=(c[(c[A>>2]|0)+116>>2]&1|0)==0;r=q?B:J;q=q?J:B;t=Mg(t,q)|0;u=Mg(z,r)|0;g=0;p=0;while(1){if((p|0)>=(f|0))break;j=d+(p+e<<2)|0;while(1){o=c[j>>2]|0;n=o+16|0;j=c[n>>2]|0;if(!(a[j+112>>0]|0))break;else j=j+116|0}if((c[((c[o>>2]&3|0)==3?o:o+48|0)+40>>2]|0)==(q|0))k=Ng(z,t,u,o)|0;else k=Ng(z,u,t,o)|0;j=c[n>>2]|0;c[j+120>>2]=k;if(!g)if((a[j+44>>0]|0)==0?(a[j+84>>0]|0)==0:0){c[(c[k+16>>2]|0)+120>>2]=o;g=k}else g=0;p=p+1|0}if(!g)x=bn(z,t,u,0,1)|0;else x=g;Dm(x,c[42219]|0,78324)|0;g=z+16|0;n=c[g>>2]|0;c[n+144>>2]=c[(c[A>>2]|0)+144>>2];c[n+188>>2]=z;JB(z,i);Cf(z);lj(z,0);vh(z,0);yi(z,0);q=q+16|0;i=c[q>>2]|0;n=c[r+16>>2]|0;r=t+16|0;o=c[r>>2]|0;p=o+16|0;v=+(~~m|0);w=+(~~((+h[(c[u+16>>2]|0)+16>>3]+ +h[p>>3])*.5)|0);m=+(~~s|0);s=+(~~((+h[i+16>>3]-+h[i+96>>3]+ +h[n+16>>3]+ +h[n+88>>3])*.5)|0);n=o+24|0;g=(c[g>>2]|0)+192|0;while(1){j=c[g>>2]|0;if(!j)break;do if((j|0)!=(t|0)){g=c[j+16>>2]|0;k=g+24|0;if((j|0)==(u|0)){h[k>>3]=m;h[g+16>>3]=w;break}else{h[k>>3]=s;break}}else{h[n>>3]=v;h[p>>3]=w;g=o}while(0);g=g+164|0}fk(z);Zf(z,0);ay(z);k=c[q>>2]|0;g=c[r>>2]|0;if(!(c[(c[A>>2]|0)+116>>2]&1)){j=g+16|0;m=+h[k+24>>3]-+h[g+24>>3]}else{j=g+24|0;m=+h[g+16>>3]+ +h[k+24>>3]}h[K>>3]=+h[k+16>>3]-+h[j>>3];h[K+8>>3]=m;i=N+16|0;t=N+32|0;u=N+48|0;r=0;while(1){if((r|0)>=(f|0))break;g=d+(r+e<<2)|0;while(1){j=c[g>>2]|0;q=j+16|0;g=c[q>>2]|0;if(!(a[g+112>>0]|0))break;else g=g+116|0}o=c[g+120>>2]|0;p=o+16|0;g=c[p>>2]|0;if(!((o|0)==(x|0)&(c[g+120>>2]|0)==0)){n=c[c[g+8>>2]>>2]|0;o=n+4|0;j=Jz(j,c[o>>2]|0)|0;c[j+8>>2]=c[n+8>>2];g=j+16|0;k=n+16|0;S=c[(c[A>>2]|0)+116>>2]&1;c[C>>2]=c[k>>2];c[C+4>>2]=c[k+4>>2];c[C+8>>2]=c[k+8>>2];c[C+12>>2]=c[k+12>>2];c[D>>2]=c[K>>2];c[D+4>>2]=c[K+4>>2];c[D+8>>2]=c[K+8>>2];c[D+12>>2]=c[K+12>>2];Og(L,C,D,S);c[g>>2]=c[L>>2];c[g+4>>2]=c[L+4>>2];c[g+8>>2]=c[L+8>>2];c[g+12>>2]=c[L+12>>2];c[j+12>>2]=c[n+12>>2];g=j+32|0;S=n+32|0;k=c[(c[A>>2]|0)+116>>2]&1;c[C>>2]=c[S>>2];c[C+4>>2]=c[S+4>>2];c[C+8>>2]=c[S+8>>2];c[C+12>>2]=c[S+12>>2];c[D>>2]=c[K>>2];c[D+4>>2]=c[K+4>>2];c[D+8>>2]=c[K+8>>2];c[D+12>>2]=c[K+12>>2];Og(M,C,D,k);c[g>>2]=c[M>>2];c[g+4>>2]=c[M+4>>2];c[g+8>>2]=c[M+8>>2];c[g+12>>2]=c[M+12>>2];g=0;while(1){if((g|0)>=(c[o>>2]|0))break;k=(c[j>>2]|0)+(g<<4)|0;T=(c[n>>2]|0)+(g<<4)|0;S=c[(c[A>>2]|0)+116>>2]&1;c[C>>2]=c[T>>2];c[C+4>>2]=c[T+4>>2];c[C+8>>2]=c[T+8>>2];c[C+12>>2]=c[T+12>>2];c[D>>2]=c[K>>2];c[D+4>>2]=c[K+4>>2];c[D+8>>2]=c[K+8>>2];c[D+12>>2]=c[K+12>>2];Og(E,C,D,S);c[k>>2]=c[E>>2];c[k+4>>2]=c[E+4>>2];c[k+8>>2]=c[E+8>>2];c[k+12>>2]=c[E+12>>2];c[N>>2]=c[E>>2];c[N+4>>2]=c[E+4>>2];c[N+8>>2]=c[E+8>>2];c[N+12>>2]=c[E+12>>2];k=g+1|0;if((k|0)>=(c[o>>2]|0)){Q=48;break}S=(c[j>>2]|0)+(k<<4)|0;k=(c[n>>2]|0)+(k<<4)|0;T=c[(c[A>>2]|0)+116>>2]&1;c[C>>2]=c[k>>2];c[C+4>>2]=c[k+4>>2];c[C+8>>2]=c[k+8>>2];c[C+12>>2]=c[k+12>>2];c[D>>2]=c[K>>2];c[D+4>>2]=c[K+4>>2];c[D+8>>2]=c[K+8>>2];c[D+12>>2]=c[K+12>>2];Og(F,C,D,T);c[S>>2]=c[F>>2];c[S+4>>2]=c[F+4>>2];c[S+8>>2]=c[F+8>>2];c[S+12>>2]=c[F+12>>2];c[i>>2]=c[F>>2];c[i+4>>2]=c[F+4>>2];c[i+8>>2]=c[F+8>>2];c[i+12>>2]=c[F+12>>2];S=g+2|0;T=(c[j>>2]|0)+(S<<4)|0;S=(c[n>>2]|0)+(S<<4)|0;k=c[(c[A>>2]|0)+116>>2]&1;c[C>>2]=c[S>>2];c[C+4>>2]=c[S+4>>2];c[C+8>>2]=c[S+8>>2];c[C+12>>2]=c[S+12>>2];c[D>>2]=c[K>>2];c[D+4>>2]=c[K+4>>2];c[D+8>>2]=c[K+8>>2];c[D+12>>2]=c[K+12>>2];Og(G,C,D,k);c[T>>2]=c[G>>2];c[T+4>>2]=c[G+4>>2];c[T+8>>2]=c[G+8>>2];c[T+12>>2]=c[G+12>>2];c[t>>2]=c[G>>2];c[t+4>>2]=c[G+4>>2];c[t+8>>2]=c[G+8>>2];c[t+12>>2]=c[G+12>>2];T=g+3|0;k=(c[n>>2]|0)+(T<<4)|0;S=c[(c[A>>2]|0)+116>>2]&1;c[C>>2]=c[k>>2];c[C+4>>2]=c[k+4>>2];c[C+8>>2]=c[k+8>>2];c[C+12>>2]=c[k+12>>2];c[D>>2]=c[K>>2];c[D+4>>2]=c[K+4>>2];c[D+8>>2]=c[K+8>>2];c[D+12>>2]=c[K+12>>2];Og(H,C,D,S);c[u>>2]=c[H>>2];c[u+4>>2]=c[H+4>>2];c[u+8>>2]=c[H+8>>2];c[u+12>>2]=c[H+12>>2];fu((c[A>>2]|0)+16|0,N);g=T}if((Q|0)==48)Q=0;g=c[(c[q>>2]|0)+96>>2]|0;if(g|0){T=g+56|0;p=(c[(c[p>>2]|0)+96>>2]|0)+56|0;S=c[(c[A>>2]|0)+116>>2]&1;c[C>>2]=c[p>>2];c[C+4>>2]=c[p+4>>2];c[C+8>>2]=c[p+8>>2];c[C+12>>2]=c[p+12>>2];c[D>>2]=c[K>>2];c[D+4>>2]=c[K+4>>2];c[D+8>>2]=c[K+8>>2];c[D+12>>2]=c[K+12>>2];Og(I,C,D,S);c[T>>2]=c[I>>2];c[T+4>>2]=c[I+4>>2];c[T+8>>2]=c[I+8>>2];c[T+12>>2]=c[I+12>>2];T=c[(c[q>>2]|0)+96>>2]|0;a[T+81>>0]=1;cB(b,T)}}r=r+1|0}Pg(z,y)}else Q=3;while(0);if((Q|0)==3?(c[41924]|0)==0:0){c[41924]=1;$l(0,78197,O)|0;Q=En(J)|0;S=(rn(b)|0)!=0;T=En(B)|0;c[P>>2]=Q;c[P+4>>2]=S?122546:122549;c[P+8>>2]=T;$l(3,78303,P)|0}l=R;return}function Eg(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0.0,C=0.0,D=0.0,E=0.0;z=l;l=l+1600|0;u=z+1552|0;n=z+1536|0;t=z+840|0;v=z+144|0;w=z+1584|0;j=z+32|0;s=z+16|0;o=z;q=c[f>>2]&3;p=c[((q|0)==3?f:f+48|0)+40>>2]|0;x=f+-48|0;q=c[((q|0)==2?f:x)+40>>2]|0;r=f+16|0;k=c[r>>2]|0;i=c[k+172>>2]|0;while(1){m=c[(c[i+16>>2]|0)+172>>2]|0;if(!m)break;else i=m}k=(c[k+96>>2]|0)+56|0;i=(c[((c[i>>2]&3|0)==3?i:i+48|0)+40>>2]|0)+16|0;m=(c[i>>2]|0)+16|0;c[k>>2]=c[m>>2];c[k+4>>2]=c[m+4>>2];c[k+8>>2]=c[m+8>>2];c[k+12>>2]=c[m+12>>2];k=c[r>>2]|0;a[(c[k+96>>2]|0)+81>>0]=1;if((g|0)!=2){k=c[i>>2]|0;C=+h[k+16>>3];E=C-+h[k+88>>3];C=+h[k+96>>3]+C;B=+h[k+24>>3];D=+h[k+80>>3]*.5+B;k=c[(c[b+16>>2]|0)+196>>2]|0;m=c[p+16>>2]|0;j=c[m+232>>2]|0;B=+(~~(+(~~(B-+h[k+(j<<6)+16>>3]-+h[m+24>>3]+ +h[k+(j<<6)+24>>3])|0)*.16666666666666666)|0);B=D-(B<5.0?5.0:B);Hg(b,d,e,p,f,t,1);Hg(b,d,e,q,f,v,0);j=t+52|0;k=c[j>>2]|0;m=k+-1|0;A=+h[t+56+(m<<5)>>3];h[16878]=A;h[16879]=+h[t+56+(m<<5)+24>>3];h[16880]=E;h[16881]=B;h[16882]=A;h[16883]=B;m=v+52|0;i=(c[m>>2]|0)+-1|0;A=+h[v+56+(i<<5)+16>>3];h[16884]=A;h[16885]=D;h[16886]=C;h[16889]=B;h[16887]=+h[v+56+(i<<5)+24>>3];h[16888]=A;i=0;while(1){if((i|0)>=(k|0)){i=0;break}k=t+56+(i<<5)|0;c[u>>2]=c[k>>2];c[u+4>>2]=c[k+4>>2];c[u+8>>2]=c[k+8>>2];c[u+12>>2]=c[k+12>>2];c[u+16>>2]=c[k+16>>2];c[u+20>>2]=c[k+20>>2];c[u+24>>2]=c[k+24>>2];c[u+28>>2]=c[k+28>>2];Mz(e,u);i=i+1|0;k=c[j>>2]|0}while(1){if((i|0)==3)break;t=135024+(i<<5)|0;c[u>>2]=c[t>>2];c[u+4>>2]=c[t+4>>2];c[u+8>>2]=c[t+8>>2];c[u+12>>2]=c[t+12>>2];c[u+16>>2]=c[t+16>>2];c[u+20>>2]=c[t+20>>2];c[u+24>>2]=c[t+24>>2];c[u+28>>2]=c[t+28>>2];Mz(e,u);i=i+1|0}j=c[m>>2]|0;while(1){i=j+-1|0;if((j|0)<=0)break;j=v+56+(i<<5)|0;c[u>>2]=c[j>>2];c[u+4>>2]=c[j+4>>2];c[u+8>>2]=c[j+8>>2];c[u+12>>2]=c[j+12>>2];c[u+16>>2]=c[j+16>>2];c[u+20>>2]=c[j+20>>2];c[u+24>>2]=c[j+24>>2];c[u+28>>2]=c[j+28>>2];Mz(e,u);j=i}if((g|0)==10)j=oy(e,w)|0;else j=uy(e,w)|0;i=c[w>>2]|0;if(i|0)y=17}else{i=(c[p+16>>2]|0)+16|0;v=k+16|0;c[n>>2]=c[i>>2];c[n+4>>2]=c[i+4>>2];c[n+8>>2]=c[i+8>>2];c[n+12>>2]=c[i+12>>2];c[u>>2]=c[v>>2];c[u+4>>2]=c[v+4>>2];c[u+8>>2]=c[v+8>>2];c[u+12>>2]=c[v+12>>2];Bg(s,n,u);v=(c[q+16>>2]|0)+16|0;i=(c[r>>2]|0)+56|0;c[n>>2]=c[v>>2];c[n+4>>2]=c[v+4>>2];c[n+8>>2]=c[v+8>>2];c[n+12>>2]=c[v+12>>2];c[u>>2]=c[i>>2];c[u+4>>2]=c[i+4>>2];c[u+8>>2]=c[i+8>>2];c[u+12>>2]=c[i+12>>2];Bg(o,n,u);i=c[(c[r>>2]|0)+96>>2]|0;D=+h[i+56>>3];E=+h[i+64>>3]-+h[i+32>>3]*.5;i=j+16|0;c[j>>2]=c[s>>2];c[j+4>>2]=c[s+4>>2];c[j+8>>2]=c[s+8>>2];c[j+12>>2]=c[s+12>>2];c[i>>2]=c[s>>2];c[i+4>>2]=c[s+4>>2];c[i+8>>2]=c[s+8>>2];c[i+12>>2]=c[s+12>>2];i=j+32|0;v=j+48|0;y=j+64|0;h[j+64>>3]=D;h[j+72>>3]=E;c[v>>2]=c[y>>2];c[v+4>>2]=c[y+4>>2];c[v+8>>2]=c[y+8>>2];c[v+12>>2]=c[y+12>>2];c[i>>2]=c[y>>2];c[i+4>>2]=c[y+4>>2];c[i+8>>2]=c[y+8>>2];c[i+12>>2]=c[y+12>>2];i=j+80|0;y=j+96|0;c[y>>2]=c[o>>2];c[y+4>>2]=c[o+4>>2];c[y+8>>2]=c[o+8>>2];c[y+12>>2]=c[o+12>>2];c[i>>2]=c[o>>2];c[i+4>>2]=c[o+4>>2];c[i+8>>2]=c[o+8>>2];c[i+12>>2]=c[o+12>>2];c[w>>2]=7;i=7;y=17}if((y|0)==17)Kz(f,c[((c[f>>2]&3|0)==2?f:x)+40>>2]|0,j,i,17224);l=z;return}function Fg(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0.0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;N=l;l=l+352|0;x=N+336|0;w=N+320|0;L=N+128|0;u=N+304|0;y=N+288|0;M=N+112|0;E=N+96|0;F=N+80|0;G=N+64|0;H=N+48|0;I=N+32|0;J=N+16|0;K=N;a=a+16|0;q=(c[a>>2]|0)+16|0;v=(c[d+(e<<2)>>2]|0)+16|0;s=(c[v>>2]|0)+16|0;c[w>>2]=c[q>>2];c[w+4>>2]=c[q+4>>2];c[w+8>>2]=c[q+8>>2];c[w+12>>2]=c[q+12>>2];c[x>>2]=c[s>>2];c[x+4>>2]=c[s+4>>2];c[x+8>>2]=c[s+8>>2];c[x+12>>2]=c[s+12>>2];Bg(u,w,x);C=+h[u>>3];D=+h[u+8>>3];u=(c[b+16>>2]|0)+16|0;v=(c[v>>2]|0)+56|0;c[w>>2]=c[u>>2];c[w+4>>2]=c[u+4>>2];c[w+8>>2]=c[u+8>>2];c[w+12>>2]=c[u+12>>2];c[x>>2]=c[v>>2];c[x+4>>2]=c[v+4>>2];c[x+8>>2]=c[v+8>>2];c[x+12>>2]=c[v+12>>2];Bg(y,w,x);A=+h[y>>3];B=+h[y+8>>3];if((f|0)>1){z=+h[(c[a>>2]|0)+80>>3];i=z*.5;z=z/+(f+-1|0)}else{i=0.0;z=0.0}p=(g|8|0)==10;m=L+8|0;q=L+16|0;r=(A+C*2.0)*.3333333333333333;s=L+32|0;t=(A*2.0+C)*.3333333333333333;n=L+24|0;u=L+48|0;v=L+64|0;w=L+80|0;x=L+96|0;y=L+112|0;k=L+128|0;o=L+136|0;i=D-i;b=0;while(1){if((b|0)>=(f|0))break;j=c[d+(b+e<<2)>>2]|0;h[L>>3]=C;h[m>>3]=D;if(p){Jg(M,r,i);c[q>>2]=c[M>>2];c[q+4>>2]=c[M+4>>2];c[q+8>>2]=c[M+8>>2];c[q+12>>2]=c[M+12>>2];Jg(E,t,i);c[s>>2]=c[E>>2];c[s+4>>2]=c[E+4>>2];c[s+8>>2]=c[E+8>>2];c[s+12>>2]=c[E+12>>2];a=4;g=3}else{h[q>>3]=C;h[n>>3]=D;Jg(F,r,i);c[s>>2]=c[F>>2];c[s+4>>2]=c[F+4>>2];c[s+8>>2]=c[F+8>>2];c[s+12>>2]=c[F+12>>2];Jg(G,r,i);c[u>>2]=c[G>>2];c[u+4>>2]=c[G+4>>2];c[u+8>>2]=c[G+8>>2];c[u+12>>2]=c[G+12>>2];Jg(H,r,i);c[v>>2]=c[H>>2];c[v+4>>2]=c[H+4>>2];c[v+8>>2]=c[H+8>>2];c[v+12>>2]=c[H+12>>2];Jg(I,t,i);c[w>>2]=c[I>>2];c[w+4>>2]=c[I+4>>2];c[w+8>>2]=c[I+8>>2];c[w+12>>2]=c[I+12>>2];Jg(J,t,i);c[x>>2]=c[J>>2];c[x+4>>2]=c[J+4>>2];c[x+8>>2]=c[J+8>>2];c[x+12>>2]=c[J+12>>2];Jg(K,t,i);c[y>>2]=c[K>>2];c[y+4>>2]=c[K+4>>2];c[y+8>>2]=c[K+8>>2];c[y+12>>2]=c[K+12>>2];h[k>>3]=A;h[o>>3]=B;a=10;g=9}h[L+(g<<4)>>3]=A;h[L+(g<<4)+8>>3]=B;Kz(j,c[((c[j>>2]&3|0)==2?j:j+-48|0)+40>>2]|0,L,a,17224);i=i+z;b=b+1|0}l=N;return}function Gg(a,d,e,f,g,i,j,k){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;k=k|0;var m=0,n=0.0,o=0,p=0,q=0,r=0,s=0.0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0,B=0.0,C=0.0,D=0.0;x=l;l=l+1440|0;t=x+1392|0;v=x+1424|0;w=x+696|0;u=x;r=c[j>>2]&3;q=c[((r|0)==3?j:j+48|0)+40>>2]|0;r=c[((r|0)==2?j:j+-48|0)+40>>2]|0;m=c[q+16>>2]|0;o=c[m+232>>2]|0;p=c[a+16>>2]|0;if((o|0)<(b[p+238>>1]|0)){y=c[p+196>>2]|0;p=o+1|0;n=+h[m+24>>3]-+h[y+(o<<6)+32>>3]-+h[(c[(c[c[y+(p<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]-+h[y+(p<<6)+40>>3]}else n=+(c[p+252>>2]|0);z=+(i+1|0);s=+(c[d+12>>2]|0)/z;n=n/z;Ig(a,d,e,q,j,w,1);Ig(a,d,e,r,j,u,0);r=w+52|0;j=u+52|0;a=(k|0)==0;d=e+80|0;m=0;while(1){if((m|0)>=(i|0))break;q=c[f+(m+g<<2)>>2]|0;p=c[r>>2]|0;o=p+-1|0;D=+h[w+56+(o<<5)>>3];B=+h[w+56+(o<<5)+8>>3];C=+h[w+56+(o<<5)+16>>3];h[16878]=D;h[16881]=B;m=m+1|0;z=+(m|0);A=s*z;h[16880]=C+A;z=B-n*z;h[16879]=z;h[16882]=D;h[16885]=z;o=(c[j>>2]|0)+-1|0;D=+h[u+56+(o<<5)+16>>3];h[16884]=D;h[16883]=z-n;B=+h[u+56+(o<<5)>>3];C=+h[u+56+(o<<5)+8>>3];h[16888]=D;h[16889]=C;h[16886]=B-A;h[16887]=z;o=0;while(1){if((o|0)>=(p|0)){o=0;break}p=w+56+(o<<5)|0;c[t>>2]=c[p>>2];c[t+4>>2]=c[p+4>>2];c[t+8>>2]=c[p+8>>2];c[t+12>>2]=c[p+12>>2];c[t+16>>2]=c[p+16>>2];c[t+20>>2]=c[p+20>>2];c[t+24>>2]=c[p+24>>2];c[t+28>>2]=c[p+28>>2];Mz(e,t);o=o+1|0;p=c[r>>2]|0}while(1){if((o|0)==3)break;y=135024+(o<<5)|0;c[t>>2]=c[y>>2];c[t+4>>2]=c[y+4>>2];c[t+8>>2]=c[y+8>>2];c[t+12>>2]=c[y+12>>2];c[t+16>>2]=c[y+16>>2];c[t+20>>2]=c[y+20>>2];c[t+24>>2]=c[y+24>>2];c[t+28>>2]=c[y+28>>2];Mz(e,t);o=o+1|0}p=c[j>>2]|0;while(1){o=p+-1|0;if((p|0)<=0)break;p=u+56+(o<<5)|0;c[t>>2]=c[p>>2];c[t+4>>2]=c[p+4>>2];c[t+8>>2]=c[p+8>>2];c[t+12>>2]=c[p+12>>2];c[t+16>>2]=c[p+16>>2];c[t+20>>2]=c[p+20>>2];c[t+24>>2]=c[p+24>>2];c[t+28>>2]=c[p+28>>2];Mz(e,t);p=o}if(a)o=uy(e,v)|0;else o=oy(e,v)|0;p=c[v>>2]|0;if(!p)break;Kz(q,c[((c[q>>2]&3|0)==2?q:q+-48|0)+40>>2]|0,o,p,17224);c[d>>2]=0}l=x;return}function Hg(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0.0;n=l;l=l+128|0;j=n+96|0;k=n+64|0;o=n+32|0;m=n;kg(o,a,b,e,0,f);c[g>>2]=c[o>>2];c[g+4>>2]=c[o+4>>2];c[g+8>>2]=c[o+8>>2];c[g+12>>2]=c[o+12>>2];c[g+16>>2]=c[o+16>>2];c[g+20>>2]=c[o+20>>2];c[g+24>>2]=c[o+24>>2];c[g+28>>2]=c[o+28>>2];c[k>>2]=c[o>>2];c[k+4>>2]=c[o+4>>2];c[k+8>>2]=c[o+8>>2];c[k+12>>2]=c[o+12>>2];c[k+16>>2]=c[o+16>>2];c[k+20>>2]=c[o+20>>2];c[k+24>>2]=c[o+24>>2];c[k+28>>2]=c[o+28>>2];c[g+48>>2]=4;if(!(i<<24>>24))Qz(d,f,2,g,0);else Nz(d,f,2,g,0);b=g+52|0;f=(c[b>>2]|0)+-1|0;o=k+24|0;h[o>>3]=+h[g+56+(f<<5)+24>>3];i=k+8|0;h[i>>3]=+h[g+56+(f<<5)+8>>3];e=c[e+16>>2]|0;p=+h[(c[(c[a+16>>2]|0)+196>>2]|0)+(c[e+232>>2]<<6)+24>>3]+ +h[e+24>>3];c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];c[j+8>>2]=c[k+8>>2];c[j+12>>2]=c[k+12>>2];c[j+16>>2]=c[k+16>>2];c[j+20>>2]=c[k+20>>2];c[j+24>>2]=c[k+24>>2];c[j+28>>2]=c[k+28>>2];mg(m,j,4,p);c[k>>2]=c[m>>2];c[k+4>>2]=c[m+4>>2];c[k+8>>2]=c[m+8>>2];c[k+12>>2]=c[m+12>>2];c[k+16>>2]=c[m+16>>2];c[k+20>>2]=c[m+20>>2];c[k+24>>2]=c[m+24>>2];c[k+28>>2]=c[m+28>>2];if(+h[k>>3]<+h[k+16>>3]?+h[i>>3]<+h[o>>3]:0){o=c[b>>2]|0;c[b>>2]=o+1;o=g+56+(o<<5)|0;c[o>>2]=c[k>>2];c[o+4>>2]=c[k+4>>2];c[o+8>>2]=c[k+8>>2];c[o+12>>2]=c[k+12>>2];c[o+16>>2]=c[k+16>>2];c[o+20>>2]=c[k+20>>2];c[o+24>>2]=c[k+24>>2];c[o+28>>2]=c[k+28>>2]}l=n;return}function Ig(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0.0;n=l;l=l+128|0;j=n+96|0;k=n+64|0;o=n+32|0;m=n;kg(o,a,b,e,0,f);c[g>>2]=c[o>>2];c[g+4>>2]=c[o+4>>2];c[g+8>>2]=c[o+8>>2];c[g+12>>2]=c[o+12>>2];c[g+16>>2]=c[o+16>>2];c[g+20>>2]=c[o+20>>2];c[g+24>>2]=c[o+24>>2];c[g+28>>2]=c[o+28>>2];c[k>>2]=c[o>>2];c[k+4>>2]=c[o+4>>2];c[k+8>>2]=c[o+8>>2];c[k+12>>2]=c[o+12>>2];c[k+16>>2]=c[o+16>>2];c[k+20>>2]=c[o+20>>2];c[k+24>>2]=c[o+24>>2];c[k+28>>2]=c[o+28>>2];c[g+48>>2]=1;if(!(i<<24>>24))Qz(d,f,2,g,0);else Nz(d,f,2,g,0);b=g+52|0;f=(c[b>>2]|0)+-1|0;o=k+24|0;h[o>>3]=+h[g+56+(f<<5)+24>>3];i=k+8|0;h[i>>3]=+h[g+56+(f<<5)+8>>3];e=c[e+16>>2]|0;p=+h[e+24>>3]-+h[(c[(c[a+16>>2]|0)+196>>2]|0)+(c[e+232>>2]<<6)+24>>3];c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];c[j+8>>2]=c[k+8>>2];c[j+12>>2]=c[k+12>>2];c[j+16>>2]=c[k+16>>2];c[j+20>>2]=c[k+20>>2];c[j+24>>2]=c[k+24>>2];c[j+28>>2]=c[k+28>>2];mg(m,j,1,p);c[k>>2]=c[m>>2];c[k+4>>2]=c[m+4>>2];c[k+8>>2]=c[m+8>>2];c[k+12>>2]=c[m+12>>2];c[k+16>>2]=c[m+16>>2];c[k+20>>2]=c[m+20>>2];c[k+24>>2]=c[m+24>>2];c[k+28>>2]=c[m+28>>2];if(+h[k>>3]<+h[k+16>>3]?+h[i>>3]<+h[o>>3]:0){o=c[b>>2]|0;c[b>>2]=o+1;o=g+56+(o<<5)|0;c[o>>2]=c[k>>2];c[o+4>>2]=c[k+4>>2];c[o+8>>2]=c[k+8>>2];c[o+12>>2]=c[k+12>>2];c[o+16>>2]=c[k+16>>2];c[o+20>>2]=c[k+20>>2];c[o+24>>2]=c[k+24>>2];c[o+28>>2]=c[k+28>>2]}l=n;return}function Jg(a,b,c){a=a|0;b=+b;c=+c;h[a>>3]=b;h[a+8>>3]=c;return}function Kg(b,d,e,f,g,i,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;var k=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0,z=0,A=0.0,B=0.0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0.0;Y=l;l=l+288|0;R=Y+256|0;Q=Y+240|0;P=Y+224|0;V=Y+280|0;W=Y+272|0;X=Y+32|0;S=Y+16|0;T=Y;m=Y+208|0;n=Y+192|0;o=c[e+(f<<2)>>2]|0;U=ww(g<<2)|0;k=0;while(1){if((k|0)>=(g|0))break;c[U+(k<<2)>>2]=c[e+(k+f<<2)>>2];k=k+1|0}sL(U,g,4,11);e=b+16|0;f=(c[e>>2]|0)+16|0;o=o+16|0;C=(c[o>>2]|0)+16|0;c[Q>>2]=c[f>>2];c[Q+4>>2]=c[f+4>>2];c[Q+8>>2]=c[f+8>>2];c[Q+12>>2]=c[f+12>>2];c[R>>2]=c[C>>2];c[R+4>>2]=c[C+4>>2];c[R+8>>2]=c[C+8>>2];c[R+12>>2]=c[C+12>>2];Bg(m,Q,R);c[S>>2]=c[m>>2];c[S+4>>2]=c[m+4>>2];c[S+8>>2]=c[m+8>>2];c[S+12>>2]=c[m+12>>2];C=d+16|0;f=(c[C>>2]|0)+16|0;o=(c[o>>2]|0)+56|0;c[Q>>2]=c[f>>2];c[Q+4>>2]=c[f+4>>2];c[Q+8>>2]=c[f+8>>2];c[Q+12>>2]=c[f+12>>2];c[R>>2]=c[o>>2];c[R+4>>2]=c[o+4>>2];c[R+8>>2]=c[o+8>>2];c[R+12>>2]=c[o+12>>2];Bg(n,Q,R);c[T>>2]=c[n>>2];c[T+4>>2]=c[n+4>>2];c[T+8>>2]=c[n+8>>2];c[T+12>>2]=c[n+12>>2];w=+h[(c[e>>2]|0)+96>>3]+ +h[S>>3];x=+h[T>>3]-+h[(c[C>>2]|0)+88>>3];u=x+w;v=u*.5;C=c[U>>2]|0;c[X>>2]=c[S>>2];c[X+4>>2]=c[S+4>>2];c[X+8>>2]=c[S+8>>2];c[X+12>>2]=c[S+12>>2];o=X+16|0;c[o>>2]=c[S>>2];c[o+4>>2]=c[S+4>>2];c[o+8>>2]=c[S+8>>2];c[o+12>>2]=c[S+12>>2];e=X+32|0;c[e>>2]=c[T>>2];c[e+4>>2]=c[T+4>>2];c[e+8>>2]=c[T+8>>2];c[e+12>>2]=c[T+12>>2];f=X+48|0;c[f>>2]=c[T>>2];c[f+4>>2]=c[T+4>>2];c[f+8>>2]=c[T+8>>2];c[f+12>>2]=c[T+12>>2];Kz(C,c[((c[C>>2]&3|0)==2?C:C+-48|0)+40>>2]|0,X,4,17224);C=c[(c[C+16>>2]|0)+96>>2]|0;h[C+56>>3]=v;z=S+8|0;r=+h[z>>3];s=+h[C+32>>3];h[C+64>>3]=(s+6.0)*.5+r;a[C+81>>0]=1;r=r+3.0;B=+h[C+24>>3];A=(u-B)*.5;B=(B+u)*.5;C=X+24|0;D=X+40|0;E=X+56|0;F=X+64|0;G=T+8|0;H=X+72|0;I=X+80|0;J=X+88|0;K=X+96|0;L=X+104|0;M=X+112|0;N=X+120|0;O=V+4|0;n=(i|0)==6&1;q=0.0;p=0.0;s=s+r;m=1;while(1){if((m|0)>=(j|0)){y=6;break}d=c[U+(m<<2)>>2]|0;if(!(m&1)){c[X>>2]=c[S>>2];c[X+4>>2]=c[S+4>>2];c[X+8>>2]=c[S+8>>2];c[X+12>>2]=c[S+12>>2];h[o>>3]=A;h[C>>3]=+h[z>>3];h[e>>3]=A;h[D>>3]=s;h[f>>3]=B;h[E>>3]=s;h[F>>3]=B;t=+h[G>>3];h[H>>3]=t;Z=+h[T>>3];h[I>>3]=Z;h[J>>3]=t;h[K>>3]=Z;Z=s+6.0;h[L>>3]=Z;h[M>>3]=+h[S>>3];h[N>>3]=Z;s=+h[(c[(c[d+16>>2]|0)+96>>2]|0)+32>>3];t=Z+s*.5;s=Z+s}else{k=d+16|0;b=c[(c[k>>2]|0)+96>>2]|0;if((m|0)==1){p=+h[b+24>>3];q=(p+u)*.5;p=(u-p)*.5}r=r+-6.0-+h[b+32>>3];c[X>>2]=c[S>>2];c[X+4>>2]=c[S+4>>2];c[X+8>>2]=c[S+8>>2];c[X+12>>2]=c[S+12>>2];h[o>>3]=+h[S>>3];t=r+-6.0;h[C>>3]=t;h[e>>3]=+h[T>>3];h[D>>3]=t;c[f>>2]=c[T>>2];c[f+4>>2]=c[T+4>>2];c[f+8>>2]=c[T+8>>2];c[f+12>>2]=c[T+12>>2];h[F>>3]=q;h[H>>3]=+h[G>>3];h[I>>3]=q;h[J>>3]=r;h[K>>3]=p;h[L>>3]=r;h[M>>3]=p;h[N>>3]=+h[z>>3];t=+h[(c[(c[k>>2]|0)+96>>2]|0)+32>>3]*.5+r}c[O>>2]=8;c[V>>2]=X;c[P>>2]=c[S>>2];c[P+4>>2]=c[S+4>>2];c[P+8>>2]=c[S+8>>2];c[P+12>>2]=c[S+12>>2];c[Q>>2]=c[T>>2];c[Q+4>>2]=c[T+4>>2];c[Q+8>>2]=c[T+8>>2];c[Q+12>>2]=c[T+12>>2];c[R>>2]=c[V>>2];c[R+4>>2]=c[V+4>>2];k=ky(P,Q,R,W,n)|0;b=c[W>>2]|0;if(!b)break;i=c[(c[d+16>>2]|0)+96>>2]|0;h[i+56>>3]=v;h[i+64>>3]=t;a[i+81>>0]=1;Kz(d,c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0,k,b,17224);m=m+1|0}a:do if((y|0)==6){v=(x+w*2.0)*.3333333333333333;u=(x*2.0+w)*.3333333333333333;while(1){if((m|0)>=(g|0))break;d=c[U+(m<<2)>>2]|0;if(!(m&1)){c[X>>2]=c[S>>2];c[X+4>>2]=c[S+4>>2];c[X+8>>2]=c[S+8>>2];c[X+12>>2]=c[S+12>>2];h[o>>3]=A;h[C>>3]=+h[z>>3];h[e>>3]=A;h[D>>3]=s;h[f>>3]=B;h[E>>3]=s;h[F>>3]=B;t=+h[G>>3];h[H>>3]=t;Z=+h[T>>3];h[I>>3]=Z;h[J>>3]=t;h[K>>3]=Z;Z=s+6.0;h[L>>3]=Z;h[M>>3]=+h[S>>3];s=Z;t=p;p=Z}else{y=(m|0)==1;t=y?v:p;q=y?u:q;p=r+-6.0;c[X>>2]=c[S>>2];c[X+4>>2]=c[S+4>>2];c[X+8>>2]=c[S+8>>2];c[X+12>>2]=c[S+12>>2];h[o>>3]=+h[S>>3];r=r+-12.0;h[C>>3]=r;h[e>>3]=+h[T>>3];h[D>>3]=r;c[f>>2]=c[T>>2];c[f+4>>2]=c[T+4>>2];c[f+8>>2]=c[T+8>>2];c[f+12>>2]=c[T+12>>2];h[F>>3]=q;h[H>>3]=+h[G>>3];h[I>>3]=q;h[J>>3]=p;h[K>>3]=t;h[L>>3]=p;h[M>>3]=t;r=p;p=+h[z>>3]}h[N>>3]=p;c[O>>2]=8;c[V>>2]=X;c[P>>2]=c[S>>2];c[P+4>>2]=c[S+4>>2];c[P+8>>2]=c[S+8>>2];c[P+12>>2]=c[S+12>>2];c[Q>>2]=c[T>>2];c[Q+4>>2]=c[T+4>>2];c[Q+8>>2]=c[T+8>>2];c[Q+12>>2]=c[T+12>>2];c[R>>2]=c[V>>2];c[R+4>>2]=c[V+4>>2];k=ky(P,Q,R,W,n)|0;b=c[W>>2]|0;if(!b)break a;Kz(d,c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0,k,b,17224);m=m+1|0;p=t}$I(U)}while(0);l=Y;return}function Lg(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0;g=l;l=l+16|0;f=g;j=(rn(b)|0)==0;j=j?17648:17640;a[f>>0]=a[j>>0]|0;a[f+1>>0]=a[j+1>>0]|0;a[f+2>>0]=a[j+2>>0]|0;a[f+3>>0]=a[j+3>>0]|0;f=hn(78335,f,0)|0;Oo(f,122277,280,1)|0;zm(f,0,80018,174185)|0;j=ww(96)|0;e=c[f+16>>2]|0;c[e+8>>2]=j;i=c[b+16>>2]|0;k=c[i+8>>2]|0;h[j>>3]=+h[k>>3];h[j+24>>3]=+h[k+24>>3];a[e+115>>0]=a[i+115>>0]|0;c[e+116>>2]=c[i+116>>2]&1^1;c[e+248>>2]=c[i+248>>2];c[e+252>>2]=c[i+252>>2];e=Em(to(b)|0,1,0)|0;while(1){if(!e)break;zm(f,1,c[e+8>>2]|0,c[e+12>>2]|0)|0;e=Em(to(b)|0,1,e)|0}e=Em(to(b)|0,2,0)|0;while(1){if(!e)break;zm(f,2,c[e+8>>2]|0,c[e+12>>2]|0)|0;e=Em(to(b)|0,2,e)|0}if(!(zm(f,2,96251,0)|0))zm(f,2,96251,174185)|0;if(!(zm(f,2,96242,0)|0))zm(f,2,96242,174185)|0;Qg(f,d);l=g;return f|0}function Mg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;e=l;l=l+16|0;d=e;a=oo(a,En(b)|0,1)|0;Oo(a,122241,304,1)|0;Nm(b,a)|0;if((Cy(b)|0)==2){f=b+16|0;b=xw((sJ(c[c[(c[f>>2]|0)+104>>2]>>2]|0)|0)+3|0)|0;c[d>>2]=c[c[(c[f>>2]|0)+104>>2]>>2];qL(b,78330,d)|0;Lm(a,86240,b)|0}l=e;return a|0}function Ng(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=bn(a,b,c,0,1)|0;Oo(c,122254,176,1)|0;Nm(d,c)|0;return c|0}function Og(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0.0;i=l;l=l+32|0;g=i+16|0;f=i;if(e|0){j=+h[b>>3];e=b+8|0;h[b>>3]=+h[e>>3];h[e>>3]=-j};c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];c[g>>2]=c[d>>2];c[g+4>>2]=c[d+4>>2];c[g+8>>2]=c[d+8>>2];c[g+12>>2]=c[d+12>>2];Bg(a,f,g);l=i;return}function Pg(a,b){a=a|0;b=b|0;c[42234]=c[b>>2];c[42238]=c[b+4>>2];c[42239]=c[b+8>>2];c[42219]=c[b+12>>2];c[42220]=c[b+16>>2];c[42226]=c[b+20>>2];c[42225]=c[b+24>>2];c[42224]=c[b+28>>2];c[42250]=c[b+32>>2];c[42242]=c[b+36>>2];c[42227]=c[b+40>>2];c[42237]=c[b+44>>2];c[42246]=c[b+48>>2];c[42245]=c[b+52>>2];c[42244]=c[b+56>>2];c[42249]=c[b+60>>2];c[42243]=c[b+64>>2];c[42228]=c[b+68>>2];c[42190]=c[b+72>>2];c[42191]=c[b+76>>2];c[42192]=c[b+80>>2];c[42202]=c[b+84>>2];c[42195]=c[b+88>>2];c[42196]=c[b+92>>2];c[42197]=c[b+96>>2];c[42199]=c[b+100>>2];c[42200]=c[b+104>>2];c[42203]=c[b+108>>2];c[42206]=c[b+112>>2];c[42204]=c[b+116>>2];c[42205]=c[b+120>>2];c[42208]=c[b+124>>2];c[42207]=c[b+128>>2];c[42209]=c[b+132>>2];c[42210]=c[b+136>>2];c[42201]=c[b+140>>2];c[42213]=c[b+144>>2];c[42185]=c[b+148>>2];c[42182]=c[b+152>>2];$I(b);Ff(a);mn(a)|0;return}function Qg(a,b){a=a|0;b=b|0;c[b>>2]=c[42234];c[b+4>>2]=c[42238];c[b+8>>2]=c[42239];c[b+12>>2]=c[42219];c[b+16>>2]=c[42220];c[b+20>>2]=c[42226];c[b+24>>2]=c[42225];c[b+28>>2]=c[42224];c[b+32>>2]=c[42250];c[b+36>>2]=c[42242];c[b+40>>2]=c[42227];c[b+44>>2]=c[42237];c[b+48>>2]=c[42246];c[b+52>>2]=c[42245];c[b+56>>2]=c[42244];c[b+60>>2]=c[42249];c[b+64>>2]=c[42243];c[b+68>>2]=c[42228];c[b+72>>2]=c[42190];c[b+76>>2]=c[42191];c[b+80>>2]=c[42192];c[b+84>>2]=c[42202];c[b+88>>2]=c[42195];c[b+92>>2]=c[42196];c[b+96>>2]=c[42197];c[b+100>>2]=c[42199];c[b+104>>2]=c[42200];c[b+108>>2]=c[42203];c[b+112>>2]=c[42206];c[b+116>>2]=c[42204];c[b+120>>2]=c[42205];c[b+124>>2]=c[42208];c[b+128>>2]=c[42207];c[b+132>>2]=c[42209];c[b+136>>2]=c[42210];c[b+140>>2]=c[42201];c[b+144>>2]=c[42213];c[b+152>>2]=c[42182];c[b+148>>2]=c[42185];c[42234]=0;c[42238]=zm(a,2,80259,0)|0;c[42239]=zm(a,2,80268,0)|0;b=zm(a,2,86614,0)|0;c[42219]=b;if(!b)c[42219]=zm(a,2,86614,174185)|0;c[42220]=0;c[42226]=0;c[42225]=zm(a,2,86494,0)|0;c[42224]=zm(a,2,86485,0)|0;c[42250]=zm(a,2,86790,0)|0;c[42242]=0;c[42227]=zm(a,2,86240,0)|0;c[42237]=zm(a,2,78340,0)|0;c[42246]=0;c[42245]=zm(a,2,86690,0)|0;c[42244]=zm(a,2,86676,0)|0;c[42249]=zm(a,2,86781,0)|0;c[42243]=0;c[42228]=0;c[42190]=zm(a,1,96049,0)|0;c[42191]=zm(a,1,96043,0)|0;c[42192]=zm(a,1,90671,0)|0;c[42202]=0;c[42195]=zm(a,1,86485,0)|0;c[42196]=zm(a,1,86494,0)|0;c[42197]=0;c[42199]=zm(a,1,86240,0)|0;c[42200]=0;c[42203]=0;c[42206]=zm(a,1,86446,0)|0;c[42204]=zm(a,1,86529,0)|0;c[42205]=zm(a,1,86535,0)|0;c[42208]=zm(a,1,86547,0)|0;c[42207]=zm(a,1,86385,0)|0;c[42209]=zm(a,1,86552,0)|0;c[42210]=zm(a,1,78352,0)|0;c[42201]=0;c[42213]=0;c[42185]=zm(a,0,86446,0)|0;return}function Rg(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0.0,g=0.0,i=0.0;d=c[(c[(c[a>>2]|0)+16>>2]|0)+96>>2]|0;a=c[(c[(c[b>>2]|0)+16>>2]|0)+96>>2]|0;b=(a|0)!=0;if(d)if(b?(f=+h[d+24>>3],i=+h[d+32>>3],e=+h[a+24>>3],g=+h[a+32>>3],!(f>e)):0)if(!(fg)a=-1;else a=i>2]|0)+116>>2]|0;if(!b)break;else a=b}b=c[a>>2]&3;d=c[(c[((b|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0;e=c[d+232>>2]|0;a=c[(c[((b|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0;b=c[a+232>>2]|0;if((e|0)<=(b|0))if((e|0)<(b|0))a=1;else a=(c[d+236>>2]|0)<(c[a+236>>2]|0)&1;else a=0;return a|0}function Tg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=l;l=l+16|0;e=d+8|0;f=d;h=(c[a+16>>2]|0)+180|0;g=(c[b+16>>2]|0)+172|0;c[f>>2]=c[h>>2];c[f+4>>2]=c[h+4>>2];c[e>>2]=c[g>>2];c[e+4>>2]=c[g+4>>2];b=Ug(a,f,b,e)|0;l=d;return b|0}function Ug(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=c[b+4>>2]|0;a:do if((f|0)>0?(g=c[e+4>>2]|0,(g|0)>0):0)if((f|0)<(g|0)){f=c[b>>2]|0;e=0;while(1){b=c[f+(e<<2)>>2]|0;if(!b){b=0;break a}if((c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)==(d|0))break;else e=e+1|0}}else{f=c[e>>2]|0;e=0;while(1){b=c[f+(e<<2)>>2]|0;if(!b){b=0;break a}if((c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)==(a|0))break;else e=e+1|0}}else b=0;while(0);return b|0}function Vg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=l;l=l+16|0;e=d+8|0;f=d;h=(c[a+16>>2]|0)+188|0;g=(c[b+16>>2]|0)+196|0;c[f>>2]=c[h>>2];c[f+4>>2]=c[h+4>>2];c[e>>2]=c[g>>2];c[e+4>>2]=c[g+4>>2];b=Ug(a,f,b,e)|0;l=d;return b|0}function Wg(a){a=a|0;var b=0,d=0,e=0,f=0;e=a+48|0;d=c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0;b=c[d+180>>2]|0;if(!b)b=xw((c[d+184>>2]<<2)+8|0)|0;else b=zw(b,(c[d+184>>2]<<2)+8|0)|0;c[(c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0)+180>>2]=b;f=c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0;d=c[f+180>>2]|0;f=f+184|0;b=c[f>>2]|0;c[f>>2]=b+1;c[d+(b<<2)>>2]=a;e=c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0;c[(c[e+180>>2]|0)+(c[e+184>>2]<<2)>>2]=0;e=a+-48|0;b=c[(c[((c[a>>2]&3|0)==2?a:e)+40>>2]|0)+16>>2]|0;d=c[b+172>>2]|0;if(!d)b=xw((c[b+176>>2]<<2)+8|0)|0;else b=zw(d,(c[b+176>>2]<<2)+8|0)|0;c[(c[(c[((c[a>>2]&3|0)==2?a:e)+40>>2]|0)+16>>2]|0)+172>>2]=b;b=c[(c[((c[a>>2]&3|0)==2?a:e)+40>>2]|0)+16>>2]|0;d=c[b+172>>2]|0;b=b+176|0;f=c[b>>2]|0;c[b>>2]=f+1;c[d+(f<<2)>>2]=a;f=c[(c[((c[a>>2]&3|0)==2?a:e)+40>>2]|0)+16>>2]|0;c[(c[f+172>>2]|0)+(c[f+176>>2]<<2)>>2]=0;return a|0}function Xg(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;e=a+4|0;f=c[e>>2]|0;d=0;while(1){if((d|0)>=(f|0))break;g=c[a>>2]|0;h=g+(d<<2)|0;if((c[h>>2]|0)==(b|0)){i=4;break}else d=d+1|0}if((i|0)==4){i=f+-1|0;c[e>>2]=i;c[h>>2]=c[g+(i<<2)>>2];c[(c[a>>2]|0)+(i<<2)>>2]=0}return}function Yg(a){a=a|0;if(!a)ma(78393,78403,117,78412);else{Xg((c[(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+180|0,a);Xg((c[(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+172|0,a);return}}function Zg(a){a=a|0;var b=0,d=0,e=0,f=0;e=a+48|0;d=c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0;b=c[d+204>>2]|0;if(!b)b=xw((c[d+208>>2]<<2)+8|0)|0;else b=zw(b,(c[d+208>>2]<<2)+8|0)|0;c[(c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0)+204>>2]=b;f=c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0;b=c[f+204>>2]|0;f=f+208|0;d=c[f>>2]|0;c[f>>2]=d+1;c[b+(d<<2)>>2]=a;e=c[(c[((c[a>>2]&3|0)==3?a:e)+40>>2]|0)+16>>2]|0;c[(c[e+204>>2]|0)+(c[e+208>>2]<<2)>>2]=0;return}function _g(a){a=a|0;$g(a,(c[(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+204|0);return}function $g(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;h=b+4|0;e=c[h>>2]|0;f=c[b>>2]|0;d=0;while(1){if((d|0)>=(e|0)){g=4;break}if((c[f+(d<<2)>>2]|0)==(a|0))break;else d=d+1|0}if((g|0)==4){if(!f)d=xw((e<<2)+8|0)|0;else d=zw(f,(e<<2)+8|0)|0;c[b>>2]=d;f=c[h>>2]|0;g=f+1|0;c[h>>2]=g;c[d+(f<<2)>>2]=a;c[(c[b>>2]|0)+(g<<2)>>2]=0}return}function ah(d,e,f){d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;n=ww(96)|0;g=n+48|0;c[g>>2]=c[g>>2]|3;c[n>>2]=c[n>>2]&-4|2;h=ww(176)|0;m=n+16|0;c[m>>2]=h;c[((c[n>>2]&3|0)==3?n:g)+40>>2]=d;j=n+-48|0;c[((c[n>>2]&3|0)==2?n:j)+40>>2]=e;a[h+112>>0]=1;if(!f){c[h+156>>2]=1;b[h+154>>1]=1;b[h+168>>1]=1;b[h+170>>1]=1}else{c[n>>2]=c[n>>2]&15|c[f>>2]&-16;c[g>>2]=c[g>>2]&15|c[f>>2]&-16;l=f+16|0;i=c[l>>2]|0;b[h+168>>1]=b[i+168>>1]|0;b[h+154>>1]=b[i+154>>1]|0;c[h+156>>2]=c[i+156>>2];b[h+170>>1]=b[i+170>>1]|0;d=c[((c[n>>2]&3|0)==3?n:g)+40>>2]|0;e=c[f>>2]&3;k=f+48|0;if((d|0)!=(c[((e|0)==3?f:k)+40>>2]|0)){g=f+-48|0;if((d|0)==(c[((e|0)==2?f:g)+40>>2]|0)){h=h+16|0;d=i+56|0;e=h+40|0;do{c[h>>2]=c[d>>2];h=h+4|0;d=d+4|0}while((h|0)<(e|0))}}else{h=h+16|0;d=i+16|0;e=h+40|0;do{c[h>>2]=c[d>>2];h=h+4|0;d=d+4|0}while((h|0)<(e|0));g=f+-48|0}d=c[((c[n>>2]&3|0)==2?n:j)+40>>2]|0;e=c[f>>2]&3;if((d|0)!=(c[((e|0)==2?f:g)+40>>2]|0)){if((d|0)==(c[((e|0)==3?f:k)+40>>2]|0)){h=(c[m>>2]|0)+56|0;d=(c[l>>2]|0)+16|0;e=h+40|0;do{c[h>>2]=c[d>>2];h=h+4|0;d=d+4|0}while((h|0)<(e|0))}}else{h=(c[m>>2]|0)+56|0;d=(c[l>>2]|0)+56|0;e=h+40|0;do{c[h>>2]=c[d>>2];h=h+4|0;d=d+4|0}while((h|0)<(e|0))}d=(c[l>>2]|0)+172|0;if(!(c[d>>2]|0))c[d>>2]=n;c[(c[m>>2]|0)+116>>2]=f}return n|0}function bh(a,b,c){a=a|0;b=b|0;c=c|0;return Wg(ah(a,b,c)|0)|0}function ch(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;a=(c[a+16>>2]|0)+192|0;f=c[a>>2]|0;d=c[b+16>>2]|0;c[d+164>>2]=f;e=f;if(f|0)c[(c[e+16>>2]|0)+168>>2]=b;c[a>>2]=b;c[d+168>>2]=0;if((e|0)==(b|0))ma(78429,78403,215,78445);else return}function dh(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;if((a|0)==(b|0))ma(78455,78403,220,78462);f=c[b+16>>2]|0;d=f+164|0;if(c[d>>2]|0)ma(78475,78403,221,78462);e=(c[a+16>>2]|0)+164|0;c[d>>2]=c[e>>2];d=c[e>>2]|0;if(d|0)c[(c[d+16>>2]|0)+168>>2]=b;c[f+168>>2]=a;c[e>>2]=b;return}function eh(a,b){a=a|0;b=b|0;var d=0,e=0;if(!(fh(a,b)|0))ma(78494,78403,231,78515);b=c[b+16>>2]|0;d=c[b+164>>2]|0;e=d;b=b+168|0;if(d|0)c[(c[d+16>>2]|0)+168>>2]=c[b>>2];b=c[b>>2]|0;if(!b)c[(c[a+16>>2]|0)+192>>2]=e;else c[(c[b+16>>2]|0)+164>>2]=e;return}function fh(a,b){a=a|0;b=b|0;a=(c[a+16>>2]|0)+192|0;while(1){a=c[a>>2]|0;if((a|0)==0|(a|0)==(b|0))break;a=(c[a+16>>2]|0)+164|0}return a|0}function gh(b){b=b|0;var d=0,e=0,f=0,g=0;d=ww(64)|0;c[d>>2]=c[d>>2]&-4|1;e=d+16|0;c[e>>2]=ww(304)|0;c[d+24>>2]=to(b)|0;g=c[e>>2]|0;a[g+156>>0]=1;h[g+96>>3]=1.0;h[g+88>>3]=1.0;h[g+80>>3]=1.0;c[g+216>>2]=1;c[g+176>>2]=0;g=ww(20)|0;f=c[e>>2]|0;c[f+172>>2]=g;c[f+184>>2]=0;f=ww(20)|0;c[(c[e>>2]|0)+180>>2]=f;ch(b,d);b=(c[b+16>>2]|0)+232|0;c[b>>2]=(c[b>>2]|0)+1;return d|0}function hh(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;g=d+48|0;e=c[(c[((c[d>>2]&3|0)==3?d:g)+40>>2]|0)+16>>2]|0;f=c[e+188>>2]|0;if(!f)e=xw((c[e+192>>2]<<2)+8|0)|0;else e=zw(f,(c[e+192>>2]<<2)+8|0)|0;c[(c[(c[((c[d>>2]&3|0)==3?d:g)+40>>2]|0)+16>>2]|0)+188>>2]=e;h=c[(c[((c[d>>2]&3|0)==3?d:g)+40>>2]|0)+16>>2]|0;f=c[h+188>>2]|0;h=h+192|0;e=c[h>>2]|0;c[h>>2]=e+1;c[f+(e<<2)>>2]=d;g=c[(c[((c[d>>2]&3|0)==3?d:g)+40>>2]|0)+16>>2]|0;c[(c[g+188>>2]|0)+(c[g+192>>2]<<2)>>2]=0;g=d+-48|0;e=c[(c[((c[d>>2]&3|0)==2?d:g)+40>>2]|0)+16>>2]|0;f=c[e+196>>2]|0;if(!f)e=xw((c[e+200>>2]<<2)+8|0)|0;else e=zw(f,(c[e+200>>2]<<2)+8|0)|0;c[(c[(c[((c[d>>2]&3|0)==2?d:g)+40>>2]|0)+16>>2]|0)+196>>2]=e;e=c[(c[((c[d>>2]&3|0)==2?d:g)+40>>2]|0)+16>>2]|0;f=c[e+196>>2]|0;e=e+200|0;h=c[e>>2]|0;c[e>>2]=h+1;c[f+(h<<2)>>2]=d;h=c[(c[((c[d>>2]&3|0)==2?d:g)+40>>2]|0)+16>>2]|0;c[(c[h+196>>2]|0)+(c[h+200>>2]<<2)>>2]=0;a[(c[b+16>>2]|0)+240>>0]=1;a[(c[(Wf(b)|0)+16>>2]|0)+240>>0]=1;return}function ih(a){a=a|0;var b=0,d=0;if(!a)ma(78393,78403,269,78532);b=c[(c[a+16>>2]|0)+116>>2]|0;if(b|0?(d=(c[b+16>>2]|0)+172|0,(c[d>>2]|0)==(a|0)):0)c[d>>2]=0;Xg((c[(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+188|0,a);Xg((c[(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+196|0,a);return}function jh(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=l;l=l+16|0;d=(c[a+16>>2]|0)+172|0;e=c[d>>2]|0;do if((e|0)!=(b|0))if(!e){c[d>>2]=b;kh(a,b);break}else ma(80440,78403,340,78570);else $l(0,78549,f)|0;while(0);l=f;return}function kh(a,d){a=a|0;d=d|0;var f=0,g=0,h=0,i=0;f=(c[d+16>>2]|0)+170|0;i=c[a+16>>2]|0;a=b[i+170>>1]|0;if((e[f>>1]|0)<(a&65535))b[f>>1]=a;g=i+168|0;h=i+154|0;f=i+156|0;a=d;while(1){if(!a)break;d=c[a+16>>2]|0;i=d+168|0;b[i>>1]=(e[i>>1]|0)+(e[g>>1]|0);i=d+154|0;b[i>>1]=(e[i>>1]|0)+(e[h>>1]|0);i=d+156|0;c[i>>2]=(c[i>>2]|0)+(c[f>>2]|0);a=c[d+172>>2]|0}return}function lh(d){d=d|0;var e=0,f=0,g=0,h=0;f=d+16|0;e=c[(c[f>>2]|0)+172>>2]|0;a:while(1){if(!e)break;mh(e,d);h=c[e+16>>2]|0;g=c[h+172>>2]|0;if(!(b[h+168>>1]|0))nh(e);while(1){if((a[(c[e+16>>2]|0)+112>>0]|0)!=1){e=g;continue a}e=c[(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0)+16>>2]|0;if((a[e+156>>0]|0)!=1){e=g;continue a}if((c[e+184>>2]|0)!=1){e=g;continue a}e=c[c[e+180>>2]>>2]|0;mh(e,d)}}c[(c[f>>2]|0)+172>>2]=0;return}function mh(a,d){a=a|0;d=d|0;var f=0;f=c[d+16>>2]|0;d=c[a+16>>2]|0;a=d+168|0;b[a>>1]=(e[a>>1]|0)-(e[f+168>>1]|0);a=d+154|0;b[a>>1]=(e[a>>1]|0)-(e[f+154>>1]|0);d=d+156|0;c[d>>2]=(c[d>>2]|0)-(c[f+156>>2]|0);return}function nh(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;if(!a)ma(78393,78403,128,78583);g=a+48|0;d=0;while(1){b=c[a>>2]|0;e=(c[(c[((b&3|0)==3?a:g)+40>>2]|0)+16>>2]|0)+180|0;f=c[(c[e>>2]|0)+(d<<2)>>2]|0;if(!f)break;if((f|0)==(a|0))Xg(e,a);d=d+1|0}g=a+-48|0;f=0;while(1){d=(c[(c[((b&3|0)==2?a:g)+40>>2]|0)+16>>2]|0)+172|0;e=c[(c[d>>2]|0)+(f<<2)>>2]|0;if(!e)break;if((e|0)==(a|0)){Xg(d,a);b=c[a>>2]|0}f=f+1|0}return}function oh(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;p=l;l=l+1040|0;n=p+1032|0;o=p;m=p+8|0;k=d+16|0;d=c[k>>2]|0;j=b[d+236>>1]|0;while(1){if((j|0)>(b[d+238>>1]|0))break;i=c[d+196>>2]|0;h=i+(j<<6)|0;i=i+(j<<6)+4|0;g=0;d=0;while(1){if((g|0)>=(c[h>>2]|0))break;e=c[(c[i>>2]|0)+(g<<2)>>2]|0;f=e+16|0;if(c[(c[f>>2]|0)+112>>2]|0){if(!d){a[n>>0]=a[17644]|0;a[n+1>>0]=a[17645]|0;a[n+2>>0]=a[17646]|0;a[n+3>>0]=a[17647]|0;d=hn(78605,n,0)|0}c[o>>2]=g;qL(m,122187,o)|0;t=oo(d,m,1)|0;Oo(t,78608,24,1)|0;q=c[(c[f>>2]|0)+180>>2]|0;r=c[q>>2]|0;r=c[(c[(c[((c[r>>2]&3|0)==2?r:r+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;q=c[q+4>>2]|0;q=c[(c[(c[((c[q>>2]&3|0)==2?q:q+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;s=(r|0)>(q|0);f=c[t+16>>2]|0;c[f+12>>2]=s?q:r;c[f+16>>2]=s?r:q;c[f+20>>2]=e}g=g+1|0}if(d|0){if((nn(d)|0)>1)ph(d,h);mn(d)|0}j=j+1|0;d=c[k>>2]|0}l=p;return}function ph(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;d=0;h=eo(a)|0;a:while(1){if(!h)break;i=fo(a,h)|0;j=h+16|0;g=i;while(1){if(!g){h=i;continue a}f=c[g+16>>2]|0;e=c[j>>2]|0;if((c[f+16>>2]|0)>(c[e+12>>2]|0)){if((c[e+16>>2]|0)<=(c[f+12>>2]|0))bn(a,h,g,0,1)|0}else{bn(a,g,h,0,1)|0;d=1}g=fo(a,g)|0}}do if(d|0){h=Jp(a,78613,1)|0;j=ww((nn(a)|0)<<2)|0;i=ww((nn(a)|0)<<2)|0;f=b+4|0;e=eo(a)|0;b:while(1){if(!e){d=23;break}if((c[(c[e+16>>2]|0)+8>>2]|0)==0?pn(a,e,1,1)|0:0){c:do if(qh(a,e,h,i)|0){g=nn(h)|0;if((rh(a,h,j)|0)!=(g|0)){d=17;break b}sL(i,g,4,12);d=0;while(1){if((d|0)>=(g|0))break c;b=i+(d<<2)|0;k=c[j+(d<<2)>>2]|0;c[(c[k+16>>2]|0)+236>>2]=c[b>>2];c[(c[f>>2]|0)+(c[b>>2]<<2)>>2]=k;d=d+1|0}}while(0);th(h)}e=fo(a,e)|0}if((d|0)==17)ma(78618,78628,265,78639);else if((d|0)==23){$I(j);break}}while(0);return}function qh(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;h=c[b+16>>2]|0;c[h+8>>2]=1;h=c[(c[(c[h+20>>2]|0)+16>>2]|0)+236>>2]|0;c[e+((nn(d)|0)<<2)>>2]=h;jo(d,b,1)|0;h=Qm(a,b)|0;f=0;while(1){if(!h)break;j=c[h>>2]&3;g=c[((j|0)==2?h:h+-48|0)+40>>2]|0;i=c[g+16>>2]|0;f=f+((c[(c[(c[i+20>>2]|0)+16>>2]|0)+236>>2]|0)>(c[(c[(c[(c[(c[((j|0)==3?h:h+48|0)+40>>2]|0)+16>>2]|0)+20>>2]|0)+16>>2]|0)+236>>2]|0)&1)|0;if(!(c[i+8>>2]|0))f=(qh(a,g,d,e)|0)+f|0;h=Sm(a,h)|0}h=Tm(a,b)|0;while(1){if(!h)break;i=c[h>>2]&3;g=c[((i|0)==3?h:h+48|0)+40>>2]|0;j=c[g+16>>2]|0;f=f+((c[(c[(c[(c[(c[((i|0)==2?h:h+-48|0)+40>>2]|0)+16>>2]|0)+20>>2]|0)+16>>2]|0)+236>>2]|0)>(c[(c[(c[j+20>>2]|0)+16>>2]|0)+236>>2]|0)&1)|0;if(!(c[j+8>>2]|0))f=(qh(a,g,d,e)|0)+f|0;h=Um(a,h)|0}return f|0}function rh(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;f=0;while(1){e=uh(a,b)|0;if(!e)break;c[d+(f<<2)>>2]=c[(c[e+16>>2]|0)+20>>2];qo(b,e)|0;e=Qm(a,e)|0;while(1){if(!e)break;g=Sm(a,e)|0;en(a,e)|0;e=g}f=f+1|0}return f|0}function sh(a,b){a=a|0;b=b|0;return (c[a>>2]|0)-(c[b>>2]|0)|0}function th(a){a=a|0;var b=0,c=0;b=eo(a)|0;while(1){if(!b)break;c=fo(a,b)|0;qo(a,b)|0;b=c}return}function uh(a,b){a=a|0;b=b|0;var c=0;c=eo(b)|0;while(1){if(!c){c=0;break}if(!(pn(a,c,1,0)|0))break;c=fo(b,c)|0}return c|0}function vh(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;wh(b);i=b+16|0;f=0;e=0;while(1){if((f|0)>=(c[(c[i>>2]|0)+220>>2]|0))break;xh(b,f);f=f+1|0;e=(yh(b,0,d)|0)+e|0}zh(b);h=1;while(1){f=c[i>>2]|0;g=c[f+180>>2]|0;if((h|0)>(g|0))break;g=(Ah(c[(c[f+184>>2]|0)+(h<<2)>>2]|0,d)|0)+e|0;h=h+1|0;e=g}do if((g|0)>0){f=Jm(b,78653)|0;if(f|0?(JA(f)|0)<<24>>24==0:0)break;Zk(b);a[173897]=1;e=yh(b,2,d)|0}while(0);Bh(b,e);return}function wh(d){d=d|0;var e=0;if(0)yA();a[173897]=0;c[41927]=d;e=((on(Wf(d)|0)|0)<<2)+4|0;c[41926]=ww(e)|0;c[41925]=ww(e)|0;ri(d);e=d+16|0;if(b[(c[e>>2]|0)+136>>1]&16)si(d);Gk(d);ul(d,1);ti(d);Ih(d);e=c[e>>2]|0;c[41928]=b[e+236>>1];c[41929]=b[e+238>>1];return}function xh(a,d){a=a|0;d=d|0;var e=0,f=0,g=0;a=c[a+16>>2]|0;c[a+192>>2]=c[(c[a+216>>2]|0)+(d<<2)>>2];a:do if((d|0)>0){d=b[a+238>>1]|0;e=a+196|0;a=b[a+236>>1]|0;while(1){if((a|0)>(d|0))break a;f=c[e>>2]|0;g=f+(a<<6)+4|0;f=f+(a<<6)|0;c[g>>2]=(c[g>>2]|0)+(c[f>>2]<<2);c[f>>2]=0;a=a+1|0}}while(0);return}function yh(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+32|0;n=o;if((b|0)>1){e=Yh(0)|0;Zh(a)}else e=2147483647;m=c[13918]|0;k=b;f=0;b=e;while(1){if((k|0)>=3)break;f=c[42181]|0;if((k|0)==2)if((e|0)>(b|0)){$h(a);e=b}else e=b;else{e=(f|0)<4?f:4;if((Wf(a)|0)==(a|0))_h(a,k);if(!k)Jh(a);Kh(a);g=Yh(0)|0;if((g|0)>(b|0)){f=e;e=g}else{Zh(a);f=e;e=g;b=g}}g=0;j=0;while(1){if((j|0)>=(f|0))break;if(0){c[n>>2]=k;c[n+4>>2]=j;c[n+8>>2]=g;c[n+12>>2]=e;c[n+16>>2]=b;AL(m,79046,n)|0}i=g+1|0;if((e|0)==0|(g|0)>=(c[41930]|0))break;ai(a,j);e=Yh(0)|0;if((e|0)>(b|0))g=i;else{Zh(a);g=+h[20878]*+(b|0)>+(e|0)?0:i;b=e}j=j+1|0}if(!e){e=0;break}else k=k+1|0}if((e|0)>(b|0))$h(a);if((b|0)>0){bi(a,0);e=Yh(0)|0}else e=b;a:do if(d|0){b=0;while(1){if((b|0)>=(f|0))break a;ci(a);b=b+1|0}}while(0);l=o;return e|0}function zh(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;p=l;l=l+16|0;n=p;Xh(a);k=a+16|0;d=c[k>>2]|0;m=c[13918]|0;j=b[d+236>>1]|0;while(1){if((j|0)>(b[d+238>>1]|0))break;e=c[d+196>>2]|0;f=c[e+(j<<6)+8>>2]|0;c[e+(j<<6)>>2]=f;g=c[e+(j<<6)+12>>2]|0;c[e+(j<<6)+4>>2]=g;i=0;while(1){if((i|0)>=(f|0))break;h=c[g+(i<<2)>>2]|0;if(!h){o=6;break}c[(c[h+16>>2]|0)+236>>2]=i;i=i+1|0}if((o|0)==6){o=0;if(0){e=En(a)|0;d=c[(c[(c[k>>2]|0)+196>>2]|0)+(j<<6)>>2]|0;c[n>>2]=e;c[n+4>>2]=j;c[n+8>>2]=i;c[n+12>>2]=d;AL(m,78996,n)|0;d=c[k>>2]|0;e=c[d+196>>2]|0}c[e+(j<<6)>>2]=i}j=j+1|0}l=p;return}function Ah(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;Tk(a);Ih(a);Jh(a);Kh(a);f=a+16|0;d=yh(a,2,b)|0;e=1;while(1){g=c[f>>2]|0;if((e|0)>(c[g+180>>2]|0))break;d=(Ah(c[(c[g+184>>2]|0)+(e<<2)>>2]|0,b)|0)+d|0;e=e+1|0}Lh(a);return d|0}function Bh(d,e){d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0;q=l;l=l+16|0;p=q;f=c[41925]|0;if(f|0){$I(f);c[41925]=0}f=c[41926]|0;if(f|0){$I(f);c[41926]=0}o=d+16|0;f=1;while(1){g=c[o>>2]|0;if((f|0)>(c[g+180>>2]|0))break;Ch(c[(c[g+184>>2]|0)+(f<<2)>>2]|0);f=f+1|0}n=b[g+236>>1]|0;f=g;while(1){if((n|0)>(b[f+238>>1]|0))break;else m=0;while(1){f=c[f+196>>2]|0;if((m|0)>=(c[f+(n<<6)>>2]|0))break;k=(c[(c[f+(n<<6)+4>>2]|0)+(m<<2)>>2]|0)+16|0;f=c[k>>2]|0;c[f+236>>2]=m;f=c[f+188>>2]|0;a:do if(f|0){g=0;while(1){i=c[f+(g<<2)>>2]|0;if(!i)break a;j=i+16|0;if((a[(c[j>>2]|0)+112>>0]|0)==4){ih(i);$I(c[j>>2]|0);$I(i);g=g+-1|0;f=c[(c[k>>2]|0)+188>>2]|0}g=g+1|0}}while(0);m=m+1|0;f=c[o>>2]|0}Dh(c[f+(n<<6)+56>>2]|0);n=n+1|0;f=c[o>>2]|0}if(0){o=c[13918]|0;d=En(d)|0;r=+zA();c[p>>2]=d;c[p+4>>2]=e;h[p+8>>3]=r;AL(o,78664,p)|0}l=q;return}function Ch(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;g=a+16|0;d=1;while(1){f=c[g>>2]|0;if((d|0)>(c[f+180>>2]|0))break;Ch(c[(c[f+184>>2]|0)+(d<<2)>>2]|0);d=d+1|0}a:do if(c[f+268>>2]|0){e=b[f+236>>1]|0;d=f;while(1){if((e|0)>(b[d+238>>1]|0))break a;j=c[(c[d+268>>2]|0)+(e<<2)>>2]|0;i=Eh(a,j,-1)|0;j=Eh(a,j,1)|0;c[(c[(c[g>>2]|0)+268>>2]|0)+(e<<2)>>2]=i;k=c[(c[(c[(Wf(a)|0)+16>>2]|0)+196>>2]|0)+(e<<6)+4>>2]|0;i=c[(c[i+16>>2]|0)+236>>2]|0;f=c[g>>2]|0;h=c[f+196>>2]|0;c[h+(e<<6)+4>>2]=k+(i<<2);c[h+(e<<6)>>2]=(c[(c[j+16>>2]|0)+236>>2]|0)+1-i;e=e+1|0;d=f}}while(0);return}function Dh(a){a=a|0;if(a|0){$I(c[a+8>>2]|0);$I(a)}return}function Eh(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=b;while(1){b=Fh(b,c)|0;if(!b)break;if(Gh(a,b)|0){d=b;continue}e=(Hh(a,b)|0)==0;d=e?d:b}return d|0}function Fh(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if(!a)ma(78703,78628,1023,78705);if((b|0)<0){a=c[a+16>>2]|0;e=c[a+236>>2]|0;if((e|0)>0){a=(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(c[a+232>>2]<<6)+4|0;d=e+-1|0;f=7}else g=0}else{a=c[a+16>>2]|0;e=c[a+236>>2]|0;a=(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(c[a+232>>2]<<6)+4|0;d=e+1|0;f=7}if((f|0)==7){a=c[(c[a>>2]|0)+(d<<2)>>2]|0;if(a)if((O((c[(c[a+16>>2]|0)+236>>2]|0)-e|0,b)|0)>0)g=a;else ma(78714,78628,1029,78705);else g=0}return g|0}function Gh(b,d){b=b|0;d=d|0;if(!(a[(c[d+16>>2]|0)+156>>0]|0))b=(Co(b,d)|0)!=0&1;else b=0;return b|0}function Hh(b,d){b=b|0;d=d|0;var e=0,f=0;d=c[d+16>>2]|0;if(((a[d+156>>0]|0)==1?(c[d+176>>2]|0)==1:0)?(c[d+184>>2]|0)==1:0){d=c[d+180>>2]|0;while(1){d=c[d>>2]|0;e=c[d+16>>2]|0;if(!(a[e+112>>0]|0))break;else d=e+116|0}if(Co(b,d)|0)d=1;else f=7}else f=7;if((f|0)==7)d=0;return d|0}function Ih(b){b=b|0;var d=0,e=0,f=0;f=l;l=l+16|0;e=f;d=c[42185]|0;a:do if((d|0)!=0|(c[42206]|0)!=0){d=GA(b,d,0)|0;if(d|0){switch(a[d>>0]|0){case 0:break a;case 111:{if(!(yJ(d,78916)|0)){Sh(b,1);break a}break}case 105:{if(!(yJ(d,83705)|0)){Sh(b,0);break a}break}default:{}}c[e>>2]=d;$l(1,78920,e)|0;break}d=Kp(b)|0;while(1){if(!d)break;if(!(Dj(d)|0))Ih(d);d=Lp(d)|0}if(c[42206]|0)Th(b)}while(0);l=f;return}function Jh(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=d+16|0;e=c[k>>2]|0;j=b[e+236>>1]|0;while(1){if((j|0)>(b[e+238>>1]|0))break;else{f=0;i=0}while(1){g=c[e+196>>2]|0;h=c[g+(j<<6)>>2]|0;if((i|0)>=(h|0))break;g=c[(c[(c[g+(j<<6)+4>>2]|0)+(i<<2)>>2]|0)+16>>2]|0;a[g+158>>0]=0;a[g+157>>0]=0;c[g+284>>2]=i;if((f|0)==0&(c[g+192>>2]|0)>0){f=Qh(h,h)|0;e=c[k>>2]|0;c[(c[e+196>>2]|0)+(j<<6)+56>>2]=f;f=1}i=i+1|0}a:do if(f){i=0;f=h;while(1){if((i|0)>=(f|0))break a;h=c[(c[g+(j<<6)+4>>2]|0)+(i<<2)>>2]|0;if(!(a[(c[h+16>>2]|0)+157>>0]|0)){Rh(d,h);e=c[k>>2]|0;f=c[e+196>>2]|0;g=f;f=c[f+(j<<6)>>2]|0}i=i+1|0}}while(0);j=j+1|0}return}function Kh(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;s=d+16|0;e=c[s>>2]|0;if(a[e+240>>0]|0){h=0;r=b[e+236>>1]|0;q=0;i=0;a:while(1){if((r|0)>(b[e+238>>1]|0))break;f=c[e+196>>2]|0;g=c[f+(r<<6)>>2]|0;if(!g){g=q;f=i}else{f=c[f+(r<<6)+4>>2]|0;o=c[(c[(c[f>>2]|0)+16>>2]|0)+236>>2]|0;e=0;while(1){if((e|0)>=(g|0))break;a[(c[(c[f+(e<<2)>>2]|0)+16>>2]|0)+157>>0]=0;e=e+1|0}e=(e<<2)+4|0;if(!h)p=xw(e)|0;else p=zw(i,e)|0;m=0;n=0;while(1){e=c[s>>2]|0;f=c[e+196>>2]|0;g=c[f+(r<<6)>>2]|0;if((g|0)<=(n|0))break;j=c[(c[f+(r<<6)+4>>2]|0)+(((c[e+116>>2]&1|0)==0?g+~n|0:n)<<2)>>2]|0;l=j+16|0;e=0;k=0;while(1){i=c[l>>2]|0;if((e|0)>=(c[i+200>>2]|0)){f=0;g=0;e=i;break}i=k+((Mh(d,c[(c[i+196>>2]|0)+(e<<2)>>2]|0)|0)!=0&1)|0;e=e+1|0;k=i}while(1){if((g|0)>=(c[e+192>>2]|0))break;i=f+((Mh(d,c[(c[e+188>>2]|0)+(g<<2)>>2]|0)|0)!=0&1)|0;f=i;g=g+1|0;e=c[l>>2]|0}if(f|k)if((k|0)==0&(a[e+157>>0]|0)==0)e=(Nh(d,j,p+(m<<2)|0,r)|0)+m|0;else e=m;else{c[p+(m<<2)>>2]=j;e=m+1|0}m=e;n=n+1|0}b:do if(m){c:do if(!(c[e+116>>2]&1)){f=p;e=p+(m<<2)|0;while(1){e=e+-4|0;if(f>>>0>=e>>>0){g=0;break c}n=c[f>>2]|0;c[f>>2]=c[e>>2];c[e>>2]=n;f=f+4|0}}else g=0;while(0);while(1){e=c[s>>2]|0;i=c[e+196>>2]|0;f=c[i+(r<<6)>>2]|0;if((g|0)>=(f|0)){m=0;g=i;break}n=c[p+(g<<2)>>2]|0;c[(c[i+(r<<6)+4>>2]|0)+(g<<2)>>2]=n;c[(c[n+16>>2]|0)+236>>2]=g+o;g=g+1|0}while(1){if((m|0)>=(f|0))break b;l=(c[(c[g+(r<<6)+4>>2]|0)+(m<<2)>>2]|0)+16|0;i=c[(c[l>>2]|0)+188>>2]|0;if(i){k=0;f=i;while(1){g=c[f+(k<<2)>>2]|0;e=c[s>>2]|0;if(!g)break;j=c[g>>2]&3;i=c[(c[(c[((j|0)==2?g:g+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;j=c[(c[(c[((j|0)==3?g:g+48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;if(!(c[e+116>>2]&1))if((i|0)<(j|0))t=36;else e=k;else if((i|0)>(j|0))t=36;else e=k;if((t|0)==36){t=0;if(Mh(d,g)|0){t=37;break a}ih(g);Oh(d,g);e=k+-1|0;f=c[(c[l>>2]|0)+188>>2]|0}k=e+1|0}f=c[e+196>>2]|0;g=f;f=c[f+(r<<6)>>2]|0}m=m+1|0}}while(0);a[(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(r<<6)+49>>0]=0;h=p;g=p;f=p}r=r+1|0;q=g;i=f}if((t|0)==37)ma(78762,78628,1561,78801);if(h|0)$I(q)}return}function Lh(a){a=a|0;var d=0,e=0;e=a+16|0;a=c[e>>2]|0;a:do if(c[a+268>>2]|0){d=b[a+236>>1]|0;while(1){if((d|0)>(b[a+238>>1]|0))break a;c[(c[a+268>>2]|0)+(d<<2)>>2]=c[c[(c[a+196>>2]|0)+(d<<6)+4>>2]>>2];d=d+1|0;a=c[e>>2]|0}}while(0);return}function Mh(a,b){a=a|0;b=b|0;if((c[(c[b+16>>2]|0)+156>>2]|0)!=0?(Ph(a,c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0)!=0:0)a=(Ph(a,c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0)!=0&1;else a=0;return a|0}function Nh(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0;l=d+16|0;g=c[l>>2]|0;a[g+157>>0]=1;a:do if((c[g+192>>2]|0)>0){h=0;j=0;while(1){i=c[(c[g+188>>2]|0)+(j<<2)>>2]|0;if(!i)break a;if((Mh(b,i)|0)!=0?(k=c[((c[i>>2]&3|0)==2?i:i+-48|0)+40>>2]|0,(a[(c[k+16>>2]|0)+157>>0]|0)==0):0)h=(Nh(b,k,e+(h<<2)|0,f)|0)+h|0;j=j+1|0;g=c[l>>2]|0}}else h=0;while(0);if((c[g+232>>2]|0)==(f|0)){c[e+(h<<2)>>2]=d;return h+1|0}else ma(78814,78628,1490,78830);return 0}function Oh(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;i=c[d>>2]&3;j=c[((i|0)==2?d:d+-48|0)+40>>2]|0;f=c[(c[j+16>>2]|0)+188>>2]|0;a:do if(!f){e=d+48|0;m=15}else{l=d+48|0;g=((i|0)==3?d:l)+40|0;e=0;while(1){h=c[f+(e<<2)>>2]|0;if(!h){e=l;m=15;break a}if((c[((c[h>>2]&3|0)==2?h:h+-48|0)+40>>2]|0)==(c[g>>2]|0))break;else e=e+1|0}jh(d,h);e=(c[d+16>>2]|0)+172|0;if(!(c[e>>2]|0))c[e>>2]=h;e=c[h+16>>2]|0;if((a[e+112>>0]|0)==4?(k=e+116|0,(c[k>>2]|0)==0):0)c[k>>2]=d;e=c[(c[((c[d>>2]&3|0)==3?d:l)+40>>2]|0)+16>>2]|0;f=c[e+204>>2]|0;if(!f)e=xw((c[e+208>>2]<<2)+8|0)|0;else e=zw(f,(c[e+208>>2]<<2)+8|0)|0;c[(c[(c[((c[d>>2]&3|0)==3?d:l)+40>>2]|0)+16>>2]|0)+204>>2]=e;i=c[(c[((c[d>>2]&3|0)==3?d:l)+40>>2]|0)+16>>2]|0;j=c[i+204>>2]|0;i=i+208|0;k=c[i>>2]|0;c[i>>2]=k+1;c[j+(k<<2)>>2]=d;d=c[(c[((c[d>>2]&3|0)==3?d:l)+40>>2]|0)+16>>2]|0;c[(c[d+204>>2]|0)+(c[d+208>>2]<<2)>>2]=0}while(0);if((m|0)==15){m=ah(j,c[((i|0)==3?d:e)+40>>2]|0,d)|0;l=c[d+16>>2]|0;d=c[m+16>>2]|0;a[d+112>>0]=(a[l+112>>0]|0)==4?4:3;c[d+96>>2]=c[l+96>>2];hh(b,m)}return}function Ph(a,b){a=a|0;b=b|0;var c=0;c=Gh(a,b)|0;return Hh(a,b)|0|c|0}function Qh(a,b){a=a|0;b=b|0;var d=0;d=ww(12)|0;c[d>>2]=a;c[d+4>>2]=b;c[d+8>>2]=ww(O(b,a)|0)|0;return d|0}function Rh(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;o=d+16|0;l=c[o>>2]|0;k=c[(c[(c[b+16>>2]|0)+196>>2]|0)+(c[l+232>>2]<<6)+56>>2]|0;a[l+157>>0]=1;a[l+158>>0]=1;l=(c[(c[(Wf(b)|0)+16>>2]|0)+180>>2]|0)>0;e=c[o>>2]|0;f=c[e+188>>2]|0;a:do if(f){m=k+4|0;n=k+8|0;d=0;b:while(1){j=c[f+(d<<2)>>2]|0;if(!j){p=e;break a}if(l){if((Co(b,c[((c[j>>2]&3|0)==3?j:j+48|0)+40>>2]|0)|0)!=0?(Co(b,c[((c[j>>2]&3|0)==2?j:j+-48|0)+40>>2]|0)|0)!=0:0)q=7}else q=7;do if((q|0)==7){q=0;h=j+16|0;if(c[(c[h>>2]|0)+156>>2]|0){e=c[j>>2]&3;g=j+-48|0;r=c[(c[((e|0)==2?j:g)+40>>2]|0)+16>>2]|0;i=c[r+284>>2]|0;f=(i|0)<(c[k>>2]|0);if((a[r+158>>0]|0)==1){if(!f){q=10;break b}e=c[(c[(c[((e|0)==3?j:j+48|0)+40>>2]|0)+16>>2]|0)+284>>2]|0;f=c[m>>2]|0;if((e|0)>=(f|0)){q=12;break b}a[(c[n>>2]|0)+((O(f,i)|0)+e)>>0]=1;ih(j);d=d+-1|0;if((a[(c[h>>2]|0)+112>>0]|0)==4)break;Oh(b,j);break}else{if(!f){q=16;break b}e=c[(c[(c[((e|0)==3?j:j+48|0)+40>>2]|0)+16>>2]|0)+284>>2]|0;f=c[m>>2]|0;if((e|0)>=(f|0)){q=18;break b}a[(c[n>>2]|0)+((O(f,e)|0)+i)>>0]=1;e=c[((c[j>>2]&3|0)==2?j:g)+40>>2]|0;if(a[(c[e+16>>2]|0)+157>>0]|0)break;Rh(b,e);break}}}while(0);f=c[o>>2]|0;d=d+1|0;e=f;f=c[f+188>>2]|0}if((q|0)==10)ma(78840,78628,1251,78872);else if((q|0)==12)ma(78884,78628,1252,78872);else if((q|0)==16)ma(78840,78628,1260,78872);else if((q|0)==18)ma(78884,78628,1261,78872)}else p=e;while(0);a[p+158>>0]=0;return}function Sh(a,b){a=a|0;b=b|0;var c=0;c=eo(a)|0;while(1){if(!c)break;Uh(a,c,b);c=fo(a,c)|0}return}function Th(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;g=l;l=l+16|0;f=g;d=eo(b)|0;while(1){if(!d)break;e=GA(d,c[42206]|0,0)|0;a:do if(e|0){switch(a[e>>0]|0){case 0:break a;case 111:{if(!(yJ(e,78916)|0)){Uh(b,d,1);break a}break}case 105:{if(!(yJ(e,83705)|0)){Uh(b,d,0);break a}break}default:{}}h=En(d)|0;c[f>>2]=e;c[f+4>>2]=h;$l(1,78951,f)|0}while(0);d=fo(b,d)|0}l=g;return}function Uh(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;j=c[41926]|0;h=d+16|0;f=c[h>>2]|0;a:do if(!(c[f+212>>2]|0)){i=(e|0)!=0;b:do if(i){g=0;d=0;e=f;while(1){f=c[(c[e+180>>2]|0)+(g<<2)>>2]|0;if(!f)break b;if(!(Vh(f)|0)){c[j+(d<<2)>>2]=f;d=d+1|0;e=c[h>>2]|0}g=g+1|0}}else{g=0;d=0;e=f;while(1){f=c[(c[e+172>>2]|0)+(g<<2)>>2]|0;if(!f)break b;if(!(Vh(f)|0)){c[j+(d<<2)>>2]=f;d=d+1|0;e=c[h>>2]|0}g=g+1|0}}while(0);if((d|0)>=2){c[j+(d<<2)>>2]=0;sL(j,d,4,13);h=i?2:3;g=i?-1:1;f=1;while(1){d=c[j+(f<<2)>>2]|0;if(!d)break a;e=c[j+(f+-1<<2)>>2]|0;e=c[((c[e>>2]&3|0)==(h|0)?e:e+(g*48|0)|0)+40>>2]|0;d=c[((c[d>>2]&3|0)==(h|0)?d:d+(g*48|0)|0)+40>>2]|0;if(Vg(e,d)|0)break a;i=ah(e,d,0)|0;a[(c[i+16>>2]|0)+112>>0]=4;hh(b,i);f=f+1|0}}}while(0);return}function Vh(a){a=a|0;var b=0;while(1){b=c[(c[a+16>>2]|0)+116>>2]|0;if(!b)break;else a=b}b=c[a>>2]&3;return (c[(c[(c[((b|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0)!=(c[(c[(c[((b|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0)|0}function Wh(a,b){a=a|0;b=b|0;return ((c[c[a>>2]>>2]|0)>>>4)-((c[c[b>>2]>>2]|0)>>>4)|0}function Xh(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;f=c[a+16>>2]|0;g=f+220|0;h=c[g>>2]|0;if((h|0)>=2){i=f+216|0;a=0;e=0;while(1){if((e|0)>=(h|0))break;d=c[(c[i>>2]|0)+(e<<2)>>2]|0;if(a|0)c[(c[a+16>>2]|0)+164>>2]=d;j=c[d+16>>2]|0;c[j+168>>2]=a;a=d;d=j;while(1){d=c[d+164>>2]|0;if(!d)break;a=d;d=c[d+16>>2]|0}e=e+1|0}c[g>>2]=1;c[f+192>>2]=c[c[f+216>>2]>>2];b[f+236>>1]=c[41928];b[f+238>>1]=c[41929]}return}function Yh(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;i=c[41927]|0;j=i+16|0;f=c[j>>2]|0;g=0;h=b[f+236>>1]|0;while(1){if((h|0)>=(b[f+238>>1]|0))break;d=c[f+196>>2]|0;if(!(a[d+(h<<6)+49>>0]|0)){e=pi(i,h)|0;d=c[j>>2]|0;f=c[d+196>>2]|0;c[f+(h<<6)+52>>2]=e;a[f+(h<<6)+49>>0]=1}else{e=c[d+(h<<6)+52>>2]|0;d=f}g=e+g|0;h=h+1|0;f=d}return g|0}function Zh(a){a=a|0;var d=0,e=0,f=0,g=0,i=0,j=0;a=c[a+16>>2]|0;g=b[a+238>>1]|0;i=a+196|0;a=b[a+236>>1]|0;while(1){if((a|0)>(g|0))break;f=c[i>>2]|0;e=c[f+(a<<6)>>2]|0;f=f+(a<<6)+4|0;d=0;while(1){if((d|0)>=(e|0))break;j=c[(c[(c[f>>2]|0)+(d<<2)>>2]|0)+16>>2]|0;h[j+16>>3]=+(c[j+236>>2]|0);d=d+1|0}a=a+1|0}return}function _h(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0;r=l;l=l+16|0;m=r;n=d+16|0;o=AA(c[(c[n>>2]|0)+232>>2]|0)|0;j=c[n>>2]|0;f=j+192|0;g=f;while(1){g=c[g>>2]|0;if(!g)break;g=c[g+16>>2]|0;a[g+157>>0]=0;g=g+164|0}h=b[j+238>>1]|0;i=j+196|0;g=b[j+236>>1]|0;while(1){if((g|0)>(h|0))break;c[(c[i>>2]|0)+(g<<6)>>2]=0;g=g+1|0}i=(e|0)==0;while(1){g=c[f>>2]|0;if(!g)break;h=g+16|0;f=c[h>>2]|0;if((c[c[(i?f+172|0:f+180|0)>>2]>>2]|0)==0?(k=f+157|0,(a[k>>0]|0)==0):0){a[k>>0]=1;CA(o,g);while(1){f=DA(o)|0;if(!f)break;if((a[(c[f+16>>2]|0)+159>>0]|0)==7){Yk(d,f,e,o);continue}else{ni(d,f);oi(o,f,e);continue}}f=c[h>>2]|0}f=f+164|0}if(DA(o)|0)$l(1,79159,m)|0;f=c[n>>2]|0;j=b[f+236>>1]|0;while(1){if((j|0)>(b[f+238>>1]|0))break;a[(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(j<<6)+49>>0]=0;if((c[f+116>>2]&1|0)!=0?(p=c[f+196>>2]|0,q=c[p+(j<<6)>>2]|0,(q|0)>0):0){g=c[p+(j<<6)+4>>2]|0;h=q+-1|0;i=(h|0)/2|0;f=0;while(1){if((f|0)>(i|0))break;hi(c[g+(f<<2)>>2]|0,c[g+(h-f<<2)>>2]|0);f=f+1|0}f=c[n>>2]|0}j=j+1|0}if((Wf(d)|0)==(d|0)?(Yh(0)|0)>0:0)bi(d,0);BA(o);l=r;return}function $h(d){d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;n=d+16|0;d=c[n>>2]|0;f=b[d+236>>1]|0;e=b[d+238>>1]|0;l=e<<16>>16;m=d+196|0;g=f;while(1){if((g|0)>(l|0))break;k=c[m>>2]|0;j=c[k+(g<<6)>>2]|0;k=k+(g<<6)+4|0;i=0;while(1){if((i|0)>=(j|0))break;o=c[(c[(c[k>>2]|0)+(i<<2)>>2]|0)+16>>2]|0;c[o+236>>2]=~~+h[o+16>>3];i=i+1|0}g=g+1|0}while(1){if((f|0)>(e<<16>>16|0))break;a[(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(f<<6)+49>>0]=0;o=c[d+196>>2]|0;sL(c[o+(f<<6)+4>>2]|0,c[o+(f<<6)>>2]|0,4,14);o=c[n>>2]|0;f=f+1|0;e=b[o+238>>1]|0;d=o}return}function ai(a,d){a=a|0;d=d|0;var e=0,f=0,g=0;g=((d|0)%4|0|0)<2&1;e=c[a+16>>2]|0;if(!(d&1)){d=b[e+236>>1]|0;f=1;e=b[e+238>>1]|0;d=(d<<16>>16<=(b[(c[(c[41927]|0)+16>>2]|0)+236>>1]|0)&1)+(d<<16>>16)|0}else{d=b[e+238>>1]|0;f=-1;e=b[e+236>>1]|0;d=((d<<16>>16>=(b[(c[(c[41927]|0)+16>>2]|0)+238>>1]|0))<<31>>31)+(d<<16>>16)|0}e=f+e|0;while(1){if((d|0)==(e|0))break;ki(a,d,g,(ji(a,d,d-f|0)|0)&255);d=d+f|0}bi(a,g^1);return}function bi(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;k=d+16|0;g=c[k>>2]|0;i=b[g+236>>1]|0;j=b[g+238>>1]|0;h=g+196|0;f=i<<16>>16;while(1){if((f|0)>(j|0)){h=i;break}a[(c[h>>2]|0)+(f<<6)+48>>0]=1;f=f+1|0}while(1){f=0;h=h<<16>>16;while(1){if((h|0)>(b[g+238>>1]|0))break;if(a[(c[g+196>>2]|0)+(h<<6)+48>>0]|0){f=(ii(d,h,e)|0)+f|0;g=c[k>>2]|0}h=h+1|0}if((f|0)<=0)break;h=b[g+236>>1]|0}return}function ci(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;o=d+16|0;e=c[o>>2]|0;n=b[e+238>>1]|0;a:while(1){if((n|0)<(b[e+236>>1]|0)){e=16;break}f=c[e+196>>2]|0;a[f+(n<<6)+48>>0]=0;p=(n|0)>0;q=n+1|0;g=0;b:while(1){l=(c[f+(n<<6)>>2]|0)+-1|0;m=f+(n<<6)+4|0;k=f+(q<<6)|0;while(1){if((g|0)>=(l|0))break b;j=c[m>>2]|0;i=c[j+(g<<2)>>2]|0;g=g+1|0;j=c[j+(g<<2)>>2]|0;if((c[(c[i+16>>2]|0)+236>>2]|0)>=(c[(c[j+16>>2]|0)+236>>2]|0)){e=7;break a}if(di(d,i,j)|0)continue;if(p){f=ei(i,j)|0;h=ei(j,i)|0}else{f=0;h=0}if((c[k>>2]|0)>0){f=(fi(i,j)|0)+f|0;h=(fi(j,i)|0)+h|0}if((h|0)<=(f|0))break}gi(d,n,i,j);e=c[o>>2]|0;f=c[e+196>>2]|0}n=n+-1|0}if((e|0)==7)ma(79110,78628,721,79136);else if((e|0)==16)return}function di(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;j=c[d+16>>2]|0;i=c[j+212>>2]|0;f=c[e+16>>2]|0;g=c[f+212>>2]|0;h=(i|0)!=(g|0);do if(!(a[173897]|0))if((g|0)==0|((i|0)==0|h^1))k=9;else{if((a[j+159>>0]|0)==7?(a[j+156>>0]|0)==1:0){b=0;break}if((a[f+159>>0]|0)==7?(a[f+156>>0]|0)==1:0){b=0;break}b=1}else if(h)b=1;else k=9;while(0);if((k|0)==9){f=c[b+16>>2]|0;b=c[(c[f+196>>2]|0)+(c[j+232>>2]<<6)+56>>2]|0;if(!b)b=0;else{j=(c[f+116>>2]&1|0)==0;k=O(c[b+4>>2]|0,c[(c[(j?d:e)+16>>2]|0)+284>>2]|0)|0;b=a[(c[b+8>>2]|0)+((c[(c[(j?e:d)+16>>2]|0)+284>>2]|0)+k)>>0]|0}}return b|0}function ei(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0;l=a+16|0;j=c[(c[d+16>>2]|0)+172>>2]|0;d=0;while(1){a=c[j>>2]|0;if(!a)break;i=c[a+16>>2]|0;k=b[i+154>>1]|0;g=c[(c[(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;i=i+16|0;f=c[(c[l>>2]|0)+172>>2]|0;a=d;while(1){d=c[f>>2]|0;if(!d)break;e=(c[(c[(c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)-g|0;if((e|0)<=0){if((e|0)==0?(m=c[d+16>>2]|0,+h[m+16>>3]>+h[i>>3]):0){d=m;n=9}}else{d=c[d+16>>2]|0;n=9}if((n|0)==9){n=0;a=(O(b[d+154>>1]|0,k)|0)+a|0}f=f+4|0}j=j+4|0;d=a}return d|0}function fi(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0;l=a+16|0;j=c[(c[d+16>>2]|0)+180>>2]|0;d=0;while(1){a=c[j>>2]|0;if(!a)break;i=c[a+16>>2]|0;k=b[i+154>>1]|0;g=c[(c[(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;i=i+56|0;f=c[(c[l>>2]|0)+180>>2]|0;a=d;while(1){d=c[f>>2]|0;if(!d)break;e=(c[(c[(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)-g|0;if((e|0)<=0){if((e|0)==0?(m=c[d+16>>2]|0,+h[m+56>>3]>+h[i>>3]):0){d=m;n=9}}else{d=c[d+16>>2]|0;n=9}if((n|0)==9){n=0;a=(O(b[d+154>>1]|0,k)|0)+a|0}f=f+4|0}j=j+4|0;d=a}return d|0}function gi(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;i=a[(c[e+16>>2]|0)+156>>0]|0;if(i<<24>>24!=(a[(c[f+16>>2]|0)+156>>0]|0)){j=b+16|0;l=c[(c[j>>2]|0)+196>>2]|0;k=c[l+(d<<6)>>2]|0;l=l+(d<<6)+4|0;b=0;g=0;h=0;while(1){if((b|0)>=(k|0))break;o=(a[(c[(c[(c[l>>2]|0)+(b<<2)>>2]|0)+16>>2]|0)+156>>0]|0)==0;b=b+1|0;g=g+(o&1)|0;h=h+((o^1)&1)|0}i=i<<24>>24==0;h=(g|0)<(h|0)?(i?e:f):i?f:e;i=0;b=0;while(1){if((b|0)>=(k|0))break;i=(c[(c[l>>2]|0)+(b<<2)>>2]|0)==(h|0)?b:i;b=b+1|0}o=(a[(c[h+16>>2]|0)+156>>0]|0)==0&1;n=0;g=i;while(1){b=g+-1|0;if((g|0)<=0){m=0;b=i;break}if((a[(c[(c[(c[l>>2]|0)+(b<<2)>>2]|0)+16>>2]|0)+156>>0]|0)!=(o|0)){m=0;b=i;break}n=n+1|0;g=b}while(1){b=b+1|0;if((b|0)>=(k|0))break;if((a[(c[(c[(c[l>>2]|0)+(b<<2)>>2]|0)+16>>2]|0)+156>>0]|0)!=(o|0))break;m=m+1|0}hi(e,f);j=c[(c[j>>2]|0)+196>>2]|0;k=c[j+(d<<6)>>2]|0;j=j+(d<<6)+4|0;b=0;while(1){if((b|0)>=(k|0)){h=0;g=i;break}i=(c[(c[j>>2]|0)+(b<<2)>>2]|0)==(h|0)?b:i;b=b+1|0}while(1){b=g+-1|0;if((g|0)<=0){g=0;b=i;break}if((a[(c[(c[(c[j>>2]|0)+(b<<2)>>2]|0)+16>>2]|0)+156>>0]|0)!=(o|0)){g=0;b=i;break}h=h+1|0;g=b}while(1){b=b+1|0;if((b|0)>=(k|0))break;if((a[(c[(c[(c[j>>2]|0)+(b<<2)>>2]|0)+16>>2]|0)+156>>0]|0)!=(o|0))break;g=g+1|0}d=h-g|0;o=n-m|0;if((((d|0)>-1?d:0-d|0)|0)>(((o|0)>-1?o:0-o|0)|0))hi(e,f)}return}function hi(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;f=c[a+16>>2]|0;e=c[f+232>>2]|0;f=f+236|0;d=c[f>>2]|0;g=b+16|0;h=c[(c[g>>2]|0)+236>>2]|0;c[f>>2]=h;f=(c[41927]|0)+16|0;c[(c[(c[(c[f>>2]|0)+196>>2]|0)+(e<<6)+4>>2]|0)+(h<<2)>>2]=a;c[(c[g>>2]|0)+236>>2]=d;c[(c[(c[(c[f>>2]|0)+196>>2]|0)+(e<<6)+4>>2]|0)+(d<<2)>>2]=b;return}function ii(d,e,f){d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;q=d+16|0;n=c[(c[q>>2]|0)+196>>2]|0;a[n+(e<<6)+48>>0]=0;r=(e|0)>0;s=e+1|0;o=(f|0)!=0;p=e+-1|0;g=0;i=0;f=n;a:while(1){l=(c[f+(e<<6)>>2]|0)+-1|0;m=f+(e<<6)+4|0;h=f+(s<<6)|0;n=g;while(1){if((n|0)>=(l|0)){f=17;break a}k=c[m>>2]|0;j=c[k+(n<<2)>>2]|0;n=n+1|0;k=c[k+(n<<2)>>2]|0;if((c[(c[j+16>>2]|0)+236>>2]|0)>=(c[(c[k+16>>2]|0)+236>>2]|0)){f=5;break a}if(di(d,j,k)|0)continue;if(r){f=ei(j,k)|0;g=ei(k,j)|0}else{f=0;g=0}if((c[h>>2]|0)>0){f=(fi(j,k)|0)+f|0;g=(fi(k,j)|0)+g|0}if((f|0)>(g|0))break;if((f|0)==(g|0)&(o&(f|0)>0)){f=g;break}}hi(j,k);i=f-g+i|0;g=c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0;a[g+(e<<6)+49>>0]=0;h=c[q>>2]|0;f=c[h+196>>2]|0;a[f+(e<<6)+48>>0]=1;if((b[h+236>>1]|0)<(e|0)){a[g+(p<<6)+49>>0]=0;a[f+(p<<6)+48>>0]=1}if((b[h+238>>1]|0)<=(e|0)){g=n;continue}a[g+(s<<6)+49>>0]=0;a[f+(s<<6)+48>>0]=1;g=n}if((f|0)==5)ma(79110,78628,770,79144);else if((f|0)==17)return i|0;return 0}function ji(a,e,f){a=a|0;e=e|0;f=f|0;var g=0,i=0.0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;p=c[41925]|0;q=a+16|0;a=c[(c[q>>2]|0)+196>>2]|0;r=c[a+(e<<6)+4>>2]|0;n=(f|0)>(e|0);o=p+4|0;m=0;while(1){f=c[a+(e<<6)>>2]|0;if((m|0)>=(f|0)){a=0;j=0;break}l=(c[r+(m<<2)>>2]|0)+16|0;a=c[l>>2]|0;a:do if(n){k=c[a+180>>2]|0;a=0;j=0;while(1){f=c[k+(j<<2)>>2]|0;if(!f)break a;g=c[f+16>>2]|0;if((b[g+154>>1]|0)>0){c[p+(a<<2)>>2]=c[(c[(c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]<<8|d[g+88>>0];a=a+1|0}j=j+1|0}}else{k=c[a+172>>2]|0;j=0;a=0;while(1){f=c[k+(j<<2)>>2]|0;if(!f)break a;g=c[f+16>>2]|0;if((b[g+154>>1]|0)>0){c[p+(a<<2)>>2]=c[(c[(c[((c[f>>2]&3|0)==3?f:f+48|0)+40>>2]|0)+16>>2]|0)+236>>2]<<8|d[g+48>>0];a=a+1|0}j=j+1|0}}while(0);b:do switch(a|0){case 0:{i=-1.0;break}case 1:{i=+(c[p>>2]|0);break}case 2:{i=+(((c[o>>2]|0)+(c[p>>2]|0)|0)/2|0|0);break}default:{sL(p,a,4,12);f=(a|0)/2|0;if(a&1|0){i=+(c[p+(f<<2)>>2]|0);break b}j=c[p+(f<<2)>>2]|0;g=(c[p+(a+-1<<2)>>2]|0)-j|0;a=c[p+(f+-1<<2)>>2]|0;f=a-(c[p>>2]|0)|0;if((f|0)==(g|0)){i=+((a+j|0)/2|0|0);break b}else{i=+(((O(f,j)|0)+(O(a,g)|0)|0)/(f+g|0)|0|0);break b}}}while(0);h[(c[l>>2]|0)+240>>3]=i;m=m+1|0;a=c[(c[q>>2]|0)+196>>2]|0}while(1){if((j|0)>=(f|0))break;g=c[r+(j<<2)>>2]|0;p=c[g+16>>2]|0;if((c[p+184>>2]|0)==0?(c[p+176>>2]|0)==0:0){a=(li(g)|0|a&255)&255;f=c[(c[(c[q>>2]|0)+196>>2]|0)+(e<<6)>>2]|0}j=j+1|0}return a|0}function ki(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0;o=c[(c[b+16>>2]|0)+196>>2]|0;s=c[o+(d<<6)+4>>2]|0;o=c[o+(d<<6)>>2]|0;q=(e|0)!=0;p=(f|e|0)==0;f=0;e=o;o=s+(o<<2)|0;while(1){n=e+-1|0;if((e|0)>0)e=s;else break;a:while(1){b:while(1){if(e>>>0>=o>>>0)break a;while(1){if(e>>>0>=o>>>0)break a;l=c[e>>2]|0;m=+h[(c[l+16>>2]|0)+240>>3];if(!(m<0.0))break;e=e+4|0}k=0;while(1){g=k<<24>>24==0;while(1){e=e+4|0;if(e>>>0>=o>>>0)break a;if(g){g=11;break}i=c[e>>2]|0;if(!(c[(c[i+16>>2]|0)+212>>2]|0)){g=13;break}}if((g|0)==11){i=c[e>>2]|0;j=i}else if((g|0)==13)j=i;if(di(b,l,j)|0)continue b;g=c[i+16>>2]|0;if(+h[g+240>>3]>=0.0)break;k=(c[g+212>>2]|0)==0?k:1}g=~~m;k=~~+h[(c[i+16>>2]|0)+240>>3];if((g|0)>(k|0)|q&(g|0)==(k|0))break}hi(l,j);f=f+1|0}e=n;o=p?o+-4|0:o}if(f|0?(r=c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0,a[r+(d<<6)+49>>0]=0,(d|0)>0):0)a[r+(d+-1<<6)+49>>0]=0;return}function li(a){a=a|0;var b=0.0,d=0,e=0,f=0,g=0;g=c[a+16>>2]|0;if((c[g+200>>2]|0)>0){f=c[g+196>>2]|0;a=c[f>>2]|0;a=c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0;d=1;while(1){e=c[f+(d<<2)>>2]|0;if(!e)break;e=c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0;a=(c[(c[e+16>>2]|0)+236>>2]|0)>(c[(c[a+16>>2]|0)+236>>2]|0)?e:a;d=d+1|0}b=+h[(c[a+16>>2]|0)+240>>3];if(!(b>=0.0))a=1;else{h[g+240>>3]=b+1.0;a=0}}else if((c[g+192>>2]|0)>0){e=c[g+188>>2]|0;d=c[e>>2]|0;a=1;d=c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0;while(1){f=c[e+(a<<2)>>2]|0;if(!f)break;f=c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0;a=a+1|0;d=(c[(c[f+16>>2]|0)+236>>2]|0)<(c[(c[d+16>>2]|0)+236>>2]|0)?f:d}b=+h[(c[d+16>>2]|0)+240>>3];if(b>0.0){h[g+240>>3]=b+-1.0;a=0}else a=1}else a=1;return a|0}function mi(a,b){a=a|0;b=b|0;return (c[(c[(c[a>>2]|0)+16>>2]|0)+236>>2]|0)-(c[(c[(c[b>>2]|0)+16>>2]|0)+236>>2]|0)|0}function ni(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;p=l;l=l+96|0;o=p+64|0;n=p+48|0;h=p+24|0;f=p;j=d+16|0;k=c[(c[j>>2]|0)+232>>2]|0;m=a+16|0;e=c[(c[m>>2]|0)+196>>2]|0;i=c[e+(k<<6)>>2]|0;do if((c[e+(k<<6)+8>>2]|0)>=1){c[(c[e+(k<<6)+4>>2]|0)+(i<<2)>>2]=d;c[(c[j>>2]|0)+236>>2]=i;a=c[m>>2]|0;f=c[a+196>>2]|0;e=f+(k<<6)|0;g=c[e>>2]|0;c[e>>2]=g+1;if((g|0)>=(c[f+(k<<6)+8>>2]|0))ma(79224,78628,1346,79260);g=c[(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(k<<6)+8>>2]|0;if((i|0)>(g|0)){m=En(d)|0;n=c[(c[j>>2]|0)+236>>2]|0;o=c[(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(k<<6)+8>>2]|0;c[h>>2]=1359;c[h+4>>2]=m;c[h+8>>2]=n;c[h+12>>2]=k;c[h+16>>2]=o;$l(1,79276,h)|0;break}e=b[a+236>>1]|0;a=b[a+238>>1]|0;if((k|0)<(e|0)|(k|0)>(a<<16>>16|0)){c[n>>2]=1364;c[n+4>>2]=k;c[n+8>>2]=e;c[n+12>>2]=a<<16>>16;$l(1,79349,n)|0;break}if(((c[f+(k<<6)+4>>2]|0)+(i<<2)|0)>>>0>((c[f+(k<<6)+12>>2]|0)+(g<<2)|0)>>>0){i=En(d)|0;n=c[(c[m>>2]|0)+196>>2]|0;m=(c[n+(k<<6)+4>>2]|0)+(c[(c[j>>2]|0)+236>>2]<<2)|0;n=(c[n+(k<<6)+12>>2]|0)+(c[(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(k<<6)+8>>2]<<2)|0;c[o>>2]=1370;c[o+4>>2]=k;c[o+8>>2]=i;c[o+12>>2]=m;c[o+16>>2]=k;c[o+20>>2]=k;c[o+24>>2]=n;$l(1,79410,o)|0}}else{n=En(a)|0;o=En(d)|0;c[f>>2]=1339;c[f+4>>2]=n;c[f+8>>2]=o;c[f+12>>2]=k;c[f+16>>2]=i;$l(1,79169,f)|0}while(0);l=p;return}function oi(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;h=d+16|0;a:do if(!e){g=0;while(1){d=c[h>>2]|0;if((g|0)>=(c[d+184>>2]|0))break a;d=c[(c[d+180>>2]|0)+(g<<2)>>2]|0;e=d+-48|0;f=(c[(c[((c[d>>2]&3|0)==2?d:e)+40>>2]|0)+16>>2]|0)+157|0;if(!(a[f>>0]|0)){a[f>>0]=1;CA(b,c[((c[d>>2]&3|0)==2?d:e)+40>>2]|0)}g=g+1|0}}else{g=0;while(1){d=c[h>>2]|0;if((g|0)>=(c[d+176>>2]|0))break a;d=c[(c[d+172>>2]|0)+(g<<2)>>2]|0;e=d+48|0;f=(c[(c[((c[d>>2]&3|0)==3?d:e)+40>>2]|0)+16>>2]|0)+157|0;if(!(a[f>>0]|0)){a[f>>0]=1;CA(b,c[((c[d>>2]&3|0)==3?d:e)+40>>2]|0)}g=g+1|0}}while(0);return}function pi(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;v=l;l=l+16|0;u=v;g=d+16|0;f=c[(c[g>>2]|0)+196>>2]|0;s=c[f+(e<<6)+4>>2]|0;t=e+1|0;d=c[(c[(c[(c[41927]|0)+16>>2]|0)+196>>2]|0)+(t<<6)>>2]|0;if((c[41931]|0)>(d|0))q=c[41932]|0;else{d=d+1|0;c[41931]=d;f=c[41932]|0;if(!f)d=xw(d<<2)|0;else d=zw(f,d<<2)|0;c[41932]=d;f=c[(c[g>>2]|0)+196>>2]|0;q=d}r=f+(t<<6)|0;d=0;while(1){if((d|0)>=(c[r>>2]|0))break;c[q+(d<<2)>>2]=0;d=d+1|0}p=f+(e<<6)|0;o=0;h=0;d=0;j=q;while(1){k=c[p>>2]|0;if((o|0)>=(k|0))break;n=c[(c[(c[s+(o<<2)>>2]|0)+16>>2]|0)+180>>2]|0;a:do if((h|0)>0){m=0;while(1){g=c[n+(m<<2)>>2]|0;if(!g)break a;k=g+16|0;i=c[(c[(c[((c[g>>2]&3|0)==2?g:g+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;while(1){g=i+1|0;if((i|0)>=(h|0))break;i=g;d=(O(c[j+(g<<2)>>2]|0,b[(c[k>>2]|0)+154>>1]|0)|0)+d|0}m=m+1|0}}while(0);i=0;while(1){g=c[n+(i<<2)>>2]|0;if(!g)break;j=c[(c[(c[((c[g>>2]&3|0)==2?g:g+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;m=q+(j<<2)|0;c[m>>2]=(c[m>>2]|0)+(b[(c[g+16>>2]|0)+154>>1]|0);h=(j|0)>(h|0)?j:h;i=i+1|0;j=q}o=o+1|0}i=f+(e<<6)+4|0;h=0;while(1){if((h|0)>=(k|0))break;g=c[(c[(c[i>>2]|0)+(h<<2)>>2]|0)+16>>2]|0;if(a[g+145>>0]|0){e=g+180|0;c[u>>2]=c[e>>2];c[u+4>>2]=c[e+4>>2];d=(qi(u,1)|0)+d|0}h=h+1|0}i=c[r>>2]|0;h=f+(t<<6)+4|0;g=0;while(1){if((g|0)>=(i|0))break;f=c[(c[(c[h>>2]|0)+(g<<2)>>2]|0)+16>>2]|0;if(a[f+145>>0]|0){t=f+172|0;c[u>>2]=c[t>>2];c[u+4>>2]=c[t+4>>2];d=(qi(u,-1)|0)+d|0}g=g+1|0}l=v;return d|0}function qi(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0;n=(d|0)<1;l=c[a>>2]|0;d=0;a=0;a:while(1){m=c[l+(d<<2)>>2]|0;if(!m)break;d=d+1|0;if(n){j=m+48|0;k=m+16|0;i=d;while(1){e=c[l+(i<<2)>>2]|0;if(!e)continue a;f=c[e+16>>2]|0;g=c[k>>2]|0;if((+h[f+56>>3]-+h[g+56>>3])*+((c[(c[(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)-(c[(c[(c[((c[m>>2]&3|0)==3?m:j)+40>>2]|0)+16>>2]|0)+236>>2]|0)|0)<0.0)a=(O(b[f+154>>1]|0,b[g+154>>1]|0)|0)+a|0;i=i+1|0}}else{j=m+-48|0;k=m+16|0;i=d;while(1){e=c[l+(i<<2)>>2]|0;if(!e)continue a;f=c[e+16>>2]|0;g=c[k>>2]|0;if((+h[f+16>>3]-+h[g+16>>3])*+((c[(c[(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)-(c[(c[(c[((c[m>>2]&3|0)==2?m:j)+40>>2]|0)+16>>2]|0)+236>>2]|0)|0)<0.0)a=(O(b[f+154>>1]|0,b[g+154>>1]|0)|0)+a|0;i=i+1|0}}}return a|0}function ri(a){a=a|0;var b=0.0,d=0.0;c[41930]=8;c[42181]=24;h[20878]=.995;a=Jm(a,79532)|0;if(a|0?(b=+tM(a),b>0.0):0){d=b*+(c[41930]|0);c[41930]=~~(d>1.0?d:1.0);b=b*+(c[42181]|0);c[42181]=~~(b>1.0?b:1.0)}return}function si(a){a=a|0;var d=0,e=0;e=(b[(c[a+16>>2]|0)+238>>1]|0)+2|0;d=ww(e<<2)|0;ui(a,d,e,0)|0;$I(d);return} +function Vq(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;g=(b|0)==2;d=(c[42039]|0)+24|0;while(1){d=c[d>>2]|0;if(!d)break;e=d+4|0;f=c[e>>2]|0;if(!((g?(a[f>>0]|0)==(a[83089]|0):0)?!(yJ(f,83089)|0):0)){h=zm(c[c[42039]>>2]|0,b,f,0)|0;c[e>>2]=h;if(!h)c[e>>2]=zm(c[c[42039]>>2]|0,b,f,174185)|0;c[d>>2]=266;cp(c[42038]|0,f)|0}d=d+12|0}return}function Wq(a){a=a|0;Xq(c[a>>2]|0);c[a+4>>2]=0;c[a>>2]=0;return}function Xq(a){a=a|0;var b=0;while(1){if(!a)break;b=c[a+12>>2]|0;switch(c[a>>2]|0){case 265:{Xq(c[a+4>>2]|0);break}case 266:case 267:{cp(c[42038]|0,c[a+8>>2]|0)|0;break}default:{}}_n(c[42038]|0,a);a=b}return}function Yq(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;h=l;l=l+1040|0;f=h;g=h+8|0;d=sJ(a)|0;d=d+2+(sJ(b)|0)|0;if(d>>>0<1025)e=g;else e=_I(d)|0;c[f>>2]=a;c[f+4>>2]=b;qL(e,83126,f)|0;d=ap(c[42038]|0,e)|0;cp(c[42038]|0,a)|0;cp(c[42038]|0,b)|0;if((e|0)!=(g|0))$I(e);l=h;return d|0}function Zq(a,b){a=a|0;b=b|0;return Tq(259,a,b)|0}function _q(a){a=a|0;return Tq(265,a,0)|0}function $q(a){a=a|0;return Tq(262,a,0)|0}function ar(a){a=a|0;var b=0,d=0;b=(c[42039]|0)+24|0;while(1){b=c[b>>2]|0;if(!b)break;if((c[b>>2]|0)==266?(d=c[b+4>>2]|0,d|0):0)Dm(a,d,c[b+8>>2]|0)|0;b=b+12|0}return}function br(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=d+4|0;a:do if((c[d>>2]|0)==262){d=c[f>>2]|0;f=eo(d)|0;while(1){if(!f)break a;cr(a,b,jo(c[c[42039]>>2]|0,f,0)|0,0,e);f=fo(d,f)|0}}else while(1){f=c[f>>2]|0;if(!f)break a;d=jo(c[c[42039]>>2]|0,c[f+4>>2]|0,0)|0;cr(a,b,d,c[f+8>>2]|0,e);f=f+12|0}while(0);return}function cr(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0;d=bn(c[c[42039]>>2]|0,a,d,f,1)|0;if(d|0){g=c[d>>2]&3;f=c[((g|0)==2?d:d+-48|0)+40>>2]|0;a=(f|0)==(a|0)?(c[((g|0)==3?d:d+48|0)+40>>2]|0)!=(f|0):0;dr(d,96242,a?e:b);dr(d,96251,a?b:e);ar(d)}return}function dr(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;if(d|0){e=zm(c[c[42039]>>2]|0,2,b,0)|0;if(!e)e=zm(c[c[42039]>>2]|0,2,b,174185)|0;Dm(a,e,d)|0}return}function er(a,b,d){a=a|0;b=b|0;d=d|0;c[42007]=b;c[42038]=a;c[41987]=0;a=d|0?d:17656;c[42041]=a;hp(a,b);Cq()|0;a=c[41987]|0;if(!a){Gp();a=c[41987]|0}return a|0}function fr(a,b){a=a|0;b=b|0;return er(0,a,b)|0}function gr(a,b){a=a|0;b=b|0;b=Kr(a,1,b)|0;if(!b)b=999;else{b=c[b+16>>2]|0;c[a+184>>2]=c[b+4>>2];c[a+172>>2]=c[b+12>>2];c[a+176>>2]=c[b>>2];c[a+180>>2]=c[b+16>>2];b=300}return b|0}function hr(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;f=i;Oo(b,122277,280,1)|0;g=b+16|0;c[(c[g>>2]|0)+144>>2]=a;if((to(b)|0)!=(b|0))c[(c[(to(b)|0)+16>>2]|0)+144>>2]=a;e=Jm(b,83342)|0;d=a+172|0;if((e|0)!=0?(c[d>>2]=0,(gr(a,e)|0)==999):0){d=Lr(a,1,e)|0;c[f>>2]=e;c[f+4>>2]=d;$l(1,83869,f)|0;d=-1}else{e=c[d>>2]|0;if(!e)d=-1;else{Gv(1);ew(b,c[c[a+180>>2]>>2]&1);d=c[(c[g>>2]|0)+8>>2]|0;c[(c[(to(b)|0)+16>>2]|0)+8>>2]=d;Fz();d=c[e>>2]|0;if(d|0?(gb[d&127](b),h=c[e+4>>2]|0,h|0):0)c[(c[g>>2]|0)+148>>2]=h;Gv(0);d=0}}l=i;return d|0}function ir(a,b){a=a|0;b=b|0;var d=0,e=0;if(Oo(b,122277,0,1)|0){d=b+16|0;a=c[d>>2]|0;e=c[a+148>>2]|0;if(e){gb[e&127](b);a=c[d>>2]|0;c[a+148>>2]=0}if(c[a+8>>2]|0)jw(b)}return 0}function jr(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;j=k+8|0;i=k;d=c[b+76>>2]|0;f=c[b>>2]|0;if((d|0)!=0?(e=c[d>>2]|0,(e|0)!=0):0){gb[e&127](b);g=12}else g=4;do if((g|0)==4)if((c[b+40>>2]|0)==0?(h=b+36|0,(c[h>>2]|0)==0):0){if(a[f+13>>0]|0)kr(b);d=b+32|0;e=c[d>>2]|0;if(!e){c[h>>2]=c[13885];g=12;break}f=bM(e,91556)|0;c[h>>2]=f;if(!f){j=c[(c[b+12>>2]|0)+16>>2]|0;h=c[d>>2]|0;d=zJ(c[(kJ()|0)>>2]|0)|0;c[i>>2]=h;c[i+4>>2]=d;hb[j&31](83132,i);d=1}else g=12}else g=12;while(0);if((g|0)==12)if(!(c[b+152>>2]&1024))d=0;else{hb[c[(c[b+12>>2]|0)+16>>2]&31](83170,j);d=1}l=k;return d|0}function kr(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=l;l=l+112|0;e=h;g=h+4|0;d=c[b+24>>2]|0;if(!d)a[g>>0]=0;else{c[e>>2]=d+1;qL(g,83188,e)|0}e=c[b+20>>2]|0;e=e|0?e:83192;d=sJ(e)|0;i=sJ(g)|0;f=b+52|0;i=d+1+i+(sJ(c[f>>2]|0)|0)|0;d=i+11|0;if((c[42042]|0)>>>0<(i+1|0)>>>0){c[42042]=d;d=bJ(c[42043]|0,d)|0;c[42043]=d}else d=c[42043]|0;yK(d,e)|0;JL(c[42043]|0,g)|0;d=c[42043]|0;d=d+(sJ(d)|0)|0;a[d>>0]=46;a[d+1>>0]=0;d=HL(c[f>>2]|0)|0;f=c[42043]|0;while(1){e=IL(d,58)|0;if(!e)break;JL(f,e+1|0)|0;i=c[42043]|0;g=i+(sJ(i)|0)|0;a[g>>0]=46;a[g+1>>0]=0;a[e>>0]=0;f=i}JL(f,d)|0;$I(d);c[b+32>>2]=c[42043];l=h;return}function lr(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;h=l;l=l+16|0;g=h+8|0;f=h;if((b|0)!=0&(d|0)!=0){if(c[a+152>>2]&1024|0){hb[c[(c[a+12>>2]|0)+16>>2]&31](83170,f);Ma(1)}if((mr(a,b,d)|0)==(d|0))e=d;else{f=c[(c[a+12>>2]|0)+16>>2]|0;c[g>>2]=d;hb[f&31](83202,g);Ma(1)}}else e=0;l=h;return e|0}function mr(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;n=o;f=c[(c[b>>2]|0)+104>>2]|0;do if(!f){j=b+40|0;h=c[j>>2]|0;if(!h){e=YL(d,1,e,c[b+36>>2]|0)|0;break}f=b+44|0;i=b+48|0;g=c[i>>2]|0;do if(((c[f>>2]|0)+-1-g|0)>>>0>>0){g=e+4096+g&-4096;c[f>>2]=g;f=bJ(h,g)|0;c[j>>2]=f;if(!f){hb[c[(c[b+12>>2]|0)+16>>2]&31](83227,n);Ma(1)}else{k=f;m=c[i>>2]|0;break}}else{k=h;m=g}while(0);UN(k+m|0,d|0,e|0)|0;n=(c[i>>2]|0)+e|0;c[i>>2]=n;a[(c[j>>2]|0)+n>>0]=0}else e=bb[f&31](b,d,e)|0;while(0);l=o;return e|0}function nr(a,b){a=a|0;b=b|0;var c=0;c=sJ(b)|0;b=(lr(a,b,c)|0)==(c|0);return (b?1:-1)|0}function or(b,c){b=b|0;c=c|0;var d=0,e=0;d=l;l=l+16|0;e=d;a[e>>0]=c;b=(lr(b,e,1)|0)==1;l=d;return (b?c:-1)|0}function pr(b){b=b|0;var d=0;d=c[b+36>>2]|0;if(((d|0)!=0?(a[b+144>>0]|0)==0:0)?(c[(c[b>>2]|0)+104>>2]|0)==0:0)b=QL(d)|0;else b=0;return b|0}function qr(a){a=a|0;var b=0,d=0;b=c[a+76>>2]|0;if(b|0?(d=c[b+4>>2]|0,d|0):0)gb[d&127](a);pr(a)|0;return}function rr(a){a=a|0;var b=0,d=0,e=0;e=l;l=l+16|0;d=c[a+76>>2]|0;if(c[a+152>>2]&1024|0){hb[c[(c[a+12>>2]|0)+16>>2]&31](83254,e);Ma(1)}if((d|0)!=0?(b=c[d+8>>2]|0,(b|0)!=0):0)gb[b&127](a);else{pr(a)|0;sr(a)}l=e;return}function sr(b){b=b|0;var d=0,e=0,f=0;d=b+32|0;if((c[d>>2]|0?(e=b+36|0,f=c[e>>2]|0,(f|0)!=(c[13885]|0)):0)?(a[b+144>>0]|0)==0:0){if(f|0){ML(f)|0;c[e>>2]=0}c[d>>2]=0}return}function tr(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=l;l=l+1056|0;f=i;h=i+24|0;g=i+8|0;c[g>>2]=d;e=MK(h,1024,b,g)|0;if((e|0)>=0){if((e|0)>1023){e=xw(e+1|0)|0;c[g>>2]=d;f=e;e=rL(e,b,g)|0}else f=h;lr(a,f,e)|0;if((f|0)!=(h|0))$I(f)}else{c[f>>2]=zJ(c[(kJ()|0)>>2]|0)|0;$l(1,83271,f)|0}l=i;return}function ur(a,b){a=a|0;b=+b;var d=0,e=0,f=0;d=l;l=l+16|0;e=d;f=vr(e,b)|0;lr(a,f,c[e>>2]|0)|0;l=d;return}function vr(b,d){b=b|0;d=+d;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;if(!(d<-1.0e15))if(!(d>1.0e15)){d=d*1.0e4;f=~~((d<0.0?-.5:.5)+d);if(!f){f=123205;e=1}else{l=(f|0)<0;k=4;i=0;e=173952;f=l?0-f|0:f;while(1){if(!((f|0)!=0|(k|0)>0))break;g=(f|0)%10|0;j=(f|0)/10|0;h=e+-1|0;if((g|0)==0&i<<24>>24==0)f=0;else{a[h>>0]=g|48;f=1;e=h}if((k|0)==1)if(!(f<<24>>24))f=1;else{e=e+-1|0;a[e>>0]=46;f=1}k=k+-1|0;i=f;f=j}if(l){e=e+-1|0;a[e>>0]=45}f=e;e=173952-e|0}}else{f=83286;e=18}else{f=83285;e=19}c[b>>2]=e;return f|0}function wr(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=l;l=l+16|0;e=d;f=vr(e,+h[b>>3])|0;lr(a,f,c[e>>2]|0)|0;lr(a,87638,1)|0;b=vr(e,+h[b+8>>3])|0;lr(a,b,c[e>>2]|0)|0;l=d;return}function xr(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;g=l;l=l+16|0;f=g;e=0;while(1){h=b+(e<<4)|0;c[f>>2]=c[h>>2];c[f+4>>2]=c[h+4>>2];c[f+8>>2]=c[h+8>>2];c[f+12>>2]=c[h+12>>2];wr(a,f);e=e+1|0;if((e|0)>=(d|0))break;lr(a,87638,1)|0}l=g;return}function yr(a,b){a=a|0;b=b|0;var d=0;d=ww(392)|0;if(d|0){c[d>>2]=19212;c[d+16>>2]=22;c[d+32>>2]=a;c[d+36>>2]=b}return d|0}function zr(a){a=a|0;var b=0,d=0,e=0,f=0;b=ww(392)|0;d=b;e=a;f=d+40|0;do{c[d>>2]=c[e>>2];d=d+4|0;e=e+4|0}while((d|0)<(f|0));f=b+60|0;e=a+60|0;c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2];c[f+16>>2]=c[e+16>>2];f=b+80|0;e=a+80|0;c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2];c[f+16>>2]=c[e+16>>2];return b|0}function Ar(a){a=a|0;Hr(a);$I(a);return}function Br(a,b){a=a|0;b=b|0;var d=0,e=0;e=a+160|0;d=c[e>>2]|0;if(d){e=c[42044]|0;if(e){d=c[e+4>>2]|0;if(!d){d=ww(632)|0;c[(c[42044]|0)+4>>2]=d}}}else{d=ww(632)|0;c[e>>2]=d;c[a+164>>2]=d}c[42044]=d;c[d+32>>2]=b;c[d>>2]=a;return}function Cr(a,b){a=a|0;b=b|0;var d=0,e=0;e=a+160|0;d=c[e>>2]|0;if(d){e=c[42045]|0;if(e){d=c[e+4>>2]|0;if(!d){d=ww(632)|0;c[(c[42045]|0)+4>>2]=d}}}else{d=ww(632)|0;c[e>>2]=d;c[a+164>>2]=d}c[42045]=d;c[d+52>>2]=b;c[d>>2]=a;return (Kr(a,3,b)|0)!=0|0}function Dr(a){a=a|0;var b=0;b=c[a+160>>2]|0;c[a+164>>2]=b;return b|0}function Er(a){a=a|0;var b=0,d=0,e=0;a=a+164|0;b=c[a>>2]|0;d=c[b+4>>2]|0;if(d|0?(e=d+52|0,(c[e>>2]|0)==0):0)c[e>>2]=c[b+52>>2];c[a>>2]=d;return d|0}function Fr(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=a+8|0;f=b+10|0;if((c[e>>2]|0)>(b|0))a=c[a>>2]|0;else{c[e>>2]=f;f=zw(c[a>>2]|0,f<<2)|0;c[a>>2]=f;a=f}c[a+(b<<2)>>2]=d;return}function Gr(a){a=a|0;var b=0;b=c[a>>2]|0;if(b|0)$I(b);c[a>>2]=0;c[a+8>>2]=0;c[a+4>>2]=0;return}function Hr(a){a=a|0;var b=0,d=0,e=0;d=a+160|0;b=c[d>>2]|0;while(1){if(!b)break;e=c[b+4>>2]|0;Gr(b+604|0);Gr(b+592|0);$I(c[b+584>>2]|0);$I(c[b+588>>2]|0);$I(b);b=e}c[42045]=0;c[42044]=0;c[a+192>>2]=0;c[a+164>>2]=0;c[d>>2]=0;c[a+28>>2]=0;return}function Ir(b,d,e,f,g,h){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,m=0,n=0;n=l;l=l+128|0;k=n+64|0;m=n;nL(k,e,63)|0;i=XJ(k,58)|0;if(i|0)a[i>>0]=0;b=b+60+(d<<2)|0;while(1){d=c[b>>2]|0;if(!d){d=b;b=0;break}nL(m,c[d+4>>2]|0,63)|0;d=XJ(m,58)|0;if(d|0)a[d>>0]=0;if((yJ(k,m)|0)<1){j=9;break}b=c[b>>2]|0}while(1){if((j|0)==9){d=b;b=c[b>>2]|0}if(!b)break;nL(m,c[b+4>>2]|0,63)|0;b=XJ(m,58)|0;if(b|0)a[b>>0]=0;if(yJ(k,m)|0)break;b=c[d>>2]|0;if((c[b+8>>2]|0)<=(f|0))break;j=9}m=xw(20)|0;c[m>>2]=c[d>>2];c[d>>2]=m;c[m+4>>2]=e;c[m+8>>2]=f;c[m+12>>2]=g;c[m+16>>2]=h;l=n;return 1}function Jr(a,b){a=a|0;b=b|0;b=l;l=l+16|0;$l(1,83366,b)|0;l=b;return 0}function Kr(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=l;l=l+144|0;r=s;o=s+80|0;p=s+16|0;n=(d+-3|0)>>>0<2?0:d;nL(o,e,63)|0;e=XJ(o,58)|0;if(e){f=e+1|0;a[e>>0]=0;e=XJ(f,58)|0;if(!e)m=0;else{a[e>>0]=0;m=e+1|0}}else{m=0;f=0}i=(f|0)!=0;j=(m|0)==0;k=(n|0)==(d|0);h=b+60+(d<<2)|0;a:while(1){e=c[h>>2]|0;if(!e){e=0;break}nL(p,c[e+4>>2]|0,63)|0;e=XJ(p,58)|0;if(!e)e=0;else{a[e>>0]=0;e=e+1|0}do if(!(yJ(p,o)|0)){g=(e|0)!=0;if(i&g?yJ(e,f)|0:0)break;if(!j?yJ(m,c[(c[(c[h>>2]|0)+12>>2]|0)+8>>2]|0)|0:0)break;if(k|g^1){q=16;break a}if(Kr(b,n,e)|0){q=16;break a}}while(0);h=c[h>>2]|0}do if((q|0)==16){e=c[h>>2]|0;if(e){f=e+16|0;if((c[f>>2]|0)==0?(Jr(0,0)|0,(c[f>>2]|0)==0):0){e=0;break}if((c[b+8>>2]|0)>0){q=c[13918]|0;o=c[e+4>>2]|0;p=c[(c[e+12>>2]|0)+8>>2]|0;c[r>>2]=c[19224+(d<<2)>>2];c[r+4>>2]=o;c[r+8>>2]=p;AL(q,83397,r)|0}}else e=0}while(0);c[b+80+(d<<2)>>2]=e;l=s;return e|0}function Lr(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;do if(!e)e=0;else{if(c[4811]|0){dm(168184,0,0);c[4811]=0}h=HL(e)|0;e=XJ(h,58)|0;if(e){a[e>>0]=0;f=b+60+(d<<2)|0;e=1;g=f;while(1){b=c[g>>2]|0;if(!b)break;d=HL(c[b+4>>2]|0)|0;b=XJ(d,58)|0;if(b|0)a[b>>0]=0;if(!((a[h>>0]|0)!=0?(jK(h,d)|0)!=0:0)){e=c[42047]|0;if(e>>>0>=(c[42048]|0)>>>0){em(168184,1)|0;e=c[42047]|0}c[42047]=e+1;a[e>>0]=32;gm(168184,c[(c[g>>2]|0)+4>>2]|0)|0;e=c[42047]|0;if(e>>>0>=(c[42048]|0)>>>0){em(168184,1)|0;e=c[42047]|0}c[42047]=e+1;a[e>>0]=58;gm(168184,c[(c[(c[g>>2]|0)+12>>2]|0)+8>>2]|0)|0;e=0}$I(d);g=c[g>>2]|0}$I(h);if(e<<24>>24){g=0;i=19}}else{$I(h);g=0;f=b+60+(d<<2)|0;e=1;i=19}if((i|0)==19){while(1){b=c[f>>2]|0;if(!b)break;d=HL(c[b+4>>2]|0)|0;b=XJ(d,58)|0;if(b|0)a[b>>0]=0;if(!((g|0)!=0?(jK(g,d)|0)==0:0)){e=c[42047]|0;if(e>>>0>=(c[42048]|0)>>>0){em(168184,1)|0;e=c[42047]|0}c[42047]=e+1;a[e>>0]=32;gm(168184,d)|0;e=0}g=d;f=c[f>>2]|0;i=19}if(e<<24>>24){e=174185;break}}e=c[42047]|0;if(e>>>0>=(c[42048]|0)>>>0){em(168184,1)|0;e=c[42047]|0}a[e>>0]=0;e=c[42046]|0;c[42047]=e}while(0);return e|0}function Mr(b){b=b|0;var d=0;if(!b)ma(96030,83414,573,83428);if(!(a[b>>0]|0))ma(96035,83414,574,83428);d=c[42050]|0;if(!d)b=0;else b=bb[c[d>>2]&31](d,b,512)|0;return b|0}function Nr(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;j=k+8|0;i=k;if(!b)ma(96091,83414,589,83445);g=b+8|0;e=c[g>>2]|0;if(!e)ma(96094,83414,590,83445);if(!(a[e>>0]|0))ma(96103,83414,591,83445);h=b+20|0;f=c[h>>2]|0;do if(!f){d=SA(e)|0;if(!d){c[i>>2]=c[g>>2];$l(0,83469,i)|0;d=0;break}i=bM(d,123632)|0;c[h>>2]=i;if(!i){c[j>>2]=zJ(c[(kJ()|0)>>2]|0)|0;c[j+4>>2]=d;$l(0,83494,j)|0;d=0;break}d=c[42051]|0;if((d|0)>49){a[b+17>>0]=1;d=1;break}else{c[42051]=d+1;d=1;break}}else{pM(f,0,0)|0;if(!(c[h>>2]|0))ma(83515,83414,614,83445);else d=1}while(0);l=k;return d|0}function Or(b){b=b|0;var d=0,e=0;if(a[b+17>>0]|0?(d=b+20|0,e=c[d>>2]|0,e|0):0){ML(e)|0;c[d>>2]=0}return}function Pr(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0.0,g=0.0;if(!b){e=-1;d=-1}else{e=c[b+48>>2]|0;f=+(e|0);if(!e){g=+h[d>>3];f=+h[d+8>>3]}else{h[d+8>>3]=f;h[d>>3]=f;g=f}e=~~(+((c[b+40>>2]|0)*72|0)/g);d=~~(+((c[b+44>>2]|0)*72|0)/f)}c[a>>2]=e;c[a+4>>2]=d;return}function Qr(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0.0;m=l;l=l+48|0;f=m+16|0;j=m;k=m+32|0;if((e|0)!=0?(a[e>>0]|0)!=0:0){if((0==0?(g=c[42178]|0,(c[42052]|0)!=(g|0)):0)?(c[42052]=g,i=c[42050]|0,i|0):0){Ll(i)|0;c[42050]=0}n=+h[(c[(c[d+16>>2]|0)+8>>2]|0)+24>>3];n=!(n>=1.0)?96.0:n;h[j+8>>3]=n;h[j>>3]=n;d=Rr(e)|0;c[f>>2]=c[j>>2];c[f+4>>2]=c[j+4>>2];c[f+8>>2]=c[j+8>>2];c[f+12>>2]=c[j+12>>2];Pr(k,d,f);d=c[k>>2]|0;f=c[k+4>>2]|0}else{d=-1;f=-1}c[b>>2]=d;c[b+4>>2]=f;l=m;return}function Rr(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+16|0;e=f;if(!a)ma(96030,83414,638,83521);if(!(c[42050]|0))c[42050]=Rl(19248,c[4353]|0)|0;b=Mr(a)|0;a:do if(!b){b=ww(64)|0;if(!b)b=0;else{d=b+8|0;c[d>>2]=ap(0,a)|0;if(!((Nr(b)|0)<<24>>24)){Sr(b);b=0;break}if(!(c[b+20>>2]|0))ma(83515,83414,653,83521);do switch(Tr(b)|0){case 0:{a=Qy(c[d>>2]|0)|0;c[b+52>>2]=a;if(!a){c[e>>2]=c[d>>2];$l(0,83538,e)|0;Sr(b);b=0;break a}break}case 2:{Ur(b);break}case 3:{Vr(b);break}case 1:{Wr(b);break}case 4:{Xr(b);break}case 6:{Yr(b);break}case 11:{Zr(b);break}case 8:{_r(b);break}case 5:{$r(b);break}case 12:{as(b);break}default:{}}while(0);Or(b);e=c[42050]|0;bb[c[e>>2]&31](e,b,1)|0}}else Or(b);while(0);l=f;return b|0}function Sr(a){a=a|0;var b=0;b=c[a+8>>2]|0;if(b|0)cp(0,b)|0;$I(a);return}function Tr(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+224|0;f=j+200|0;g=j;h=a+20|0;b=c[h>>2]|0;a:do if((b|0)!=0?(xN(f,1,20,b)|0)==20:0){d=0;while(1){if(d>>>0>=10){i=13;break a}if(!(eL(f,c[19284+(d<<4)>>2]|0,c[19284+(d<<4)+4>>2]|0)|0))break;d=d+1|0}e=a+28|0;c[e>>2]=c[19284+(d<<4)+12>>2];b=c[19284+(d<<4)+8>>2]|0;a=a+24|0;c[a>>2]=b;switch(d|0){case 7:break;case 8:{if(eL(f+8|0,83754,4)|0)break a;c[e>>2]=83759;c[a>>2]=11;b=11;break a}default:break a}while(1){if(!(hL(g,200,c[h>>2]|0)|0)){i=11;break}if(!(eL(g,83749,4)|0)){i=8;break}}if((i|0)==8){c[e>>2]=86879;c[a>>2]=8;b=8;break}else if((i|0)==11){b=c[a>>2]|0;break}}else i=13;while(0);if((i|0)==13){c[a+28>>2]=83764;c[a+24>>2]=0;b=0}l=j;return b|0}function Ur(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+16|0;b=f+4|0;d=f;c[a+48>>2]=0;e=a+20|0;pM(c[e>>2]|0,6,0)|0;if((js(c[e>>2]|0,2,b)|0)<<24>>24?(js(c[e>>2]|0,2,d)|0)<<24>>24:0){c[a+40>>2]=c[b>>2];c[a+44>>2]=c[d>>2]}l=f;return}function Vr(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+16|0;b=f+4|0;d=f;c[a+48>>2]=0;e=a+20|0;pM(c[e>>2]|0,16,0)|0;if((bs(c[e>>2]|0,4,b)|0)<<24>>24?(bs(c[e>>2]|0,4,d)|0)<<24>>24:0){c[a+40>>2]=c[b>>2];c[a+44>>2]=c[d>>2]}l=f;return}function Wr(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;b=h+12|0;d=h+8|0;e=h+4|0;f=h;c[a+48>>2]=0;g=a+20|0;pM(c[g>>2]|0,16,0)|0;if((((js(c[g>>2]|0,2,b)|0)<<24>>24?(js(c[g>>2]|0,2,d)|0)<<24>>24:0)?(js(c[g>>2]|0,2,e)|0)<<24>>24:0)?(js(c[g>>2]|0,2,f)|0)<<24>>24:0){c[a+40>>2]=c[b>>2]<<16|c[d>>2];c[a+44>>2]=c[e>>2]<<16|c[f>>2]}l=h;return}function Xr(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+32|0;b=m+16|0;e=m+12|0;f=m+8|0;h=m+4|0;i=m;c[a+48>>2]=0;j=a+20|0;while(1){if(!((bs(c[j>>2]|0,1,b)|0)<<24>>24))break;d=c[b>>2]|0;if((d|0)==255)continue;if(XJ(83737,d)|0)continue;if((d|0)==192){k=6;break}g=c[j>>2]|0;if((d|0)==194){k=11;break}if(!((bs(g,2,e)|0)<<24>>24))break;pM(c[j>>2]|0,(c[e>>2]|0)+-2|0,1)|0}if((k|0)==6){if(((bs(c[j>>2]|0,3,i)|0)<<24>>24?(bs(c[j>>2]|0,2,f)|0)<<24>>24:0)?(bs(c[j>>2]|0,2,h)|0)<<24>>24:0){c[a+44>>2]=c[f>>2];c[a+40>>2]=c[h>>2]}}else if((((k|0)==11?(bs(g,3,i)|0)<<24>>24:0)?(bs(c[j>>2]|0,2,f)|0)<<24>>24:0)?(bs(c[j>>2]|0,2,h)|0)<<24>>24:0){c[a+44>>2]=c[f>>2];c[a+40>>2]=c[h>>2]}l=m;return}function Yr(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+1056|0;j=m;b=m+32|0;e=m+28|0;f=m+24|0;g=m+20|0;h=m+16|0;c[a+48>>2]=72;i=a+20|0;pM(c[i>>2]|0,0,0)|0;while(1){if(!(hL(b,1024,c[i>>2]|0)|0))break;d=iL(b,83722)|0;if(!d)continue;c[j>>2]=e;c[j+4>>2]=f;c[j+8>>2]=g;c[j+12>>2]=h;if((dM(d,89345,j)|0)==4){k=5;break}}if((k|0)==5){j=c[e>>2]|0;c[a+32>>2]=j;k=c[f>>2]|0;c[a+36>>2]=k;c[a+40>>2]=(c[g>>2]|0)-j;c[a+44>>2]=(c[h>>2]|0)-k}l=m;return}function Zr(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;g=l;l=l+16|0;b=g+4|0;d=g;c[a+48>>2]=0;e=a+20|0;pM(c[e>>2]|0,15,0)|0;h=(CN(c[e>>2]|0)|0)==88;f=c[e>>2]|0;if(h){pM(f,24,0)|0;if((js(c[e>>2]|0,4,b)|0)<<24>>24?(js(c[e>>2]|0,4,d)|0)<<24>>24:0){c[a+40>>2]=c[b>>2];c[a+44>>2]=c[d>>2]}}else{pM(f,26,0)|0;if((js(c[e>>2]|0,2,b)|0)<<24>>24?(js(c[e>>2]|0,2,d)|0)<<24>>24:0){c[a+40>>2]=c[b>>2];c[a+44>>2]=c[d>>2]}}l=g;return}function _r(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0;F=l;l=l+352|0;C=F+80|0;B=F+72|0;E=F+64|0;D=F+56|0;A=F+48|0;d=F+40|0;s=F+32|0;t=F+24|0;u=F+16|0;v=F+8|0;w=F;x=F+328|0;y=F+128|0;z=F+96|0;if(!(c[42053]|0)){if(FM(168216,83607,1)|0){c[d>>2]=83607;$l(1,83634,d)|0}c[42053]=168216}m=b+20|0;pM(c[m>>2]|0,0,0)|0;n=z+12|0;o=z+20|0;p=z+8|0;q=z+16|0;r=z+4|0;d=0;g=0;f=0;e=0;a:while(1){if(!(hL(y,200,c[m>>2]|0)|0))break;if(g<<24>>24==0|d<<24>>24==0){i=y;k=e}else break;b:while(1){j=f;c:while(1){while(1){if(rN(168216,i,4,z,0)|0){f=j;e=k;continue a}a[i+(c[n>>2]|0)>>0]=0;a[i+(c[o>>2]|0)>>0]=0;e=i+(c[p>>2]|0)|0;f=i+(c[q>>2]|0)|0;i=i+((c[r>>2]|0)+1)|0;if(!(yJ(e,96043)|0))break;if(!(yJ(e,96049)|0))break c;if(yJ(e,83681)|0)continue;c[C>>2]=t;c[C+4>>2]=u;c[C+8>>2]=v;c[C+12>>2]=w;if((dM(f,83689,C)|0)==4)break b}c[A>>2]=s;c[A+4>>2]=x;if((dM(f,83671,A)|0)!=2){c[D>>2]=s;if((dM(f,86246,D)|0)==1){e=1;f=is(+h[s>>3],83678)|0}else{e=g;f=j}}else{e=1;f=is(+h[s>>3],x)|0}if(!(d<<24>>24)){d=0;g=e;j=f}else{g=e;e=k;continue a}}c[E>>2]=s;c[E+4>>2]=x;if((dM(f,83671,E)|0)!=2){c[B>>2]=s;if((dM(f,86246,B)|0)==1){d=1;e=is(+h[s>>3],83678)|0}else e=k}else{d=1;e=is(+h[s>>3],x)|0}if(!(g<<24>>24)){g=0;f=j;k=e}else{f=j;continue a}}d=1;g=1;f=~~(+h[v>>3]+1.0-+h[t>>3])>>>0;e=~~(+h[w>>3]+1.0-+h[u>>3])>>>0}c[b+48>>2]=0;c[b+40>>2]=f;c[b+44>>2]=e;l=F;return}function $r(a){a=a|0;var b=0,d=0,e=0,f=0.0,g=0.0;d=l;l=l+32|0;b=d;c[a+48>>2]=0;e=a+20|0;pM(c[e>>2]|0,0,0)|0;if(!(cs(c[e>>2]|0,b)|0)){g=+h[b>>3];c[a+32>>2]=~~g;f=+h[b+8>>3];c[a+36>>2]=~~f;c[a+40>>2]=~~(+h[b+16>>3]-g);c[a+44>>2]=~~(+h[b+24>>3]-f)}l=d;return}function as(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+16|0;b=f+4|0;d=f;c[a+48>>2]=0;e=a+20|0;pM(c[e>>2]|0,6,0)|0;if((bs(c[e>>2]|0,1,b)|0)<<24>>24?(bs(c[e>>2]|0,1,d)|0)<<24>>24:0){c[a+40>>2]=c[b>>2];c[a+44>>2]=c[d>>2]}l=f;return}function bs(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;c[d>>2]=0;e=0;while(1){if(e>>>0>=b>>>0){e=1;break}f=CN(a)|0;if(LL(a)|0){e=0;break}c[d>>2]=c[d>>2]<<8|f;e=e+1|0}return e|0}function cs(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;h=l;l=l+1040|0;d=h;e=h+16|0;while(1){if(!(hL(e,1024,a)|0)){a=1;break}f=iL(e,83597)|0;if(f|0){g=4;break}}if((g|0)==4){c[d+4>>2]=e;c[d>>2]=f+9;c[d+8>>2]=a;a=ds(d,b)|0}l=h;return a|0}function ds(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;g=l;l=l+1024|0;f=g;es(b);e=a[c[b>>2]>>0]|0;if(!(e<<24>>24))e=(fs(b)|0)&255;else e=e<<24>>24;if((((e|0)==91?(c[b>>2]=(c[b>>2]|0)+1,gs(b,f),(hs(f,d)|0)==0):0)?(gs(b,f),(hs(f,d+8|0)|0)==0):0)?(gs(b,f),(hs(f,d+16|0)|0)==0):0){gs(b,f);e=(hs(f,d+24|0)|0)!=0&1}else e=1;l=g;return e|0}function es(b){b=b|0;var d=0;d=c[b>>2]|0;while(1){d=a[d>>0]|0;if(!(d<<24>>24))d=(fs(b)|0)&255;else d=d<<24>>24;if(!((d&255)<<24>>24))break;if(!(YJ(d&255)|0))break;d=(c[b>>2]|0)+1|0;c[b>>2]=d}return}function fs(b){b=b|0;var d=0;d=b+4|0;if(!(hL(c[d>>2]|0,1024,c[b+8>>2]|0)|0))b=0;else{d=c[d>>2]|0;c[b>>2]=d;b=a[d>>0]|0}return b|0}function gs(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;es(b);e=0;f=c[b>>2]|0;while(1){f=a[f>>0]|0;if(!(f<<24>>24))g=(fs(b)|0)&255;else g=f<<24>>24;f=g<<24>>24;if(!f)break;if(!((f|0)==46|(f+-48|0)>>>0<10))break;a[d+e>>0]=g;e=e+1|0;f=(c[b>>2]|0)+1|0;c[b>>2]=f;if((e|0)==1023){e=1023;break}}a[d+e>>0]=0;return}function hs(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0;e=l;l=l+16|0;f=e;d=+uM(a,f);if((c[f>>2]|0)==(a|0))a=1;else{h[b>>3]=d;a=0}l=e;return a|0}function is(a,b){a=+a;b=b|0;var c=0.0;do if(!(yJ(b,83705)|0)){a=a*72.0;c=a;a=a>=0.0?.5:-.5}else{if(!(yJ(b,83708)|0)){a=a*.75;c=a;a=a>=0.0?.5:-.5;break}if(!(yJ(b,83711)|0)){a=a*12.0;c=a;a=a>=0.0?.5:-.5;break}if(yJ(b,83678)|0?yJ(b,83714)|0:0)if(!(yJ(b,83716)|0)){a=a*28.346456664;c=a;a=a>=0.0?.5:-.5;break}else{b=(yJ(b,83719)|0)==0;c=a*2.8346456663999997;return (b?~~(c+(c>=0.0?.5:-.5)):0)|0}c=a>=0.0?.5:-.5}while(0);return ~~(a+c)|0}function js(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;c[d>>2]=0;e=0;while(1){if(e>>>0>=b>>>0){e=1;break}f=CN(a)|0;if(LL(a)|0){e=0;break}c[d>>2]=c[d>>2]|f<<(e<<3);e=e+1|0}return e|0}function ks(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;a=c[b+20>>2]|0;if(a|0)ML(a)|0;if(c[b+52>>2]|0?(e=c[b+60>>2]|0,e|0):0)gb[e&127](b);$I(b);return}function ls(){var a=0;zm(0,1,86240,90527)|0;a=yr(0,1)|0;tE(a,0);return a|0}function ms(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0.0,n=0.0,o=0.0,p=0.0;k=l;l=l+304|0;j=k+24|0;i=k+8|0;f=k;g=k+40|0;if((gr(b,e)|0)!=999)if((hr(b,d)|0)==-1)b=-1;else{b=c[d+16>>2]|0;e=b+16|0;if(!(a[(c[b+8>>2]|0)+81>>0]|0)){p=+h[e>>3];o=+h[b+24>>3];n=+h[b+32>>3];m=+h[b+40>>3];c[j>>2]=~~(p+(p>=0.0?.5:-.5));c[j+4>>2]=~~(o+(o>=0.0?.5:-.5));c[j+8>>2]=~~(n+(n>=0.0?.5:-.5));c[j+12>>2]=~~(m+(m>=0.0?.5:-.5));qL(g,83918,j)|0}else{m=+h[b+24>>3];n=+h[e>>3];o=+h[b+40>>3];p=+h[b+32>>3];c[i>>2]=~~(m+(m>=0.0?.5:-.5));c[i+4>>2]=~~(n+(n>=0.0?.5:-.5));c[i+8>>2]=~~(o+(o>=0.0?.5:-.5));c[i+12>>2]=~~(p+(p>=0.0?.5:-.5));qL(g,83918,i)|0}Mm(d,87705,g,174185)|0;b=0}else{b=Lr(b,1,e)|0;c[f>>2]=e;c[f+4>>2]=b;$l(1,83869,f)|0;b=-1}l=k;return b|0}function ns(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=l;l=l+16|0;g=i;f=c[b+60>>2]|0;Cr(a,d)|0;b=c[a+164>>2]|0;c[b+56>>2]=cD(b,c[b+52>>2]|0)|0;if((Oo(f,122277,0,1)|0)!=0?(c[(c[f+16>>2]|0)+8>>2]|0)!=0:0)h=5;else if(!(c[b+152>>2]&67108864)){cm(83930,g);b=-1}else h=5;if((h|0)==5){c[b+36>>2]=e;if(!e){h=b+152|0;c[h>>2]=c[h>>2]|134217728}h=Hv(a,f)|0;eD(b);Hr(a);b=h}l=i;return b|0}function os(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=l;l=l+16|0;g=i;f=c[b+60>>2]|0;Cr(a,d)|0;b=c[a+164>>2]|0;c[b+56>>2]=cD(b,c[b+52>>2]|0)|0;if((Oo(f,122277,0,1)|0)!=0?(c[(c[f+16>>2]|0)+8>>2]|0)!=0:0)h=5;else if(!(c[b+152>>2]&67108864)){cm(83930,g);b=-1}else h=5;if((h|0)==5){Br(a,e);h=Hv(a,f)|0;eD(b);rr(b);Hr(a);b=h}l=i;return b|0}function ps(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+16|0;h=m+8|0;g=m;b=c[b+60>>2]|0;Cr(a,d)|0;j=c[a+164>>2]|0;c[j+56>>2]=cD(j,c[j+52>>2]|0)|0;if((Oo(b,122277,0,1)|0)!=0?(c[(c[b+16>>2]|0)+8>>2]|0)!=0:0)k=5;else if(!(c[j+152>>2]&67108864)){cm(83930,g);b=-1}else k=5;do if((k|0)==5){if(e|0?(i=_I(4096)|0,c[e>>2]=i,i|0):0){g=j+40|0;c[g>>2]=i;c[j+44>>2]=4096;d=j+48|0;c[d>>2]=0;b=Hv(a,b)|0;eD(j);if(!b){c[e>>2]=c[g>>2];c[f>>2]=c[d>>2]}Hr(a);break}$l(1,83951,h)|0;b=-1}while(0);l=m;return b|0}function qs(a,b){a=a|0;b=b|0;rE(a,0,b);return}function rs(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;if(!((a|0)!=0?(zs(a)|0)!=0:0))a=84007;e=sJ(a)|0;if((e|0)>=104){d=xw(e+25|0)|0;if(!d)d=0;else f=6}else f=6;if((f|0)==6){yK(d,a)|0;c[b>>2]=e}return d|0}function ss(a,b){a=a|0;b=b|0;jo(b,a,1)|0;return}function ts(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;c[b>>2]=d;c[b+4>>2]=d+4096;c[b+12>>2]=0;c[b+8>>2]=0;c[a>>2]=b;c[a+4>>2]=b;c[a+8>>2]=d;c[a+12>>2]=e;c[a+16>>2]=f;return}function us(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;xs(e,b);i=e+12|0;j=e+16|0;b=0;a:while(1){k=ys(e)|0;if(!k)break;b=b+1|0;f=c[i>>2]|0;if(f|0)hb[f&31](k,d);h=Vm(a,k)|0;while(1){if(!h)continue a;g=c[h>>2]&3;f=c[((g|0)==3?h:h+48|0)+40>>2]|0;if((f|0)==(k|0))f=c[((g|0)==2?h:h+-48|0)+40>>2]|0;if(!(ab[c[j>>2]&63](f,-1)|0))xs(e,f);h=Wm(a,h,k)|0}}return b|0}function vs(a){a=a|0;var b=0;a=c[(c[a>>2]|0)+12>>2]|0;while(1){if(!a)break;b=c[a+12>>2]|0;ws(a);a=b}return}function ws(a){a=a|0;$I(c[a>>2]|0);$I(a);return}function xs(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;j=k+8|0;f=k;g=a+8|0;i=a+4|0;d=c[i>>2]|0;if((c[g>>2]|0)==(c[d+4>>2]|0)){d=c[d+12>>2]|0;do if(!d){e=xw(16)|0;if(!e){$l(1,83988,f)|0;Ua(168248,1)}c[e+8>>2]=c[i>>2];c[e+12>>2]=0;d=xw(4e6)|0;c[e>>2]=d;if(!d){$l(1,83988,j)|0;Ua(168248,1)}else{c[e+4>>2]=d+4e6;c[(c[i>>2]|0)+12>>2]=e;h=e;break}}else h=d;while(0);c[i>>2]=h;c[g>>2]=c[h>>2]}ab[c[a+16>>2]&63](b,1)|0;j=c[g>>2]|0;c[g>>2]=j+4;c[j>>2]=b;l=k;return}function ys(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;f=a+8|0;b=c[f>>2]|0;d=a+4|0;e=c[d>>2]|0;if((b|0)==(c[e>>2]|0))if((e|0)==(c[a>>2]|0))b=0;else{b=c[e+8>>2]|0;c[d>>2]=b;b=c[b+4>>2]|0;c[f>>2]=b;g=4}else g=4;if((g|0)==4){b=b+-4|0;c[f>>2]=b;b=c[b>>2]|0}return b|0}function zs(b){b=b|0;var c=0;a:while(1){c=b;b=b+1|0;c=a[c>>0]|0;switch(c<<24>>24){case 95:continue a;case 0:{b=1;break a}default:{}}if(!(hK(c&255)|0)){b=0;break}}return b|0}function As(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=0;f=eo(a)|0;while(1){if(!f)break;e=Qm(b,f)|0;while(1){if(!e)break;if(jo(a,c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,0)|0){fn(a,e,1)|0;d=d+1|0}e=Sm(b,e)|0}f=fo(a,f)|0}return d|0}function Bs(a){a=a|0;a=Mo(a,84012,0)|0;if(!a)ma(84017,84020,529,84029);else return c[a+8>>2]|0;return 0}function Cs(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;u=l;l=l+4320|0;s=u+24|0;r=u+8|0;q=u;t=u+4184|0;p=u+4160|0;f=u+40|0;if(nn(b)|0){To(b,0,84038,-12,0);To(b,1,84050,16,0);o=rs(e,f,t)|0;k=Ds(b)|0;m=xw((nn(k)|0)<<2)|0;ts(p,u+4144|0,u+48|0,23,22);h=eo(k)|0;n=p+16|0;i=o+(c[f>>2]|0)|0;j=c[13918]|0;e=0;while(1){if(!h)break;if(!(ab[c[n>>2]&63](h,-1)|0)){c[q>>2]=e;qL(i,84952,q)|0;v=Jp(k,o,1)|0;w=Jp(b,o,1)|0;Oo(w,84038,12,0)|0;a[(Mo(w,84038,0)|0)+8>>0]=1;f=us(k,h,v,p)|0;Fs(v,w);g=Gs(w)|0;Hs(b,w);c[m+(e<<2)>>2]=w;ro(k,v)|0;if(0){c[r>>2]=e;c[r+4>>2]=f;c[r+8>>2]=g;AL(j,84062,r)|0}e=e+1|0}h=fo(k,h)|0}if(0){r=nn(b)|0;v=on(b)|0;w=En(b)|0;c[s>>2]=r;c[s+4>>2]=v;c[s+8>>2]=e;c[s+12>>2]=w;AL(j,84092,s)|0}mn(k)|0;Uo(b,0,84038);Uo(b,1,84050);vs(p);f=zw(m,e<<2)|0;if((o|0)!=(t|0))$I(o)}else{f=0;e=0}c[d>>2]=e;l=u;return f|0}function Ds(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;a[h>>0]=a[17652]|0;a[h+1>>0]=a[17653]|0;a[h+2>>0]=a[17654]|0;a[h+3>>0]=a[17655]|0;h=hn(84139,h,0)|0;Ks(h,b);d=eo(b)|0;while(1){if(!d)break;if(!(c[(Mo(d,84050,0)|0)+12>>2]|0)){g=oo(h,En(d)|0,1)|0;Oo(g,84050,16,1)|0;c[(c[g+16>>2]|0)+12>>2]=d;c[(Mo(d,84050,0)|0)+12>>2]=g}d=fo(b,d)|0}e=eo(b)|0;while(1){if(!e)break;f=c[(Mo(e,84050,0)|0)+12>>2]|0;d=Qm(b,e)|0;while(1){if(!d)break;g=c[(Mo(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0,84050,0)|0)+12>>2]|0;do if((g|0)!=(f|0))if(g>>>0>f>>>0){bn(h,f,g,0,1)|0;break}else{bn(h,g,f,0,1)|0;break}while(0);d=Sm(b,d)|0}e=fo(b,e)|0}l=i;return h|0}function Es(b,d){b=b|0;d=d|0;var e=0;b=(c[b+16>>2]|0)+8|0;e=a[b>>0]|0;if((d|0)>=0)a[b>>0]=d;return e|0}function Fs(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;e=eo(a)|0;while(1){if(!e)break;f=c[(c[e+16>>2]|0)+12>>2]|0;a:do if((c[f>>2]&3|0)==1)jo(b,f,1)|0;else{d=eo(f)|0;while(1){if(!d)break a;jo(b,d,1)|0;d=fo(f,d)|0}}while(0);e=fo(a,e)|0}return}function Gs(a){a=a|0;return As(a,c[a+60>>2]|0)|0}function Hs(a,b){a=a|0;b=b|0;Is(a,b,0);return}function Is(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0;g=(d|0)==0;b=Kp(b)|0;while(1){if(!b)break;if((a[(Mo(b,84038,0)|0)+8>>0]|0)==0?(f=Js(b,c,d)|0,f|0):0){if(g)e=(WJ(En(b)|0,93039,7)|0)==0;else e=1;Is(b,f,e&1)}b=Lp(b)|0}return}function Js(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=0;g=eo(a)|0;while(1){if(!g)break;f=oo(b,En(g)|0,0)|0;if(f){if(!e)e=Jp(b,En(a)|0,1)|0;jo(e,f,1)|0}g=fo(a,g)|0}if((d|0)!=0&(e|0)==0)e=Jp(b,En(a)|0,1)|0;if(e|0?(As(e,a)|0,Nm(a,e)|0,(WJ(En(e)|0,93039,7)|0)==0):0)c[(Oo(e,84012,12,0)|0)+8>>2]=a;return e|0}function Ks(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;h=l;l=l+16|0;g=h;d=Kp(b)|0;e=c[13918]|0;while(1){if(!d)break;a:do if(!(WJ(En(d)|0,93039,7)|0)){f=oo(a,En(d)|0,1)|0;Oo(f,84050,16,1)|0;c[(c[f+16>>2]|0)+12>>2]=d;b=eo(d)|0;while(1){if(!b)break a;if(c[(Mo(b,84050,0)|0)+12>>2]|0){k=En(b)|0;j=En(d)|0;i=En(c[(Mo(b,84050,0)|0)+12>>2]|0)|0;c[g>>2]=k;c[g+4>>2]=j;c[g+8>>2]=i;AL(e,84142,g)|0}c[(Mo(b,84050,0)|0)+12>>2]=f;b=fo(d,b)|0}}else Ks(a,d);while(0);d=Lp(d)|0}l=h;return}function Ls(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0.0;n=+h[a>>3];j=~~(n+(n>=0.0?.5:-.5));n=+h[a+8>>3];a=~~(n+(n>=0.0?.5:-.5));n=+h[b>>3];g=~~(n+(n>=0.0?.5:-.5));n=+h[b+8>>3];f=~~(n+(n>=0.0?.5:-.5));l=g-j|0;i=((l|0)>-1?l:0-l|0)<<1;l=l>>31|1;m=f-a|0;k=((m|0)>-1?m:0-m|0)<<1;m=m>>31|1;a:do if((i|0)>(k|0)){e=0-i|0;d=k-(i>>1)|0;b=j;while(1){Dx(c,b,a);if((b|0)==(g|0))break a;j=(d|0)>-1;d=d+k+(j?e:0)|0;b=b+l|0;a=(j?m:0)+a|0}}else{e=0-k|0;d=j;b=i-(k>>1)|0;while(1){Dx(c,d,a);if((a|0)==(f|0))break a;k=(b|0)>-1;d=(k?l:0)+d|0;b=b+i+(k?e:0)|0;a=a+m|0}}while(0);return}function Ms(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+16|0;k=n;j=n+4|0;do if((a|0)<1)d=0;else{f=e+16|0;if((c[f>>2]|0)>>>0<4){d=Ns(a,b,d,e)|0;break}m=xw(a<<5)|0;d=0;while(1){if((d|0)==(a|0))break;g=c[b+(d<<2)>>2]|0;eB(g);h=m+(d<<5)|0;g=(c[g+16>>2]|0)+16|0;c[h>>2]=c[g>>2];c[h+4>>2]=c[g+4>>2];c[h+8>>2]=c[g+8>>2];c[h+12>>2]=c[g+12>>2];c[h+16>>2]=c[g+16>>2];c[h+20>>2]=c[g+20>>2];c[h+24>>2]=c[g+24>>2];c[h+28>>2]=c[g+28>>2];d=d+1|0}if((c[f>>2]|0)==4){h=e+28|0;a:do if(c[h>>2]&2|0){f=e+24|0;c[f>>2]=ww(a<<2)|0;d=0;while(1){if((d|0)==(a|0))break a;g=Jm(c[b+(d<<2)>>2]|0,84209)|0;if(g|0?(c[k>>2]=j,g=(dM(g,122187,k)|0)>0,i=c[j>>2]|0,g&(i|0)>-1):0)c[(c[f>>2]|0)+(d<<2)>>2]=i;d=d+1|0}}while(0);d=Os(a,m,e)|0;if(c[h>>2]&2)$I(c[e+24>>2]|0)}else d=0;$I(m)}while(0);l=n;return d|0}function Ns(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0.0,K=0.0;G=l;l=l+144|0;B=G+136|0;A=G+64|0;F=G+48|0;v=G+40|0;u=G;t=G+120|0;x=G+104|0;C=G+96|0;D=c[f+20>>2]|0;c[x>>2]=0;c[x+4>>2]=0;c[x+8>>2]=0;c[x+12>>2]=0;a:do if((b|0)>=1){o=(D|0)==0;E=c[13918]|0;p=t+4|0;q=t+8|0;r=t+12|0;y=x+4|0;w=x+8|0;z=x+12|0;n=0;g=0;while(1){if((n|0)==(b|0))break;s=c[d+(n<<2)>>2]|0;eB(s);if(!o?(a[D+n>>0]|0)!=0:0){m=c[s+16>>2]|0;H=+h[m+16>>3];i=~~(H+(H>=0.0?.5:-.5));c[t>>2]=i;H=+h[m+24>>3];j=~~(H+(H>=0.0?.5:-.5));c[p>>2]=j;H=+h[m+32>>3];k=~~(H+(H>=0.0?.5:-.5));c[q>>2]=k;H=+h[m+40>>3];m=~~(H+(H>=0.0?.5:-.5));c[r>>2]=m;if(!g){c[x>>2]=c[t>>2];c[x+4>>2]=c[t+4>>2];c[x+8>>2]=c[t+8>>2];c[x+12>>2]=c[t+12>>2]}else{c[x>>2]=c[((c[x>>2]|0)>(i|0)?t:x)>>2];c[y>>2]=c[((c[y>>2]|0)>(j|0)?t:x)+4>>2];c[w>>2]=c[((c[w>>2]|0)<(k|0)?t:x)+8>>2];c[z>>2]=c[((c[z>>2]|0)<(m|0)?t:x)+12>>2]}g=g+1|0}if(0>2){m=En(s)|0;s=c[s+16>>2]|0;K=+h[s+16>>3];J=+h[s+24>>3];I=+h[s+32>>3];H=+h[s+40>>3];c[u>>2]=m;h[u+8>>3]=K;h[u+16>>3]=J;h[u+24>>3]=I;h[u+32>>3]=H;AL(E,84276,u)|0}n=n+1|0}q=xw(b<<5)|0;g=0;while(1){if((g|0)==(b|0))break;u=q+(g<<5)|0;t=(c[(c[d+(g<<2)>>2]|0)+16>>2]|0)+16|0;c[u>>2]=c[t>>2];c[u+4>>2]=c[t+4>>2];c[u+8>>2]=c[t+8>>2];c[u+12>>2]=c[t+12>>2];c[u+16>>2]=c[t+16>>2];c[u+20>>2]=c[t+20>>2];c[u+24>>2]=c[t+24>>2];c[u+28>>2]=c[t+28>>2];g=g+1|0}o=f+8|0;p=Rs(b,q,c[o>>2]|0)|0;if(0){c[v>>2]=p;AL(E,84304,v)|0}if((p|0)>=1){n=(D|0)!=0;if(n){i=((c[w>>2]|0)+(c[x>>2]|0)|0)/2|0;g=((c[z>>2]|0)+(c[y>>2]|0)|0)/2|0}else{i=0;g=0}c[C+4>>2]=g;c[C>>2]=i;m=ww(b<<4)|0;k=f+16|0;g=0;while(1){if((g|0)>=(b|0))break;i=c[d+(g<<2)>>2]|0;j=m+(g<<4)|0;c[m+(g<<4)+12>>2]=g;if((c[k>>2]|0)==3){x=(c[i+16>>2]|0)+16|0;y=c[o>>2]|0;z=En(i)|0;c[A>>2]=c[x>>2];c[A+4>>2]=c[x+4>>2];c[A+8>>2]=c[x+8>>2];c[A+12>>2]=c[x+12>>2];c[A+16>>2]=c[x+16>>2];c[A+20>>2]=c[x+20>>2];c[A+24>>2]=c[x+24>>2];c[A+28>>2]=c[x+28>>2];c[B>>2]=c[C>>2];c[B+4>>2]=c[C+4>>2];Ss(A,j,p,y,B,z)}else{c[B>>2]=c[C>>2];c[B+4>>2]=c[C+4>>2];Ts(e,i,j,p,f,B)}g=g+1|0}j=ww(b<<2)|0;g=0;while(1){if((g|0)>=(b|0))break;c[j+(g<<2)>>2]=m+(g<<4);g=g+1|0}sL(j,b,4,23);k=xx()|0;g=ww(b<<3)|0;b:do if(n){i=0;while(1){if((i|0)>=(b|0)){i=0;break}if(a[D+i>>0]|0){e=c[j+(i<<2)>>2]|0;f=g+(c[e+12>>2]<<3)|0;c[B>>2]=c[C>>2];c[B+4>>2]=c[C+4>>2];Vs(e,k,f,B)}i=i+1|0}while(1){if((i|0)>=(b|0))break b;if(!(a[D+i>>0]|0)){C=c[j+(i<<2)>>2]|0;Ws(i,C,k,g+(c[C+12>>2]<<3)|0,p,c[o>>2]|0,q)}i=i+1|0}}else{i=0;while(1){if((i|0)>=(b|0))break b;D=c[j+(i<<2)>>2]|0;Ws(i,D,k,g+(c[D+12>>2]<<3)|0,p,c[o>>2]|0,q);i=i+1|0}}while(0);$I(j);i=0;while(1){if((i|0)>=(b|0))break;$I(c[m+(i<<4)+4>>2]|0);i=i+1|0}$I(m);Ax(k);$I(q);if(0>1){i=0;while(1){if((i|0)>=(b|0))break a;C=c[g+(i<<3)>>2]|0;D=c[g+(i<<3)+4>>2]|0;c[F>>2]=i;c[F+4>>2]=C;c[F+8>>2]=D;AL(E,84320,F)|0;i=i+1|0}}}else g=0}else g=0;while(0);l=G;return g|0}function Os(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0.0,j=0,k=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;z=l;l=l+16|0;g=z;x=ww(a<<3)|0;f=c[d+4>>2]|0;y=d+28|0;e=(f|0)>0;do if(!(c[y>>2]&1))if(e){k=1;w=(a+-1+f|0)/(f|0)|0;break}else{f=~~+N(+(+C(+(+(a|0)))));k=1;w=(a+-1+f|0)/(f|0)|0;break}else if(e){k=0;w=f;f=(a+-1+f|0)/(f|0)|0;break}else{f=~~+N(+(+C(+(+(a|0)))));k=0;w=f;f=(a+-1+f|0)/(f|0)|0;break}while(0);if(0){v=c[13918]|0;c[g>>2]=k|0?84215:84225;c[g+4>>2]=w;c[g+8>>2]=f;AL(v,84238,g)|0}t=ww((f<<3)+8|0)|0;u=ww((w<<3)+8|0)|0;v=ww(a*24|0)|0;j=d+8|0;e=0;g=v;while(1){if((e|0)>=(a|0))break;p=+h[b+(e<<5)+8>>3];o=+h[b+(e<<5)+24>>3];q=+((c[j>>2]|0)>>>0);h[g>>3]=+h[b+(e<<5)+16>>3]-+h[b+(e<<5)>>3]+q;h[g+8>>3]=o-p+q;c[g+16>>2]=e;e=e+1|0;g=g+24|0}s=ww(a<<2)|0;e=0;while(1){if((e|0)>=(a|0))break;c[s+(e<<2)>>2]=v+(e*24|0);e=e+1|0}e=c[d+24>>2]|0;if(!e){if(!(c[y>>2]&64))sL(s,a,4,25)}else{c[42101]=e;sL(s,a,4,24)}r=(k|0)==0;e=0;g=0;j=0;while(1){if((j|0)>=(a|0)){i=0.0;e=0;break}k=c[s+(j<<2)>>2]|0;d=t+(g<<3)|0;q=+h[d>>3];p=+h[k>>3];h[d>>3]=q>p?q:p;d=u+(e<<3)|0;p=+h[d>>3];q=+h[k+8>>3];h[d>>3]=p>q?p:q;if(r){e=e+1|0;d=(e|0)==(w|0);e=d?0:e;g=g+(d&1)|0}else{g=g+1|0;d=(g|0)==(f|0);e=e+(d&1)|0;g=d?0:g}j=j+1|0}while(1){if((e|0)>(f|0)){i=0.0;e=w;break}d=t+(e<<3)|0;q=+h[d>>3];h[d>>3]=i;i=q+i;e=e+1|0}while(1){if((e|0)<=0)break;d=e+-1|0;q=+h[u+(d<<3)>>3];h[u+(e<<3)>>3]=i;i=q+i;e=d}h[u>>3]=i;e=0;g=0;d=0;while(1){if((d|0)>=(a|0))break;k=c[(c[s+(d<<2)>>2]|0)+16>>2]|0;i=+h[b+(k<<5)>>3];m=-i;p=+h[b+(k<<5)+8>>3];q=-p;n=+h[b+(k<<5)+16>>3];o=+h[b+(k<<5)+24>>3];j=c[y>>2]|0;do if(!(j&4))if(!(j&8)){i=(m-n+ +h[t+(g<<3)>>3]+ +h[t+(g+1<<3)>>3])*.5;break}else{i=i-n+ +h[t+(g+1<<3)>>3];break}else i=+h[t+(g<<3)>>3];while(0);c[x+(k<<3)>>2]=~~i;do if(!(j&16))if(!(j&32)){i=(q-o+ +h[u+(e<<3)>>3]+ +h[u+(e+1<<3)>>3])*.5;break}else{i=+h[u+(e+1<<3)>>3];break}else i=p-o+ +h[u+(e<<3)>>3];while(0);c[x+(k<<3)+4>>2]=~~i;if(r){e=e+1|0;k=(e|0)==(w|0);e=k?0:e;g=g+(k&1)|0}else{g=g+1|0;k=(g|0)==(f|0);e=e+(k&1)|0;g=k?0:g}d=d+1|0}$I(v);$I(s);$I(t);$I(u);l=z;return x|0}function Ps(a,b){a=a|0;b=b|0;var d=0;d=c[42101]|0;a=c[d+(c[(c[a>>2]|0)+16>>2]<<2)>>2]|0;b=c[d+(c[(c[b>>2]|0)+16>>2]<<2)>>2]|0;return ((a|0)>(b|0)?1:((a|0)<(b|0))<<31>>31)|0}function Qs(a,b){a=a|0;b=b|0;var d=0.0,e=0.0;a=c[a>>2]|0;b=c[b>>2]|0;e=+h[a>>3]+ +h[a+8>>3];d=+h[b>>3]+ +h[b+8>>3];return (ed)<<31>>31)|0}function Rs(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0.0,g=0.0,i=0.0,j=0.0,k=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0,s=0;s=l;l=l+96|0;q=s+80|0;r=s+48|0;p=s+8|0;m=s;k=(a*100|0)+-1|0;e=+(d<<1|0);n=0.0;o=0.0;d=0;while(1){if((d|0)>=(a|0))break;j=+h[b+(d<<5)+16>>3]-+h[b+(d<<5)>>3]+e;i=+h[b+(d<<5)+24>>3]-+h[b+(d<<5)+8>>3]+e;n=n-j-i;o=o-i*j;d=d+1|0}i=+(k|0);j=n*n-i*4.0*o;if(!(j<0.0)){e=+C(+j);g=i*2.0;f=(e-n)/g;g=(-n-e)/g;d=~~f;d=(d|0)==0?1:d;if(0>2){m=c[13918]|0;YL(84463,27,1,m)|0;h[p>>3]=i;h[p+8>>3]=n;h[p+16>>3]=o;h[p+24>>3]=j;h[p+32>>3]=e;AL(m,84491,p)|0;c[r>>2]=d;h[r+8>>3]=f;c[r+16>>2]=~~g;h[r+24>>3]=g;AL(m,84517,r)|0;h[q>>3]=(f*i+n)*f+o;h[q+8>>3]=(g*i+n)*g+o;AL(m,84539,q)|0}}else{h[m>>3]=j;$l(1,84436,m)|0;d=-1}l=s;return d|0}function Ss(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0.0,w=0.0;u=l;l=l+32|0;t=u+16|0;s=u;p=+h[a>>3];q=+h[a+8>>3];n=+h[a+16>>3];o=+h[a+24>>3];r=xx()|0;j=c[f>>2]|0;a=j-e|0;k=c[f+4>>2]|0;i=k-e|0;j=e-~~(p+(p>=0.0?.5:-.5))+j+~~(n+(n>=0.0?.5:-.5))|0;k=e-~~(q+(q>=0.0?.5:-.5))+k+~~(o+(o>=0.0?.5:-.5))|0;if((a|0)>-1)f=(a|0)/(d|0)|0;else f=((a+1|0)/(d|0)|0)+-1|0;if((i|0)>-1)m=(i|0)/(d|0)|0;else m=((i+1|0)/(d|0)|0)+-1|0;if((j|0)>-1)j=(j|0)/(d|0)|0;else j=((j+1|0)/(d|0)|0)+-1|0;if((k|0)>-1)i=(k|0)/(d|0)|0;else i=((k+1|0)/(d|0)|0)+-1|0;while(1){if((f|0)>(j|0))break;else a=m;while(1){if((a|0)>(i|0))break;Dx(r,f,a);a=a+1|0}f=f+1|0}k=b+4|0;c[k>>2]=Hx(r)|0;j=Gx(r)|0;m=b+8|0;c[m>>2]=j;w=+(e<<1|0);v=+(d|0);i=~~+N(+((n+w-p)/v));a=~~+N(+((o+w-q)/v));c[b>>2]=a+i;a:do if(0>2){f=c[13918]|0;c[s>>2]=g;c[s+4>>2]=j;c[s+8>>2]=i;c[s+12>>2]=a;AL(f,84395,s)|0;a=0;while(1){if((a|0)>=(c[m>>2]|0))break a;g=c[k>>2]|0;s=c[g+(a<<3)+4>>2]|0;c[t>>2]=c[g+(a<<3)>>2];c[t+4>>2]=s;AL(f,84422,t)|0;a=a+1|0}}while(0);Ax(r);l=u;return}function Ts(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0.0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,O=0,P=0,Q=0.0,R=0.0;P=l;l=l+128|0;F=P+112|0;E=P+104|0;O=P+16|0;M=P;H=P+64|0;I=P+56|0;z=P+40|0;A=P+96|0;y=P+88|0;v=P+24|0;w=P+80|0;x=P+72|0;K=c[f+8>>2]|0;G=c[f+12>>2]|0;C=(a|0)==0?b:a;L=xx()|0;J=b+16|0;B=c[J>>2]|0;t=+h[B+16>>3];D=(c[g>>2]|0)-~~(t+(t>=0.0?.5:-.5))|0;t=+h[B+24>>3];B=(c[g+4>>2]|0)-~~(t+(t>=0.0?.5:-.5))|0;a:do if((c[f+16>>2]|0)==1){v=xw((nn(b)|0)<<2)|0;a=0;g=eo(b)|0;while(1){if(!g)break;x=g+16|0;c[v+(a<<2)>>2]=c[(c[x>>2]|0)+112>>2];c[(c[x>>2]|0)+112>>2]=0;a=a+1|0;g=fo(b,g)|0}o=D-K|0;p=B-K|0;q=D+K|0;r=B+K|0;n=1;while(1){a=c[J>>2]|0;if((n|0)>(c[a+180>>2]|0))break;m=c[(c[a+184>>2]|0)+(n<<2)>>2]|0;i=c[m+16>>2]|0;t=+h[i+16>>3];a=~~(t+(t>=0.0?.5:-.5));t=+h[i+24>>3];g=~~(t+(t>=0.0?.5:-.5));t=+h[i+32>>3];f=~~(t+(t>=0.0?.5:-.5));t=+h[i+40>>3];i=~~(t+(t>=0.0?.5:-.5));b:do if((f|0)>(a|0)&(i|0)>(g|0)){a=o+a|0;j=p+g|0;f=q+f|0;k=r+i|0;if((a|0)>-1)g=(a|0)/(e|0)|0;else g=((a+1|0)/(e|0)|0)+-1|0;if((j|0)>-1)j=(j|0)/(e|0)|0;else j=((j+1|0)/(e|0)|0)+-1|0;if((f|0)>-1)i=(f|0)/(e|0)|0;else i=((f+1|0)/(e|0)|0)+-1|0;if((k|0)>-1)f=(k|0)/(e|0)|0;else f=((k+1|0)/(e|0)|0)+-1|0;while(1){if((g|0)>(i|0))break;else a=j;while(1){if((a|0)>(f|0))break;Dx(L,g,a);a=a+1|0}g=g+1|0}a=eo(m)|0;while(1){if(!a)break b;c[(c[a+16>>2]|0)+212>>2]=m;a=fo(m,a)|0}}while(0);n=n+1|0}r=z+8|0;s=H+4|0;t=+(K|0);u=I+4|0;q=A+4|0;p=y+4|0;o=eo(b)|0;while(1){if(!o)break;PA(z,o);R=+h[z>>3];Q=+h[r>>3];m=D+~~(R+(R>=0.0?.5:-.5))|0;c[H>>2]=m;n=B+~~(Q+(Q>=0.0?.5:-.5))|0;c[s>>2]=n;g=o+16|0;a=c[g>>2]|0;c:do if(!(c[a+212>>2]|0)){c[I>>2]=~~((+h[a+96>>3]+ +h[a+88>>3])*.5+t);c[u>>2]=~~(+h[a+80>>3]*.5+t);c[E>>2]=c[H>>2];c[E+4>>2]=c[H+4>>2];c[F>>2]=c[I>>2];c[F+4>>2]=c[I+4>>2];Ys(A,E,F);a=c[A>>2]|0;f=c[q>>2]|0;c[E>>2]=c[H>>2];c[E+4>>2]=c[H+4>>2];c[F>>2]=c[I>>2];c[F+4>>2]=c[I+4>>2];Zs(y,E,F);i=c[y>>2]|0;j=c[p>>2]|0;if((a|0)>-1)g=(a|0)/(e|0)|0;else g=((a+1|0)/(e|0)|0)+-1|0;if((f|0)>-1)k=(f|0)/(e|0)|0;else k=((f+1|0)/(e|0)|0)+-1|0;if((i|0)>-1)i=(i|0)/(e|0)|0;else i=((i+1|0)/(e|0)|0)+-1|0;if((j|0)>-1)f=(j|0)/(e|0)|0;else f=((j+1|0)/(e|0)|0)+-1|0;while(1){if((g|0)>(i|0))break;else a=k;while(1){if((a|0)>(f|0))break;Dx(L,g,a);a=a+1|0}g=g+1|0}if((m|0)>-1)a=(m|0)/(e|0)|0;else a=((m+1|0)/(e|0)|0)+-1|0;c[H>>2]=a;if((n|0)>-1)a=(n|0)/(e|0)|0;else a=((n+1|0)/(e|0)|0)+-1|0;c[s>>2]=a;a=Qm(C,o)|0;while(1){if(!a)break c;c[F>>2]=c[H>>2];c[F+4>>2]=c[H+4>>2];_s(a,F,L,D,B,e,G);a=Sm(C,a)|0}}else{if((m|0)>-1)a=(m|0)/(e|0)|0;else a=((m+1|0)/(e|0)|0)+-1|0;c[H>>2]=a;if((n|0)>-1)a=(n|0)/(e|0)|0;else a=((n+1|0)/(e|0)|0)+-1|0;c[s>>2]=a;a=Qm(C,o)|0;while(1){if(!a)break c;if((c[(c[g>>2]|0)+212>>2]|0)!=(c[(c[(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0)){c[F>>2]=c[H>>2];c[F+4>>2]=c[H+4>>2];_s(a,F,L,D,B,e,G)}a=Sm(C,a)|0}}while(0);o=fo(b,o)|0}a=0;g=eo(b)|0;while(1){if(!g)break;c[(c[g+16>>2]|0)+112>>2]=c[v+(a<<2)>>2];a=a+1|0;g=fo(b,g)|0}$I(v)}else{r=v+8|0;s=H+4|0;t=+(K|0);u=I+4|0;q=w+4|0;p=x+4|0;o=eo(b)|0;while(1){if(!o)break a;PA(v,o);Q=+h[v>>3];R=+h[r>>3];m=D+~~(Q+(Q>=0.0?.5:-.5))|0;c[H>>2]=m;n=B+~~(R+(R>=0.0?.5:-.5))|0;c[s>>2]=n;a=c[o+16>>2]|0;c[I>>2]=~~((+h[a+96>>3]+ +h[a+88>>3])*.5+t);c[u>>2]=~~(+h[a+80>>3]*.5+t);c[E>>2]=c[H>>2];c[E+4>>2]=c[H+4>>2];c[F>>2]=c[I>>2];c[F+4>>2]=c[I+4>>2];Ys(w,E,F);a=c[w>>2]|0;f=c[q>>2]|0;c[E>>2]=c[H>>2];c[E+4>>2]=c[H+4>>2];c[F>>2]=c[I>>2];c[F+4>>2]=c[I+4>>2];Zs(x,E,F);i=c[x>>2]|0;j=c[p>>2]|0;if((a|0)>-1)g=(a|0)/(e|0)|0;else g=((a+1|0)/(e|0)|0)+-1|0;if((f|0)>-1)k=(f|0)/(e|0)|0;else k=((f+1|0)/(e|0)|0)+-1|0;if((i|0)>-1)i=(i|0)/(e|0)|0;else i=((i+1|0)/(e|0)|0)+-1|0;if((j|0)>-1)f=(j|0)/(e|0)|0;else f=((j+1|0)/(e|0)|0)+-1|0;while(1){if((g|0)>(i|0))break;else a=k;while(1){if((a|0)>(f|0))break;Dx(L,g,a);a=a+1|0}g=g+1|0}if((m|0)>-1)a=(m|0)/(e|0)|0;else a=((m+1|0)/(e|0)|0)+-1|0;c[H>>2]=a;if((n|0)>-1)a=(n|0)/(e|0)|0;else a=((n+1|0)/(e|0)|0)+-1|0;c[s>>2]=a;a=Qm(C,o)|0;while(1){if(!a)break;c[F>>2]=c[H>>2];c[F+4>>2]=c[H+4>>2];_s(a,F,L,D,B,e,G);a=Sm(C,a)|0}o=fo(b,o)|0}}while(0);i=d+4|0;c[i>>2]=Hx(L)|0;j=d+8|0;c[j>>2]=Gx(L)|0;g=c[J>>2]|0;Q=+(K<<1|0);R=+(e|0);a=~~+N(+((+h[g+32>>3]+Q-+h[g+16>>3])/R));g=~~+N(+((+h[g+40>>3]+Q-+h[g+24>>3])/R));c[d>>2]=g+a;d:do if(0>2){f=c[13918]|0;d=En(b)|0;b=c[j>>2]|0;c[M>>2]=d;c[M+4>>2]=b;c[M+8>>2]=a;c[M+12>>2]=g;AL(f,84395,M)|0;a=0;while(1){if((a|0)>=(c[j>>2]|0))break d;b=c[i>>2]|0;M=c[b+(a<<3)+4>>2]|0;c[O>>2]=c[b+(a<<3)>>2];c[O+4>>2]=M;AL(f,84422,O)|0;a=a+1|0}}while(0);Ax(L);l=P;return}function Us(a,b){a=a|0;b=b|0;return (c[c[b>>2]>>2]|0)-(c[c[a>>2]>>2]|0)|0}function Vs(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;j=l;l=l+32|0;h=j+16|0;i=j;k=c[a+4>>2]|0;g=c[a+8>>2]|0;c[d>>2]=0-(c[e>>2]|0);f=d+4|0;c[f>>2]=0-(c[e+4>>2]|0);a=0;e=k;while(1){if((a|0)>=(g|0))break;c[h>>2]=c[e>>2];c[h+4>>2]=c[e+4>>2];Bx(b,h);a=a+1|0;e=e+8|0}if(0>1){k=c[13918]|0;b=c[d>>2]|0;d=c[f>>2]|0;c[i>>2]=g;c[i+4>>2]=b;c[i+8>>2]=d;AL(k,84369,i)|0}l=j;return}function Ws(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,l=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0;k=c[b+12>>2]|0;l=+h[i+(k<<5)>>3];m=+h[i+(k<<5)+8>>3];n=+h[i+(k<<5)+16>>3];o=+h[i+(k<<5)+24>>3];if(!((a|0)==0?(q=+(g<<1|0),p=+(f|0),(Xs((~~+N(+((q-l+n)/p))|0)/-2|0,(~~+N(+((q-m+o)/p))|0)/-2|0,b,d,e,f,i)|0)!=0):0))j=3;a:do if((j|0)==3?(Xs(0,0,b,d,e,f,i)|0)==0:0)if((~~+N(+(n-l))|0)<(~~+N(+(o-m))|0)){k=1;while(1){j=0-k|0;a=0;while(1){if((a|0)<=(j|0)){g=j;break}if(Xs(j,a,b,d,e,f,i)|0)break a;a=a+-1|0}while(1){if((g|0)>=(k|0))break;if(Xs(g,a,b,d,e,f,i)|0)break a;g=g+1|0}while(1){if((a|0)>=(k|0))break;if(Xs(g,a,b,d,e,f,i)|0)break a;a=a+1|0}while(1){if((g|0)<=(j|0))break;if(Xs(g,a,b,d,e,f,i)|0)break a;g=g+-1|0}while(1){if((a|0)<=0)break;if(!(Xs(g,a,b,d,e,f,i)|0))a=a+-1|0;else break a}k=k+1|0}}else{k=1;while(1){j=0-k|0;a=0;while(1){if((a|0)>=(k|0)){g=j;break}if(Xs(a,j,b,d,e,f,i)|0)break a;a=a+1|0}while(1){if((g|0)>=(k|0))break;if(Xs(a,g,b,d,e,f,i)|0)break a;g=g+1|0}while(1){if((a|0)<=(j|0))break;if(Xs(a,g,b,d,e,f,i)|0)break a;a=a+-1|0}while(1){if((g|0)<=(j|0))break;if(Xs(a,g,b,d,e,f,i)|0)break a;g=g+-1|0}while(1){if((a|0)>=0)break;if(!(Xs(a,g,b,d,e,f,i)|0))a=a+1|0;else break a}k=k+1|0}}while(0);return}function Xs(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0;t=l;l=l+48|0;r=t+32|0;s=t+8|0;q=t;m=d+4|0;o=c[d+8>>2]|0;p=q+4|0;j=c[m>>2]|0;k=0;while(1){if((k|0)>=(o|0)){n=5;break}v=j;u=c[v+4>>2]|0;c[q>>2]=(c[v>>2]|0)+a;c[p>>2]=u+b;c[r>>2]=c[q>>2];c[r+4>>2]=c[q+4>>2];if(Ex(e,r)|0){j=0;break}j=j+8|0;k=k+1|0}if((n|0)==5){d=c[d+12>>2]|0;x=+h[i+(d<<5)>>3];w=+h[i+(d<<5)+8>>3];c[f>>2]=(O(g,a)|0)-~~(x+(x>=0.0?.5:-.5));d=f+4|0;c[d>>2]=(O(g,b)|0)-~~(w+(w>=0.0?.5:-.5));j=c[m>>2]|0;k=0;while(1){if((k|0)>=(o|0))break;u=j;v=c[u+4>>2]|0;c[q>>2]=(c[u>>2]|0)+a;c[p>>2]=v+b;c[r>>2]=c[q>>2];c[r+4>>2]=c[q+4>>2];Bx(e,r);j=j+8|0;k=k+1|0}if(0>1){j=c[13918]|0;u=c[f>>2]|0;v=c[d>>2]|0;c[s>>2]=o;c[s+4>>2]=a;c[s+8>>2]=b;c[s+12>>2]=u;c[s+16>>2]=v;AL(j,84335,s)|0;j=1}else j=1}l=t;return j|0}function Ys(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=(c[b+4>>2]|0)-(c[d+4>>2]|0)|0;c[a>>2]=(c[b>>2]|0)-(c[d>>2]|0);c[a+4>>2]=e;return}function Zs(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=(c[d+4>>2]|0)+(c[b+4>>2]|0)|0;c[a>>2]=(c[d>>2]|0)+(c[b>>2]|0);c[a+4>>2]=e;return}function _s(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0.0,k=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;A=l;l=l+112|0;x=A+96|0;w=A+80|0;r=A+48|0;s=A+32|0;y=A+16|0;z=A;n=A+64|0;h[y>>3]=+(c[b>>2]|0);t=y+8|0;h[t>>3]=+(c[b+4>>2]|0);a:do if((i|0)!=0?(u=a+16|0,m=c[(c[u>>2]|0)+8>>2]|0,(m|0)!=0):0){q=+(e|0);p=+(f|0);o=1.0/+(g|0);n=z+8|0;i=0;while(1){if((i|0)>=(c[m+4>>2]|0))break a;f=c[m>>2]|0;a=c[f+(i*48|0)>>2]|0;b=c[f+(i*48|0)+4>>2]|0;g=c[f+(i*48|0)+8>>2]|0;e=c[f+(i*48|0)+12>>2]|0;m=f+(i*48|0)+16|0;c[r>>2]=c[m>>2];c[r+4>>2]=c[m+4>>2];c[r+8>>2]=c[m+8>>2];c[r+12>>2]=c[m+12>>2];f=f+(i*48|0)+32|0;c[s>>2]=c[f>>2];c[s+4>>2]=c[f+4>>2];c[s+8>>2]=c[f+8>>2];c[s+12>>2]=c[f+12>>2];if(!g){c[y>>2]=c[a>>2];c[y+4>>2]=c[a+4>>2];c[y+8>>2]=c[a+8>>2];c[y+12>>2]=c[a+12>>2];m=a+16|0;c[z>>2]=c[m>>2];c[z+4>>2]=c[m+4>>2];c[z+8>>2]=c[m+8>>2];c[z+12>>2]=c[m+12>>2];m=2}else{c[y>>2]=c[r>>2];c[y+4>>2]=c[r+4>>2];c[y+8>>2]=c[r+8>>2];c[y+12>>2]=c[r+12>>2];c[z>>2]=c[a>>2];c[z+4>>2]=c[a+4>>2];c[z+8>>2]=c[a+8>>2];c[z+12>>2]=c[a+12>>2];m=1}j=+h[y>>3]+q;h[y>>3]=j;k=+h[t>>3]+p;h[t>>3]=k;if(!(j>=0.0))j=(j+1.0)*o+-1.0;else j=j*o;h[y>>3]=j;if(!(k>=0.0))j=(k+1.0)*o+-1.0;else j=k*o;h[t>>3]=j;j=+h[z>>3]+q;h[z>>3]=j;k=+h[n>>3]+p;h[n>>3]=k;if(!(j>=0.0))j=(j+1.0)*o+-1.0;else j=j*o;h[z>>3]=j;if(!(k>=0.0))j=(k+1.0)*o+-1.0;else j=k*o;h[n>>3]=j;c[w>>2]=c[y>>2];c[w+4>>2]=c[y+4>>2];c[w+8>>2]=c[y+8>>2];c[w+12>>2]=c[y+12>>2];c[x>>2]=c[z>>2];c[x+4>>2]=c[z+4>>2];c[x+8>>2]=c[z+8>>2];c[x+12>>2]=c[z+12>>2];Ls(w,x,d);while(1){if((m|0)>=(b|0))break;c[y>>2]=c[z>>2];c[y+4>>2]=c[z+4>>2];c[y+8>>2]=c[z+8>>2];c[y+12>>2]=c[z+12>>2];g=a+(m<<4)|0;c[z>>2]=c[g>>2];c[z+4>>2]=c[g+4>>2];c[z+8>>2]=c[g+8>>2];c[z+12>>2]=c[g+12>>2];j=+h[z>>3]+q;h[z>>3]=j;k=+h[n>>3]+p;h[n>>3]=k;if(!(j>=0.0))j=(j+1.0)*o+-1.0;else j=j*o;h[z>>3]=j;if(!(k>=0.0))j=(k+1.0)*o+-1.0;else j=k*o;h[n>>3]=j;c[w>>2]=c[y>>2];c[w+4>>2]=c[y+4>>2];c[w+8>>2]=c[y+8>>2];c[w+12>>2]=c[y+12>>2];c[x>>2]=c[z>>2];c[x+4>>2]=c[z+4>>2];c[x+8>>2]=c[z+8>>2];c[x+12>>2]=c[z+12>>2];Ls(w,x,d);m=m+1|0}if(e|0){c[y>>2]=c[z>>2];c[y+4>>2]=c[z+4>>2];c[y+8>>2]=c[z+8>>2];c[y+12>>2]=c[z+12>>2];c[z>>2]=c[s>>2];c[z+4>>2]=c[s+4>>2];c[z+8>>2]=c[s+8>>2];c[z+12>>2]=c[s+12>>2];j=+h[z>>3]+q;h[z>>3]=j;k=+h[n>>3]+p;h[n>>3]=k;if(!(j>=0.0))j=(j+1.0)*o+-1.0;else j=j*o;h[z>>3]=j;if(!(k>=0.0))j=(k+1.0)*o+-1.0;else j=k*o;h[n>>3]=j;c[w>>2]=c[y>>2];c[w+4>>2]=c[y+4>>2];c[w+8>>2]=c[y+8>>2];c[w+12>>2]=c[y+12>>2];c[x>>2]=c[z>>2];c[x+4>>2]=c[z+4>>2];c[x+8>>2]=c[z+8>>2];c[x+12>>2]=c[z+12>>2];Ls(w,x,d)}i=i+1|0;m=c[(c[u>>2]|0)+8>>2]|0}}else v=4;while(0);if((v|0)==4){PA(n,c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0);c[z>>2]=c[n>>2];c[z+4>>2]=c[n+4>>2];c[z+8>>2]=c[n+8>>2];c[z+12>>2]=c[n+12>>2];j=+h[z>>3]+ +(e|0);h[z>>3]=j;m=z+8|0;k=+h[m>>3]+ +(f|0);h[m>>3]=k;if(!(j>=0.0))j=(j+1.0)/+(g|0)+-1.0;else j=j/+(g|0);h[z>>3]=j;if(!(k>=0.0))j=(k+1.0)/+(g|0)+-1.0;else j=k/+(g|0);h[m>>3]=j;c[w>>2]=c[y>>2];c[w+4>>2]=c[y+4>>2];c[w+8>>2]=c[y+8>>2];c[w+12>>2]=c[y+12>>2];c[x>>2]=c[z>>2];c[x+4>>2]=c[z+4>>2];c[x+8>>2]=c[z+8>>2];c[x+12>>2]=c[z+12>>2];Ls(w,x,d)}l=A;return}function $s(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0;a:do if((a|0)<1)f=0-a|0;else{s=(e|0)==0;q=(f|0)==0;j=0;while(1){if((j|0)==(a|0)){f=0;break a}r=c[b+(j<<2)>>2]|0;g=s?r:e;k=c[d+(j<<3)>>2]|0;l=c[d+(j<<3)+4>>2]|0;m=+(k|0);n=m*.013888888888888888;o=+(l|0);p=o*.013888888888888888;i=eo(r)|0;while(1){if(!i)break;f=c[i+16>>2]|0;t=c[f+132>>2]|0;h[t>>3]=+h[t>>3]+n;t=t+8|0;h[t>>3]=+h[t>>3]+p;t=f+16|0;h[t>>3]=+h[t>>3]+m;t=f+24|0;h[t>>3]=+h[t>>3]+o;f=c[f+108>>2]|0;if(f|0){t=f+56|0;h[t>>3]=+h[t>>3]+m;t=f+64|0;h[t>>3]=+h[t>>3]+o}b:do if(!q){f=Qm(g,i)|0;while(1){if(!f)break b;at(f,k,l);f=Sm(g,f)|0}}while(0);i=fo(r,i)|0}bt(r,k,l);j=j+1|0}}while(0);return f|0}function at(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0.0,k=0,l=0.0,m=0,n=0;e=c[a+16>>2]|0;a=c[e+96>>2]|0;if(a|0){m=a+56|0;h[m>>3]=+h[m>>3]+ +(b|0);m=a+64|0;h[m>>3]=+h[m>>3]+ +(d|0)}a=c[e+108>>2]|0;if(a|0){m=a+56|0;h[m>>3]=+h[m>>3]+ +(b|0);m=a+64|0;h[m>>3]=+h[m>>3]+ +(d|0)}a=c[e+100>>2]|0;if(a|0){m=a+56|0;h[m>>3]=+h[m>>3]+ +(b|0);m=a+64|0;h[m>>3]=+h[m>>3]+ +(d|0)}a=c[e+104>>2]|0;if(a|0){m=a+56|0;h[m>>3]=+h[m>>3]+ +(b|0);m=a+64|0;h[m>>3]=+h[m>>3]+ +(d|0)}m=c[e+8>>2]|0;a:do if(m|0){l=+(b|0);j=+(d|0);b=c[m+4>>2]|0;a=0;while(1){if((a|0)>=(b|0))break a;k=c[m>>2]|0;d=c[k+(a*48|0)>>2]|0;f=c[k+(a*48|0)+4>>2]|0;g=c[k+(a*48|0)+8>>2]|0;i=c[k+(a*48|0)+12>>2]|0;e=0;while(1){if((e|0)>=(f|0))break;n=d+(e<<4)|0;h[n>>3]=+h[n>>3]+l;n=d+(e<<4)+8|0;h[n>>3]=+h[n>>3]+j;e=e+1|0}if(g|0){n=k+(a*48|0)+16|0;h[n>>3]=+h[n>>3]+l;n=k+(a*48|0)+24|0;h[n>>3]=+h[n>>3]+j}if(i|0){n=k+(a*48|0)+32|0;h[n>>3]=+h[n>>3]+l;n=k+(a*48|0)+40|0;h[n>>3]=+h[n>>3]+j}a=a+1|0}}while(0);return}function bt(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0,k=0.0,l=0.0,m=0,n=0.0,o=0;j=b+16|0;b=c[j>>2]|0;o=b+16|0;m=b+24|0;f=b+32|0;b=b+40|0;g=+(d|0);l=+h[f>>3]+g;i=+(e|0);n=+h[m>>3]+i;k=+h[b>>3]+i;h[o>>3]=+h[o>>3]+g;h[m>>3]=n;h[f>>3]=l;h[b>>3]=k;b=c[j>>2]|0;f=c[b+12>>2]|0;if((f|0)!=0?(a[f+81>>0]|0)!=0:0){o=f+56|0;h[o>>3]=+h[o>>3]+g;f=f+64|0;h[f>>3]=+h[f>>3]+i;f=1}else f=1;while(1){if((f|0)>(c[b+180>>2]|0))break;bt(c[(c[b+184>>2]|0)+(f<<2)>>2]|0,d,e);f=f+1|0;b=c[j>>2]|0}return}function ct(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=Ms(a,b,d,e)|0;if(!f)a=1;else{a=$s(a,b,f,d,c[e+12>>2]|0)|0;$I(f)}return a|0}function dt(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0;p=l;l=l+32|0;o=p;n=ct(a,b,d,e)|0;if(!n){eB(d);m=(c[d+16>>2]|0)+16|0;c[o>>2]=c[m>>2];c[o+4>>2]=c[m+4>>2];c[o+8>>2]=c[m+8>>2];c[o+12>>2]=c[m+12>>2];c[o+16>>2]=c[m+16>>2];c[o+20>>2]=c[m+20>>2];c[o+24>>2]=c[m+24>>2];c[o+28>>2]=c[m+28>>2];f=o+8|0;g=o+16|0;i=o+24|0;e=0;while(1){if((e|0)>=(a|0))break;k=c[(c[b+(e<<2)>>2]|0)+16>>2]|0;j=c[k+180>>2]|0;k=k+184|0;d=1;while(1){if((d|0)>(j|0))break;r=(c[(c[(c[k>>2]|0)+(d<<2)>>2]|0)+16>>2]|0)+16|0;h[o>>3]=+h[(+h[o>>3]<+h[r>>3]?o:r)>>3];r=c[(c[(c[k>>2]|0)+(d<<2)>>2]|0)+16>>2]|0;q=r+16|0;h[f>>3]=+h[(+h[f>>3]<+h[r+24>>3]?o:q)+8>>3];h[g>>3]=+h[(+h[g>>3]>+h[r+32>>3]?o:q)+16>>3];h[i>>3]=+h[(+h[i>>3]>+h[r+40>>3]?o:q)+24>>3];d=d+1|0}e=e+1|0}c[m>>2]=c[o>>2];c[m+4>>2]=c[o+4>>2];c[m+8>>2]=c[o+8>>2];c[m+12>>2]=c[o+12>>2];c[m+16>>2]=c[o+16>>2];c[m+20>>2]=c[o+20>>2];c[m+24>>2]=c[o+24>>2];c[m+28>>2]=c[o+28>>2]}l=p;return n|0}function et(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;g=l;l=l+16|0;f=g;if(!e)ma(84553,84559,1400,84566);d=ft(a,d,d)|0;c[e+8>>2]=d;if(0){h=c[13918]|0;c[f>>2]=d;AL(h,84578,f)|0}c[e+12>>2]=0;c[e+20>>2]=0;gt(a,b,e)|0;l=g;return c[e+16>>2]|0}function ft(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;f=i+4|0;g=Jm(b,84708)|0;a:do if(g){c[h>>2]=f;h=(dM(g,122187,h)|0)==1;b=c[f>>2]|0;if(h&(b|0)>-1)d=b;else{switch(a[g>>0]|0){case 84:case 116:break;default:break a}d=e}}while(0);l=i;return d|0}function gt(a,b,c){a=a|0;b=b|0;c=c|0;return ht(Jm(a,84591)|0,b,c)|0}function ht(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0;u=l;l=l+64|0;r=u+40|0;q=u+32|0;t=u+24|0;s=u+16|0;m=u+8|0;k=u;i=u+48|0;j=u+44|0;if(!e)ma(84553,84559,1292,84600);o=e+28|0;c[o>>2]=0;p=e+16|0;c[p>>2]=d;n=e+4|0;c[n>>2]=0;c[e+24>>2]=0;a:do if(b|0?(f=a[b>>0]|0,f<<24>>24):0)switch(f<<24>>24|0){case 97:if(!(WJ(b,84618,5)|0)){c[p>>2]=4;m=it(b+5|0,e)|0;c[k>>2]=j;m=(dM(m,122187,k)|0)>0;d=c[j>>2]|0;if(!(m&(d|0)>0))break a;c[n>>2]=d;break a}else{if(WJ(b,84624,6)|0)break a;c[p>>2]=5;c[m>>2]=i;m=(dM(b+5|0,84631,m)|0)>0;v=+g[i>>2];g[e>>2]=m&v>0.0?v:1.0;break a}case 99:{if(f<<24>>24!=99)break a;if(yJ(b,93039)|0)break a;c[p>>2]=1;break a}case 103:{if(f<<24>>24!=103)break a;if(yJ(b,96286)|0)break a;c[p>>2]=3;break a}case 110:{if(f<<24>>24!=110)break a;if(yJ(b,96273)|0)break a;c[p>>2]=2;break a}default:break a}while(0);if(0){d=c[13918]|0;YL(84634,11,1,d)|0;c[s>>2]=jt(c[p>>2]|0)|0;AL(d,84646,s)|0;if((c[p>>2]|0)==5){h[t>>3]=+g[e>>2];AL(d,84659,t)|0}c[q>>2]=c[n>>2];AL(d,84672,q)|0;c[r>>2]=c[o>>2];AL(d,84685,r)|0}l=u;return c[p>>2]|0}function it(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;a:do if((a[b>>0]|0)==95){f=d+28|0;e=1;while(1){b=b+1|0;b:while(1){if(!e)break a;d=a[b>>0]|0;if(!(d<<24>>24))break a;switch(d<<24>>24|0){case 99:{g=10;break b}case 105:{g=9;break b}case 117:{g=11;break b}case 116:{g=12;break b}case 98:{d=32;break b}case 108:{g=7;break b}case 114:{g=8;break b}default:e=0}}if((g|0)==7){g=0;d=4}else if((g|0)==8){g=0;d=8}else if((g|0)==9){g=0;d=64}else if((g|0)==10){g=0;d=1}else if((g|0)==11){g=0;d=2}else if((g|0)==12){g=0;d=16}c[f>>2]=c[f>>2]|d}}while(0);return b|0}function jt(a){a=a|0;switch(a|0){case 1:{a=93039;break}case 2:{a=96273;break}case 3:{a=96286;break}case 4:{a=84618;break}case 5:{a=84624;break}default:a=84698}return a|0}function kt(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+96|0;k=n;m=n+80|0;do if(a){if(!e){e=aJ(1,20)|0;c[e+4>>2]=d>>>0>80?d:80}d=c[e>>2]|0;j=c[e+4>>2]|0;if(!d){h=100;d=a;i=aJ(100,j)|0}else{h=d+100|0;i=bJ(c[e+8>>2]|0,O(h,j)|0)|0;WN(i+(O(j,d)|0)|0,0,j*100|0)|0;d=a}while(1){d=lt(k,d,b,m)|0;if(!d)break;a=c[e>>2]|0;f=h<<1;g=O(h,j)|0;if((a|0)==(h|0)){i=bJ(i,O(f,j)|0)|0;WN(i+g|0,0,g|0)|0;a=c[e>>2]|0}else f=h;a=i+(O(a,j)|0)|0;g=k;h=a+80|0;do{c[a>>2]=c[g>>2];a=a+4|0;g=g+4|0}while((a|0)<(h|0));c[e>>2]=(c[e>>2]|0)+1;h=f}if(c[m>>2]|0){m=e+16|0;c[m>>2]=c[m>>2]|1}d=c[e>>2]|0;if(!d){$I(i);$I(e);e=0;break}else{c[e+8>>2]=bJ(i,O(d,j)|0)|0;break}}while(0);l=n;return e|0}function lt(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;j=l;l=l+80|0;h=j+64|0;i=j;c[f>>2]=0;do{g=a[d>>0]|0;d=d+1|0}while((YJ(g)|0)!=0);a:do switch(g|0){case 69:{c[b>>2]=0;d=mt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e>>2];break}case 101:{c[b>>2]=1;d=mt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e>>2];break}case 80:{c[b>>2]=2;d=nt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+4>>2];break}case 112:{c[b>>2]=3;d=nt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+4>>2];break}case 98:{c[b>>2]=4;d=nt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+8>>2];break}case 66:{c[b>>2]=5;d=nt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+8>>2];break}case 99:{d=ot(d,h)|0;if(!d){c[f>>2]=1;d=0;break a}g=pt(c[h>>2]|0,i)|0;c[h>>2]=g;if(!g){c[f>>2]=1;d=0;break a}if(!(c[i>>2]|0)){c[b>>2]=9;c[b+8>>2]=c[i+8>>2];if(!e)break a;c[b+72>>2]=c[e+24>>2];break a}else{c[b>>2]=14;f=b+8|0;g=i;h=f+64|0;do{c[f>>2]=c[g>>2];f=f+4|0;g=g+4|0}while((f|0)<(h|0));if(!e)break a;c[b+72>>2]=c[e+40>>2];break a}}case 67:{d=ot(d,h)|0;if(!d){c[f>>2]=1;d=0;break a}g=pt(c[h>>2]|0,i)|0;c[h>>2]=g;if(!g){c[f>>2]=1;d=0;break a}if(!(c[i>>2]|0)){c[b>>2]=8;c[b+8>>2]=c[i+8>>2];if(!e)break a;c[b+72>>2]=c[e+20>>2];break a}else{c[b>>2]=13;f=b+8|0;g=i;h=f+64|0;do{c[f>>2]=c[g>>2];f=f+4|0;g=g+4|0}while((f|0)<(h|0));if(!e)break a;c[b+72>>2]=c[e+40>>2];break a}}case 76:{c[b>>2]=6;d=nt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+12>>2];break}case 84:{c[b>>2]=7;d=qt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}d=qt(d,b+16|0)|0;if(!d){c[f>>2]=1;d=0;break a}d=rt(d,b+24|0)|0;if(!d){c[f>>2]=1;d=0;break a}d=qt(d,b+32|0)|0;if(!d){c[f>>2]=1;d=0;break a}d=ot(d,b+40|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+16>>2];break}case 70:{c[b>>2]=10;d=qt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}d=ot(d,b+16|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+28>>2];break}case 83:{c[b>>2]=11;d=ot(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+32>>2];break}case 73:{c[b>>2]=12;d=mt(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}d=ot(d,b+40|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+36>>2];break}case 116:{c[b>>2]=15;d=st(d,b+8|0)|0;if(!d){c[f>>2]=1;d=0;break a}if(e)c[b+72>>2]=c[e+44>>2];break}case 0:{d=0;break}default:{c[f>>2]=1;d=0}}while(0);l=j;return d|0}function mt(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0;i=l;l=l+16|0;e=i;h[b>>3]=+uM(a,e);f=c[e>>2]|0;if(((f|0)!=(a|0)?(h[b+8>>3]=+uM(f,e),g=c[e>>2]|0,(f|0)!=(g|0)):0)?(h[b+16>>3]=+uM(g,e),d=c[e>>2]|0,(g|0)!=(d|0)):0){h[b+24>>3]=+uM(d,e);a=c[e>>2]|0;a=(d|0)==(a|0)?0:a}else a=0;l=i;return a|0}function nt(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0;k=l;l=l+16|0;j=k+4|0;g=k;a=tt(a,j)|0;do if(a){d=c[j>>2]|0;i=aJ(d,24)|0;c[b>>2]=d;e=i;f=0;while(1){if((f|0)>=(d|0)){d=9;break}h[e>>3]=+uM(a,g);d=c[g>>2]|0;if((a|0)==(d|0)){d=5;break}h[e+8>>3]=+uM(d,g);a=c[g>>2]|0;if((d|0)==(a|0)){d=7;break}h[e+16>>3]=0.0;e=e+24|0;d=c[b>>2]|0;f=f+1|0}if((d|0)==5){c[j>>2]=f;$I(i);a=0;break}else if((d|0)==7){c[j>>2]=f;$I(i);a=0;break}else if((d|0)==9){c[j>>2]=f;c[b+4>>2]=i;break}}else a=0;while(0);l=k;return a|0}function ot(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+16|0;i=j;b=tt(b,i)|0;f=c[i>>2]|0;do if(!((b|0)==0|(f|0)<1)){while(1){h=a[b>>0]|0;e=h<<24>>24==0;if(e^h<<24>>24!=45)b=b+1|0;else break}if(!e){h=aJ(f+1|0,1)|0;g=h;e=f;while(1){b=b+1|0;if((e|0)<=0){e=9;break}e=a[b>>0]|0;if(!(e<<24>>24)){e=8;break}a[g>>0]=e;e=(c[i>>2]|0)+-1|0;c[i>>2]=e;g=g+1|0}if((e|0)==8){$I(h);b=0;break}else if((e|0)==9){a[g>>0]=0;c[d>>2]=h;break}}else b=0}else b=0;while(0);l=j;return b|0}function pt(b,d){b=b|0;d=d|0;var e=0;e=a[b>>0]|0;switch(e|0){case 91:{b=ut(b+1|0,d)|0;break}case 40:{b=vt(b+1|0,d)|0;break}case 47:case 35:{c[d>>2]=0;c[d+8>>2]=b;break}default:if(!(hK(e)|0))b=0;else{c[d>>2]=0;c[d+8>>2]=b}}return b|0}function qt(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0;f=l;l=l+16|0;d=f;e=+uM(a,d);d=c[d>>2]|0;if((d|0)==(a|0))d=0;else h[b>>3]=e;l=f;return d|0}function rt(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;a=tt(a,e)|0;e=c[e>>2]|0;c[b>>2]=(e|0)<0?0:e|0?2:1;l=d;return a|0}function st(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[b>>2]=ZJ(a,e,10)|0;b=c[e>>2]|0;l=d;return ((b|0)==(a|0)?0:b)|0}function tt(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[b>>2]=CL(a,e,10)|0;b=c[e>>2]|0;l=d;return ((b|0)==(a|0)?0:b)|0}function ut(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;m=o;c[b>>2]=1;n=b+8|0;i=qt(a,n)|0;do if(((((i|0)!=0?(j=qt(i,b+16|0)|0,(j|0)!=0):0)?(e=qt(j,b+24|0)|0,(e|0)!=0):0)?(f=qt(e,b+32|0)|0,(f|0)!=0):0)?(k=b+40|0,d=tt(f,k)|0,(d|0)!=0):0){b=c[k>>2]|0;f=aJ(b,8)|0;e=0;while(1){if((e|0)>=(b|0)){d=13;break}d=qt(d,m)|0;if(!d){d=9;break}g[f+(e<<3)>>2]=+h[m>>3];d=ot(d,f+(e<<3)+4|0)|0;if(!d){d=12;break}e=e+1|0;b=c[k>>2]|0}if((d|0)==9){$I(f);a=0;break}else if((d|0)==12){$I(f);a=0;break}else if((d|0)==13){c[n+36>>2]=f;break}}else a=0;while(0);l=o;return a|0}function vt(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;p=l;l=l+16|0;n=p;c[b>>2]=2;k=qt(a,b+8|0)|0;do if(((((((k|0)!=0?(m=qt(k,b+16|0)|0,(m|0)!=0):0)?(e=qt(m,b+24|0)|0,(e|0)!=0):0)?(f=qt(e,b+32|0)|0,(f|0)!=0):0)?(i=qt(f,b+40|0)|0,(i|0)!=0):0)?(j=qt(i,b+48|0)|0,(j|0)!=0):0)?(o=b+56|0,d=tt(j,o)|0,(d|0)!=0):0){e=c[o>>2]|0;i=aJ(e,8)|0;f=0;while(1){if((f|0)>=(e|0)){d=15;break}d=qt(d,n)|0;if(!d){d=11;break}g[i+(f<<3)>>2]=+h[n>>3];d=ot(d,i+(f<<3)+4|0)|0;if(!d){d=14;break}f=f+1|0;e=c[o>>2]|0}if((d|0)==11){$I(i);a=0;break}else if((d|0)==14){$I(i);a=0;break}else if((d|0)==15){c[b+60>>2]=i;break}}else a=0;while(0);l=p;return a|0}function wt(a,b,c){a=a|0;b=b|0;c=c|0;return kt(a,b,c,0)|0}function xt(a){a=a|0;return wt(a,0,0)|0}function yt(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;e=c[a+12>>2]|0;if(a|0){f=c[a+8>>2]|0;g=a+4|0;h=(e|0)==0;b=0;while(1){if((b|0)>=(c[a>>2]|0))break;d=f+(O(c[g>>2]|0,b)|0)|0;if(!h)gb[e&127](d);zt(d);b=b+1|0}$I(f);$I(a)}return}function zt(a){a=a|0;switch(c[a>>2]|0){case 3:case 2:{$I(c[a+8+4>>2]|0);break}case 5:case 4:{$I(c[a+8+4>>2]|0);break}case 6:{$I(c[a+8+4>>2]|0);break}case 7:{$I(c[a+40>>2]|0);break}case 9:case 8:{$I(c[a+8>>2]|0);break}case 14:case 13:{At(a+8|0);break}case 10:{$I(c[a+16>>2]|0);break}case 11:{$I(c[a+8>>2]|0);break}case 12:{$I(c[a+40>>2]|0);break}default:{}}return}function At(a){a=a|0;var b=0,d=0,e=0;switch(c[a>>2]|0){case 1:{e=a+40|0;b=a+8+36|0;a=0;while(1){d=c[b>>2]|0;if((a|0)>=(c[e>>2]|0))break;$I(c[d+(a<<3)+4>>2]|0);a=a+1|0}$I(d);break}case 2:{e=a+56|0;d=a+60|0;a=0;while(1){b=c[d>>2]|0;if((a|0)>=(c[e>>2]|0))break;$I(c[b+(a<<3)+4>>2]|0);a=a+1|0}$I(b);break}default:{}}return}function Bt(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;k=o+4|0;n=o;c[d>>2]=0;c[e>>2]=(rn(so(b)|0)|0)!=0&1;f=c[42229]|0;a:do if(f|0?(h=Km(b,f)|0,i=a[h>>0]|0,i<<24>>24):0){f=19444;while(1){g=c[f>>2]|0;if(!g)break a;if(i<<24>>24==(a[g>>0]|0)?(yJ(h,g)|0)==0:0)break;f=f+12|0}c[d>>2]=c[f+4>>2];c[e>>2]=c[f+8>>2]}while(0);f=c[42240]|0;if((f|0?(c[e>>2]|0)==1:0)?(j=Km(b,f)|0,a[j>>0]|0):0)Ct(j,e);f=c[42241]|0;if((f|0?(c[d>>2]|0)==1:0)?(m=Km(b,f)|0,a[m>>0]|0):0)Ct(m,d);if(a[(c[b+16>>2]|0)+153>>0]|0){j=b+-48|0;i=so(c[((c[b>>2]&3|0)==2?b:j)+40>>2]|0)|0;m=c[b>>2]&3;Bt(bn(i,c[((m|0)==2?b:j)+40>>2]|0,c[((m|0)==3?b:b+48|0)+40>>2]|0,0,0)|0,k,n);c[e>>2]=c[k>>2]|c[e>>2];c[d>>2]=c[n>>2]|c[d>>2]}l=o;return}function Ct(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;m=o;k=o+4|0;j=0;e=0;a:while(1){c[d>>2]=e;g=(j|0)<4;h=(j|0)==3;i=(j|0)==0;while(1){if(!(g&(a[b>>0]|0)!=0))break a;c[k>>2]=0;f=Dt(b,k)|0;e=c[k>>2]|0;if(!e){n=5;break a}b=(e|0)==8;if(!(h&b)){if(!(i&b))break;if(a[f>>0]|0)break}c[k>>2]=0;b=f}e=c[d>>2]|e<<(j<<3);j=j+1|0;b=f}if((n|0)==5){c[m>>2]=b;$l(0,84713,m)|0}l=o;return}function Dt(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=l;l=l+16|0;e=f;c[e>>2]=0;d=Et(a,19504,e)|0;if((d|0)==(a|0)){while(1){d=Et(a,19520,e)|0;if((a|0)==(d|0))break;else a=d}d=Et(a,19568,e)|0}a=c[e>>2]|0;if((a|0)!=0&(a&15|0)==0){a=a|1;c[e>>2]=a}c[b>>2]=c[b>>2]|a;l=f;return d|0}function Et(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;while(1){e=c[b>>2]|0;if(!e)break;f=sJ(e)|0;if(!(WJ(a,e,f)|0)){g=4;break}b=b+8|0}if((g|0)==4){c[d>>2]=c[d>>2]|c[b+4>>2];a=a+f|0}return a|0}function Ft(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0,g=0,i=0;g=0;d=0.0;while(1){if((g|0)==4)break;f=b>>(g<<3)&15;e=1336;while(1){if(!(c[e+16>>2]|0))break;if((f|0)==(c[e>>2]|0)){i=6;break}e=e+24|0}if((i|0)==6){i=0;d=+h[e+8>>3]+d}g=g+1|0}return +(d*10.0*+FA(a,c[42233]|0,1.0,0.0))}function Gt(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=+f;g=g|0;var i=0.0,j=0.0,k=0.0,m=0,n=0.0,o=0,p=0;p=l;l=l+96|0;m=p+80|0;o=p;k=f>4.0?f*.0875:.35;i=+h[d+8>>3];n=i*k;j=+h[d>>3];k=j*k;e=+h[b>>3];j=e+j;h[m>>3]=j;f=+h[b+8>>3];i=i+f;h[m+8>>3]=i;d=o+64|0;if(!(g&32)){c[d>>2]=c[m>>2];c[d+4>>2]=c[m+4>>2];c[d+8>>2]=c[m+8>>2];c[d+12>>2]=c[m+12>>2];c[o>>2]=c[m>>2];c[o+4>>2]=c[m+4>>2];c[o+8>>2]=c[m+8>>2];c[o+12>>2]=c[m+12>>2];m=o+32|0;c[m>>2]=c[b>>2];c[m+4>>2]=c[b+4>>2];c[m+8>>2]=c[b+8>>2];c[m+12>>2]=c[b+12>>2];f=i;e=j}else{c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];c[o>>2]=c[b>>2];c[o+4>>2]=c[b+4>>2];c[o+8>>2]=c[b+8>>2];c[o+12>>2]=c[b+12>>2];b=o+32|0;c[b>>2]=c[m>>2];c[b+4>>2]=c[m+4>>2];c[b+8>>2]=c[m+8>>2];c[b+12>>2]=c[m+12>>2]}h[o+16>>3]=e+n;h[o+24>>3]=f-k;h[o+48>>3]=e-n;h[o+56>>3]=f+k;do if(!(g&64))if(!(g&128)){ID(a,o+16|0,3,g>>>4&1^1);break}else{ID(a,o+32|0,3,g>>>4&1^1);break}else ID(a,o,3,g>>>4&1^1);while(0);l=p;return}function Ht(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=+f;g=g|0;var i=0.0,j=0.0,k=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0,x=0,y=0;x=l;l=l+160|0;n=x+144|0;w=x;q=e*4.0;y=(g&32|0)==0;q=!(q1.0)|y?0.0:(f+-1.0)*.05/e;u=+h[d+8>>3];r=-u;v=q*r;t=+h[d>>3];q=t*q;r=s*r;s=t*s;p=+h[b>>3];e=p+t;h[n>>3]=e;o=+h[b+8>>3];f=u+o;h[n+8>>3]=f;t=t*.5+p;u=u*.5+o;d=w+128|0;if(y){c[d>>2]=c[n>>2];c[d+4>>2]=c[n+4>>2];c[d+8>>2]=c[n+8>>2];c[d+12>>2]=c[n+12>>2];c[w>>2]=c[n>>2];c[w+4>>2]=c[n+4>>2];c[w+8>>2]=c[n+8>>2];c[w+12>>2]=c[n+12>>2];y=w+64|0;c[y>>2]=c[b>>2];c[y+4>>2]=c[b+4>>2];c[y+8>>2]=c[b+8>>2];c[y+12>>2]=c[b+12>>2];i=o;j=p;k=o;m=p;f=o;e=p}else{c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];c[w>>2]=c[b>>2];c[w+4>>2]=c[b+4>>2];c[w+8>>2]=c[b+8>>2];c[w+12>>2]=c[b+12>>2];y=w+64|0;c[y>>2]=c[n>>2];c[y+4>>2]=c[n+4>>2];c[y+8>>2]=c[n+8>>2];c[y+12>>2]=c[n+12>>2];i=f+s;j=e+r;k=f-s;m=e-r}h[w+16>>3]=e-v;h[w+24>>3]=f-q;h[w+32>>3]=t-r;h[w+40>>3]=u-s;h[w+48>>3]=m;h[w+56>>3]=k;h[w+80>>3]=j;h[w+88>>3]=i;h[w+96>>3]=t+r;h[w+104>>3]=u+s;h[w+112>>3]=e+v;h[w+120>>3]=f+q;do if(!(g&64))if(!(g&128)){ID(a,w,9,1);break}else{ID(a,w+48|0,6,1);break}else ID(a,w,6,1);while(0);l=x;return}function It(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=+f;g=g|0;var i=0.0,j=0.0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0;q=l;l=l+64|0;p=q;t=+h[d+8>>3];s=+h[d>>3];k=+h[b>>3];e=k+s;m=+h[b+8>>3];f=m+t;i=k+s*.2;j=m+t*.2;k=k+s*.6;m=m+t*.6;h[p>>3]=i-t;h[p+8>>3]=j+s;n=p+16|0;h[n>>3]=i+t;o=p+24|0;h[o>>3]=j-s;h[p+32>>3]=k+t;h[p+40>>3]=m-s;h[p+48>>3]=k-t;h[p+56>>3]=m+s;if(!(g&64)){if(g&128|0){d=2;g=1;r=3}}else{d=3;g=0;r=3}if((r|0)==3){h[p+(g<<4)>>3]=i;h[p+(g<<4)+8>>3]=j;h[p+(d<<4)>>3]=k;h[p+(d<<4)+8>>3]=m}ID(a,p,4,1);c[p>>2]=c[b>>2];c[p+4>>2]=c[b+4>>2];c[p+8>>2]=c[b+8>>2];c[p+12>>2]=c[b+12>>2];h[n>>3]=e;h[o>>3]=f;LD(a,p,2);l=q;return}function Jt(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=+f;g=g|0;var i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0;o=l;l=l+64|0;n=o;j=+h[d+8>>3];r=j*-.4;i=+h[d>>3];q=i*.4;t=+h[b>>3];e=t+i*.8;s=+h[b+8>>3];f=s+j*.8;i=t+i;j=s+j;h[n>>3]=t+r;k=n+8|0;h[k>>3]=s+q;d=n+16|0;h[d>>3]=t-r;m=n+24|0;h[m>>3]=s-q;h[n+32>>3]=e-r;h[n+40>>3]=f-q;h[n+48>>3]=e+r;h[n+56>>3]=f+q;if(!(g&64)){if(g&128|0){c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];d=2;p=5}}else{c[n>>2]=c[b>>2];c[n+4>>2]=c[b+4>>2];c[n+8>>2]=c[b+8>>2];c[n+12>>2]=c[b+12>>2];d=3;p=5}if((p|0)==5){h[n+(d<<4)>>3]=e;h[n+(d<<4)+8>>3]=f}ID(a,n,4,g>>>4&1^1);h[n>>3]=e;h[k>>3]=f;h[n+16>>3]=i;h[m>>3]=j;LD(a,n,2);l=o;return}function Kt(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=+f;g=g|0;var i=0,j=0,k=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0;j=l;l=l+80|0;i=j;n=+h[d+8>>3];k=n*-.3333333333333333;p=+h[d>>3];f=p*.3333333333333333;q=+h[b>>3];m=q+p*.5;o=+h[b+8>>3];e=o+n*.5;d=i+64|0;h[i+64>>3]=q+p;h[i+72>>3]=o+n;c[i>>2]=c[d>>2];c[i+4>>2]=c[d+4>>2];c[i+8>>2]=c[d+8>>2];c[i+12>>2]=c[d+12>>2];h[i+16>>3]=m+k;h[i+24>>3]=e+f;d=i+32|0;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];h[i+48>>3]=m-k;h[i+56>>3]=e-f;do if(!(g&64)){d=g>>>4&1^1;if(!(g&128)){ID(a,i,4,d);break}else{ID(a,i,3,d);break}}else ID(a,d,3,g>>>4&1^1);while(0);l=j;return}function Lt(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=+d;e=+e;f=f|0;var g=0,i=0,j=0.0,k=0.0,m=0.0;g=l;l=l+32|0;i=g;k=+h[c>>3];e=+h[c+8>>3];d=+C(+(e*e+k*k))*.5;m=+h[b>>3];k=k*.5;h[i>>3]=m+k-d;j=+h[b+8>>3];e=e*.5;h[i+8>>3]=j-d+e;h[i+16>>3]=m+d+k;h[i+24>>3]=j+d+e;HD(a,i,2,f>>>4&1^1);l=g;return}function Mt(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=+f;g=g|0;var i=0.0,j=0.0,k=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0;t=l;l=l+112|0;q=t+48|0;r=t+16|0;s=t;n=f>4.0?f*.125:.5;p=+h[b>>3];o=+h[d>>3];i=+h[b+8>>3];m=+h[d+8>>3];e=m*n;f=o*n;c[r>>2]=c[b>>2];c[r+4>>2]=c[b+4>>2];c[r+8>>2]=c[b+8>>2];c[r+12>>2]=c[b+12>>2];h[r+16>>3]=o+p;h[r+24>>3]=m+i;h[q>>3]=n*(o-m)+p;j=n*(m+o);k=j+i;h[q+8>>3]=k;h[q+48>>3]=j+p;i=n*(m-o)+i;h[q+56>>3]=i;o=e*-.95;m=o+f+p;n=f*1.3333333333333333;if(!(g&32)){e=e*1.3333333333333333;j=f*-.33333333333333326;i=i-e;f=k-e;e=m-n}else{e=e*1.3333333333333333;j=f*2.333333333333333;i=i+e;f=k+e;e=m+n}h[q+16>>3]=e;h[q+24>>3]=f;h[q+32>>3]=j-o+p;h[q+40>>3]=i;LD(a,r,2);if(!(g&64)){if(g&128|0)QA(s,q,3,.5,q,0)}else QA(s,q,3,.5,0,q);KD(a,q,4,0,0,0);l=t;return}function Nt(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=+f;g=g|0;var i=0;g=l;l=l+32|0;i=g;e=+h[d>>3]+ +h[b>>3];f=+h[d+8>>3]+ +h[b+8>>3];c[i>>2]=c[b>>2];c[i+4>>2]=c[b+4>>2];c[i+8>>2]=c[b+8>>2];c[i+12>>2]=c[b+12>>2];h[i+16>>3]=e;h[i+24>>3]=f;LD(a,i,2);l=g;return}function Ot(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0.0,j=0,k=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0,s=0;n=l;l=l+80|0;j=n+72|0;k=n+8|0;m=n;i=+Ft(a,g);i=i*i;h[m>>3]=i;c[f+12>>2]=g;g=f+32|0;a=e+3|0;f=b+(a<<4)|0;c[g>>2]=c[f>>2];c[g+4>>2]=c[f+4>>2];c[g+8>>2]=c[f+8>>2];c[g+12>>2]=c[f+12>>2];if((e|0)>(d|0)?(o=+h[b+(e<<4)>>3]-+h[f>>3],p=+h[b+(e<<4)+8>>3]-+h[b+(a<<4)+8>>3],p*p+o*o>2]=c[r>>2];c[s+4>>2]=c[r+4>>2];c[s+8>>2]=c[r+8>>2];c[s+12>>2]=c[r+12>>2];q=k+32|0;a=b+(e+1<<4)|0;c[q>>2]=c[a>>2];c[q+4>>2]=c[a+4>>2];c[q+8>>2]=c[a+8>>2];c[q+12>>2]=c[a+12>>2];f=k+16|0;d=b+(e+2<<4)|0;c[f>>2]=c[d>>2];c[f+4>>2]=c[d+4>>2];c[f+8>>2]=c[d+8>>2];c[f+12>>2]=c[d+12>>2];c[k>>2]=c[g>>2];c[k+4>>2]=c[g+4>>2];c[k+8>>2]=c[g+8>>2];c[k+12>>2]=c[g+12>>2];c[j>>2]=k;c[j+4>>2]=m;Gz(j,26,k,1);c[r>>2]=c[s>>2];c[r+4>>2]=c[s+4>>2];c[r+8>>2]=c[s+8>>2];c[r+12>>2]=c[s+12>>2];c[a>>2]=c[q>>2];c[a+4>>2]=c[q+4>>2];c[a+8>>2]=c[q+8>>2];c[a+12>>2]=c[q+12>>2];c[d>>2]=c[f>>2];c[d+4>>2]=c[f+4>>2];c[d+8>>2]=c[f+8>>2];c[d+12>>2]=c[f+12>>2];m=b+(e+3<<4)|0;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];c[m+8>>2]=c[k+8>>2];c[m+12>>2]=c[k+12>>2];l=n;return e|0}function Pt(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0;f=c[a>>2]|0;d=+h[b>>3]-+h[f>>3];e=+h[b+8>>3]-+h[f+8>>3];return e*e+d*d<=+h[c[a+4>>2]>>3]|0}function Qt(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0.0,k=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0,s=0;o=l;l=l+80|0;k=o+72|0;m=o+8|0;n=o;j=+Ft(a,g);j=j*j;h[n>>3]=j;c[f+8>>2]=g;f=f+16|0;a=b+(d<<4)|0;c[f>>2]=c[a>>2];c[f+4>>2]=c[a+4>>2];c[f+8>>2]=c[a+8>>2];c[f+12>>2]=c[a+12>>2];if(!((e|0)>(d|0)?(i=d+3|0,p=+h[a>>3]-+h[b+(i<<4)>>3],q=+h[b+(d<<4)+8>>3]-+h[b+(i<<4)+8>>3],q*q+p*p>2]=c[e>>2];c[m+4>>2]=c[e+4>>2];c[m+8>>2]=c[e+8>>2];c[m+12>>2]=c[e+12>>2];g=m+16|0;d=b+(i+2<<4)|0;c[g>>2]=c[d>>2];c[g+4>>2]=c[d+4>>2];c[g+8>>2]=c[d+8>>2];c[g+12>>2]=c[d+12>>2];r=m+32|0;a=b+(i+1<<4)|0;c[r>>2]=c[a>>2];c[r+4>>2]=c[a+4>>2];c[r+8>>2]=c[a+8>>2];c[r+12>>2]=c[a+12>>2];s=m+48|0;c[s>>2]=c[f>>2];c[s+4>>2]=c[f+4>>2];c[s+8>>2]=c[f+8>>2];c[s+12>>2]=c[f+12>>2];c[k>>2]=s;c[k+4>>2]=n;Gz(k,26,m,0);n=b+(i<<4)|0;c[n>>2]=c[s>>2];c[n+4>>2]=c[s+4>>2];c[n+8>>2]=c[s+8>>2];c[n+12>>2]=c[s+12>>2];c[a>>2]=c[r>>2];c[a+4>>2]=c[r+4>>2];c[a+8>>2]=c[r+8>>2];c[a+12>>2]=c[r+12>>2];c[d>>2]=c[g>>2];c[d+4>>2]=c[g+4>>2];c[d+8>>2]=c[g+8>>2];c[d+12>>2]=c[g+12>>2];c[e>>2]=c[m>>2];c[e+4>>2]=c[m+4>>2];c[e+8>>2]=c[m+8>>2];c[e+12>>2]=c[m+12>>2];l=o;return i|0}function Rt(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0.0,k=0.0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0,v=0,w=0;u=(g|0)!=0;l=(i|0)!=0;if(!((e|0)==(d|0)&(u&l))){if(l){j=+Ft(a,i);k=+h[b+(e<<4)>>3];p=+h[b+(e<<4)+8>>3];l=e+3|0;r=b+(l<<4)|0;n=+h[r>>3];l=b+(l<<4)+8|0;o=+h[l>>3];t=k-n;s=p-o;t=+C(+(s*s+t*t))*.9;j=j>=t?t:j;if(p==o){m=(k>3]=k;h[b+(w<<4)+8>>3]=p;e=b+(e+2<<4)|0;h[r>>3]=m;h[l>>3]=j;c[e>>2]=c[r>>2];c[e+4>>2]=c[r+4>>2];c[e+8>>2]=c[r+8>>2];c[e+12>>2]=c[r+12>>2];c[f+12>>2]=i;h[f+32>>3]=n;h[f+40>>3]=o}if(u){m=+Ft(a,g);l=b+(d<<4)|0;k=+h[l>>3];j=+h[b+(d<<4)+8>>3];w=d+3|0;o=+h[b+(w<<4)>>3];p=+h[b+(w<<4)+8>>3];t=k-o;s=j-p;t=+C(+(s*s+t*t))*.9;m=m>=t?t:m;if(j==p){n=(k>3]=n;h[b+(w<<4)+8>>3]=m;c[l>>2]=c[v>>2];c[l+4>>2]=c[v+4>>2];c[l+8>>2]=c[v+8>>2];c[l+12>>2]=c[v+12>>2];v=d+2|0;h[b+(v<<4)>>3]=o;h[b+(v<<4)+8>>3]=p;v=16}}else{r=b+(e<<4)|0;s=+h[r>>3];t=+h[b+(e<<4)+8>>3];l=e+3|0;u=b+(l<<4)|0;k=+h[u>>3];l=b+(l<<4)+8|0;j=+h[l>>3];m=+Ft(a,g);q=+Ft(a,i);n=s-k;p=t-j;n=+C(+(p*p+n*n));w=!(q+m>=n);n=n*.3333333333333333;m=w?m:n;n=w?q:n;if(t==j){w=s>3]=q;h[b+(w<<4)+8>>3]=o;c[r>>2]=c[v>>2];c[r+4>>2]=c[v+4>>2];c[r+8>>2]=c[v+8>>2];c[r+12>>2]=c[v+12>>2];v=b+(e+2<<4)|0;h[u>>3]=p;h[l>>3]=m;c[v>>2]=c[u>>2];c[v+4>>2]=c[u+4>>2];c[v+8>>2]=c[u+8>>2];c[v+12>>2]=c[u+12>>2];c[f+12>>2]=i;h[f+32>>3]=s;h[f+40>>3]=t;v=16}if((v|0)==16){c[f+8>>2]=g;h[f+16>>3]=k;h[f+24>>3]=j}return}function St(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=+d;e=e|0;var f=0.0,g=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0.0;n=+h[b>>3];k=+h[c>>3]-n;o=+h[b+8>>3];l=+h[c+8>>3]-o;j=d*10.0/(+C(+(k*k+l*l))+.0001);k=j*((k>=0.0?.0001:-.0001)+k);j=((l>=0.0?.0001:-.0001)+l)*j;l=k*.5;m=j*.5;i=n-m;f=o-l;n=m+n;l=o+l;o=i+k;m=f+j;k=n+k;j=l+j;g=o>k?o:k;g=n>g?n:g;d=m>j?m:j;d=l>d?l:d;k=o>3]=i>3]=f>3]=i>g?i:g;h[a+24>>3]=f>d?f:d;return}function Tt(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=+f;g=+g;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0,t=0.0;q=l;l=l+48|0;m=q+32|0;k=q+16|0;p=q;n=(c[a+16>>2]|0)+12|0;o=c[n>>2]|0;c[n>>2]=b;GD(a,c[(c[a>>2]|0)+336>>2]|0);PD(a,g);t=+h[e>>3]-+h[d>>3];b=e+8|0;s=+h[b>>3]-+h[d+8>>3];r=10.0/(+C(+(t*t+s*s))+.0001);h[e>>3]=r*((t>=0.0?.0001:-.0001)+t);h[b>>3]=((s>=0.0?.0001:-.0001)+s)*r;b=0;while(1){if((b|0)>=4)break;j=i>>(b<<3)&255;if(!j)break;c[k>>2]=c[d>>2];c[k+4>>2]=c[d+4>>2];c[k+8>>2]=c[d+8>>2];c[k+12>>2]=c[d+12>>2];c[m>>2]=c[e>>2];c[m+4>>2]=c[e+4>>2];c[m+8>>2]=c[e+8>>2];c[m+12>>2]=c[e+12>>2];Ut(p,a,k,m,f,g,j);c[d>>2]=c[p>>2];c[d+4>>2]=c[p+4>>2];c[d+8>>2]=c[p+8>>2];c[d+12>>2]=c[p+12>>2];b=b+1|0}c[n>>2]=o;l=q;return}function Ut(a,b,d,e,f,g,i){a=a|0;b=b|0;d=d|0;e=e|0;f=+f;g=+g;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0;q=l;l=l+32|0;m=q+16|0;k=q;n=i&15;j=1336;while(1){o=c[j>>2]|0;if(!o)break;if((n|0)==(o|0)){p=4;break}j=j+24|0}if((p|0)==4){r=+h[j+8>>3]*f;h[e>>3]=r*+h[e>>3];o=e+8|0;h[o>>3]=r*+h[o>>3];p=c[j+16>>2]|0;c[k>>2]=c[d>>2];c[k+4>>2]=c[d+4>>2];c[k+8>>2]=c[d+8>>2];c[k+12>>2]=c[d+12>>2];c[m>>2]=c[e>>2];c[m+4>>2]=c[e+4>>2];c[m+8>>2]=c[e+8>>2];c[m+12>>2]=c[e+12>>2];jb[p&15](b,k,m,f,g,i);h[d>>3]=+h[e>>3]+ +h[d>>3];p=d+8|0;h[p>>3]=+h[o>>3]+ +h[p>>3]};c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];l=q;return}function Vt(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;g=i+8|0;f=i;d=Jm(b,84815)|0;if((d|0)!=0?(a[d>>0]|0)!=0:0){e=d;h=5}else{d=Jm(b,84827)|0;if((d|0)!=0?(a[d>>0]|0)!=0:0){e=d;h=5}else d=0}if((h|0)==5){d=wt(e,0,120)|0;if(!d){c[f>>2]=En(b)|0;$l(0,84834,f)|0;c[g>>2]=e;$l(3,84887,g)|0}}l=i;return d|0}function Wt(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;g=l;l=l+16|0;f=ww(304)|0;if(!f)$l(1,84895,g)|0;e=a+16|0;a=c[e>>2]|0;c[f>>2]=a;c[e>>2]=f;if(!a){c[f+144>>2]=3;c[f+148>>2]=0;h[f+152>>3]=1.0}else{b=f+16|0;d=a+16|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));b=f+56|0;d=a+56|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));c[f+144>>2]=c[a+144>>2];c[f+148>>2]=c[a+148>>2];h[f+152>>3]=+h[a+152>>3];c[f+136>>2]=c[a+136>>2];b=f+96|0;d=a+96|0;e=b+40|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0))}l=g;return f|0}function Xt(a){a=a|0;var b=0;a=a+16|0;b=c[a>>2]|0;if(!b)ma(84921,84925,117,84932);else{$I(c[b+212>>2]|0);$I(c[b+208>>2]|0);$I(c[b+216>>2]|0);$I(c[b+220>>2]|0);$I(c[b+224>>2]|0);$I(c[b+228>>2]|0);$I(c[b+232>>2]|0);$I(c[b+236>>2]|0);$I(c[b+240>>2]|0);$I(c[b+244>>2]|0);$I(c[b+248>>2]|0);$I(c[b+252>>2]|0);$I(c[b+256>>2]|0);$I(c[b+272>>2]|0);$I(c[b+284>>2]|0);$I(c[b+280>>2]|0);c[a>>2]=c[b>>2];$I(b);return}}function Yt(d,e,f,g,h,i,j){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;var k=0,l=0;l=c[d+16>>2]|0;k=c[d+152>>2]|0;if((e|0)!=0&(k&32768|0)!=0)c[l+192>>2]=e;if(((k&65536|0)!=0?(c[l+212>>2]=rw(i,j)|0,(f|0)!=0):0)?(a[f>>0]|0)!=0:0){c[l+208>>2]=rw(f,j)|0;d=1}else d=0;do if(k&4194304){if(g|0?a[g>>0]|0:0){c[l+228>>2]=rw(g,j)|0;d=l+260|0;b[d>>1]=b[d>>1]|1;d=1;break}e=c[l+192>>2]|0;if(e){c[l+228>>2]=HL(e)|0;d=1}}while(0);if((h|0)!=0&(k&8388608|0)!=0?(a[h>>0]|0)!=0:0){c[l+244>>2]=rw(h,j)|0;d=1}return d|0}function Zt(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;j=l;l=l+80|0;i=j;h=j+8|0;g=c[(c[b>>2]|0)+168>>2]|0;f=c[(c[(c[g+16>>2]|0)+8>>2]|0)+92>>2]|0;_t(b,e);b=Jm(d,86799)|0;if((b|0)!=0?(a[b>>0]|0)!=0:0){gm(e,b)|0;f=e+4|0;b=c[f>>2]|0;if(b>>>0>=(c[e+8>>2]|0)>>>0){em(e,1)|0;b=c[f>>2]|0}a[b>>0]=0;b=c[e>>2]|0;c[f>>2]=b}else{if((g|0)!=(d|0)&(f|0)!=0){gm(e,f)|0;f=e+4|0;b=c[f>>2]|0;if(b>>>0>=(c[e+8>>2]|0)>>>0){em(e,1)|0;b=c[f>>2]|0}c[f>>2]=b+1;a[b>>0]=95}switch(Do(d)|0){case 0:{f=(g|0)==(d|0)?96286:84946;b=(c[d>>2]|0)>>>4;break}case 1:{f=96273;b=(c[d>>2]|0)>>>4;break}case 2:{f=96237;b=(c[d>>2]|0)>>>4;break}default:{f=0;b=0}}gm(e,f)|0;c[i>>2]=b;qL(h,84952,i)|0;gm(e,h)|0;f=e+4|0;b=c[f>>2]|0;if(b>>>0>=(c[e+8>>2]|0)>>>0){em(e,1)|0;b=c[f>>2]|0}a[b>>0]=0;b=c[e>>2]|0;c[f>>2]=b}l=j;return b|0}function _t(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=l;l=l+144|0;h=i;g=i+8|0;e=c[b+160>>2]|0;if((e|0)>1?c[b+152>>2]&64|0:0){gm(d,c[(c[(c[b>>2]|0)+308>>2]|0)+(e<<2)>>2]|0)|0;f=d+4|0;e=c[f>>2]|0;if(e>>>0>=(c[d+8>>2]|0)>>>0){em(d,1)|0;e=c[f>>2]|0}c[f>>2]=e+1;a[e>>0]=95}f=c[b+196>>2]|0;e=c[b+200>>2]|0;if((f|0)>0|(e|0)>0){c[h>>2]=f;c[h+4>>2]=e;qL(g,84956,h)|0;gm(d,g)|0}l=i;return}function $t(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0,i=0.0,j=0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0.0,s=0;s=l;l=l+48|0;p=s+16|0;f=s+32|0;q=s;r=+h[(c[a+16>>2]|0)+152>>3];o=au(d,0,f)|0;if((o+-1|0)>>>0>=2){e=+h[b+16>>3];k=(e+ +h[b>>3])*.5;h[q>>3]=k;i=+h[b+24>>3];m=(i+ +h[b+8>>3])*.5;h[q+8>>3]=m;k=e-k;m=i-m;n=r>.5;if(n)PD(a,.5);j=c[f>>2]|0;i=0.0;f=c[j+8>>2]|0;while(1){d=c[f>>2]|0;if(!d)break;b=f+4|0;if(+g[b>>2]==0.0)e=i;else{ED(a,d);if(!(c[f+12>>2]|0))e=6.283185307179586;else e=+g[b>>2]*6.283185307179586+i;c[p>>2]=c[q>>2];c[p+4>>2]=c[q+4>>2];c[p+8>>2]=c[q+8>>2];c[p+12>>2]=c[q+12>>2];b=$E(p,k,m,i,e)|0;KD(a,c[b>>2]|0,c[b+4>>2]|0,0,0,1);YI(b)}i=e;f=f+12|0}if(n)PD(a,r);bu(j)}l=s;return o|0}function au(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,h=0,i=0,j=0.0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0;r=l;l=l+16|0;o=r+8|0;n=r;q=ww(12)|0;i=HL(b)|0;a:do if(!d){d=1;f=i;while(1){switch(a[f>>0]|0){case 0:break a;case 58:{d=d+1|0;break}default:{}}f=f+1|0}}while(0);c[q+4>>2]=i;p=ww((d*12|0)+12|0)|0;c[q+8>>2]=p;m=1.0;h=0;d=0;f=i;while(1){f=EL(f,93017)|0;if(!f){f=20;break}j=+cu(f);if(!(j>=0.0)){f=17;break}k=j-m;if(k>0.0)if((c[4920]|0)!=0?!(k<1.0e-05&k>-1.0e-05):0){c[n>>2]=b;$l(0,84967,n)|0;c[4920]=0;j=m;d=3}else j=m;k=m-j;if(j>0.0)a[p+(h*12|0)+8>>0]=1;if(a[f>>0]|0)c[p+(h*12|0)>>2]=f;f=h+1|0;g[p+(h*12|0)+4>>2]=j;if(k<1.0e-05&k>-1.0e-05){h=f;f=30;break}else{m=k;h=f;f=0}}b:do if((f|0)==17){if(!(c[4920]|0))d=1;else{c[o>>2]=b;$l(1,85002,o)|0;c[4920]=0;d=2}bu(q)}else if((f|0)==20)if(m>0.0){f=0;i=0;while(1){if((f|0)>=(h|0))break;o=i+(+g[p+(f*12|0)+4>>2]==0.0&1)|0;f=f+1|0;i=o}if((i|0)<=0){f=p+((h+-1|0)*12|0)+4|0;g[f>>2]=m+ +g[f>>2];f=30;break}j=m/+(i|0);f=0;while(1){if((f|0)>=(h|0)){f=30;break b}i=p+(f*12|0)+4|0;if(+g[i>>2]==0.0)g[i>>2]=j;f=f+1|0}}else f=30;while(0);if((f|0)==30){while(1){f=h+-1|0;if((h|0)<=0)break;if(+g[p+(f*12|0)+4>>2]>0.0)break;else h=f}c[p+(h*12|0)>>2]=0;c[q>>2]=h;c[e>>2]=q}l=r;return d|0}function bu(a){a=a|0;$I(c[a+4>>2]|0);$I(c[a+8>>2]|0);$I(a);return}function cu(b){b=b|0;var d=0.0,e=0,f=0,g=0;f=l;l=l+16|0;e=f;b=XJ(b,59)|0;if(!b)d=0.0;else{g=b+1|0;a[b>>0]=0;d=+uM(g,e);d=(d>=0.0?(c[e>>2]|0)!=(g|0):0)?d:-1.0}l=f;return +d}function du(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,i=0,j=0,k=0,m=0.0,n=0.0,o=0,p=0,q=0,r=0,s=0.0,t=0;t=l;l=l+80|0;i=t+64|0;r=t;s=+h[(c[a+16>>2]|0)+152>>3];q=au(d,0,i)|0;if((q+-1|0)>>>0>=2){if(!e){c[r>>2]=c[b>>2];c[r+4>>2]=c[b+4>>2];c[r+8>>2]=c[b+8>>2];c[r+12>>2]=c[b+12>>2];p=r+16|0;o=b+16|0;c[p>>2]=c[o>>2];c[p+4>>2]=c[o+4>>2];c[p+8>>2]=c[o+8>>2];c[p+12>>2]=c[o+12>>2];p=r+32|0;o=b+32|0;c[p>>2]=c[o>>2];c[p+4>>2]=c[o+4>>2];c[p+8>>2]=c[o+8>>2];c[p+12>>2]=c[o+12>>2];p=r+48|0;o=b+48|0;c[p>>2]=c[o>>2];c[p+4>>2]=c[o+4>>2];c[p+8>>2]=c[o+8>>2];c[p+12>>2]=c[o+12>>2]}else{p=b+32|0;c[r>>2]=c[p>>2];c[r+4>>2]=c[p+4>>2];c[r+8>>2]=c[p+8>>2];c[r+12>>2]=c[p+12>>2];p=r+16|0;o=b+48|0;c[p>>2]=c[o>>2];c[p+4>>2]=c[o+4>>2];c[p+8>>2]=c[o+8>>2];c[p+12>>2]=c[o+12>>2];p=r+32|0;c[p>>2]=c[b>>2];c[p+4>>2]=c[b+4>>2];c[p+8>>2]=c[b+8>>2];c[p+12>>2]=c[b+12>>2];p=r+48|0;o=b+16|0;c[p>>2]=c[o>>2];c[p+4>>2]=c[o+4>>2];c[p+8>>2]=c[o+8>>2];c[p+12>>2]=c[o+12>>2]}k=r+16|0;m=+h[k>>3];f=+h[r>>3];n=m-f;o=r+32|0;h[o>>3]=f;h[k>>3]=f;p=s>.5;if(p)PD(a,.5);i=c[i>>2]|0;j=r+48|0;e=c[i+8>>2]|0;while(1){d=c[e>>2]|0;if(!d)break;b=e+4|0;if(!(+g[b>>2]==0.0)){ED(a,d);if(!(c[e+12>>2]|0))f=m;else f=n*+g[b>>2]+ +h[r>>3];h[o>>3]=f;h[k>>3]=f;ID(a,r,4,1);f=+h[k>>3];h[j>>3]=f;h[r>>3]=f}e=e+12|0}if(p)PD(a,s);bu(i)}l=t;return q|0}function eu(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=c[a+16>>2]|0;e=c[a+152>>2]|0;if(e&4259840|0){f=e&131072;g=f>>>16^2;c[d+264>>2]=g;h=d+268|0;c[h>>2]=g+2;g=d+272|0;$I(c[g>>2]|0);d=ww(c[h>>2]<<4)|0;c[g>>2]=d;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];g=d+16|0;b=b+16|0;c[g>>2]=c[b>>2];c[g+4>>2]=c[b+4>>2];c[g+8>>2]=c[b+8>>2];c[g+12>>2]=c[b+12>>2];if(!(e&8192))gD(a,d,d,2)|0;if(!f)_v(d)}return}function fu(a,b){a=a|0;b=b|0;var c=0,d=0.0,e=0,f=0,g=0,i=0.0,j=0.0,k=0.0,m=0.0,n=0.0,o=0,p=0,q=0;q=l;l=l+144|0;c=q+80|0;e=q+16|0;f=q;k=+h[b>>3];o=a+16|0;m=+h[o>>3];if(!(((((((((!(k>m)?(n=+h[a>>3],!(k>3],i=+h[a+24>>3],!(d>i)):0)?(j=+h[a+8>>3],!(d>3],!(k>m|k>3],!(k>i|k>3],!(k>m|k>3],!(k>i|k>3],!(k>m|k>3],!(n>i|n>3];if(!(d>+h[o>>3])){if(d<+h[a>>3]){c=a;p=16}}else{c=o;p=16}if((p|0)==16){p=0;h[c>>3]=d}d=+h[b+(e<<4)+8>>3];if(!(d>+h[f>>3])){if(d<+h[g>>3]){c=a;p=19}}else{c=o;p=19}if((p|0)==19){p=0;h[c+8>>3]=d}e=e+1|0}}while(0);l=q;return}function gu(a){a=a|0;var b=0,d=0,e=0,f=0,g=0.0,h=0,i=0;b=l;l=l+48|0;d=b+32|0;e=b+16|0;f=b;i=a+48|0;h=a+16|0;c[f>>2]=c[a>>2];c[f+4>>2]=c[a+4>>2];c[f+8>>2]=c[a+8>>2];c[f+12>>2]=c[a+12>>2];c[e>>2]=c[i>>2];c[e+4>>2]=c[i+4>>2];c[e+8>>2]=c[i+8>>2];c[e+12>>2]=c[i+12>>2];c[d>>2]=c[h>>2];c[d+4>>2]=c[h+4>>2];c[d+8>>2]=c[h+8>>2];c[d+12>>2]=c[h+12>>2];g=+dw(f,e,d);h=a+32|0;c[f>>2]=c[a>>2];c[f+4>>2]=c[a+4>>2];c[f+8>>2]=c[a+8>>2];c[f+12>>2]=c[a+12>>2];c[e>>2]=c[i>>2];c[e+4>>2]=c[i+4>>2];c[e+8>>2]=c[i+8>>2];c[e+12>>2]=c[i+12>>2];c[d>>2]=c[h>>2];c[d+4>>2]=c[h+4>>2];c[d+8>>2]=c[h+8>>2];c[d+12>>2]=c[h+12>>2];a=g<4.0&+dw(f,e,d)<4.0&1;l=b;return a|0}function hu(b,d){b=b|0;d=d|0;var e=0,f=0.0,g=0.0,i=0.0,j=0,k=0,m=0,n=0.0;m=l;l=l+16|0;k=m;j=c[b+152>>2]|0;n=+h[b+432>>3];i=+h[b+352>>3]*.013888888888888888;f=i*n;h[b+488>>3]=f;g=+h[b+440>>3];i=i*g;h[b+496>>3]=i;h[b+520>>3]=n*.013888888888888888;e=b+528|0;h[e>>3]=g*.013888888888888888;if(j&4096|c[42184]|0)h[e>>3]=g*-.013888888888888888;e=(c[b+360>>2]|0)==0;n=+((c[b+448>>2]|0)>>>0);g=+((c[b+452>>2]|0)>>>0);h[b+368>>3]=(e?n:g)/f;h[b+376>>3]=(e?g:n)/i;MD(b,GA(d,zm(d,0,86595,0)|0,174185)|0);c[b+160>>2]=0;iu(b,d);if(j&2|0)ju(b,d);e=eo(d)|0;while(1){if(!e)break;a[(c[e+16>>2]|0)+116>>0]=0;e=fo(d,e)|0}ku(b,k);while(1){if(!((lu(b)|0)<<24>>24))break;if((mu(b)|0)>1)lD(b);nu(b);while(1){if(!((ou(b)|0)<<24>>24))break;pu(b,d);qu(b)}if((mu(b)|0)>1)mD(b);ru(b,k)}su(b);l=m;return}function iu(a,b){a=a|0;b=b|0;var d=0;d=Wt(a)|0;c[d+4>>2]=0;c[d+8>>2]=b;c[d+12>>2]=0;rv(a,c[(c[b+16>>2]|0)+12>>2]|0,b);hD(a,b);return}function ju(b,c){b=b|0;c=c|0;var d=0,e=0,f=0,g=0;ED(b,119592);d=Jm(c,85423)|0;if(d|0?a[d>>0]|0:0)ED(b,d);d=Jm(c,86503)|0;if(d|0?a[d>>0]|0:0)CD(b,d);Dv(b,c);g=eo(c)|0;while(1){if(!g)break;d=Jm(g,122540)|0;if(d|0?a[d>>0]|0:0)CD(b,d);d=Jm(g,122531)|0;if(d|0?a[d>>0]|0:0)ED(b,d);d=Jm(g,86469)|0;do if(d|0?a[d>>0]|0:0){if(!(XJ(d,58)|0)){CD(b,d);break}e=HL(d)|0;d=e;while(1){d=EL(d,93017)|0;if(!d)break;if(!(a[d>>0]|0)){d=0;continue}CD(b,d);d=0}$I(e)}while(0);d=Jm(g,86503)|0;if(d|0?a[d>>0]|0:0)CD(b,d);f=Qm(c,g)|0;while(1){if(!f)break;d=Jm(f,122540)|0;do if(d|0?a[d>>0]|0:0){if(!(XJ(d,58)|0)){CD(b,d);break}e=HL(d)|0;d=e;while(1){d=EL(d,93017)|0;if(!d)break;if(!(a[d>>0]|0)){d=0;continue}CD(b,d);d=0}$I(e)}while(0);d=Jm(f,86503)|0;if(d|0?a[d>>0]|0:0)CD(b,d);f=Sm(c,f)|0}g=fo(c,g)|0}return}function ku(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;e=i+8|0;g=i;h=c[a>>2]|0;d=c[h+312>>2]|0;f=a+156|0;c[f>>2]=d;h=c[h+316>>2]|0;if(!h)if((d|0)>1?(c[a+152>>2]&64|0)==0:0){c[e>>2]=c[a+52>>2];$l(0,85598,e)|0;c[f>>2]=1;e=1;d=0}else{e=1;d=0}else{d=h+4|0;if((c[h>>2]|0)>1?(c[a+152>>2]&64|0)==0:0){c[g>>2]=c[a+52>>2];$l(0,85598,g)|0;c[h+8>>2]=(c[f>>2]|0)+1}e=c[d>>2]|0;d=h+8|0}c[a+160>>2]=e;c[b>>2]=d;l=i;return}function lu(a){a=a|0;return (c[a+160>>2]|0)<=(c[a+156>>2]|0)|0}function mu(a){a=a|0;var b=0;b=c[(c[a>>2]|0)+316>>2]|0;return c[((b|0)==0?a+156|0:b)>>2]|0}function nu(a){a=a|0;var b=0,d=0;d=a+172|0;b=c[d+4>>2]|0;a=a+196|0;c[a>>2]=c[d>>2];c[a+4>>2]=b;return}function ou(a){a=a|0;var b=0,d=0;d=c[a+196>>2]|0;if(((d|0)>-1?(d|0)<(c[a+164>>2]|0):0)?(b=c[a+200>>2]|0,(b|0)>-1):0)a=(b|0)<(c[a+168>>2]|0)&1;else a=0;return a|0}function pu(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;p=l;l=l+176|0;k=p;f=p+48|0;m=p+32|0;n=c[d+16>>2]|0;o=c[d+152>>2]|0;if((c[d+160>>2]|0)<=1?(c[d+196>>2]|0)<=0:0)h=0;else{dm(m,128,f);g=n+212|0;h=c[g>>2]|0;_t(d,m);gm(m,h)|0;i=m+4|0;f=c[i>>2]|0;if(f>>>0>=(c[m+8>>2]|0)>>>0){em(m,1)|0;f=c[i>>2]|0}a[f>>0]=0;f=c[m>>2]|0;c[i>>2]=f;c[g>>2]=f}_E(Jm(e,85048)|0);uu(d);jD(d);CD(d,122106);ED(d,119592);do if(o&4259840|0){if((c[n+208>>2]|0)==0?(b[n+260>>1]&1)==0:0)break;if(o&655360){i=o&131072;c[n+264>>2]=i>>>16^2;f=ww((i>>>12^32)+32|0)|0;g=d+288|0;c[f>>2]=c[g>>2];c[f+4>>2]=c[g+4>>2];c[f+8>>2]=c[g+8>>2];c[f+12>>2]=c[g+12>>2];g=f+16|0;q=d+304|0;c[g>>2]=c[q>>2];c[g+4>>2]=c[q+4>>2];c[g+8>>2]=c[q+8>>2];c[g+12>>2]=c[q+12>>2];if(!i){_v(f);g=4}else g=2}else{f=0;g=0}if(!(o&8192))gD(d,f,f,g)|0;c[n+272>>2]=f;c[n+268>>2]=g}while(0);if(o&32768|0?(j=c[(c[e+16>>2]|0)+12>>2]|0,j|0):0)c[n+192>>2]=c[j>>2];g=(o&4|0)!=0;do if(!g){f=n+208|0;if((c[f>>2]|0)==0?(b[n+260>>1]&1)==0:0)break;q=d+256|0;c[k>>2]=c[q>>2];c[k+4>>2]=c[q+4>>2];c[k+8>>2]=c[q+8>>2];c[k+12>>2]=c[q+12>>2];c[k+16>>2]=c[q+16>>2];c[k+20>>2]=c[q+20>>2];c[k+24>>2]=c[q+24>>2];c[k+28>>2]=c[q+28>>2];eu(d,k);xD(d,c[f>>2]|0,c[n+228>>2]|0,c[n+244>>2]|0,c[n+212>>2]|0)}while(0);vu(d,e);f=c[(c[e+16>>2]|0)+12>>2]|0;if(f|0)qw(d,4,f);do if(!g){if((c[n+208>>2]|0)==0?(b[n+260>>1]&1)==0:0)break;yD(d)}while(0);wu(d,e,o);kD(d);if(h|0){hm(m);c[n+212>>2]=h}l=p;return}function qu(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;h=l;l=l+32|0;d=h+24|0;b=h+16|0;j=h+8|0;f=h;g=a+196|0;i=a+188|0;c[b>>2]=c[g>>2];c[b+4>>2]=c[g+4>>2];c[d>>2]=c[i>>2];c[d+4>>2]=c[i+4>>2];tu(j,b,d);i=c[j+4>>2]|0;e=g;c[e>>2]=c[j>>2];c[e+4>>2]=i;if(!((ou(a)|0)<<24>>24)){e=a+180|0;if(!(c[a+184>>2]|0))c[a+200>>2]=c[a+176>>2];else c[g>>2]=c[a+172>>2];c[b>>2]=c[g>>2];c[b+4>>2]=c[g+4>>2];c[d>>2]=c[e>>2];c[d+4>>2]=c[e+4>>2];tu(f,b,d);i=c[f+4>>2]|0;j=g;c[j>>2]=c[f>>2];c[j+4>>2]=i}l=h;return}function ru(a,b){a=a|0;b=b|0;var d=0;d=c[b>>2]|0;if(!d){d=a+160|0;c[d>>2]=(c[d>>2]|0)+1}else{c[a+160>>2]=c[d>>2];c[b>>2]=d+4}return}function su(a){a=a|0;iD(a);Xt(a);return}function tu(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=(c[d+4>>2]|0)+(c[b+4>>2]|0)|0;c[a>>2]=(c[d>>2]|0)+(c[b>>2]|0);c[a+4>>2]=e;return}function uu(a){a=a|0;var b=0.0,d=0.0,e=0.0,f=0,g=0.0,i=0,j=0,k=0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0.0;t=l;l=l+48|0;n=t+32|0;f=t+24|0;j=t+8|0;k=t+16|0;m=t;r=a+196|0;q=c[r>>2]|0;r=c[r+4>>2]|0;p=f;c[p>>2]=q;c[p+4>>2]=r;p=a+164|0;i=c[p>>2]|0;p=c[p+4>>2]|0;s=j;c[s>>2]=i;c[s+4>>2]=p;s=a+360|0;if(!(c[s>>2]|0)){k=q;j=r}else{c[n>>2]=c[f>>2];c[n+4>>2]=c[f+4>>2];Cv(k,n);r=k;k=c[r>>2]|0;r=c[r+4>>2]|0;p=f;c[p>>2]=k;c[p+4>>2]=r;c[n>>2]=c[j>>2];c[n+4>>2]=c[j+4>>2];Cv(m,n);p=m;i=c[p>>2]|0;p=c[p+4>>2]|0;c[j>>2]=i;c[j+4>>2]=p;j=r}d=+h[a+320>>3];g=d*+(k|0)-+h[a+240>>3];h[a+288>>3]=g;e=+h[a+328>>3];o=e*+(j|0)-+h[a+248>>3];h[a+296>>3]=o;h[a+304>>3]=d+g;h[a+312>>3]=e+o;f=a+472|0;if(!(c[(c[a+12>>2]|0)+28>>2]|0)){r=a+456|0;c[f>>2]=c[r>>2];c[f+4>>2]=c[r+4>>2];c[f+8>>2]=c[r+8>>2];c[f+12>>2]=c[r+12>>2]}else{q=a+456|0;c[f>>2]=c[((c[f>>2]|0)<(c[q>>2]|0)?f:q)>>2];r=a+476|0;c[r>>2]=c[((c[r>>2]|0)<(c[a+460>>2]|0)?f:q)+4>>2];r=a+480|0;c[r>>2]=c[((c[r>>2]|0)>(c[a+464>>2]|0)?f:q)+8>>2];r=a+484|0;c[r>>2]=c[((c[r>>2]|0)>(c[a+468>>2]|0)?f:q)+12>>2]}m=c[a+152>>2]|0;b=+h[a+336>>3];if(!(m&128)){b=(+(k|0)-+(i|0)*.5)*d+b;h[a+256>>3]=b;g=(+(j|0)-+(p|0)*.5)*e+ +h[a+344>>3];o=g;d=d+b;g=g+e}else{d=+h[a+368>>3]*.5;e=b-d;h[a+256>>3]=e;g=+h[a+344>>3];u=+h[a+376>>3]*.5;o=g-u;d=d+b;g=u+g;b=e}h[a+264>>3]=o;h[a+272>>3]=d;h[a+280>>3]=g;if(!(c[s>>2]|0)){e=+h[a+352>>3];h[a+504>>3]=+h[a+384>>3]/e-b;if(!(m&4096|c[42184])){d=+h[a+392>>3]/e;b=o}else{d=-g;b=+h[a+392>>3]/e}h[a+512>>3]=d-b}else{f=a+384|0;e=+h[a+352>>3];h[a+512>>3]=-g-+h[a+392>>3]/e;if(!(m&4096|c[42184]))d=+h[f>>3]/e;else{d=-d;b=+h[f>>3]/e}h[a+504>>3]=d-b}l=t;return}function vu(b,d){b=b|0;d=d|0;var e=0,f=0.0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=l;l=l+48|0;q=s;o=s+40|0;p=s+36|0;r=s+32|0;e=Jm(d,85423)|0;if(!e){j=1;e=121990}else{i=(a[e>>0]|0)==0;j=i&1;e=i?121990:e}h=c[b+152>>2]|0;i=(a[e>>0]|0)==116;if(!(h&256))if(i){m=(yJ(e,122171)|0)==0;k=m?121990:e;m=m?1:j;n=8}else{k=e;m=j;n=8}else if(!(i?!(yJ(e,122171)|0):0)){k=e;m=j;n=8}if((n|0)==8?!((m|0)!=0&(h&33554432|0)!=0):0)if(!((yv(k,o,p)|0)<<24>>24)){ED(b,k);CD(b,122171);r=b+256|0;c[q>>2]=c[r>>2];c[q+4>>2]=c[r+4>>2];c[q+8>>2]=c[r+8>>2];c[q+12>>2]=c[r+12>>2];c[q+16>>2]=c[r+16>>2];c[q+20>>2]=c[r+20>>2];c[q+24>>2]=c[r+24>>2];c[q+28>>2]=c[r+28>>2];JD(b,q,1)}else{c[r>>2]=0;i=c[o>>2]|0;ED(b,i);CD(b,122171);xv(d,r)|0;e=c[o+4>>2]|0;h=EA(d,c[42188]|0,0,0)|0;f=+g[p>>2];if(!e)FD(b,122106,h,f);else FD(b,e,h,f);r=(c[r>>2]|0)>>>1&1|2;p=b+256|0;c[q>>2]=c[p>>2];c[q+4>>2]=c[p+4>>2];c[q+8>>2]=c[p+8>>2];c[q+12>>2]=c[p+12>>2];c[q+16>>2]=c[p+16>>2];c[q+20>>2]=c[p+20>>2];c[q+24>>2]=c[p+24>>2];c[q+28>>2]=c[p+28>>2];JD(b,q,r);$I(i)}e=c[(c[(c[d+16>>2]|0)+8>>2]|0)+88>>2]|0;if(e|0)Av(b,e);l=s;return}function wu(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;g=(c[a>>2]|0)+28|0;c[g>>2]=(c[g>>2]|0)+1;g=(d&4|0)!=0;if(!g)xu(a,b,d);a:do if(!(d&1)){if(d&16|0){rD(a);f=eo(b)|0;while(1){if(!f)break;e=Qm(b,f)|0;while(1){if(!e)break;zu(a,e);e=Sm(b,e)|0}f=fo(b,f)|0}sD(a);pD(a);e=eo(b)|0;while(1){if(!e)break;yu(a,e);e=fo(b,e)|0}qD(a);break}if(!(d&8)){f=eo(b)|0;while(1){if(!f)break a;yu(a,f);e=Qm(b,f)|0;while(1){if(!e)break;yu(a,c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0);zu(a,e);e=Sm(b,e)|0}f=fo(b,f)|0}}pD(a);e=eo(b)|0;while(1){if(!e)break;if((Au(b,e)|0)<<24>>24)yu(a,e);e=fo(b,e)|0}qD(a);rD(a);f=eo(b)|0;while(1){if(!f)break;e=Qm(b,f)|0;while(1){if(!e)break;if((Bu(b,e)|0)<<24>>24)zu(a,e);e=Sm(b,e)|0}f=fo(b,f)|0}sD(a)}else{pD(a);e=eo(b)|0;while(1){if(!e)break;yu(a,e);e=fo(b,e)|0}qD(a);rD(a);f=eo(b)|0;while(1){if(!f)break;e=Qm(b,f)|0;while(1){if(!e)break;zu(a,e);e=Sm(b,e)|0}f=fo(b,f)|0}sD(a)}while(0);if(g)xu(a,b,d);return}function xu(e,f,i){e=e|0;f=f|0;i=i|0;var j=0,k=0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0;P=l;l=l+128|0;w=P+72|0;N=P+64|0;H=P+112|0;I=P;J=P+104|0;K=f+16|0;L=(i&4|0)!=0;M=e+16|0;x=I+32|0;y=I+16|0;A=I+8|0;B=I+24|0;C=I+48|0;D=I+40|0;E=I+56|0;F=(i&8|0)==0;G=J+4|0;v=1;while(1){j=c[K>>2]|0;if((v|0)>(c[j+180>>2]|0))break;u=c[(c[j+184>>2]|0)+(v<<2)>>2]|0;if((vv(e,u)|0)<<24>>24){if(L)xu(e,u,i);wv(e,u);r=c[M>>2]|0;s=r+208|0;if(!(c[s>>2]|0))t=(b[r+260>>1]&1)!=0;else t=1;_E(Jm(u,85048)|0);if(!(L|t^1)){q=(c[u+16>>2]|0)+16|0;c[w>>2]=c[q>>2];c[w+4>>2]=c[q+4>>2];c[w+8>>2]=c[q+8>>2];c[w+12>>2]=c[q+12>>2];c[w+16>>2]=c[q+16>>2];c[w+20>>2]=c[q+20>>2];c[w+24>>2]=c[q+24>>2];c[w+28>>2]=c[q+28>>2];eu(e,w);xD(e,c[s>>2]|0,c[r+228>>2]|0,c[r+244>>2]|0,c[r+212>>2]|0)}c[H>>2]=0;j=xv(u,H)|0;if(!j)p=0;else{GD(e,j);p=c[H>>2]&1}q=u+16|0;j=d[(c[q>>2]|0)+112>>0]|0;do if(!(j&1)){if(j&2|0){j=HA(u,0,91300)|0;k=HA(u,0,91308)|0;O=29;break}if(j&8|0){j=HA(u,0,91316)|0;k=HA(u,0,91324)|0;O=29;break}if(j&4|0){j=HA(u,0,91332)|0;k=HA(u,0,91340)|0;O=29;break}j=Jm(u,122540)|0;if(!j)k=0;else k=(a[j>>0]|0)==0?0:j;j=Jm(u,122531)|0;if(!j)j=k;else j=(a[j>>0]|0)==0?k:j;m=Jm(u,86469)|0;if(m)k=(a[m>>0]|0)==0?k:m;if(!((p|0)!=0&(k|0)!=0)){m=Jm(u,85423)|0;if(m|0?a[m>>0]|0:0){k=m;O=29;break}j=(j|0)==0?122106:j;n=(k|0)==0?119592:k;c[J>>2]=0;if(!p)k=0;else O=31}else O=29}else{j=HA(u,0,91284)|0;k=HA(u,0,91292)|0;O=29}while(0);if((O|0)==29){c[J>>2]=0;j=(j|0)==0?122106:j;n=(k|0)==0?119592:k;O=31}if((O|0)==31){O=0;if(!((yv(n,J,w)|0)<<24>>24)){ED(e,n);k=1}else{ED(e,c[J>>2]|0);k=c[G>>2]|0;m=EA(u,c[42188]|0,0,0)|0;o=+g[w>>2];if(!k)FD(e,122106,m,o);else FD(e,k,m,o);k=(c[H>>2]|0)>>>1&1|2}}m=c[42187]|0;if((m|0?(z=Km(u,m)|0,z|0):0)?a[z>>0]|0:0)PD(e,+FA(u,c[42187]|0,1.0,0.0));p=c[H>>2]|0;do if(p&4){m=EA(u,c[42186]|0,1,0)|0;if(m|k|0){n=c[q>>2]|0;Q=n+16|0;c[I>>2]=c[Q>>2];c[I+4>>2]=c[Q+4>>2];c[I+8>>2]=c[Q+8>>2];c[I+12>>2]=c[Q+12>>2];n=n+32|0;c[x>>2]=c[n>>2];c[x+4>>2]=c[n+4>>2];c[x+8>>2]=c[n+8>>2];c[x+12>>2]=c[n+12>>2];h[y>>3]=+h[x>>3];h[B>>3]=+h[A>>3];h[C>>3]=+h[I>>3];h[E>>3]=+h[D>>3];if(!m)CD(e,122171);else CD(e,j);zy(e,I,4,p,k)}}else{if(!(p&64)){if(EA(u,c[42186]|0,1,0)|0){CD(e,j);Q=(c[q>>2]|0)+16|0;c[w>>2]=c[Q>>2];c[w+4>>2]=c[Q+4>>2];c[w+8>>2]=c[Q+8>>2];c[w+12>>2]=c[Q+12>>2];c[w+16>>2]=c[Q+16>>2];c[w+20>>2]=c[Q+20>>2];c[w+24>>2]=c[Q+24>>2];c[w+28>>2]=c[Q+28>>2];JD(e,w,k);break}if(!k)break;CD(e,122171);Q=(c[q>>2]|0)+16|0;c[w>>2]=c[Q>>2];c[w+4>>2]=c[Q+4>>2];c[w+8>>2]=c[Q+8>>2];c[w+12>>2]=c[Q+12>>2];c[w+16>>2]=c[Q+16>>2];c[w+20>>2]=c[Q+20>>2];c[w+24>>2]=c[Q+24>>2];c[w+28>>2]=c[Q+28>>2];JD(e,w,k);break}Q=c[q>>2]|0;p=Q+16|0;c[I>>2]=c[p>>2];c[I+4>>2]=c[p+4>>2];c[I+8>>2]=c[p+8>>2];c[I+12>>2]=c[p+12>>2];Q=Q+32|0;c[x>>2]=c[Q>>2];c[x+4>>2]=c[Q+4>>2];c[x+8>>2]=c[Q+8>>2];c[x+12>>2]=c[Q+12>>2];h[y>>3]=+h[x>>3];h[B>>3]=+h[A>>3];h[C>>3]=+h[I>>3];h[E>>3]=+h[D>>3];if(!(EA(u,c[42186]|0,1,0)|0))CD(e,122171);else CD(e,j);if((du(e,I,n,0)|0)>1){c[N>>2]=En(u)|0;$l(3,85431,N)|0}Q=(c[q>>2]|0)+16|0;c[w>>2]=c[Q>>2];c[w+4>>2]=c[Q+4>>2];c[w+8>>2]=c[Q+8>>2];c[w+12>>2]=c[Q+12>>2];c[w+16>>2]=c[Q+16>>2];c[w+20>>2]=c[Q+20>>2];c[w+24>>2]=c[Q+24>>2];c[w+28>>2]=c[Q+28>>2];JD(e,w,0)}while(0);$I(c[J>>2]|0);j=c[(c[q>>2]|0)+12>>2]|0;if(j|0)qw(e,5,j);if(t){if(L){Q=(c[q>>2]|0)+16|0;c[w>>2]=c[Q>>2];c[w+4>>2]=c[Q+4>>2];c[w+8>>2]=c[Q+8>>2];c[w+12>>2]=c[Q+12>>2];c[w+16>>2]=c[Q+16>>2];c[w+20>>2]=c[Q+20>>2];c[w+24>>2]=c[Q+24>>2];c[w+28>>2]=c[Q+28>>2];eu(e,w);xD(e,c[s>>2]|0,c[r+228>>2]|0,c[r+244>>2]|0,c[r+212>>2]|0)}yD(e)}a:do if(!F){k=eo(u)|0;while(1){if(!k)break a;yu(e,k);j=Qm(u,k)|0;while(1){if(!j)break;zu(e,j);j=Sm(u,j)|0}k=fo(u,k)|0}}while(0);zv(e,f);if(!L)xu(e,u,i)}v=v+1|0}l=P;return}function yu(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;j=l;l=l+32|0;e=j;h=c[b>>2]|0;i=d+16|0;a:do if(((c[(c[i>>2]|0)+8>>2]|0?(nv(b,so(d)|0,d)|0)<<24>>24:0)?(k=b+256|0,c[e>>2]=c[k>>2],c[e+4>>2]=c[k+4>>2],c[e+8>>2]=c[k+8>>2],c[e+12>>2]=c[k+12>>2],c[e+16>>2]=c[k+16>>2],c[e+20>>2]=c[k+20>>2],c[e+24>>2]=c[k+24>>2],c[e+28>>2]=c[k+28>>2],(ov(d,e)|0)<<24>>24):0)?(f=(c[i>>2]|0)+116|0,g=c[h+28>>2]|0,(g|0)!=(a[f>>0]|0)):0){a[f>>0]=g;MD(b,En(d)|0);e=GA(d,c[42214]|0,174185)|0;if(a[e>>0]|0)MD(b,e);e=GA(d,c[42202]|0,174185)|0;b:do if(a[e>>0]|0){Eu(e)|0;e=168408;while(1){f=e;e=e+4|0;f=c[f>>2]|0;if(!f)break b;if((a[f>>0]|0)!=105)continue;if(!(yJ(f,119127)|0))break a}}while(0);pv(b,d);hb[c[(c[(c[(c[i>>2]|0)+8>>2]|0)+4>>2]|0)+20>>2]&31](b,d);e=c[(c[i>>2]|0)+108>>2]|0;if(e|0?a[e+81>>0]|0:0)qw(b,10,e);qv(b)}while(0);l=j;return}function zu(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;h=l;l=l+32|0;g=h;e=b+256|0;c[g>>2]=c[e>>2];c[g+4>>2]=c[e+4>>2];c[g+8>>2]=c[e+8>>2];c[g+12>>2]=c[e+12>>2];c[g+16>>2]=c[e+16>>2];c[g+20>>2]=c[e+20>>2];c[g+24>>2]=c[e+24>>2];c[g+28>>2]=c[e+28>>2];a:do if((Cu(d,g)|0)<<24>>24?(f=d+-48|0,(Du(b,d)|0)<<24>>24):0){i=d+48|0;e=sJ(En(c[((c[d>>2]&3|0)==3?d:i)+40>>2]|0)|0)|0;e=_I(e+3+(sJ(En(c[((c[d>>2]&3|0)==2?d:f)+40>>2]|0)|0)|0)|0)|0;yK(e,En(c[((c[d>>2]&3|0)==3?d:i)+40>>2]|0)|0)|0;i=(rn(so(c[((c[d>>2]&3|0)==2?d:f)+40>>2]|0)|0)|0)==0;g=e+(sJ(e)|0)|0;if(i){a[g>>0]=a[122549]|0;a[g+1>>0]=a[122550]|0;a[g+2>>0]=a[122551]|0}else{a[g>>0]=a[122546]|0;a[g+1>>0]=a[122547]|0;a[g+2>>0]=a[122548]|0}JL(e,En(c[((c[d>>2]&3|0)==2?d:f)+40>>2]|0)|0)|0;MD(b,e);$I(e);e=GA(d,c[42236]|0,174185)|0;if(a[e>>0]|0)MD(b,e);e=GA(d,c[42230]|0,174185)|0;b:do if(!(a[e>>0]|0))e=0;else{Eu(e)|0;e=168408;while(1){f=e;e=e+4|0;f=c[f>>2]|0;if(!f){e=168408;break b}if((a[f>>0]|0)!=105)continue;if(!(yJ(f,119127)|0))break a}}while(0);Fu(b,d,e);Gu(b,d,e);Hu(b)}while(0);l=h;return}function Au(a,b){a=a|0;b=b|0;var d=0,e=0;d=a+16|0;a=1;while(1){e=c[d>>2]|0;if((a|0)>(c[e+180>>2]|0)){a=1;break}if(!(Co(c[(c[e+184>>2]|0)+(a<<2)>>2]|0,b)|0))a=a+1|0;else{a=0;break}}return a|0}function Bu(a,b){a=a|0;b=b|0;var d=0,e=0;d=a+16|0;a=1;while(1){e=c[d>>2]|0;if((a|0)>(c[e+180>>2]|0)){a=1;break}if(!(Co(c[(c[e+184>>2]|0)+(a<<2)>>2]|0,b)|0))a=a+1|0;else{a=0;break}}return a|0}function Cu(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+64|0;i=j+32|0;f=j;g=b+16|0;b=c[g>>2]|0;e=c[b+8>>2]|0;if((e|0)!=0?(e=e+8|0,c[f>>2]=c[e>>2],c[f+4>>2]=c[e+4>>2],c[f+8>>2]=c[e+8>>2],c[f+12>>2]=c[e+12>>2],c[f+16>>2]=c[e+16>>2],c[f+20>>2]=c[e+20>>2],c[f+24>>2]=c[e+24>>2],c[f+28>>2]=c[e+28>>2],c[i>>2]=c[d>>2],c[i+4>>2]=c[d+4>>2],c[i+8>>2]=c[d+8>>2],c[i+12>>2]=c[d+12>>2],c[i+16>>2]=c[d+16>>2],c[i+20>>2]=c[d+20>>2],c[i+24>>2]=c[d+24>>2],c[i+28>>2]=c[d+28>>2],(mv(f,i)|0)!=0):0)b=1;else h=3;do if((h|0)==3){e=c[b+96>>2]|0;if(e){c[i>>2]=c[d>>2];c[i+4>>2]=c[d+4>>2];c[i+8>>2]=c[d+8>>2];c[i+12>>2]=c[d+12>>2];c[i+16>>2]=c[d+16>>2];c[i+20>>2]=c[d+20>>2];c[i+24>>2]=c[d+24>>2];c[i+28>>2]=c[d+28>>2];if((DB(e,i)|0)<<24>>24){b=1;break}b=c[g>>2]|0}b=c[b+108>>2]|0;if((b|0?a[b+81>>0]|0:0)?(c[i>>2]=c[d>>2],c[i+4>>2]=c[d+4>>2],c[i+8>>2]=c[d+8>>2],c[i+12>>2]=c[d+12>>2],c[i+16>>2]=c[d+16>>2],c[i+20>>2]=c[d+20>>2],c[i+24>>2]=c[d+24>>2],c[i+28>>2]=c[d+28>>2],(DB(b,i)|0)<<24>>24):0){b=1;break}b=0}while(0);l=j;return b|0}function Du(b,d){b=b|0;d=d|0;var e=0,f=0;a:do if((c[b+156>>2]|0)>=2?(e=GA(d,c[42235]|0,174185)|0,(iv(b,e)|0)<<24>>24==0):0)if(!(a[e>>0]|0)){e=0;while(1){if((e|0)>=2){e=0;break a}f=(e|0)==1;f=GA(c[((c[d>>2]&3|0)==((f?2:3)|0)?d:d+((f?-1:1)*48|0)|0)+40>>2]|0,c[42212]|0,174185)|0;if(!(a[f>>0]|0)){e=1;break a}if(!((iv(b,f)|0)<<24>>24))e=e+1|0;else{e=1;break}}}else e=0;else e=1;while(0);return e|0}function Eu(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;p=l;l=l+192|0;o=p+24|0;n=p+16|0;m=p+8|0;k=p;g=p+48|0;j=p+32|0;if(a[85305]|0){dm(168672,128,173952);a[85305]=0}dm(j,128,p+56|0);c[g>>2]=b;h=j+4|0;i=j+8|0;d=0;e=0;a:while(1){f=d;b:while(1)switch(gv(g,j)|0){case 0:{d=21;break a}case 40:if(!(f<<24>>24)){f=1;continue b}else{d=7;break a}case 41:if(!(f<<24>>24)){d=9;break a}else{f=0;continue b}default:break b}if(!(f<<24>>24)){if((e|0)==63){d=12;break}d=c[42169]|0;if(d>>>0>=(c[42170]|0)>>>0){em(168672,1)|0;d=c[42169]|0}c[42169]=d+1;a[d>>0]=0;c[168408+(e<<2)>>2]=c[42169];e=e+1|0}d=c[h>>2]|0;if(d>>>0>=(c[i>>2]|0)>>>0){em(j,1)|0;d=c[h>>2]|0}a[d>>0]=0;d=c[j>>2]|0;c[h>>2]=d;gm(168672,d)|0;d=c[42169]|0;if(d>>>0>=(c[42170]|0)>>>0){em(168672,1)|0;d=c[42169]|0}c[42169]=d+1;a[d>>0]=0;d=f}do if((d|0)==7){c[k>>2]=b;$l(1,85306,k)|0;c[42102]=0;hm(j)}else if((d|0)==9){c[m>>2]=b;$l(1,85340,m)|0;c[42102]=0;hm(j)}else if((d|0)==12){c[n>>2]=b;$l(0,85368,n)|0;c[42165]=0;hm(j)}else if((d|0)==21){if(f<<24>>24){c[o>>2]=b;$l(1,85391,o)|0;c[42102]=0;hm(j);break}c[168408+(e<<2)>>2]=0;hm(j);d=c[42169]|0;if(d>>>0>=(c[42170]|0)>>>0){em(168672,1)|0;d=c[42169]|0}a[d>>0]=0;c[42169]=c[42168]}while(0);l=p;return 168408}function Fu(d,f,g){d=d|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;A=l;l=l+160|0;y=A+24|0;w=A+20|0;v=A+16|0;o=A;p=A+32|0;x=c[d+152>>2]|0;c[y>>2]=0;c[w>>2]=0;c[v>>2]=0;z=Wt(d)|0;c[z+4>>2]=3;c[z+8>>2]=f;c[z+12>>2]=9;t=f+16|0;n=c[(c[t>>2]|0)+96>>2]|0;if((n|0?(a[n+82>>0]|0)==0:0)?(KA(Jm(f,85121)|0,0)|0)<<24>>24:0){n=z+260|0;b[n>>1]=b[n>>1]|512}if(g|0?c[(c[t>>2]|0)+8>>2]|0:0)GD(d,g);g=c[42251]|0;if((g|0?(i=Km(f,g)|0,i|0):0)?a[i>>0]|0:0)PD(d,+FA(f,c[42251]|0,1.0,0.0));do if(x&16777216|0){g=f+48|0;if((e[(c[(so(c[((c[f>>2]&3|0)==3?f:g)+40>>2]|0)|0)+16>>2]|0)+178>>1]|0)>2){m=+h[(c[(c[(c[((c[f>>2]&3|0)==3?f:g)+40>>2]|0)+16>>2]|0)+132>>2]|0)+16>>3]*72.0;h[z+176>>3]=+(~~(m+(m>=0.0?.5:-.5))|0);m=+h[(c[(c[(c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0)+16>>2]|0)+132>>2]|0)+16>>3]*72.0;h[z+184>>3]=+(~~(m+(m>=0.0?.5:-.5))|0);break}else{n=z+176|0;c[n>>2]=0;c[n+4>>2]=0;c[n+8>>2]=0;c[n+12>>2]=0;break}}while(0);if(x&32768|0){n=c[t>>2]|0;g=c[n+96>>2]|0;if(!g)g=c[z+192>>2]|0;else{g=c[g>>2]|0;c[z+192>>2]=g}i=z+196|0;c[i>>2]=g;k=z+204|0;c[k>>2]=g;j=z+200|0;c[j>>2]=g;g=c[n+108>>2]|0;if(g|0)c[i>>2]=c[g>>2];g=c[n+104>>2]|0;if(g|0)c[j>>2]=c[g>>2];g=c[n+100>>2]|0;if(g|0)c[k>>2]=c[g>>2]}if(!(x&65536))j=0;else{dm(o,128,p);c[z+212>>2]=rw(Zt(d,f,o)|0,f)|0;hm(o);g=Jm(f,96264)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)q=31;else{g=Jm(f,96269)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)q=31;else i=0}if((q|0)==31)i=rw(g,f)|0;g=Jm(f,85134)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)q=36;else q=34;do if((q|0)==34){g=Jm(f,85143)|0;if(g|0?a[g>>0]|0:0){q=36;break}if(i|0){g=HL(i)|0;q=39}}while(0);if((q|0)==36){g=rw(g,f)|0;q=39}if((q|0)==39)c[z+208>>2]=g;g=Jm(f,85151)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)q=44;else q=42;do if((q|0)==42){g=Jm(f,85161)|0;if(g|0?a[g>>0]|0:0){q=44;break}if(i|0){g=HL(i)|0;q=47}}while(0);if((q|0)==44){g=rw(g,f)|0;q=47}if((q|0)==47)c[z+216>>2]=g;g=Jm(f,85170)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)q=52;else q=50;do if((q|0)==50){g=Jm(f,85179)|0;if(g|0?a[g>>0]|0:0){q=52;break}if(i|0)c[z+220>>2]=HL(i)|0}while(0);if((q|0)==52){c[z+220>>2]=rw(g,f)|0;q=z+260|0;b[q>>1]=b[q>>1]|128}g=Jm(f,85187)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)q=59;else q=57;do if((q|0)==57){g=Jm(f,85196)|0;if(g|0?a[g>>0]|0:0){q=59;break}if(i|0)c[z+224>>2]=HL(i)|0}while(0);if((q|0)==59){c[z+224>>2]=rw(g,f)|0;q=z+260|0;b[q>>1]=b[q>>1]|256}j=i}do if(x&8388608){g=Jm(f,85204)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)i=rw(g,f)|0;else i=0;g=Jm(f,85211)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0){q=z+260|0;b[q>>1]=b[q>>1]|64;g=rw(g,f)|0;q=72}else q=70;if((q|0)==70?i|0:0){g=HL(i)|0;q=72}if((q|0)==72)c[z+244>>2]=g;g=Jm(f,85222)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0){g=rw(g,f)|0;q=78}else q=76;if((q|0)==76?i|0:0){g=HL(i)|0;q=78}if((q|0)==78)c[z+248>>2]=g;g=Jm(f,85234)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0){c[z+252>>2]=rw(g,f)|0;p=z+260|0;b[p>>1]=b[p>>1]|16}else q=82;if((q|0)==82?i|0:0)c[z+252>>2]=HL(i)|0;g=Jm(f,85245)|0;if(g|0?a[g>>0]|0:0){q=z+260|0;b[q>>1]=b[q>>1]|32;c[z+256>>2]=rw(g,f)|0;break}if(i)c[z+256>>2]=HL(i)|0;else i=0}else i=0;while(0);do if(x&4194304|0){g=Jm(f,96229)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0)q=94;else q=92;do if((q|0)==92){g=Jm(f,85256)|0;if(g|0?a[g>>0]|0:0){q=94;break}g=c[z+192>>2]|0;if(g|0)c[z+228>>2]=HL(g)|0}while(0);if((q|0)==94){p=_u(g,f)|0;c[z+228>>2]=rw(p,f)|0;$I(p);p=z+260|0;b[p>>1]=b[p>>1]|1}g=Jm(f,85268)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0){p=_u(g,f)|0;c[z+232>>2]=rw(p,f)|0;$I(p);p=z+260|0;b[p>>1]=b[p>>1]|8}else q=100;if((q|0)==100?(r=c[z+192>>2]|0,r|0):0)c[z+232>>2]=HL(r)|0;g=Jm(f,85281)|0;if((g|0)!=0?(a[g>>0]|0)!=0:0){r=_u(g,f)|0;c[z+236>>2]=rw(r,f)|0;$I(r);r=z+260|0;b[r>>1]=b[r>>1]|2}else q=105;if((q|0)==105?(s=c[z+200>>2]|0,s|0):0)c[z+236>>2]=HL(s)|0;g=Jm(f,85293)|0;if(g|0?a[g>>0]|0:0){s=_u(g,f)|0;c[z+240>>2]=rw(s,f)|0;$I(s);s=z+260|0;b[s>>1]=b[s>>1]|4;break}g=c[z+204>>2]|0;if(g|0)c[z+240>>2]=HL(g)|0}while(0);$I(j);$I(i);do if(x&4259840|0?(u=c[(c[t>>2]|0)+8>>2]|0,u|0):0){if(!(c[z+208>>2]|0)){if((x&524288|0)==0|(c[z+228>>2]|0)==0)break}else if(!(x&524288))break;m=+h[(c[d+16>>2]|0)+152>>3]*.5;m=m>2.0?m:2.0;i=c[u+4>>2]|0;g=0;while(1){if((g|0)>=(i|0))break;$u(y,w,v,(c[u>>2]|0)+(g*48|0)|0,m);g=g+1|0}j=c[v>>2]|0;c[z+276>>2]=j;k=c[w>>2]|0;c[z+280>>2]=k;if(!(x&8192)){g=0;i=0;while(1){if((i|0)>=(j|0))break;g=(c[k+(i<<2)>>2]|0)+g|0;i=i+1|0}y=c[y>>2]|0;gD(d,y,y,g)|0;g=y}else g=c[y>>2]|0;c[z+284>>2]=g;c[z+264>>2]=2;c[z+272>>2]=g;c[z+268>>2]=c[k>>2]}while(0);vD(d,f);g=c[z+208>>2]|0;if(!((g|0)==0?!(b[z+260>>1]&1):0))xD(d,g,c[z+228>>2]|0,c[z+244>>2]|0,c[z+212>>2]|0);l=A;return}function Gu(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0.0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0.0,N=0.0,O=0,P=0,Q=0,R=0,S=0;P=l;l=l+240|0;L=P+224|0;K=P+208|0;x=P+128|0;w=P+112|0;O=P+64|0;C=P+48|0;D=P+32|0;E=P+16|0;F=P;G=P+192|0;H=P+176|0;y=P+160|0;B=P+144|0;c[E>>2]=0;c[E+4>>2]=0;c[E+8>>2]=0;c[E+12>>2]=0;M=+h[(c[b+16>>2]|0)+152>>3];_E(Jm(e,85048)|0);J=e+16|0;a:do if(c[(c[J>>2]|0)+8>>2]|0){N=+FA(e,c[42233]|0,1.0,0.0);k=GA(e,c[42221]|0,174185)|0;v=(f|0)!=0;b:do if(v){g=f;while(1){i=g;g=g+4|0;i=c[i>>2]|0;if(!i){o=0;break b}if((a[i>>0]|0)!=116)continue;if(!(yJ(i,95939)|0)){o=1;break}}}else o=0;while(0);j=k;q=0;i=0;c:while(1){switch(a[j>>0]|0){case 0:break c;case 58:{g=q+1|0;break}case 59:{g=q;i=i+1|0;break}default:g=q}j=j+1|0;q=g}n=(q|0)!=0;if((i|0)!=0&n)if(!(Ou(b,e,f,k,q+1|0,N,M)|0))break;else m=122106;else m=k;g=d[(c[J>>2]|0)+115>>0]|0;if(!(g&1))if(!(g&2))if(!(g&8))if(!(g&4)){i=m;j=HA(e,c[42222]|0,m)|0}else{j=91340;g=91332;k=168892;i=168892;p=18}else{j=91324;g=91316;k=168892;i=168892;p=18}else{j=91308;g=91300;k=168892;i=168892;p=18}else{j=91292;g=91284;k=168892;i=168892;p=18}if((p|0)==18){i=c[i>>2]|0;i=HA(e,i,Pu(m,g)|0)|0;g=HA(e,c[k>>2]|0,j)|0;if((i|0)==(m|0)){i=m;j=g}else{CD(b,i);j=g}}if((j|0)!=(m|0))ED(b,j);if(o<<24>>24){i=(a[i>>0]|0)==0?122106:i;g=(a[j>>0]|0)==0?122106:j;CD(b,122171);ED(b,i);u=O;r=c[c[(c[J>>2]|0)+8>>2]>>2]|0;s=u+48|0;do{c[u>>2]=c[r>>2];u=u+4|0;r=r+4|0}while((u|0)<(s|0));J=eA(O,Qu(e)|0,M,0,0)|0;ID(b,c[J+8>>2]|0,c[J>>2]|0,1);Ru(J);CD(b,i);if((g|0)!=(i|0))ED(b,g);g=c[O+8>>2]|0;if(g|0){I=O+16|0;J=c[O>>2]|0;c[K>>2]=c[I>>2];c[K+4>>2]=c[I+4>>2];c[K+8>>2]=c[I+8>>2];c[K+12>>2]=c[I+12>>2];c[L>>2]=c[J>>2];c[L+4>>2]=c[J+4>>2];c[L+8>>2]=c[J+8>>2];c[L+12>>2]=c[J+12>>2];Tt(b,2,K,L,N,M,g)}g=c[O+12>>2]|0;if(!g)break;J=O+32|0;O=(c[O>>2]|0)+((c[O+4>>2]|0)+-1<<4)|0;c[K>>2]=c[J>>2];c[K+4>>2]=c[J+4>>2];c[K+8>>2]=c[J+8>>2];c[K+12>>2]=c[J+12>>2];c[L>>2]=c[O>>2];c[L+4>>2]=c[O+4>>2];c[L+8>>2]=c[O+8>>2];c[L+12>>2]=c[O+12>>2];Tt(b,3,K,L,N,M,g);break}g=c[J>>2]|0;if(!n){do if(!(a[g+115>>0]&3)){if(a[i>>0]|0){CD(b,i);ED(b,j);break}CD(b,122106);if(!(a[j>>0]|0)){ED(b,122106);break}else{ED(b,j);break}}while(0);k=b+152|0;m=O+4|0;n=O+8|0;o=O+12|0;p=O+32|0;q=O+16|0;j=0;while(1){g=c[(c[J>>2]|0)+8>>2]|0;if((j|0)>=(c[g+4>>2]|0))break a;u=O;r=(c[g>>2]|0)+(j*48|0)|0;s=u+48|0;do{c[u>>2]=c[r>>2];u=u+4|0;r=r+4|0}while((u|0)<(s|0));g=c[O>>2]|0;i=c[m>>2]|0;do if(!(c[k>>2]&16384)){KD(b,g,i,0,0,0);g=c[n>>2]|0;if(g|0){I=c[O>>2]|0;c[K>>2]=c[q>>2];c[K+4>>2]=c[q+4>>2];c[K+8>>2]=c[q+8>>2];c[K+12>>2]=c[q+12>>2];c[L>>2]=c[I>>2];c[L+4>>2]=c[I+4>>2];c[L+8>>2]=c[I+8>>2];c[L+12>>2]=c[I+12>>2];Tt(b,2,K,L,N,M,g)}g=c[o>>2]|0;if(g|0){I=(c[O>>2]|0)+((c[m>>2]|0)+-1<<4)|0;c[K>>2]=c[p>>2];c[K+4>>2]=c[p+4>>2];c[K+8>>2]=c[p+8>>2];c[K+12>>2]=c[p+12>>2];c[L>>2]=c[I>>2];c[L+4>>2]=c[I+4>>2];c[L+8>>2]=c[I+8>>2];c[L+12>>2]=c[I+12>>2];Tt(b,3,K,L,N,M,g)}if((c[(c[(c[J>>2]|0)+8>>2]|0)+4>>2]|0)>1){if(!(c[n>>2]|0)){if(!(v&(c[o>>2]|0)!=0))break}else if(!v)break;GD(b,f)}}else KD(b,g,i,c[n>>2]|0,c[o>>2]|0,0);while(0);j=j+1|0}}I=c[(c[g+8>>2]|0)+4>>2]|0;A=I*48|0;z=_I(A)|0;A=_I(A)|0;t=+(q+2|0)*.5;v=O+4|0;p=C+8|0;q=D+8|0;e=E+8|0;f=F+8|0;o=0;while(1){if((o|0)>=(I|0))break;u=O;r=(c[c[(c[J>>2]|0)+8>>2]>>2]|0)+(o*48|0)|0;s=u+48|0;do{c[u>>2]=c[r>>2];u=u+4|0;r=r+4|0}while((u|0)<(s|0));g=c[v>>2]|0;c[z+(o*48|0)+4>>2]=g;c[A+(o*48|0)+4>>2]=g;n=g<<4;m=_I(n)|0;c[z+(o*48|0)>>2]=m;n=_I(n)|0;c[A+(o*48|0)>>2]=n;k=c[O>>2]|0;c[F>>2]=c[k>>2];c[F+4>>2]=c[k+4>>2];c[F+8>>2]=c[k+8>>2];c[F+12>>2]=c[k+12>>2];k=0;while(1){if((k|0)>=(g+-1|0))break;c[C>>2]=c[F>>2];c[C+4>>2]=c[F+4>>2];c[C+8>>2]=c[F+8>>2];c[C+12>>2]=c[F+12>>2];g=k+1|0;j=(c[O>>2]|0)+(g<<4)|0;c[D>>2]=c[j>>2];c[D+4>>2]=c[j+4>>2];c[D+8>>2]=c[j+8>>2];c[D+12>>2]=c[j+12>>2];j=m+(k<<4)|0;if(!k){c[K>>2]=c[C>>2];c[K+4>>2]=c[C+4>>2];c[K+8>>2]=c[C+8>>2];c[K+12>>2]=c[C+12>>2];c[L>>2]=c[D>>2];c[L+4>>2]=c[D+4>>2];c[L+8>>2]=c[D+8>>2];c[L+12>>2]=c[D+12>>2];Su(G,K,L);c[j>>2]=c[G>>2];c[j+4>>2]=c[G+4>>2];c[j+8>>2]=c[G+8>>2];c[j+12>>2]=c[G+12>>2]}else{c[K>>2]=c[E>>2];c[K+4>>2]=c[E+4>>2];c[K+8>>2]=c[E+8>>2];c[K+12>>2]=c[E+12>>2];c[L>>2]=c[D>>2];c[L+4>>2]=c[D+4>>2];c[L+8>>2]=c[D+8>>2];c[L+12>>2]=c[D+12>>2];Su(H,K,L);c[j>>2]=c[H>>2];c[j+4>>2]=c[H+4>>2];c[j+8>>2]=c[H+8>>2];c[j+12>>2]=c[H+12>>2]}R=c[O>>2]|0;s=k+2|0;S=R+(s<<4)|0;c[E>>2]=c[S>>2];c[E+4>>2]=c[S+4>>2];c[E+8>>2]=c[S+8>>2];c[E+12>>2]=c[S+12>>2];u=k+3|0;R=R+(u<<4)|0;c[F>>2]=c[R>>2];c[F+4>>2]=c[R+4>>2];c[F+8>>2]=c[R+8>>2];c[F+12>>2]=c[R+12>>2];Q=m+(g<<4)|0;r=m+(s<<4)|0;c[w>>2]=c[C>>2];c[w+4>>2]=c[C+4>>2];c[w+8>>2]=c[C+8>>2];c[w+12>>2]=c[C+12>>2];c[x>>2]=c[D>>2];c[x+4>>2]=c[D+4>>2];c[x+8>>2]=c[D+8>>2];c[x+12>>2]=c[D+12>>2];c[K>>2]=c[S>>2];c[K+4>>2]=c[S+4>>2];c[K+8>>2]=c[S+8>>2];c[K+12>>2]=c[S+12>>2];c[L>>2]=c[R>>2];c[L+4>>2]=c[R+4>>2];c[L+8>>2]=c[R+8>>2];c[L+12>>2]=c[R+12>>2];Tu(y,w,x,K,L);c[r>>2]=c[y>>2];c[r+4>>2]=c[y+4>>2];c[r+8>>2]=c[y+8>>2];c[r+12>>2]=c[y+12>>2];c[Q>>2]=c[y>>2];c[Q+4>>2]=c[y+4>>2];c[Q+8>>2]=c[y+8>>2];c[Q+12>>2]=c[y+12>>2];h[n+(k<<4)>>3]=+h[C>>3]-+h[j>>3]*t;h[n+(k<<4)+8>>3]=+h[p>>3]-+h[m+(k<<4)+8>>3]*t;h[n+(g<<4)>>3]=+h[D>>3]-+h[Q>>3]*t;h[n+(g<<4)+8>>3]=+h[q>>3]-+h[m+(g<<4)+8>>3]*t;h[n+(s<<4)>>3]=+h[E>>3]-+h[r>>3]*t;h[n+(s<<4)+8>>3]=+h[e>>3]-+h[m+(s<<4)+8>>3]*t;k=u;g=c[v>>2]|0}S=m+(k<<4)|0;c[K>>2]=c[E>>2];c[K+4>>2]=c[E+4>>2];c[K+8>>2]=c[E+8>>2];c[K+12>>2]=c[E+12>>2];c[L>>2]=c[F>>2];c[L+4>>2]=c[F+4>>2];c[L+8>>2]=c[F+8>>2];c[L+12>>2]=c[F+12>>2];Su(B,K,L);c[S>>2]=c[B>>2];c[S+4>>2]=c[B+4>>2];c[S+8>>2]=c[B+8>>2];c[S+12>>2]=c[B+12>>2];h[n+(k<<4)>>3]=+h[F>>3]-+h[S>>3]*t;h[n+(k<<4)+8>>3]=+h[f>>3]-+h[m+(k<<4)+8>>3]*t;o=o+1|0}s=HL(i)|0;f=0;r=i;g=i;j=i;i=s;while(1){i=EL(i,93017)|0;if(!i)break;e=(a[i>>0]|0)==0?122106:i;if((e|0)!=(j|0))if(!(a[(c[J>>2]|0)+115>>0]&3)){CD(b,e);ED(b,e);j=e}else j=e;m=(f|0)==0;n=f>>>0<2;i=0;while(1){if((i|0)>=(I|0))break;o=c[A+(i*48|0)>>2]|0;p=c[z+(i*48|0)>>2]|0;q=c[A+(i*48|0)+4>>2]|0;k=0;while(1){if((k|0)>=(q|0))break;S=o+(k<<4)|0;h[S>>3]=+h[S>>3]+ +h[p+(k<<4)>>3];S=o+(k<<4)+8|0;h[S>>3]=+h[S>>3]+ +h[p+(k<<4)+8>>3];k=k+1|0}KD(b,o,q,0,0,0);i=i+1|0}f=f+1|0;r=m?e:r;g=n?e:g;i=0}i=c[O+8>>2]|0;if(!i)i=0;else{if(g){if(!(a[(c[J>>2]|0)+115>>0]&3)){CD(b,g);ED(b,g)}}else g=0;R=O+16|0;S=c[O>>2]|0;c[K>>2]=c[R>>2];c[K+4>>2]=c[R+4>>2];c[K+8>>2]=c[R+8>>2];c[K+12>>2]=c[R+12>>2];c[L>>2]=c[S>>2];c[L+4>>2]=c[S+4>>2];c[L+8>>2]=c[S+8>>2];c[L+12>>2]=c[S+12>>2];Tt(b,2,K,L,N,M,i);i=g}j=O+12|0;g=c[j>>2]|0;if(g|0){if((i|0)!=(r|0)?(a[(c[J>>2]|0)+115>>0]&3)==0:0){CD(b,r);ED(b,r);g=c[j>>2]|0}R=O+32|0;S=(c[O>>2]|0)+((c[v>>2]|0)+-1<<4)|0;c[K>>2]=c[R>>2];c[K+4>>2]=c[R+4>>2];c[K+8>>2]=c[R+8>>2];c[K+12>>2]=c[R+12>>2];c[L>>2]=c[S>>2];c[L+4>>2]=c[S+4>>2];c[L+8>>2]=c[S+8>>2];c[L+12>>2]=c[S+12>>2];Tt(b,3,K,L,N,M,g)}$I(s);g=0;while(1){if((g|0)>=(I|0))break;$I(c[z+(g*48|0)>>2]|0);$I(c[A+(g*48|0)>>2]|0);g=g+1|0}$I(z);$I(A)}while(0);l=P;return}function Hu(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;x=l;l=l+64|0;r=x+48|0;u=x+32|0;t=x+16|0;s=x;w=c[a+16>>2]|0;v=c[w+8>>2]|0;q=w+208|0;if(!((c[q>>2]|0)==0?!(b[w+260>>1]&1):0))d=3;a:do if((d|0)==3?(yD(a),p=w+276|0,e=c[p>>2]|0,e|0):0){h=w+280|0;d=c[h>>2]|0;i=w+268|0;j=w+284|0;k=w+272|0;m=w+228|0;n=w+244|0;o=w+212|0;f=c[d>>2]|0;g=1;while(1){if((g|0)>=(e|0))break a;c[i>>2]=c[d+(g<<2)>>2];c[k>>2]=(c[j>>2]|0)+(f<<4);xD(a,c[q>>2]|0,c[m>>2]|0,c[n>>2]|0,c[o>>2]|0);yD(a);y=c[h>>2]|0;f=(c[y+(g<<2)>>2]|0)+f|0;g=g+1|0;e=c[p>>2]|0;d=y}}while(0);c[w+268>>2]=0;c[w+272>>2]=0;q=v+16|0;d=c[q>>2]|0;e=c[d+8>>2]|0;if(!e)f=w+260|0;else{p=c[e>>2]|0;d=c[p>>2]|0;y=c[p+8>>2]|0;o=p+16|0;c[t>>2]=c[o>>2];c[t+4>>2]=c[o+4>>2];c[t+8>>2]=c[o+8>>2];c[t+12>>2]=c[o+12>>2];p=p+32|0;c[s>>2]=c[p>>2];c[s+4>>2]=c[p+4>>2];c[s+8>>2]=c[p+8>>2];c[s+12>>2]=c[p+12>>2];if(!y){c[u>>2]=c[d>>2];c[u+4>>2]=c[d+4>>2];c[u+8>>2]=c[d+8>>2];c[u+12>>2]=c[d+12>>2]}else{c[u>>2]=c[t>>2];c[u+4>>2]=c[t+4>>2];c[u+8>>2]=c[t+8>>2];c[u+12>>2]=c[t+12>>2]}f=w+260|0;p=b[f>>1]|0;o=c[w+220>>2]|0;c[r>>2]=c[u>>2];c[r+4>>2]=c[u+4>>2];c[r+8>>2]=c[u+8>>2];c[r+12>>2]=c[u+12>>2];Iu(a,r,(p<<8&65535)<<16>>16>>15&255,o,(p<<14&65535)<<16>>16>>15&255);p=c[(c[q>>2]|0)+8>>2]|0;o=c[p>>2]|0;p=(c[p+4>>2]|0)+-1|0;d=c[o+(p*48|0)>>2]|0;e=c[o+(p*48|0)+4>>2]|0;y=c[o+(p*48|0)+12>>2]|0;n=o+(p*48|0)+16|0;c[t>>2]=c[n>>2];c[t+4>>2]=c[n+4>>2];c[t+8>>2]=c[n+8>>2];c[t+12>>2]=c[n+12>>2];t=o+(p*48|0)+32|0;c[s>>2]=c[t>>2];c[s+4>>2]=c[t+4>>2];c[s+8>>2]=c[t+8>>2];c[s+12>>2]=c[t+12>>2];if(!y){y=d+(e+-1<<4)|0;c[u>>2]=c[y>>2];c[u+4>>2]=c[y+4>>2];c[u+8>>2]=c[y+8>>2];c[u+12>>2]=c[y+12>>2]}else{c[u>>2]=c[s>>2];c[u+4>>2]=c[s+4>>2];c[u+8>>2]=c[s+8>>2];c[u+12>>2]=c[s+12>>2]}d=b[f>>1]|0;y=c[w+224>>2]|0;c[r>>2]=c[u>>2];c[r+4>>2]=c[u+4>>2];c[r+8>>2]=c[u+8>>2];c[r+12>>2]=c[u+12>>2];Iu(a,r,(d<<7&65535)<<16>>16>>15&255,y,(d<<13&65535)<<16>>16>>15&255);d=c[q>>2]|0}e=c[d+96>>2]|0;g=(b[f>>1]<<12&65535)<<16>>16>>15<<16>>16;m=w+216|0;h=c[m>>2]|0;n=w+232|0;i=c[n>>2]|0;o=w+248|0;j=c[o>>2]|0;p=w+212|0;k=c[p>>2]|0;if(!((JA(GA(v,c[42231]|0,122100)|0)|0)<<24>>24))d=0;else d=c[(c[q>>2]|0)+8>>2]|0;Ju(a,e,11,g,h,i,j,k,d);j=c[(c[q>>2]|0)+108>>2]|0;k=(b[f>>1]<<12&65535)<<16>>16>>15<<16>>16;i=c[m>>2]|0;h=c[n>>2]|0;e=c[o>>2]|0;g=c[p>>2]|0;if(!((JA(GA(v,c[42231]|0,122100)|0)|0)<<24>>24))d=0;else d=c[(c[q>>2]|0)+8>>2]|0;Ju(a,j,11,k,i,h,e,g,d);Ju(a,c[(c[q>>2]|0)+100>>2]|0,7,(b[f>>1]<<13&65535)<<16>>16>>15<<16>>16,c[w+224>>2]|0,c[w+240>>2]|0,c[w+256>>2]|0,c[p>>2]|0,0);Ju(a,c[(c[q>>2]|0)+104>>2]|0,6,(b[f>>1]<<14&65535)<<16>>16>>15<<16>>16,c[w+220>>2]|0,c[w+236>>2]|0,c[w+252>>2]|0,c[p>>2]|0,0);wD(a);Xt(a);l=x;return}function Iu(a,d,e,f,g){a=a|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0;j=l;l=l+16|0;h=j;i=c[a+16>>2]|0;if(!(e<<24>>24))f=c[i+208>>2]|0;if(!(g<<24>>24==0?((f|0)==0?(b[i+260>>1]&1)==0:0):0)){c[h>>2]=c[d>>2];c[h+4>>2]=c[d+4>>2];c[h+8>>2]=c[d+8>>2];c[h+12>>2]=c[d+12>>2];Nu(a,h)}l=j;return}function Ju(b,d,e,f,g,h,i,j,k){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;var m=0,n=0,o=0,p=0,q=0,r=0;r=l;l=l+16|0;o=r;q=c[b+152>>2]|0;if(d|0?a[d+81>>0]|0:0){if(!j)n=0;else{n=ww((sJ(j)|0)+11|0)|0;switch(e|0){case 11:{m=86240;break}case 7:{m=86656;break}case 6:{m=86666;break}default:ma(123205,84925,2730,85060)}c[o>>2]=j;c[o+4>>2]=m;qL(n,85076,o)|0}o=b+16|0;j=(c[o>>2]|0)+12|0;p=c[j>>2]|0;c[j>>2]=e;j=(f|0)!=0|(g|0)!=0;m=(q&4|0)==0;if(j&m){Ku(b,d);xD(b,g,h,i,n)}qw(b,e,d);if(k|0)Lu(b,d,k);if(j){if(!m){Ku(b,d);xD(b,g,h,i,n)}yD(b)}$I(n);c[(c[o>>2]|0)+12>>2]=p}l=r;return}function Ku(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0;d=c[a+16>>2]|0;e=c[a+152>>2]|0;if(e&4259840|0){f=e&131072;i=f>>>16^2;c[d+264>>2]=i;j=d+268|0;c[j>>2]=i+2;i=d+272|0;$I(c[i>>2]|0);d=ww(c[j>>2]<<4)|0;c[i>>2]=d;i=b+56|0;j=b+24|0;h[d>>3]=+h[i>>3]-+h[j>>3]*.5;g=b+64|0;b=b+32|0;h[d+8>>3]=+h[g>>3]-+h[b>>3]*.5;h[d+16>>3]=+h[j>>3]*.5+ +h[i>>3];h[d+24>>3]=+h[b>>3]*.5+ +h[g>>3];if(!(e&8192))gD(a,d,d,2)|0;if(!f)_v(d)}return}function Lu(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0.0;o=l;l=l+96|0;g=o+80|0;i=o+32|0;j=o+16|0;k=o;f=c[d>>2]|0;while(1){m=a[f>>0]|0;if(!(m<<24>>24))break;if(!(YJ(m&255)|0)){n=4;break}else f=f+1|0}if((n|0)==4){p=+h[d+24>>3];m=d+56|0;Mu(i,+h[m>>3]+p*.5,+h[d+64>>3]-+h[d+32>>3]*.5);n=i+16|0;Mu(j,+h[i>>3]-p,+h[i+8>>3]);c[n>>2]=c[j>>2];c[n+4>>2]=c[j+4>>2];c[n+8>>2]=c[j+8>>2];c[n+12>>2]=c[j+12>>2];n=i+32|0;c[g>>2]=c[m>>2];c[g+4>>2]=c[m+4>>2];c[g+8>>2]=c[m+8>>2];c[g+12>>2]=c[m+12>>2];WA(k,e,g);c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];c[n+8>>2]=c[k+8>>2];c[n+12>>2]=c[k+12>>2];GD(b,c[(c[b>>2]|0)+336>>2]|0);CD(b,c[d+8>>2]|0);LD(b,i,3)}l=o;return}function Mu(a,b,c){a=a|0;b=+b;c=+c;h[a>>3]=b;h[a+8>>3]=c;return}function Nu(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0.0,i=0.0,j=0,k=0;d=c[a+16>>2]|0;e=c[a+152>>2]|0;if(e&4259840|0){f=e&131072;j=f>>>16^2;c[d+264>>2]=j;k=d+268|0;c[k>>2]=j+2;j=d+272|0;$I(c[j>>2]|0);d=ww(c[k>>2]<<4)|0;c[j>>2]=d;i=+h[b>>3];h[d>>3]=i+-3.0;g=+h[b+8>>3];h[d+8>>3]=g+-3.0;h[d+16>>3]=i+3.0;h[d+24>>3]=g+3.0;if(!(e&8192))gD(a,d,d,2)|0;if(!f)_v(d)}return}function Ou(a,b,d,e,f,h,i){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;h=+h;i=+i;var j=0,k=0,m=0.0,n=0.0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;J=l;l=l+256|0;D=J+224|0;C=J+208|0;j=J+192|0;F=J+144|0;G=J+96|0;H=J+48|0;E=J;k=J+240|0;e=au(e,f,k)|0;if((e|0)>1){z=b+48|0;A=so(c[((c[b>>2]&3|0)==3?b:z)+40>>2]|0)|0;z=En(c[((c[b>>2]&3|0)==3?b:z)+40>>2]|0)|0;A=(rn(A)|0)!=0;B=En(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0;c[j>>2]=z;c[j+4>>2]=A?85095:85100;c[j+8>>2]=B;$l(3,85105,j)|0;if((e|0)==2)e=1;else I=4}else if((e|0)==1)e=1;else I=4;if((I|0)==4){B=b+16|0;r=c[k>>2]|0;s=r+8|0;t=H+4|0;u=F+8|0;v=F+12|0;w=(d|0)!=0;q=(d|0)==0;x=F+32|0;y=F+4|0;z=F+16|0;A=E+4|0;e=0;p=0;while(1){f=c[(c[B>>2]|0)+8>>2]|0;if((p|0)>=(c[f+4>>2]|0))break;j=F;f=(c[f>>2]|0)+(p*48|0)|0;b=j+48|0;do{c[j>>2]=c[f>>2];j=j+4|0;f=f+4|0}while((j|0)<(b|0));b=1;m=1.0;o=c[s>>2]|0;a:while(1){f=c[o>>2]|0;if(!f)break;k=o+4|0;n=+g[k>>2];do if(n<1.0e-05&n>-1.0e-05)f=b;else{CD(a,f);n=+g[k>>2];m=m-n;e=c[o>>2]|0;if(b|0){Yu(F,n,H,E);k=c[H>>2]|0;KD(a,k,c[t>>2]|0,0,0,0);$I(k);if(m<1.0e-05&m>-1.0e-05){I=11;break a}else{f=0;break}}if(m<1.0e-05&m>-1.0e-05){I=13;break a}j=G;f=E;b=j+48|0;do{c[j>>2]=c[f>>2];j=j+4|0;f=f+4|0}while((j|0)<(b|0));n=+g[k>>2];Yu(G,n/(m+n),H,E);$I(c[G>>2]|0);f=c[H>>2]|0;KD(a,f,c[t>>2]|0,0,0,0);$I(f);f=0}while(0);b=f;o=o+12|0}if((I|0)==11){I=0;$I(c[E>>2]|0)}else if((I|0)==13){I=0;o=c[E>>2]|0;KD(a,o,c[A>>2]|0,0,0,0);$I(o)}if(c[u>>2]|0){CD(a,c[c[s>>2]>>2]|0);ED(a,c[c[s>>2]>>2]|0);k=c[F>>2]|0;o=c[u>>2]|0;c[C>>2]=c[z>>2];c[C+4>>2]=c[z+4>>2];c[C+8>>2]=c[z+8>>2];c[C+12>>2]=c[z+12>>2];c[D>>2]=c[k>>2];c[D+4>>2]=c[k+4>>2];c[D+8>>2]=c[k+8>>2];c[D+12>>2]=c[k+12>>2];Tt(a,2,C,D,h,i,o)}if(c[v>>2]|0){CD(a,e);ED(a,e);k=(c[F>>2]|0)+((c[y>>2]|0)+-1<<4)|0;o=c[v>>2]|0;c[C>>2]=c[x>>2];c[C+4>>2]=c[x+4>>2];c[C+8>>2]=c[x+8>>2];c[C+12>>2]=c[x+12>>2];c[D>>2]=c[k>>2];c[D+4>>2]=c[k+4>>2];c[D+8>>2]=c[k+8>>2];c[D+12>>2]=c[k+12>>2];Tt(a,3,C,D,h,i,o)}do if((c[(c[(c[B>>2]|0)+8>>2]|0)+4>>2]|0)>1){if(!(c[u>>2]|0)){if(!(w&(c[v>>2]|0)!=0))break}else if(q)break;GD(a,d)}while(0);p=p+1|0}bu(r);e=0}l=J;return e|0}function Pu(b,d){b=b|0;d=d|0;var e=0,f=0;e=1;a:while(1){switch(a[b>>0]|0){case 0:break a;case 58:{e=e+1|0;break}default:{}}b=b+1|0}f=O((sJ(d)|0)+1|0,e)|0;b=f+10|0;if((c[42166]|0)<(f|0)){c[42166]=b;b=bJ(c[42167]|0,b)|0;c[42167]=b}else b=c[42167]|0;yK(b,d)|0;while(1){e=e+-1|0;b=c[42167]|0;if(!e)break;f=b+(sJ(b)|0)|0;a[f>>0]=58;a[f+1>>0]=0;JL(b,d)|0}return b|0}function Qu(b){b=b|0;var d=0,e=0;d=c[42229]|0;a:do if(!d)e=7;else{d=Km(b,d)|0;switch(a[d>>0]|0){case 110:if(!(yJ(d,120501)|0)){d=1;break a}else{e=7;break a}case 102:if(!(yJ(d,85082)|0)){d=2;break a}else{e=7;break a}case 98:{if(!(yJ(d,85090)|0)){d=3;break a}if(!(yJ(d,96056)|0)){d=4;break a}else{e=7;break a}}default:{e=7;break a}}}while(0);if((e|0)==7){d=(rn(so(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0)|0)!=0;d=d?2:1}return d|0}function Ru(a){a=a|0;if(a|0){$I(c[a+8>>2]|0);$I(a)}return}function Su(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0.0;e=+h[b>>3]-+h[c>>3];f=+h[b+8>>3]-+h[c+8>>3];d=2.0/+C(+(e*e+.0001+f*f));h[a>>3]=d*f;h[a+8>>3]=-(e*d);return}function Tu(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0.0;g=+h[c>>3]-+h[d>>3];i=+h[c+8>>3]-+h[d+8>>3];f=+C(+(i*i+g*g));if(f<.0001){j=+h[b>>3]-+h[e>>3];f=+h[b+8>>3]-+h[e+8>>3];i=f;g=j;f=+C(+(j*j+.0001+f*f))}j=2.0/f;h[a>>3]=i*j;h[a+8>>3]=-(j*g);return}function Uu(a,b,c){a=+a;b=+b;c=+c;return +(c*.5*(1.0-a/b))}function Vu(a,b,c){a=+a;b=+b;c=+c;return +(c*.5)}function Wu(a,b,c){a=+a;b=+b;c=+c;return +(c*.5*(a/b))}function Xu(a,b,c){a=+a;b=+b;c=+c;b=a/b;return +((!(b<=.5)?1.0-b:b)*c)}function Yu(a,b,d,e){a=a|0;b=+b;d=d|0;e=e|0;var f=0.0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0;p=l;l=l+16|0;o=p;n=c[a+4>>2]|0;j=(n+-1|0)/3|0;if((n+-4|0)>>>0<3){c[d+4>>2]=4;c[d>>2]=ww(64)|0;c[e+4>>2]=4;n=ww(64)|0;c[e>>2]=n;QA(o,c[a>>2]|0,3,b,c[d>>2]|0,n)}else{n=ww(j<<3)|0;g=0;i=c[a>>2]|0;f=0.0;while(1){if((g|0)>=(j|0))break;q=+Zu(i);h[n+(g<<3)>>3]=q;g=g+1|0;i=i+48|0;f=q+f}b=f*b;m=0;f=0.0;while(1){if((j|0)<=(m|0))break;f=+h[n+(m<<3)>>3]+f;if(f>=b)break;m=m+1|0}k=m*3|0;g=k+4|0;i=d+4|0;c[i>>2]=g;c[d>>2]=ww(g<<4)|0;g=((j-m|0)*3|0)+1|0;j=e+4|0;c[j>>2]=g;c[e>>2]=ww(g<<4)|0;g=0;while(1){if((g|0)>=(c[i>>2]|0))break;r=(c[d>>2]|0)+(g<<4)|0;s=(c[a>>2]|0)+(g<<4)|0;c[r>>2]=c[s>>2];c[r+4>>2]=c[s+4>>2];c[r+8>>2]=c[s+8>>2];c[r+12>>2]=c[s+12>>2];g=g+1|0}g=g+-4|0;i=0;while(1){if((i|0)>=(c[j>>2]|0))break;s=(c[e>>2]|0)+(i<<4)|0;r=(c[a>>2]|0)+(g<<4)|0;c[s>>2]=c[r>>2];c[s+4>>2]=c[r+4>>2];c[s+8>>2]=c[r+8>>2];c[s+12>>2]=c[r+12>>2];g=g+1|0;i=i+1|0}q=+h[n+(m<<3)>>3];QA(o,(c[a>>2]|0)+(k<<4)|0,3,(b-f+q)/q,(c[d>>2]|0)+(k<<4)|0,c[e>>2]|0);$I(n)}l=p;return}function Zu(a){a=a|0;var b=0.0,c=0.0,d=0.0,e=0.0,f=0.0;e=+h[a+16>>3];d=+h[a>>3]-e;f=+h[a+24>>3];b=+h[a+8>>3]-f;d=+C(+(b*b+d*d));b=+h[a+32>>3];e=e-b;c=+h[a+40>>3];f=f-c;d=+C(+(f*f+e*e))+d;b=b-+h[a+48>>3];c=c-+h[a+56>>3];return +(d+ +C(+(c*c+b*b)))}function _u(b,d){b=b|0;d=d|0;d=to(d)|0;if((a[(c[d+16>>2]|0)+115>>0]|0)==1)d=zB(b)|0;else d=wB(b,d)|0;return fv(d)|0}function $u(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=+f;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;q=l;l=l+1664|0;m=q+1600|0;n=q+800|0;o=q;p=xw(24)|0;c[p+16>>2]=1;j=((c[e+4>>2]|0)+-1|0)/3|0;h=0;i=p;while(1){if((h|0)>=(j|0))break;k=h*3|0;g=0;while(1){if((g|0)==4)break;r=m+(g<<4)|0;s=(c[e>>2]|0)+(g+k<<4)|0;c[r>>2]=c[s>>2];c[r+4>>2]=c[s+4>>2];c[r+8>>2]=c[s+8>>2];c[r+12>>2]=c[s+12>>2];g=g+1|0}h=h+1|0;i=av(m,i)|0}g=0;h=0;i=p;while(1){if(!i){h=p;g=p;break}j=c[i+16>>2]|0;k=n+(g<<4)|0;e=o+(g<<4)|0;bv(h,i,j,k,e,f);g=g+1|0;if(!((g|0)==50|(j|0)==0)){h=i;i=j;continue}cv(a,b,d,g,n,o);c[n>>2]=c[k>>2];c[n+4>>2]=c[k+4>>2];c[n+8>>2]=c[k+8>>2];c[n+12>>2]=c[k+12>>2];c[o>>2]=c[e>>2];c[o+4>>2]=c[e+4>>2];c[o+8>>2]=c[e+8>>2];c[o+12>>2]=c[e+12>>2];h=i;g=1;i=j}while(1){if(!h)break;s=c[h+16>>2]|0;$I(g);h=s;g=s}l=q;return}function av(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=l;l=l+144|0;f=g+128|0;d=g+64|0;e=g;if(!(gu(a)|0)){QA(f,a,3,.5,d,e);d=av(e,av(d,b)|0)|0}else{d=b+16|0;if((c[d>>2]|0)==1){c[d>>2]=0;c[b>>2]=c[a>>2];c[b+4>>2]=c[a+4>>2];c[b+8>>2]=c[a+8>>2];c[b+12>>2]=c[a+12>>2]}d=a+48|0;c[f>>2]=c[d>>2];c[f+4>>2]=c[d+4>>2];c[f+8>>2]=c[d+8>>2];c[f+12>>2]=c[d+12>>2];d=ev(f,b)|0}l=g;return d|0}function bv(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=+g;var i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0;r=l;l=l+96|0;n=r+80|0;m=r+64|0;k=r+48|0;o=r+32|0;p=r+16|0;q=r;c[o>>2]=c[b>>2];c[o+4>>2]=c[b+4>>2];c[o+8>>2]=c[b+8>>2];c[o+12>>2]=c[b+12>>2];do if(a){c[p>>2]=c[a>>2];c[p+4>>2]=c[a+4>>2];c[p+8>>2]=c[a+8>>2];c[p+12>>2]=c[a+12>>2];if(!d){i=+h[o>>3];h[q>>3]=i*2.0-+h[p>>3];j=+h[o+8>>3];h[q+8>>3]=j*2.0-+h[p+8>>3];break}else{c[q>>2]=c[d>>2];c[q+4>>2]=c[d+4>>2];c[q+8>>2]=c[d+8>>2];c[q+12>>2]=c[d+12>>2];i=+h[o>>3];j=+h[o+8>>3];break}}else{c[q>>2]=c[d>>2];c[q+4>>2]=c[d+4>>2];c[q+8>>2]=c[d+8>>2];c[q+12>>2]=c[d+12>>2];i=+h[o>>3];h[p>>3]=i*2.0-+h[q>>3];j=+h[o+8>>3];h[p+8>>3]=j*2.0-+h[q+8>>3]}while(0);c[k>>2]=c[p>>2];c[k+4>>2]=c[p+4>>2];c[k+8>>2]=c[p+8>>2];c[k+12>>2]=c[p+12>>2];c[m>>2]=c[o>>2];c[m+4>>2]=c[o+4>>2];c[m+8>>2]=c[o+8>>2];c[m+12>>2]=c[o+12>>2];c[n>>2]=c[q>>2];c[n+4>>2]=c[q+4>>2];c[n+8>>2]=c[q+8>>2];c[n+12>>2]=c[q+12>>2];t=+dv(k,m,n);s=+E(+t)*g;g=+F(+t)*g;h[e>>3]=i+s;h[e+8>>3]=j+g;h[f>>3]=i-s;h[f+8>>3]=j-g;l=r;return}function cv(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0;i=e<<1;j=c[d>>2]|0;h=0;k=0;while(1){if((h|0)>=(j|0))break;l=(c[(c[b>>2]|0)+(h<<2)>>2]|0)+k|0;h=h+1|0;k=l}l=j+1|0;c[d>>2]=l;l=zw(c[b>>2]|0,l<<2)|0;c[b>>2]=l;c[l+(h<<2)>>2]=i;c[a>>2]=zw(c[a>>2]|0,k+i<<4)|0;b=i+-1+k|0;h=0;while(1){if((h|0)>=(e|0))break;l=(c[a>>2]|0)+(h+k<<4)|0;j=f+(h<<4)|0;c[l>>2]=c[j>>2];c[l+4>>2]=c[j+4>>2];c[l+8>>2]=c[j+8>>2];c[l+12>>2]=c[j+12>>2];l=(c[a>>2]|0)+(b-h<<4)|0;j=g+(h<<4)|0;c[l>>2]=c[j>>2];c[l+4>>2]=c[j+4>>2];c[l+8>>2]=c[j+8>>2];c[l+12>>2]=c[j+12>>2];h=h+1|0}return}function dv(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0.0;f=+h[b+8>>3];d=+h[b>>3];e=+K(+(+h[c+8>>3]-f),+(+h[c>>3]-d));d=+K(+(+h[a+8>>3]-f),+(+h[a>>3]-d));e=e-d;return +((e>0.0?e+-6.283185307179586:e)*.5+d)}function ev(a,b){a=a|0;b=b|0;var d=0;d=xw(24)|0;c[d+16>>2]=0;c[d>>2]=c[a>>2];c[d+4>>2]=c[a+4>>2];c[d+8>>2]=c[a+8>>2];c[d+12>>2]=c[a+12>>2];c[b+16>>2]=d;return d|0}function fv(b){b=b|0;var c=0,d=0,e=0,f=0,g=0;c=b;f=b;a:while(1){e=0;while(1){d=c;c=c+1|0;d=a[d>>0]|0;if(!(d<<24>>24))break a;if(e<<24>>24){g=5;break}if(d<<24>>24!=92)break;else e=1}b:do if((g|0)==5){g=0;switch(d<<24>>24|0){case 114:{d=13;break b}case 108:case 110:{d=10;break b}default:break b}}while(0);a[f>>0]=d;f=f+1|0}a[f>>0]=0;return b|0}function gv(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;e=c[b>>2]|0;while(1){g=a[e>>0]|0;if(!(g<<24>>24)){f=0;break}f=g<<24>>24;if(!(g<<24>>24==44|(YJ(f)|0)!=0)){h=5;break}e=e+1|0}a:do if((h|0)==5){switch(f|0){case 0:{f=0;break a}case 41:case 40:{e=e+1|0;break a}default:{}}h=d+4|0;i=d+8|0;while(1){if((hv(g<<24>>24)|0)<<24>>24){f=1;break a}f=c[h>>2]|0;if(f>>>0>=(c[i>>2]|0)>>>0){em(d,1)|0;f=c[h>>2]|0}c[h>>2]=f+1;a[f>>0]=g;f=e+1|0;e=f;g=a[f>>0]|0}}while(0);c[b>>2]=e;return f|0}function hv(a){a=a|0;switch(a|0){case 0:case 44:case 41:case 40:{a=1;break}default:a=0}return a|0}function iv(a,b){a=a|0;b=b|0;return jv(c[a>>2]|0,c[a+160>>2]|0,c[a+156>>2]|0,b)|0}function jv(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+160|0;k=o+20|0;m=o+16|0;n=o;c[k>>2]=0;c[m>>2]=0;dm(n,128,o+24|0);gm(n,f)|0;g=n+4|0;f=c[g>>2]|0;if(f>>>0>=(c[n+8>>2]|0)>>>0){em(n,1)|0;f=c[g>>2]|0}a[f>>0]=0;h=c[n>>2]|0;c[g>>2]=h;i=b+300|0;j=b+296|0;f=0;g=h;a:while(1){if(f){f=1;break}f=GL(g,c[i>>2]|0,k)|0;if(!f){f=0;break}g=GL(f,c[j>>2]|0,m)|0;h=(g|0)!=0;if(h)f=GL(0,c[j>>2]|0,m)|0;else f=0;switch(((f|0)!=0&1)+(h&1)&3){case 2:{g=kv(b,g,0)|0;f=kv(b,f,e)|0;h=(g|0)>(f|0);f=(f&g|0)>-1&(((h?g:f)|0)>=(d|0)&((h?f:g)|0)<=(d|0));g=0;continue a}case 1:{f=(kv(b,g,d)|0)==(d|0);g=0;continue a}default:{f=0;g=0;continue a}}}hm(n);l=o;return f|0}function kv(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;h=a[d>>0]|0;if(!(h<<24>>24==97?(yJ(d,85419)|0)==0:0))f=3;a:do if((f|0)==3){if((lv(d)|0)<<24>>24){e=sM(d)|0;break}g=c[b+308>>2]|0;if(!g)e=-1;else{b=c[b+312>>2]|0;e=1;while(1){if((e|0)>(b|0)){e=-1;break a}f=c[g+(e<<2)>>2]|0;if(h<<24>>24==(a[f>>0]|0)?(yJ(d,f)|0)==0:0)break a;e=e+1|0}}}while(0);return e|0}function lv(b){b=b|0;var c=0;while(1){c=a[b>>0]|0;if(!(c<<24>>24)){b=1;break}if(((c&255)+-48|0)>>>0<10)b=b+1|0;else{b=0;break}}return b|0}function mv(a,b){a=a|0;b=b|0;if((+h[a+16>>3]>=+h[b>>3]?+h[b+16>>3]>=+h[a>>3]:0)?+h[a+24>>3]>=+h[b+8>>3]:0)a=+h[b+24>>3]>=+h[a+8>>3]&1;else a=0;return a|0}function nv(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0;a:do if((c[b+156>>2]|0)>=2?(f=GA(e,c[42212]|0,174185)|0,(iv(b,f)|0)<<24>>24==0):0)if(!(a[f>>0]|0))if(!(Vm(d,e)|0))f=1;else{f=Vm(d,e)|0;while(1){if(!f){f=0;break a}g=GA(f,c[42235]|0,174185)|0;if(!(a[g>>0]|0)){f=1;break a}if((iv(b,g)|0)<<24>>24){f=1;break a}f=Wm(d,f,e)|0}}else f=0;else f=1;while(0);return f|0}function ov(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=l;l=l+64|0;e=d+32|0;f=d;a=(c[a+16>>2]|0)+48|0;c[f>>2]=c[a>>2];c[f+4>>2]=c[a+4>>2];c[f+8>>2]=c[a+8>>2];c[f+12>>2]=c[a+12>>2];c[f+16>>2]=c[a+16>>2];c[f+20>>2]=c[a+20>>2];c[f+24>>2]=c[a+24>>2];c[f+28>>2]=c[a+28>>2];c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];c[e+8>>2]=c[b+8>>2];c[e+12>>2]=c[b+12>>2];c[e+16>>2]=c[b+16>>2];c[e+20>>2]=c[b+20>>2];c[e+24>>2]=c[b+24>>2];c[e+28>>2]=c[b+28>>2];b=(mv(f,e)|0)&255;l=d;return b|0}function pv(a,d){a=a|0;d=d|0;var f=0.0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0,t=0,u=0.0,v=0.0;r=c[a+152>>2]|0;s=Wt(a)|0;c[s+4>>2]=2;c[s+8>>2]=d;c[s+12>>2]=8;if(r&16777216|0){if((e[(c[(so(d)|0)+16>>2]|0)+178>>1]|0)>2){f=+h[(c[(c[d+16>>2]|0)+132>>2]|0)+16>>3]*72.0;f=+(~~(f+(f>=0.0?.5:-.5))|0)}else f=0.0;h[s+168>>3]=f}k=d+16|0;rv(a,c[(c[k>>2]|0)+104>>2]|0,d);do if(r&4259840|0){if((c[s+208>>2]|0)==0?(b[s+260>>1]&1)==0:0)break;p=Cy(d)|0;l=c[k>>2]|0;f=+h[l+16>>3];q=+h[l+24>>3];l=sv(d)|0;a:do if((p|2|0)==3){n=c[(c[k>>2]|0)+12>>2]|0;if(!((tv(n)|0)<<24>>24))g=0;else g=(c[n+4>>2]|l|0)!=0;if(!((r&524288|0)==0|((n|0)==0|g))){i=n+8|0;o=c[i>>2]|0;o=(o|0)<3?1:o;j=n+4|0;m=c[j>>2]|0;m=(m|0)>1?m:1;p=c[n+44>>2]|0;g=Jm(d,87739)|0;if(!g)g=0;else g=sM(g)|0;g=(g+-4|0)>>>0>56?20:g;if(!(c[j>>2]|l)){c[s+264>>2]=0;i=ww(32)|0;g=c[k>>2]|0;v=+h[g+88>>3];h[i>>3]=f-v;u=+h[g+80>>3]*.5;h[i+8>>3]=q-u;h[i+16>>3]=v+f;h[i+24>>3]=u+q;g=2;break}i=c[i>>2]|0;if(((i|0)<3?+h[n+32>>3]==0.0:0)?+h[n+24>>3]==0.0:0){i=s+264|0;if(c[n>>2]|0){c[i>>2]=1;i=ww(32)|0;h[i>>3]=f;h[i+8>>3]=q;g=(m<<1)+-1|0;h[i+16>>3]=+h[p+(g<<4)>>3]+f;h[i+24>>3]=+h[p+(g<<4)+8>>3]+q;g=2;break}c[i>>2]=2;i=(m<<1)+-1|0;i=uv(+h[p+(i<<4)>>3],+h[p+(i<<4)+8>>3],g)|0;j=0;while(1){if((j|0)>=(g|0))break a;p=i+(j<<4)|0;h[p>>3]=+h[p>>3]+f;p=i+(j<<4)+8|0;h[p>>3]=+h[p>>3]+q;j=j+1|0}}m=O(i,m+-1|0)|0;c[s+264>>2]=2;if((i|0)<(g|0)){i=ww(o<<4)|0;g=0;while(1){if((g|0)>=(o|0)){g=o;break a}n=g+m|0;h[i+(g<<4)>>3]=+h[p+(n<<4)>>3]+f;h[i+(g<<4)+8>>3]=+h[p+(n<<4)+8>>3]+q;g=g+1|0}}else{l=(i|0)/(g|0)|0;i=ww(g<<4)|0;j=0;k=0;while(1){if((j|0)>=(g|0))break a;o=k+m|0;h[i+(j<<4)>>3]=+h[p+(o<<4)>>3]+f;h[i+(j<<4)+8>>3]=+h[p+(o<<4)+8>>3]+q;j=j+1|0;k=k+l|0}}}else t=31}else t=31;while(0);if((t|0)==31){c[s+264>>2]=0;i=ww(32)|0;g=c[k>>2]|0;h[i>>3]=f-+h[g+88>>3];v=+h[g+80>>3]*.5;h[i+8>>3]=q-v;h[i+16>>3]=+h[g+96>>3]+f;h[i+24>>3]=v+q;g=2}if(!(r&8192))gD(a,i,i,g)|0;c[s+272>>2]=i;c[s+268>>2]=g}while(0);_E(Jm(d,85048)|0);tD(a,d);return}function qv(a){a=a|0;uD(a);Xt(a);return}function rv(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+144|0;j=m;f=Jm(e,96264)|0;i=Jm(e,96229)|0;k=Jm(e,85204)|0;dm(j,128,m+16|0);if(!d)h=0;else h=c[d>>2]|0;if(!((f|0)!=0?(a[f>>0]|0)!=0:0))f=Jm(e,96269)|0;g=Zt(b,e,j)|0;if(!i)d=0;else d=_u(i,e)|0;Yt(b,h,f,d,k,g,e)|0;$I(d);hm(j);l=m;return}function sv(b){b=b|0;var d=0,e=0;b=HA(b,c[42202]|0,174185)|0;a:do if(!(a[b>>0]|0))b=0;else{Eu(b)|0;b=0;d=168408;while(1){e=c[d>>2]|0;if(!e)break a;e=(yJ(e,95923)|0)==0;b=e?1:b;d=d+4|0}}while(0);return b|0}function tv(a){a=a|0;var b=0.0;if(((c[a+8>>2]|0)==4?(b=+h[a+16>>3],((~~(b+(b>=0.0?.5:-.5))|0)%90|0|0)==0):0)?+h[a+24>>3]==0.0:0)a=+h[a+32>>3]==0.0&1;else a=0;return a|0}function uv(a,b,c){a=+a;b=+b;c=c|0;var d=0.0,e=0,f=0.0,g=0;f=6.283185307179586/+(c|0);g=ww(c<<4)|0;d=0.0;e=0;while(1){if((e|0)>=(c|0))break;h[g+(e<<4)>>3]=+E(+d)*a;h[g+(e<<4)+8>>3]=+F(+d)*b;d=d+f;e=e+1|0}return g|0}function vv(b,d){b=b|0;d=d|0;var e=0;a:do if((c[b+156>>2]|0)>=2?(e=GA(d,zm(d,0,86583,0)|0,174185)|0,(iv(b,e)|0)<<24>>24==0):0)if(!(a[e>>0]|0)){e=eo(d)|0;while(1){if(!e){e=0;break a}if((nv(b,d,e)|0)<<24>>24){e=1;break a}e=fo(d,e)|0}}else e=0;else e=1;while(0);return e|0}function wv(a,b){a=a|0;b=b|0;var d=0;d=Wt(a)|0;c[d+4>>2]=1;c[d+8>>2]=b;c[d+12>>2]=1;rv(a,c[(c[b+16>>2]|0)+12>>2]|0,b);nD(a,b);return}function xv(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;b=Jm(b,86479)|0;a:do if((b|0)!=0?(a[b>>0]|0)!=0:0){Eu(b)|0;e=168408;b=0;while(1){while(1){f=c[e>>2]|0;if(!f){e=168408;break a}if(!(yJ(f,95923)|0)){g=10;break}if(!(yJ(f,91378)|0)){f=e;g=12;break}if(!(yJ(f,91385)|0)){f=e;g=14;break}if(!(yJ(f,91360)|0)){f=e;g=16;break}e=e+4|0}if((g|0)==10){e=e+4|0;b=b|1;continue}else if((g|0)==12){while(1){h=f;f=f+4|0;g=c[f>>2]|0;c[h>>2]=g;if(!g)break;else g=12}b=b|3;continue}else if((g|0)==14){while(1){g=f;f=f+4|0;h=c[f>>2]|0;c[g>>2]=h;if(!h)break;else g=14}b=b|64;continue}else if((g|0)==16){while(1){g=f;f=f+4|0;h=c[f>>2]|0;c[g>>2]=h;if(!h)break;else g=16}b=b|4;continue}}}else{e=0;b=0}while(0);c[d>>2]=b;return e|0}function yv(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,h=0,i=0,j=0,k=0,m=0;k=l;l=l+16|0;i=k;j=k+4|0;c[j>>2]=0;m=(au(b,0,j)|0)==0;j=c[j>>2]|0;if((m?(f=c[j>>2]|0,(f|0)>=2):0)?(h=j+8|0,(c[c[h>>2]>>2]|0)!=0):0){if((f|0)>2)$l(0,85446,i)|0;m=xw((sJ(b)|0)+1|0)|0;c[d>>2]=m;yK(m,c[c[h>>2]>>2]|0)|0;if(!(c[(c[h>>2]|0)+12>>2]|0))c[d+4>>2]=0;else{m=c[d>>2]|0;m=m+((sJ(m)|0)+1)|0;c[d+4>>2]=m;yK(m,c[(c[h>>2]|0)+12>>2]|0)|0}b=c[h>>2]|0;do if(!(a[b+8>>0]|0))if(!(a[b+20>>0]|0)){g[e>>2]=0.0;break}else{g[e>>2]=1.0-+g[b+16>>2];break}else c[e>>2]=c[b+4>>2];while(0);bu(j);b=1}else{c[d>>2]=0;bu(j);b=0}l=k;return b|0}function zv(a,b){a=a|0;b=b|0;oD(a,b);Xt(a);return}function Av(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,i=0,j=0,k=0.0,m=0.0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;x=l;l=l+96|0;p=x+48|0;s=x+16|0;w=x+8|0;v=x;t=x+80|0;c[t>>2]=1e3;f=xw(16e3)|0;u=a+256|0;e=1;j=1;i=0;q=0;r=c[b+8>>2]|0;while(1){if((q|0)>=(c[b>>2]|0))break;d=c[r>>2]|0;a:do switch(d|0){case 1:case 0:{n=r+80|0;c[s>>2]=c[n>>2];c[s+4>>2]=c[n+4>>2];c[s+8>>2]=c[n+8>>2];c[s+12>>2]=c[n+12>>2];c[s+16>>2]=c[n+16>>2];c[s+20>>2]=c[n+20>>2];c[s+24>>2]=c[n+24>>2];c[s+28>>2]=c[n+28>>2];c[p>>2]=c[u>>2];c[p+4>>2]=c[u+4>>2];c[p+8>>2]=c[u+8>>2];c[p+12>>2]=c[u+12>>2];c[p+16>>2]=c[u+16>>2];c[p+20>>2]=c[u+20>>2];c[p+24>>2]=c[u+24>>2];c[p+28>>2]=c[u+28>>2];if(!(mv(s,p)|0))d=j;else{z=r+8|0;A=r+24|0;h[f>>3]=+h[z>>3]-+h[A>>3];n=r+16|0;y=r+32|0;h[f+8>>3]=+h[n>>3]-+h[y>>3];h[f+16>>3]=+h[A>>3]+ +h[z>>3];h[f+24>>3]=+h[y>>3]+ +h[n>>3];HD(a,f,2,(d|0)==0?j:0);d=j}break}case 3:case 2:{A=r+80|0;c[s>>2]=c[A>>2];c[s+4>>2]=c[A+4>>2];c[s+8>>2]=c[A+8>>2];c[s+12>>2]=c[A+12>>2];c[s+16>>2]=c[A+16>>2];c[s+20>>2]=c[A+20>>2];c[s+24>>2]=c[A+24>>2];c[s+28>>2]=c[A+28>>2];c[p>>2]=c[u>>2];c[p+4>>2]=c[u+4>>2];c[p+8>>2]=c[u+8>>2];c[p+12>>2]=c[u+12>>2];c[p+16>>2]=c[u+16>>2];c[p+20>>2]=c[u+20>>2];c[p+24>>2]=c[u+24>>2];c[p+28>>2]=c[u+28>>2];if(!(mv(s,p)|0))d=j;else{d=r+8|0;f=Bv(f,t,c[d+4>>2]|0,c[d>>2]|0)|0;ID(a,f,c[d>>2]|0,(c[r>>2]|0)==2?j:0);d=j}break}case 5:case 4:{A=r+80|0;c[s>>2]=c[A>>2];c[s+4>>2]=c[A+4>>2];c[s+8>>2]=c[A+8>>2];c[s+12>>2]=c[A+12>>2];c[s+16>>2]=c[A+16>>2];c[s+20>>2]=c[A+20>>2];c[s+24>>2]=c[A+24>>2];c[s+28>>2]=c[A+28>>2];c[p>>2]=c[u>>2];c[p+4>>2]=c[u+4>>2];c[p+8>>2]=c[u+8>>2];c[p+12>>2]=c[u+12>>2];c[p+16>>2]=c[u+16>>2];c[p+20>>2]=c[u+20>>2];c[p+24>>2]=c[u+24>>2];c[p+28>>2]=c[u+28>>2];if(!(mv(s,p)|0))d=j;else{d=r+8|0;f=Bv(f,t,c[d+4>>2]|0,c[d>>2]|0)|0;KD(a,f,c[d>>2]|0,0,0,(c[r>>2]|0)==4?j&255:0);d=j}break}case 6:{A=r+80|0;c[s>>2]=c[A>>2];c[s+4>>2]=c[A+4>>2];c[s+8>>2]=c[A+8>>2];c[s+12>>2]=c[A+12>>2];c[s+16>>2]=c[A+16>>2];c[s+20>>2]=c[A+20>>2];c[s+24>>2]=c[A+24>>2];c[s+28>>2]=c[A+28>>2];c[p>>2]=c[u>>2];c[p+4>>2]=c[u+4>>2];c[p+8>>2]=c[u+8>>2];c[p+12>>2]=c[u+12>>2];c[p+16>>2]=c[u+16>>2];c[p+20>>2]=c[u+20>>2];c[p+24>>2]=c[u+24>>2];c[p+28>>2]=c[u+28>>2];if(!(mv(s,p)|0))d=j;else{d=r+8|0;f=Bv(f,t,c[d+4>>2]|0,c[d>>2]|0)|0;LD(a,f,c[d>>2]|0);d=j}break}case 7:{A=r+80|0;c[s>>2]=c[A>>2];c[s+4>>2]=c[A+4>>2];c[s+8>>2]=c[A+8>>2];c[s+12>>2]=c[A+12>>2];c[s+16>>2]=c[A+16>>2];c[s+20>>2]=c[A+20>>2];c[s+24>>2]=c[A+24>>2];c[s+28>>2]=c[A+28>>2];c[p>>2]=c[u>>2];c[p+4>>2]=c[u+4>>2];c[p+8>>2]=c[u+8>>2];c[p+12>>2]=c[u+12>>2];c[p+16>>2]=c[u+16>>2];c[p+20>>2]=c[u+20>>2];c[p+24>>2]=c[u+24>>2];c[p+28>>2]=c[u+28>>2];if(!(mv(s,p)|0))d=j;else{h[f>>3]=+h[r+8>>3];h[f+8>>3]=+h[r+16>>3];d=c[r+112>>2]|0;c[p>>2]=c[f>>2];c[p+4>>2]=c[f+4>>2];c[p+8>>2]=c[f+8>>2];c[p+12>>2]=c[f+12>>2];BD(a,p,d);d=j}break}case 8:{ED(a,c[r+8>>2]|0);d=1;break}case 9:{CD(a,c[r+8>>2]|0);d=1;break}case 13:{if((c[r+8>>2]|0)!=2){d=r+16|0;z=c[d+36>>2]|0;A=c[z+12>>2]|0;o=+g[z+8>>2];d=~~(+K(+(+h[r+40>>3]-+h[r+24>>3]),+(+h[r+32>>3]-+h[d>>3]))*57.29577951308232);ED(a,c[z+4>>2]|0);FD(a,A,d,o);d=2;break a}A=c[r+68>>2]|0;j=c[A+4>>2]|0;n=c[A+12>>2]|0;o=+g[A+8>>2];k=+h[r+40>>3];m=+h[r+16>>3];if(k==m?+h[r+48>>3]==+h[r+24>>3]:0)d=0;else d=~~(+H(+((m-k)/+h[r+32>>3]))*57.29577951308232);ED(a,j);FD(a,n,d,o);d=3;break}case 14:{$l(0,85512,v)|0;d=j;break}case 12:{if(!e){e=0;d=j}else{$l(0,85552,w)|0;e=0;d=j}break}case 11:{Eu(c[r+8>>2]|0)|0;GD(a,168408);i=168408;d=j;break}default:d=j}while(0);j=d;q=q+1|0;r=r+120|0}if(i|0)GD(a,c[(c[a>>2]|0)+336>>2]|0);$I(f);l=x;return}function Bv(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;g=c[b>>2]|0;f=g<<1;f=(f|0)>(e|0)?f:e;if((g|0)<(e|0)){a=zw(a,f<<4)|0;c[b>>2]=f}b=0;while(1){if((b|0)>=(e|0))break;h[a+(b<<4)>>3]=+h[d+(b*24|0)>>3];h[a+(b<<4)+8>>3]=+h[d+(b*24|0)+8>>3];b=b+1|0}return a|0}function Cv(a,b){a=a|0;b=b|0;var d=0;d=c[b>>2]|0;c[a>>2]=c[b+4>>2];c[a+4>>2]=d;return}function Dv(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;g=d+16|0;f=1;while(1){d=c[g>>2]|0;if((f|0)>(c[d+180>>2]|0))break;e=c[(c[d+184>>2]|0)+(f<<2)>>2]|0;Dv(b,e);d=Jm(e,122540)|0;if(d|0?a[d>>0]|0:0)CD(b,d);d=Jm(e,122531)|0;if(d|0?a[d>>0]|0:0)CD(b,d);d=Jm(e,85423)|0;if(d|0?a[d>>0]|0:0)CD(b,d);d=Jm(e,86469)|0;if(d|0?a[d>>0]|0:0)ED(b,d);d=Jm(e,86503)|0;if(d|0?a[d>>0]|0:0)CD(b,d);f=f+1|0}return}function Ev(a){a=a|0;var b=0,d=0,e=0;b=c[42172]|0;if(!b){b=Rl(19684,c[4345]|0)|0;c[42172]=b}if(!(bb[c[b>>2]&31](b,a,4)|0)){d=c[42172]|0;e=c[d>>2]|0;b=HL(a)|0;bb[e&31](d,b,1)|0;b=1}else b=0;return b|0}function Fv(a,b,c){a=a|0;b=b|0;c=c|0;$I(b);return}function Gv(a){a=a|0;var b=0;b=c[42173]|0;if(!a){if((b|0)>0?(b=b+-1|0,c[42173]=b,(b|0)==0):0){cL(1,c[42174]|0)|0;$I(c[42174]|0)}}else{c[42173]=b+1;if(!b){c[42174]=HL(cL(1,0)|0)|0;cL(1,134865)|0}}return}function Hv(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0;u=l;l=l+96|0;r=u+72|0;q=u+56|0;p=u+48|0;t=u+32|0;s=u+24|0;e=u+8|0;d=u;if(0)yA();do if((Oo(b,122277,0,1)|0)!=0?(o=b+16|0,(c[(c[o>>2]|0)+8>>2]|0)!=0):0){Iv(b);Jv(a,b);Kv(a,b);Gv(1);j=a+56|0;k=a+184|0;m=a+192|0;n=a+28|0;i=Dr(a)|0;a:while(1){if(!i){g=33;break}d=c[j>>2]|0;if(!d){c[i+20>>2]=0;d=0}else{c[i+20>>2]=c[d+8>>2];d=c[d+12>>2]|0}c[i+24>>2]=d;c[i+12>>2]=a;c[i+28>>2]=c[k>>2];c[i+620>>2]=24748;c[i+624>>2]=14;if(!(c[(c[o>>2]|0)+8>>2]|0)){g=13;break}e=i+52|0;g=cD(i,c[e>>2]|0)|0;c[i+56>>2]=g;switch(g|0){case 999:{g=16;break a}case 21:{d=1;break}case 24:{d=520;break}default:d=Lv(b)|0}f=i+152|0;c[f>>2]=c[f>>2]|d;d=c[m>>2]|0;do if(!d)g=24;else{if(c[d+152>>2]&32|0?(yJ(c[e>>2]|0,c[d+52>>2]|0)|0)==0:0){d=c[42175]|0;if(!d){g=27;break}c[d+8>>2]=i;c[i+36>>2]=c[d+36>>2];g=29;break}eD(d);c[m>>2]=0;c[n>>2]=0;g=24}while(0);if((g|0)==24){c[42175]=0;g=27}if((g|0)==27?(g=0,(dD(i)|0)==0):0){c[m>>2]=i;g=29}if((g|0)==29){c[i+8>>2]=0;c[i+104>>2]=24860;Mv(i);Nv(i);Ov(i,b);Pv(i,b);Qv(i,b);if(!(c[f>>2]&128))hu(i,b);c[42175]=i}i=Er(a)|0}if((g|0)==13){$l(1,85710,s)|0;Gv(0);if(!0){d=-1;break}d=c[13918]|0;s=En(b)|0;v=+zA();c[t>>2]=s;h[t+8>>3]=v;AL(d,85681,t)|0;d=-1;break}else if((g|0)==16){c[p>>2]=c[e>>2];$l(1,85731,p)|0;Gv(0);if(!0){d=-1;break}d=c[13918]|0;t=En(b)|0;v=+zA();c[q>>2]=t;h[q+8>>3]=v;AL(d,85681,q)|0;d=-1;break}else if((g|0)==33){Gv(0);if(!0){d=0;break}d=c[13918]|0;t=En(b)|0;v=+zA();c[r>>2]=t;h[r+8>>3]=v;AL(d,85681,r)|0;d=0;break}}else g=5;while(0);if((g|0)==5){$l(1,85633,d)|0;if(!0)d=-1;else{d=c[13918]|0;t=En(b)|0;v=+zA();c[e>>2]=t;h[e+8>>3]=v;AL(d,85681,e)|0;d=-1}}l=u;return d|0}function Iv(a){a=a|0;var b=0;b=eo(a)|0;while(1){if(!b)break;Vv(a,b);b=fo(a,b)|0}return}function Jv(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0.0;o=l;l=l+32|0;k=o+24|0;f=o+16|0;j=o+8|0;n=o;c[b+168>>2]=d;g=b+293|0;a[g>>0]=0;e=Jm(d,90530)|0;if(e|0?(c[f>>2]=j,c[f+4>>2]=n,i=dM(e,90537,f)|0,(i|0)>0):0){p=+h[j>>3]*72.0;e=b+208|0;h[e>>3]=p;h[b+200>>3]=p;if((i|0)!=1)h[e>>3]=+h[n>>3]*72.0;a[g>>0]=1}f=b+292|0;a[f>>0]=0;e=Jm(d,86133)|0;if(e|0?(c[k>>2]=j,c[k+4>>2]=n,m=dM(e,90537,k)|0,(m|0)>0):0){p=+h[j>>3]*72.0;e=b+224|0;h[e>>3]=p;h[b+216>>3]=p;if((m|0)!=1)h[e>>3]=+h[n>>3]*72.0;a[f>>0]=1}e=b+294|0;a[e>>0]=0;f=b+232|0;g=d+16|0;n=(c[(c[g>>2]|0)+8>>2]|0)+48|0;c[f>>2]=c[n>>2];c[f+4>>2]=c[n+4>>2];c[f+8>>2]=c[n+8>>2];c[f+12>>2]=c[n+12>>2];f=c[(c[g>>2]|0)+8>>2]|0;if(+h[f+48>>3]>.001?+h[f+56>>3]>.001:0)a[e>>0]=1;c[b+288>>2]=a[f+81>>0]|0?90:0;e=b+196|0;c[e>>2]=86137;f=Jm(d,86140)|0;if(f|0?a[f>>0]|0:0)c[e>>2]=f;n=b+256|0;m=(c[g>>2]|0)+16|0;c[n>>2]=c[m>>2];c[n+4>>2]=c[m+4>>2];c[n+8>>2]=c[m+8>>2];c[n+12>>2]=c[m+12>>2];c[n+16>>2]=c[m+16>>2];c[n+20>>2]=c[m+20>>2];c[n+24>>2]=c[m+24>>2];c[n+28>>2]=c[m+28>>2];c[42186]=zm(d,0,86535,0)|0;c[42187]=zm(d,0,86520,0)|0;c[b+320>>2]=HA(0,c[42196]|0,93027)|0;h[b+328>>3]=+FA(0,c[42195]|0,14.0,1.0);c[b+336>>2]=19720;c[b+188>>2]=En(d)|0;l=o;return}function Kv(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;e=b+304|0;f=c[e>>2]|0;if(f|0){$I(f);c[e>>2]=0}f=b+308|0;e=c[f>>2]|0;if(e|0){$I(e);c[f>>2]=0}g=b+316|0;e=c[g>>2]|0;if(e|0){$I(e);c[g>>2]=0}e=Jm(d,85884)|0;if(e){c[b+312>>2]=Tv(b,d,e)|0;e=Jm(d,85891)|0;if(e|0?a[e>>0]|0:0)c[g>>2]=Uv(b,e)|0}else{c[f>>2]=0;c[b+312>>2]=1}return}function Lv(b){b=b|0;b=Jm(b,85852)|0;a:do if(!b)b=0;else switch(a[b>>0]|0){case 110:{if(!(yJ(b+1|0,85864)|0))b=1;else{b=0;break a}break}case 101:{if(!(yJ(b+1|0,85874)|0))b=16;else{b=0;break a}break}default:{b=0;break a}}while(0);return b|0}function Mv(b){b=b|0;var d=0.0,e=0;e=c[b>>2]|0;if(!(a[e+292>>0]|0)){if((c[b+56>>2]|0)==300)d=+h[(c[b+68>>2]|0)+8>>3];else d=4.0;h[b+248>>3]=d;h[b+240>>3]=d}else{b=b+240|0;e=e+216|0;c[b>>2]=c[e>>2];c[b+4>>2]=c[e+4>>2];c[b+8>>2]=c[e+8>>2];c[b+12>>2]=c[e+12>>2]}return}function Nv(b){b=b|0;var d=0;d=c[b>>2]|0;a:do if(!(a[d+293>>0]|0))switch(c[b+56>>2]|0){case 300:{d=b+416|0;b=(c[b+84>>2]|0)+8|0;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];break a}case 30:case 21:case 22:case 4:case 3:case 2:{h[b+424>>3]=36.0;h[b+416>>3]=36.0;break a}default:{d=b+416|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;break a}}else{b=b+416|0;d=d+200|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2]}while(0);return}function Ov(b,d){b=b|0;d=d|0;var e=0.0,f=0;f=c[(c[b>>2]|0)+192>>2]|0;e=+h[(c[(c[d+16>>2]|0)+8>>2]|0)+24>>3];do if(!(e!=0.0)){if(f|0?a[f+128>>0]|0:0){b=b+432|0;f=f+112|0;c[b>>2]=c[f>>2];c[b+4>>2]=c[f+4>>2];c[b+8>>2]=c[f+8>>2];c[b+12>>2]=c[f+12>>2];break}d=b+432|0;if((c[b+56>>2]|0)==300){b=(c[b+84>>2]|0)+40|0;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];break}else{h[b+440>>3]=96.0;h[d>>3]=96.0;break}}else{h[b+440>>3]=e;h[b+432>>3]=e}while(0);return}function Pv(b,d){b=b|0;d=d|0;var e=0.0,f=0.0,g=0,i=0.0,j=0.0,k=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;A=l;l=l+112|0;t=A+80|0;u=A+56|0;s=A+40|0;v=A+32|0;w=A+24|0;x=A+16|0;y=A+8|0;z=A;m=c[b>>2]|0;o=+h[m+272>>3];q=+h[m+280>>3];p=+h[m+256>>3];r=+h[m+264>>3];f=+h[b+240>>3];e=p-f;h[b+208>>3]=e;i=+h[b+248>>3];j=r-i;h[b+216>>3]=j;f=f+o;h[b+224>>3]=f;i=i+q;h[b+232>>3]=i;e=f-e;j=i-j;h[x>>3]=1.0;g=c[(c[d+16>>2]|0)+8>>2]|0;i=+h[g+64>>3];do if(i>.001?(k=+h[g+72>>3],k>.001):0){e=e==0.0?i:e;f=j==0.0?k:j;if(!(if&(i>e&(a[g+80>>0]|0)!=0)):0){k=e;j=f;i=1.0;break}n=i/e>3]=i;k=e;j=f}else{k=e;i=1.0}while(0);f=(p+o)*.5;h[y>>3]=f;e=(r+q)*.5;h[z>>3]=e;c[b+360>>2]=c[m+288>>2];k=i*k;h[v>>3]=k;j=i*j;h[w>>3]=j;g=Jm(d,85783)|0;if(g){m=_I((sJ(g)|0)+1|0)|0;n=_I((sJ(g)|0)+1|0)|0;c[s>>2]=v;c[s+4>>2]=w;c[s+8>>2]=x;c[s+12>>2]=m;do if((dM(g,85792,s)|0)==4){g=oo(c[d+60>>2]|0,m,0)|0;if(g|0){u=c[g+16>>2]|0;h[y>>3]=+h[u+16>>3];h[z>>3]=+h[u+24>>3]}}else{c[u>>2]=v;c[u+4>>2]=w;c[u+8>>2]=x;c[u+12>>2]=m;c[u+16>>2]=n;if((dM(g,85812,u)|0)!=4){c[t>>2]=v;c[t+4>>2]=w;c[t+8>>2]=x;c[t+12>>2]=y;c[t+16>>2]=z;dM(g,85832,t)|0;break}g=oo(c[d+60>>2]|0,m,0)|0;if(g|0){u=c[g+16>>2]|0;h[y>>3]=+h[u+16>>3];h[z>>3]=+h[u+24>>3]}}while(0);$I(m);$I(n);k=+h[v>>3];j=+h[w>>3];i=+h[x>>3];f=+h[y>>3];e=+h[z>>3]}h[b+368>>3]=k;h[b+376>>3]=j;h[b+352>>3]=i;h[b+336>>3]=f;h[b+344>>3]=e;l=A;return}function Qv(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0,k=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0.0,P=0.0,Q=0.0;M=l;l=l+224|0;J=M+200|0;z=M+168|0;E=M+144|0;I=M+120|0;F=M+96|0;G=M+64|0;e=M+184|0;v=M+176|0;w=M+160|0;y=M+136|0;x=M+112|0;A=M+80|0;B=M+48|0;C=M+32|0;D=M+16|0;K=M+8|0;L=M;u=c[b>>2]|0;c[G>>2]=0;c[G+4>>2]=0;c[G+8>>2]=0;c[G+12>>2]=0;H=b+368|0;c[I>>2]=c[H>>2];c[I+4>>2]=c[H+4>>2];c[I+8>>2]=c[H+8>>2];c[I+12>>2]=c[H+12>>2];H=b+360|0;if(c[H>>2]|0){c[J>>2]=c[I>>2];c[J+4>>2]=c[I+4>>2];c[J+8>>2]=c[I+8>>2];c[J+12>>2]=c[I+12>>2];Rv(e,J);c[I>>2]=c[e>>2];c[I+4>>2]=c[e+4>>2];c[I+8>>2]=c[e+8>>2];c[I+12>>2]=c[e+12>>2]}t=b+416|0;c[F>>2]=c[t>>2];c[F+4>>2]=c[t+4>>2];c[F+8>>2]=c[t+8>>2];c[F+12>>2]=c[t+12>>2];if((a[u+294>>0]|0)!=0?(c[b+152>>2]&32|0)!=0:0){i=+h[u+232>>3]-+h[F>>3]*2.0;h[E>>3]=i;k=+h[u+240>>3]-+h[F+8>>3]*2.0;p=E+8|0;h[p>>3]=k;if(!(i<.0001)){o=+h[I>>3];e=~~(o/i);f=b+164|0;c[f>>2]=e;if(o-i*+(e|0)>.0001){e=e+1|0;c[f>>2]=e}}else{c[b+164>>2]=1;e=1}if(!(k<.0001)){g=+h[I+8>>3];f=~~(g/k);j=b+168|0;c[j>>2]=f;if(g-k*+(f|0)>.0001){f=f+1|0;c[j>>2]=f}}else{c[b+168>>2]=1;f=1;g=+h[I+8>>3]}c[b+204>>2]=O(f,e)|0;o=+h[(+h[I>>3]>3];h[I>>3]=o;e=p;f=I;m=+h[(g>3];g=o;j=21}else{if(c[b+68>>2]|0){e=c[b+84>>2]|0;i=+h[e+24>>3]-+h[F>>3]*2.0;i=i<0.0?0.0:i;h[E>>3]=i;o=+h[e+32>>3]-+h[F+8>>3]*2.0;e=E+8|0;h[e>>3]=o;if(o<0.0){f=E;j=17}else e=E}else{h[E+8>>3]=0.0;f=E;e=E;j=17}if((j|0)==17){h[e>>3]=0.0;e=f;i=+h[f>>3]}c[b+204>>2]=1;c[b+168>>2]=1;c[b+164>>2]=1;g=+h[I>>3];if(i>3]=g;i=g}e=E+8|0;k=+h[e>>3];m=+h[I+8>>3];if(k>3]=m;r=e;m=+h[e>>3]}n=+h[F>>3];s=b+432|0;k=+h[s>>3]*.013888888888888888*(n*2.0+i);c[b+448>>2]=~~(k+(k>=0.0?.5:-.5));q=F+8|0;k=+h[q>>3];t=b+440|0;o=+h[t>>3]*.013888888888888888*(k*2.0+m);c[b+452>>2]=~~(o+(o>=0.0?.5:-.5));j=b+188|0;p=b+180|0;e=b+172|0;f=u+196|0;c[e>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;c[e+16>>2]=0;c[e+20>>2]=0;Sv(v,b,a[c[f>>2]>>0]|0);u=v;v=c[u+4>>2]|0;e=p;c[e>>2]=c[u>>2];c[e+4>>2]=v;Sv(w,b,a[(c[f>>2]|0)+1>>0]|0);e=w;w=c[e>>2]|0;e=c[e+4>>2]|0;v=j;c[v>>2]=w;c[v+4>>2]=e;w=(c[p>>2]|0)+w|0;if(!((((w|0)>-1?w:0-w|0)|0)==1?(w=(c[b+184>>2]|0)+e|0,(((w|0)>-1?w:0-w|0)|0)==1):0)){Sv(y,b,66);v=y;y=c[v+4>>2]|0;w=p;c[w>>2]=c[v>>2];c[w+4>>2]=y;Sv(x,b,76);w=x;x=c[w+4>>2]|0;y=j;c[y>>2]=c[w>>2];c[y+4>>2]=x;c[z>>2]=c[f>>2];$l(0,85763,z)|0}if(a[(c[(c[d+16>>2]|0)+8>>2]|0)+82>>0]|0){if(i>g){m=(i-g)*.5;h[G>>3]=m}else m=0.0;i=+h[r>>3];o=+h[I+8>>3];if(i>o){i=(i-o)*.5;h[G+8>>3]=i}else i=0.0}else{i=0.0;m=0.0}if(!(c[H>>2]|0))j=1;else{c[J>>2]=c[I>>2];c[J+4>>2]=c[I+4>>2];c[J+8>>2]=c[I+8>>2];c[J+12>>2]=c[I+12>>2];Rv(A,J);c[I>>2]=c[A>>2];c[I+4>>2]=c[A+4>>2];c[I+8>>2]=c[A+8>>2];c[I+12>>2]=c[A+12>>2];c[J>>2]=c[E>>2];c[J+4>>2]=c[E+4>>2];c[J+8>>2]=c[E+8>>2];c[J+12>>2]=c[E+12>>2];Rv(B,J);c[E>>2]=c[B>>2];c[E+4>>2]=c[B+4>>2];c[E+8>>2]=c[B+8>>2];c[E+12>>2]=c[B+12>>2];c[J>>2]=c[F>>2];c[J+4>>2]=c[F+4>>2];c[J+8>>2]=c[F+8>>2];c[J+12>>2]=c[F+12>>2];Rv(C,J);c[F>>2]=c[C>>2];c[F+4>>2]=c[C+4>>2];c[F+8>>2]=c[C+8>>2];c[F+12>>2]=c[C+12>>2];c[J>>2]=c[G>>2];c[J+4>>2]=c[G+4>>2];c[J+8>>2]=c[G+8>>2];c[J+12>>2]=c[G+12>>2];Rv(D,J);c[G>>2]=c[D>>2];c[G+4>>2]=c[D+4>>2];c[G+8>>2]=c[D+8>>2];c[G+12>>2]=c[D+12>>2];n=+h[F>>3];m=+h[G>>3];k=+h[q>>3];i=+h[G+8>>3];g=+h[I>>3];j=(c[H>>2]|0)==0}o=m+n;h[b+384>>3]=o;P=i+k;h[b+392>>3]=P;N=m+n+g;h[b+400>>3]=N;Q=+h[I+8>>3];n=i+k+Q;h[b+408>>3]=n;m=+h[b+352>>3];h[b+320>>3]=g/m;h[b+328>>3]=Q/m;m=+h[s>>3];o=o*.013888888888888888*m;f=b+456|0;c[f>>2]=~~(o+(o>=0.0?.5:-.5));o=+h[t>>3];k=P*.013888888888888888*o;c[b+460>>2]=~~(k+(k>=0.0?.5:-.5));m=N*.013888888888888888*m;e=b+464|0;c[e>>2]=~~(m+(m>=0.0?.5:-.5));o=n*.013888888888888888*o;c[b+468>>2]=~~(o+(o>=0.0?.5:-.5));if(!j){c[J>>2]=c[f>>2];c[J+4>>2]=c[f+4>>2];Cv(K,J);I=K;K=c[I+4>>2]|0;b=f;c[b>>2]=c[I>>2];c[b+4>>2]=K;c[J>>2]=c[e>>2];c[J+4>>2]=c[e+4>>2];Cv(L,J);b=L;K=c[b+4>>2]|0;L=e;c[L>>2]=c[b>>2];c[L+4>>2]=K}l=M;return}function Rv(a,b){a=a|0;b=b|0;var c=0.0;c=+h[b>>3];h[a>>3]=+h[b+8>>3];h[a+8>>3]=c;return}function Sv(a,b,d){a=a|0;b=b|0;d=d|0;d=(d<<24>>24)+-66|0;switch(d>>>1|d<<31|0){case 9:{c[b+176>>2]=(c[b+168>>2]|0)+-1;b=0;d=-1;break}case 0:{b=0;d=1;break}case 5:{b=1;d=0;break}case 8:{c[b+172>>2]=(c[b+164>>2]|0)+-1;b=-1;d=0;break}default:{b=0;d=0}}c[a>>2]=b;c[a+4>>2]=d;return}function Tv(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;j=l;l=l+16|0;g=j;f=Jm(d,86004)|0;i=b+296|0;c[i>>2]=(f|0)==0?86013:f;d=Jm(d,86017)|0;f=b+300|0;d=(d|0)==0?86030:d;c[f>>2]=d;d=KL(c[i>>2]|0,d)|0;if(d|0){c[g>>2]=a[d>>0];$l(0,86032,g)|0;c[f>>2]=174185}d=HL(e)|0;c[b+304>>2]=d;h=b+308|0;f=0;b=0;while(1){e=EL(d,c[i>>2]|0)|0;if(!e)break;g=b+1|0;if((b|0)<(f|0))d=c[h>>2]|0;else{f=f+128|0;d=c[h>>2]|0;if(!d)d=xw(f<<2)|0;else d=zw(d,f<<2)|0;c[h>>2]=d}c[d+(g<<2)>>2]=e;b=g;d=0}if(b|0){i=zw(c[h>>2]|0,(b<<2)+8|0)|0;c[h>>2]=i;c[i>>2]=0;c[(c[h>>2]|0)+(b+1<<2)>>2]=0}l=j;return b|0}function Uv(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;j=k;i=a+312|0;d=xw((c[i>>2]<<2)+8|0)|0;e=0;h=1;while(1){g=c[i>>2]|0;if((h|0)>(g|0))break;f=e+1|0;if((jv(a,h,g,b)|0)<<24>>24){c[d+(f<<2)>>2]=h;e=f}h=h+1|0}if(!e){c[j>>2]=b;$l(0,85903,j)|0;$I(d);d=0}else{c[d>>2]=e;c[d+(e+1<<2)>>2]=(c[i>>2]|0)+1}l=k;return d|0}function Vv(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0.0,g=0.0;d=c[b+16>>2]|0;g=+h[d+16>>3];h[d+48>>3]=g-+h[d+88>>3];e=+h[d+24>>3];f=+h[d+80>>3]*.5;h[d+56>>3]=e-f;h[d+64>>3]=+h[d+96>>3]+g;h[d+72>>3]=f+e;b=Qm(a,b)|0;while(1){if(!b)break;Wv(b);b=Sm(a,b)|0}return}function Wv(a){a=a|0;a=c[(c[a+16>>2]|0)+8>>2]|0;if(a|0)Xv(a);return}function Xv(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;C=l;l=l+240|0;v=C+192|0;u=C+176|0;w=C+64|0;x=C+32|0;y=C;z=C+144|0;A=C+112|0;B=a+4|0;if((c[B>>2]|0)<=0)ma(86171,84925,3994,86185);b=c[a>>2]|0;d=w;e=b;f=d+48|0;do{c[d>>2]=c[e>>2];d=d+4|0;e=e+4|0}while((d|0)<(f|0));d=v;e=b;f=d+48|0;do{c[d>>2]=c[e>>2];d=d+4|0;e=e+4|0}while((d|0)<(f|0));Yv(x,v);i=x+8|0;j=y+8|0;k=x+16|0;m=y+16|0;n=x+24|0;o=y+24|0;p=w+8|0;q=w+12|0;r=w+32|0;s=w+4|0;t=w+16|0;g=0;while(1){if((g|0)>=(c[B>>2]|0))break;if((g|0)>0){b=(c[a>>2]|0)+(g*48|0)|0;d=w;e=b;f=d+48|0;do{c[d>>2]=c[e>>2];d=d+4|0;e=e+4|0}while((d|0)<(f|0));d=v;e=b;f=d+48|0;do{c[d>>2]=c[e>>2];d=d+4|0;e=e+4|0}while((d|0)<(f|0));Yv(y,v);h[x>>3]=+h[(+h[x>>3]<+h[y>>3]?x:y)>>3];h[i>>3]=+h[(+h[i>>3]<+h[j>>3]?x:y)+8>>3];h[k>>3]=+h[(+h[k>>3]>+h[m>>3]?x:y)+16>>3];h[n>>3]=+h[(+h[n>>3]>+h[o>>3]?x:y)+24>>3]}b=c[p>>2]|0;if(b|0){f=c[w>>2]|0;c[u>>2]=c[t>>2];c[u+4>>2]=c[t+4>>2];c[u+8>>2]=c[t+8>>2];c[u+12>>2]=c[t+12>>2];c[v>>2]=c[f>>2];c[v+4>>2]=c[f+4>>2];c[v+8>>2]=c[f+8>>2];c[v+12>>2]=c[f+12>>2];St(z,u,v,1.0,b);c[y>>2]=c[z>>2];c[y+4>>2]=c[z+4>>2];c[y+8>>2]=c[z+8>>2];c[y+12>>2]=c[z+12>>2];c[y+16>>2]=c[z+16>>2];c[y+20>>2]=c[z+20>>2];c[y+24>>2]=c[z+24>>2];c[y+28>>2]=c[z+28>>2];h[x>>3]=+h[(+h[x>>3]<+h[y>>3]?x:y)>>3];h[i>>3]=+h[(+h[i>>3]<+h[j>>3]?x:y)+8>>3];h[k>>3]=+h[(+h[k>>3]>+h[m>>3]?x:y)+16>>3];h[n>>3]=+h[(+h[n>>3]>+h[o>>3]?x:y)+24>>3]}b=c[q>>2]|0;if(b|0){f=(c[w>>2]|0)+((c[s>>2]|0)+-1<<4)|0;c[u>>2]=c[r>>2];c[u+4>>2]=c[r+4>>2];c[u+8>>2]=c[r+8>>2];c[u+12>>2]=c[r+12>>2];c[v>>2]=c[f>>2];c[v+4>>2]=c[f+4>>2];c[v+8>>2]=c[f+8>>2];c[v+12>>2]=c[f+12>>2];St(A,u,v,1.0,b);c[y>>2]=c[A>>2];c[y+4>>2]=c[A+4>>2];c[y+8>>2]=c[A+8>>2];c[y+12>>2]=c[A+12>>2];c[y+16>>2]=c[A+16>>2];c[y+20>>2]=c[A+20>>2];c[y+24>>2]=c[A+24>>2];c[y+28>>2]=c[A+28>>2];h[x>>3]=+h[(+h[x>>3]<+h[y>>3]?x:y)>>3];h[i>>3]=+h[(+h[i>>3]<+h[j>>3]?x:y)+8>>3];h[k>>3]=+h[(+h[k>>3]>+h[m>>3]?x:y)+16>>3];h[n>>3]=+h[(+h[n>>3]>+h[o>>3]?x:y)+24>>3]}g=g+1|0}B=a+8|0;c[B>>2]=c[x>>2];c[B+4>>2]=c[x+4>>2];c[B+8>>2]=c[x+8>>2];c[B+12>>2]=c[x+12>>2];c[B+16>>2]=c[x+16>>2];c[B+20>>2]=c[x+20>>2];c[B+24>>2]=c[x+24>>2];c[B+28>>2]=c[x+28>>2];l=C;return}function Yv(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0;n=l;l=l+48|0;i=n+32|0;j=n;k=c[b+4>>2]|0;if((k|0)<=0)ma(86201,84925,3968,86213);if(((k>>>0)%3|0|0)!=1)ma(86223,84925,3969,86213);m=j+16|0;d=c[b>>2]|0;c[m>>2]=c[d>>2];c[m+4>>2]=c[d+4>>2];c[m+8>>2]=c[d+8>>2];c[m+12>>2]=c[d+12>>2];c[j>>2]=c[d>>2];c[j+4>>2]=c[d+4>>2];c[j+8>>2]=c[d+8>>2];c[j+12>>2]=c[d+12>>2];e=i+8|0;f=j+8|0;g=j+24|0;b=1;while(1){if((b|0)>=(k|0))break;p=+h[d+(b<<4)+8>>3];t=b+1|0;o=+h[d+(t<<4)+8>>3];r=(+h[d+(t<<4)>>3]+ +h[d+(b<<4)>>3])*.5;h[i>>3]=r;p=(o+p)*.5;h[e>>3]=p;o=+h[(+h[j>>3]>3];h[j>>3]=o;s=+h[(+h[f>>3]>3];h[f>>3]=s;r=+h[(+h[m>>3]>r?m:i)>>3];h[m>>3]=r;p=+h[(+h[g>>3]>p?m:i)+8>>3];h[g>>3]=p;t=d+(b+2<<4)|0;c[i>>2]=c[t>>2];c[i+4>>2]=c[t+4>>2];c[i+8>>2]=c[t+8>>2];c[i+12>>2]=c[t+12>>2];q=+h[i>>3];h[j>>3]=+h[(o>3];o=+h[e>>3];h[f>>3]=+h[(s>3];h[m>>3]=+h[(r>q?m:i)>>3];h[g>>3]=+h[(p>o?m:i)+8>>3];b=b+3|0}c[a>>2]=c[j>>2];c[a+4>>2]=c[j+4>>2];c[a+8>>2]=c[j+8>>2];c[a+12>>2]=c[j+12>>2];c[a+16>>2]=c[j+16>>2];c[a+20>>2]=c[j+20>>2];c[a+24>>2]=c[j+24>>2];c[a+28>>2]=c[j+28>>2];l=n;return}function Zv(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0.0,f=0.0,g=0.0,i=0,j=0.0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0.0;q=+h[a>>3];r=+h[c>>3];k=!(q>=r);if((!k?q<=+h[c+16>>3]:0)?(e=+h[a+8>>3],e>=+h[c+8>>3]):0)i=e<=+h[c+24>>3];else i=0;e=+h[b>>3];if((e>=r?e<=+h[c+16>>3]:0)?(f=+h[b+8>>3],f>=+h[c+8>>3]):0){d=f<=+h[c+24>>3];if(!(i^d))if(i&d)d=1;else l=11;else d=0}else if(i)d=0;else l=11;a:do if((l|0)==11){p=+h[a+8>>3];do if(q==e){r=+h[c+8>>3];if(!(k|p>=r^+h[b+8>>3]>=r^1)?q<=+h[c+16>>3]:0){d=0;break a}}else{j=+h[b+8>>3];if(p==j){if(!(q>=r^e>=r))break;if(!(p>=+h[c+8>>3]))break;if(!(p<=+h[c+24>>3]))break;else{d=0;break a}}o=(j-p)/(e-q);l=q>3];if(!(!(r>=g)|!(r<=e)|!(f>=m))?f<=+h[c+24>>3]:0){d=0;break a}n=+h[c+16>>3];f=(n-r)*o+f;if(f>=m?!(!(n<=e)|(n>=g?!(f<=+h[c+24>>3]):1)):0){d=0;break a}l=p=r?!(!(m<=f)|(!(m>=g)|!(e<=n))):0){d=0;break a}p=+h[c+24>>3];q=(p-m)/o+e;if(q>=r?!(!(p<=f)|(!(p>=g)|!(q<=n))):0){d=0;break a}}while(0);d=-1}while(0);return d|0}function _v(a){a=a|0;var b=0,c=0.0;b=a+16|0;c=+h[b>>3];h[a+32>>3]=c;h[a+48>>3]=c;h[a+40>>3]=+h[a+24>>3];h[a+56>>3]=+h[a+8>>3];h[b>>3]=+h[a>>3];return}function $v(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0.0,g=0.0,i=0.0;if((c[42176]|0)!=(d|0)){TJ(+(d|0)*.15915494309189535,167112,167120);c[42176]=d}g=+h[b>>3];e=+h[20890];f=+h[b+8>>3];i=+h[20889];h[a>>3]=e*g-i*f;h[a+8>>3]=i*g+f*e;return}function aw(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0,g=0.0,i=0,j=0,k=0;k=l;l=l+16|0;f=k;e=+h[b>>3];i=b+8|0;g=+h[i>>3];a:do switch(d|0){case 0:{j=11;break}case 90:{h[b>>3]=g;e=-e;j=10;break}case 180:{e=-g;j=10;break}case 270:{h[b>>3]=g;j=10;break}default:{if((d|0)<0){c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];bw(a,f,0-d|0);break a}if((d|0)>360){c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];aw(a,f,(d>>>0)%360|0);break a}else{c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];$v(a,f,d);break a}}}while(0);if((j|0)==10){h[i>>3]=e;j=11}if((j|0)==11){c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2]}l=k;return}function bw(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0,g=0.0,i=0,j=0,k=0;k=l;l=l+16|0;f=k;e=+h[b>>3];i=b+8|0;g=+h[i>>3];a:do switch(d|0){case 0:{j=11;break}case 90:{h[b>>3]=-g;j=10;break}case 180:{e=-g;j=10;break}case 270:{h[b>>3]=g;j=10;break}default:{if((d|0)<0){c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];aw(a,f,0-d|0);break a}if((d|0)>360){c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];bw(a,f,(d>>>0)%360|0);break a}else{c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];$v(a,f,360-d|0);break a}}}while(0);if((j|0)==10){h[i>>3]=e;j=11}if((j|0)==11){c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2]}l=k;return}function cw(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0.0,g=0.0;g=+h[c>>3];d=+h[c+8>>3];f=d+ +h[b>>3];e=g+ +h[b+24>>3];d=d+ +h[b+16>>3];h[a>>3]=g+ +h[b+8>>3];h[a+8>>3]=f;h[a+16>>3]=e;h[a+24>>3]=d;return}function dw(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0.0,g=0.0;f=+h[a>>3];d=+h[b>>3]-f;g=+h[a+8>>3];e=+h[b+8>>3]-g;f=(+h[c+8>>3]-g)*d-(+h[c>>3]-f)*e;f=f*f;return +(f<1.0e-10?0.0:f/(e*e+d*d))}function ew(b,d){b=b|0;d=d|0;var e=0,f=0.0,g=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+16|0;g=n+8|0;i=n;e=ww(96)|0;m=b+16|0;c[(c[m>>2]|0)+8>>2]=e;e=Jm(b,86250)|0;if(!e){e=Na(86259)|0;if(e|0)k=3}else k=3;if((k|0)==3)Va(86271,e|0,1)|0;e=(fw(b)|0)&255;a[(c[m>>2]|0)+115>>0]=e;if(0==0?(e=Jm(b,86282)|0,c[42178]=e,(e|0)==0):0)c[42178]=c[42177];f=+FA(b,zm(b,0,86292,0)|0,0.0,0.0);h[c[(c[m>>2]|0)+8>>2]>>3]=f;e=Jm(b,86300)|0;a:do if(!e)e=0;else{switch(a[e>>0]|0){case 76:{if(!(yJ(e,86308)|0)){e=1;break a}break}case 66:{if(!(yJ(e,86311)|0)){e=2;break a}break}case 82:{e=(yJ(e,86314)|0)==0;e=e?3:0;break a}default:{e=0;break a}}e=0}while(0);c[(c[m>>2]|0)+116>>2]=e<<2|(d<<24>>24==0?0:e);f=+FA(b,zm(b,0,86317,0)|0,.25,.02);h[i>>3]=f;f=f*72.0;c[(c[m>>2]|0)+248>>2]=~~(f+(f>=0.0?.5:-.5));e=GA(b,zm(b,0,86325,0)|0,0)|0;if(e){c[g>>2]=i;if(dM(e,86246,g)|0){f=+h[i>>3];if(f<.02){h[i>>3]=.02;f=.02}}else{h[i>>3]=.5;f=.5}if(iL(e,86333)|0)a[(c[m>>2]|0)+276>>0]=1}else{h[i>>3]=.5;f=.5}f=f*72.0;c[(c[m>>2]|0)+252>>2]=~~(f+(f>=0.0?.5:-.5));i=(EA(b,zm(b,0,86341,0)|0,0,0)|0)&255;a[(c[m>>2]|0)+243>>0]=i;i=VA(GA(b,zm(b,0,86351,0)|0,0)|0,19732,19748)|0;c[(c[m>>2]|0)+244>>2]=i;gw(b);i=hw(b,86361,(c[(c[m>>2]|0)+8>>2]|0)+64|0)|0;e=c[(c[m>>2]|0)+8>>2]|0;a[e+80>>0]=i;hw(b,86366,e+48|0)|0;e=JA(Jm(b,86371)|0)|0;a[(c[(c[m>>2]|0)+8>>2]|0)+82>>0]=e;e=Jm(b,86378)|0;do if(!e){e=Jm(b,86385)|0;if(e|0){e=(a[e>>0]|32)<<24>>24==108&1;k=27;break}e=Jm(b,86397)|0;if(e|0){e=JA(e)|0;k=27}}else{e=(sM(e)|0)==90&1;k=27}while(0);if((k|0)==27)a[(c[(c[m>>2]|0)+8>>2]|0)+81>>0]=e;c[42180]=VA(Jm(b,86407)|0,19764,19780)|0;a[174080]=JA(Jm(b,86419)|0)|0;c[42182]=0;c[42183]=0;h[(c[(c[m>>2]|0)+8>>2]|0)+24>>3]=0.0;e=Jm(b,86431)|0;if((e|0)!=0?(a[e>>0]|0)!=0:0)k=32;else k=30;if(((k|0)==30?(j=Jm(b,86435)|0,j|0):0)?a[j>>0]|0:0){e=j;k=32}if((k|0)==32){f=+tM(e);h[(c[(c[m>>2]|0)+8>>2]|0)+24>>3]=f}iw(b);c[42185]=zm(b,0,86446,0)|0;c[42188]=zm(b,0,86455,0)|0;c[42189]=zm(b,0,90530,0)|0;c[42190]=zm(b,1,96049,0)|0;c[42191]=zm(b,1,96043,0)|0;c[42192]=zm(b,1,90671,0)|0;c[42193]=zm(b,1,122540,0)|0;c[42194]=zm(b,1,86469,0)|0;c[42202]=zm(b,1,86479,0)|0;c[42195]=zm(b,1,86485,0)|0;c[42196]=zm(b,1,86494,0)|0;c[42197]=zm(b,1,86503,0)|0;k=zm(b,1,86240,0)|0;c[42199]=k;if(!k)c[42199]=zm(b,1,86240,90527)|0;c[42200]=zm(b,1,86513,0)|0;c[42203]=zm(b,1,86341,0)|0;c[42217]=zm(b,1,86520,0)|0;c[42206]=zm(b,1,86446,0)|0;c[42198]=zm(b,1,90530,0)|0;c[42204]=zm(b,1,86529,0)|0;c[42205]=zm(b,1,86535,0)|0;c[42208]=zm(b,1,86547,0)|0;c[42207]=zm(b,1,86385,0)|0;c[42209]=zm(b,1,86552,0)|0;c[42210]=zm(b,1,86563,0)|0;c[42211]=zm(b,1,122089,0)|0;c[42201]=zm(b,1,86573,0)|0;c[42212]=zm(b,1,86583,0)|0;c[42213]=zm(b,1,86589,0)|0;c[42214]=zm(b,1,86595,0)|0;c[42215]=zm(b,1,86603,0)|0;c[42216]=zm(b,1,86612,0)|0;c[42218]=zm(b,1,86455,0)|0;c[42219]=zm(b,2,86614,0)|0;c[42221]=zm(b,2,122540,0)|0;c[42222]=zm(b,2,86469,0)|0;c[42224]=zm(b,2,86485,0)|0;c[42225]=zm(b,2,86494,0)|0;c[42226]=zm(b,2,86503,0)|0;c[42227]=zm(b,2,86240,0)|0;c[42228]=zm(b,2,86513,0)|0;c[42237]=zm(b,2,86621,0)|0;c[42229]=zm(b,2,86632,0)|0;c[42240]=zm(b,2,86636,0)|0;c[42241]=zm(b,2,86646,0)|0;c[42242]=zm(b,2,86656,0)|0;c[42243]=zm(b,2,86666,0)|0;c[42244]=zm(b,2,86676,0)|0;c[42245]=zm(b,2,86690,0)|0;c[42246]=zm(b,2,86704,0)|0;c[42247]=zm(b,2,86719,0)|0;c[42248]=zm(b,2,86733,0)|0;c[42220]=zm(b,2,86744,0)|0;c[42232]=zm(b,2,86341,0)|0;c[42230]=zm(b,2,86479,0)|0;c[42231]=zm(b,2,86751,0)|0;c[42233]=zm(b,2,86760,0)|0;c[42234]=zm(b,2,86770,0)|0;c[42235]=zm(b,2,86583,0)|0;c[42236]=zm(b,2,86595,0)|0;c[42249]=zm(b,2,86781,0)|0;c[42250]=zm(b,2,86790,0)|0;c[42251]=zm(b,2,86520,0)|0;e=Vt(b)|0;c[(c[(c[m>>2]|0)+8>>2]|0)+88>>2]=e;e=Jm(b,86799)|0;if(e|0?a[e>>0]|0:0){b=rw(e,b)|0;c[(c[(c[m>>2]|0)+8>>2]|0)+92>>2]=b}l=n;return}function fw(a){a=a|0;var b=0,d=0;d=l;l=l+16|0;b=d;a=HA(a,zm(a,0,86883,0)|0,86891)|0;if(((((((jK(a,86897)|0)!=0?(jK(a,86905)|0)!=0:0)?(jK(a,86912)|0)!=0:0)?(jK(a,86915)|0)!=0:0)?(jK(a,86926)|0)!=0:0)?(jK(a,86937)|0)!=0:0)?(jK(a,86947)|0)!=0:0)if((jK(a,86958)|0)!=0?(jK(a,86964)|0)!=0:0)if((jK(a,86891)|0)!=0?(jK(a,86969)|0)!=0:0){c[b>>2]=a;$l(0,86974,b)|0;a=0}else a=0;else a=2;else a=1;l=d;return a|0}function gw(b){b=b|0;var d=0.0,e=0,f=0;e=Jm(b,86841)|0;a:do if(e|0?(f=a[e>>0]|0,f<<24>>24):0)switch(f<<24>>24|0){case 97:{if(f<<24>>24!=97)break a;if(yJ(e,86847)|0)break a;c[(c[(c[b+16>>2]|0)+8>>2]|0)+84>>2]=4;break a}case 99:{if(f<<24>>24!=99)break a;if(yJ(e,86852)|0)break a;c[(c[(c[b+16>>2]|0)+8>>2]|0)+84>>2]=3;break a}case 101:{if(f<<24>>24!=101)break a;if(yJ(e,86861)|0)break a;c[(c[(c[b+16>>2]|0)+8>>2]|0)+84>>2]=5;break a}case 102:{if(f<<24>>24!=102)break a;if(yJ(e,86868)|0)break a;c[(c[(c[b+16>>2]|0)+8>>2]|0)+84>>2]=2;break a}default:{d=+tM(e);if(!(d>0.0))break a;b=c[(c[b+16>>2]|0)+8>>2]|0;c[b+84>>2]=1;h[b+16>>3]=d;break a}}while(0);return}function hw(b,d,e){b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+48|0;m=o+32|0;i=o+16|0;k=o+8|0;j=o;n=o+40|0;a[n>>0]=0;b=Jm(b,d)|0;do if(b){c[i>>2]=k;c[i+4>>2]=j;c[i+8>>2]=n;i=(dM(b,86825,i)|0)>1;g=+h[k>>3];f=+h[j>>3];if(i&g>0.0&f>0.0){g=g*72.0;h[e>>3]=+(~~(g+(g>=0.0?.5:-.5))|0);g=f*72.0;h[e+8>>3]=+(~~(g+(g>=0.0?.5:-.5))|0);b=(a[n>>0]|0)==33;break}a[n>>0]=0;c[m>>2]=k;c[m+4>>2]=n;m=(dM(b,86835,m)|0)>0;f=+h[k>>3];if(m&f>0.0){g=f*72.0;g=+(~~(g+(g>=0.0?.5:-.5))|0);h[e>>3]=g;h[e+8>>3]=g;b=(a[n>>0]|0)==33}else b=0}else b=0;while(0);l=o;return b&1|0}function iw(b){b=b|0;var d=0,e=0,f=0.0,g=0.0,i=0;d=Jm(b,86240)|0;do if(d|0?a[d>>0]|0:0){e=(c[(c[b+60>>2]|0)+16>>2]|0)+113|0;a[e>>0]=a[e>>0]|8;e=(dp(d)|0)!=0;g=+FA(b,zm(b,0,86485,0)|0,14.0,1.0);i=HA(b,zm(b,0,86494,0)|0,93027)|0;d=mw(b,d,e?2:0,g,i,HA(b,zm(b,0,86503,0)|0,122106)|0)|0;i=b+16|0;c[(c[i>>2]|0)+12>>2]=d;d=Jm(b,90662)|0;e=(d|0)!=0;do if((to(b)|0)==(b|0)){if(e?(a[d>>0]|0)==116:0){d=1;break}d=0}else{if(e?(a[d>>0]|0)==98:0){d=0;break}d=1}while(0);e=Jm(b,86802)|0;a:do if(e)switch(a[e>>0]|0){case 108:{d=d|2;break a}case 114:{d=d|4;break a}default:break a}while(0);a[(c[i>>2]|0)+275>>0]=d;if((to(b)|0)!=(b|0)){d=c[(c[i>>2]|0)+12>>2]|0;f=+h[d+24>>3]+16.0;g=+h[d+32>>3]+8.0;b=(c[(c[(to(b)|0)+16>>2]|0)+116>>2]&1|0)==0;d=c[i>>2]|0;e=a[d+275>>0]<<1&2;if(b){b=e&255;h[d+48+(b<<4)>>3]=f;h[d+48+(b<<4)+8>>3]=g;break}else{b=(e^3)&255;h[d+48+(b<<4)>>3]=g;h[d+48+(b<<4)+8>>3]=f;break}}}while(0);return}function jw(a){a=a|0;var b=0,d=0,e=0;e=a+16|0;d=c[e>>2]|0;b=c[d+8>>2]|0;do if(!b)b=d;else{d=c[b+88>>2]|0;if(d){yt(d);d=c[e>>2]|0;b=c[d+8>>2]|0;if(!b){b=d;break}}$I(c[b+92>>2]|0);b=c[e>>2]|0}while(0);$I(c[b+8>>2]|0);e=c[e>>2]|0;c[e+8>>2]=0;pw(c[e+12>>2]|0);Uo(a,0,122277);return}function kw(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;f=c[d>>2]|0;l=d+24|0;c[l>>2]=0;c[l+4>>2]=0;c[l+8>>2]=0;c[l+12>>2]=0;if(a[f>>0]|0){i=xw((sJ(f)|0)+1|0)|0;a[i>>0]=0;j=d+12|0;e=i;a:while(1){b:while(1){h=f+1|0;g=a[f>>0]|0;if(!(g<<24>>24))break a;if(!(g<<24>>24==-1|((g&255)<161|(c[j>>2]|0)!=2))){a[e>>0]=g;h=a[h>>0]|0;g=e+2|0;a[e+1>>0]=h;if(!(h<<24>>24)){e=g;break a}else{e=g;f=f+2|0;continue}}switch(g<<24>>24){case 92:break b;case 10:{k=12;break b}default:{}}a[e>>0]=g;e=e+1|0;f=h}if((k|0)==12){k=0;f=e+1|0;a[e>>0]=0;lw(b,d,i,110);e=f;i=f;f=h;continue}g=a[h>>0]|0;switch(g<<24>>24|0){case 114:case 108:case 110:{g=e+1|0;a[e>>0]=0;lw(b,d,i,a[h>>0]|0);e=g;break}default:{a[e>>0]=g;e=e+1|0;g=i}}i=g;f=(a[h>>0]|0)==0?h:f+2|0}if((i|0)!=(e|0)){a[e>>0]=0;lw(b,d,i,110)}d=d+40|0;c[d>>2]=c[l>>2];c[d+4>>2]=c[l+4>>2];c[d+8>>2]=c[l+8>>2];c[d+12>>2]=c[l+12>>2]}return}function lw(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=l;l=l+32|0;q=s+16|0;p=s;r=e+76|0;k=b[r>>1]|0;o=e+72|0;m=c[o>>2]|0;if(!m)n=ww((k*56|0)+112|0)|0;else n=yw(m,k+2|0,56,k+1|0)|0;c[o>>2]=n;k=b[r>>1]|0;m=n+(k*56|0)|0;c[m>>2]=f;a[n+(k*56|0)+48>>0]=g;if((f|0)!=0?(a[f>>0]|0)!=0:0){c[41782]=c[e+4>>2];h[20893]=+h[e+16>>3];g=c[d+144>>2]|0;c[n+(k*56|0)+4>>2]=bb[c[g>>2]&31](g,167128,1)|0;qA(p,d,m);j=+h[p>>3];h[q>>3]=j;i=+h[p+8>>3]}else{h[q>>3]=0.0;i=+(~~(+h[e+16>>3]*1.2)|0);h[n+(k*56|0)+40>>3]=i;j=0.0}b[r>>1]=(b[r>>1]|0)+1<<16>>16;r=e+24|0;h[r>>3]=+h[(+h[r>>3]>j?r:q)>>3];r=e+32|0;h[r>>3]=+h[r>>3]+i;l=s;return}function mw(b,e,f,g,i,j){b=b|0;e=e|0;f=f|0;g=+g;i=i|0;j=j|0;var k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+32|0;r=u+16|0;q=u+8|0;p=u;t=ww(88)|0;switch(Do(b)|0){case 0:{m=0;s=c[b+60>>2]|0;n=b;o=0;break}case 1:{m=0;s=to(so(b)|0)|0;n=0;o=b;break}case 2:{m=b;s=to(so(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0)|0;n=0;o=0;break}default:{m=0;s=0;n=0;o=0}}c[t+4>>2]=i;c[t+8>>2]=j;h[t+16>>3]=g;k=s+16|0;j=t+12|0;c[j>>2]=d[(c[k>>2]|0)+115>>0];a:do if(f&4){c[t>>2]=HL(e)|0;if(f&2|0)a[t+82>>0]=1}else switch(f|0){case 2:{c[t>>2]=HL(e)|0;a[t+82>>0]=1;if(!(UF(b,t)|0))break a;switch(Do(b)|0){case 0:{c[p>>2]=En(n)|0;$l(3,87017,p)|0;break a}case 1:{c[q>>2]=En(o)|0;$l(3,87039,q)|0;break a}case 2:{p=En(c[((c[m>>2]&3|0)==3?m:m+48|0)+40>>2]|0)|0;q=(rn(s)|0)!=0;s=En(c[((c[m>>2]&3|0)==2?m:m+-48|0)+40>>2]|0)|0;c[r>>2]=p;c[r+4>>2]=q?122546:122549;c[r+8>>2]=s;$l(3,87060,r)|0;break a}default:break a}}case 0:{i=nw(e,b,0)|0;c[t>>2]=i;if((c[j>>2]|0)==1)i=zB(i)|0;else i=wB(i,s)|0;$I(c[t>>2]|0);c[t>>2]=i;kw(c[(c[k>>2]|0)+144>>2]|0,t);break a}default:ma(87087,87103,166,87112)}while(0);l=u;return t|0}function nw(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;switch(Do(d)|0){case 0:{i=En(d)|0;g=sJ(i)|0;f=c[(c[d+16>>2]|0)+12>>2]|0;if(f){f=c[f>>2]|0;if(!b){v=0;t=2;u=2;s=2;h=2;y=87135;m=87132;j=90527;o=174185;q=174185;p=0;r=0;n=2;w=f;x=87129}else{v=0;t=2;u=2;s=2;h=2;y=87135;m=87132;j=90527;o=174185;q=174185;p=0;r=0;n=sJ(f)|0;w=f;x=87129}}else{v=0;t=2;u=2;s=2;h=2;y=87135;m=87132;j=90527;o=174185;q=174185;p=0;r=0;n=2;w=87123;x=87129}break}case 1:{i=En(so(d)|0)|0;g=sJ(i)|0;j=En(d)|0;h=sJ(j)|0;f=c[(c[d+16>>2]|0)+104>>2]|0;if(f){f=c[f>>2]|0;if(!b){v=0;t=2;u=2;s=2;y=87135;m=87132;o=174185;q=174185;p=0;r=0;n=2;w=f;x=87129}else{v=0;t=2;u=2;s=2;y=87135;m=87132;o=174185;q=174185;p=0;r=0;n=sJ(f)|0;w=f;x=87129}}else{v=0;t=2;u=2;s=2;y=87135;m=87132;o=174185;q=174185;p=0;r=0;n=2;w=87123;x=87129}break}case 2:{h=d+48|0;i=En(to(so(c[((c[d>>2]&3|0)==3?d:h)+40>>2]|0)|0)|0)|0;g=sJ(i)|0;l=En(c[((c[d>>2]&3|0)==3?d:h)+40>>2]|0)|0;k=sJ(l)|0;f=d+16|0;q=c[(c[f>>2]|0)+52>>2]|0;if(!q)r=0;else r=sJ(q)|0;m=En(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)|0;f=c[f>>2]|0;o=c[f+92>>2]|0;if(!o)p=0;else p=sJ(o)|0;j=sJ(m)|0;f=c[f+96>>2]|0;if(f){f=c[f>>2]|0;if(!b)n=2;else n=sJ(f)|0}else{n=2;f=87123}x=(rn(to(so(c[((c[d>>2]&3|0)==3?d:h)+40>>2]|0)|0)|0)|0)==0;v=1;t=k;u=j;s=k+2+(r|0?r+1|0:0)+j+(p|0?p+1|0:0)|0;h=2;y=l;j=90527;w=f;x=x?122549:122546;break}default:{v=0;t=2;u=2;s=2;h=2;g=2;y=87135;m=87132;j=90527;i=87126;o=174185;q=174185;p=0;r=0;n=2;w=87123;x=87129}}e=(e|0)==0;l=0;f=b;a:while(1){d=f+1|0;b:do switch(a[f>>0]|0){case 0:break a;case 92:{f=f+2|0;switch(a[d>>0]|0){case 78:{k=h;break b}case 71:{k=g;break b}case 69:{k=s;break b}case 72:{k=u;break b}case 84:{k=t;break b}case 76:{k=n;break b}case 92:{if(!e){k=1;break b}break}default:{}}k=2;break}default:{k=1;f=d}}while(0);l=l+k|0}s=xw(l+1|0)|0;n=(v|0)==0;l=(r|0)==0;d=(p|0)==0;f=s;g=b;c:while(1){k=g+1|0;h=a[g>>0]|0;switch(h<<24>>24){case 0:break c;case 92:break;default:{a[f>>0]=h;f=f+1|0;g=k;continue c}}h=g+2|0;g=a[k>>0]|0;switch(g<<24>>24|0){case 71:{g=i;while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=h;continue c}g=g+1|0;f=f+1|0}}case 78:{g=j;while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=h;continue c}g=g+1|0;f=f+1|0}}case 69:{if(n){g=h;continue c}else g=y;while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24))break;g=g+1|0;f=f+1|0}if(l)g=x;else{a[f>>0]=58;g=q;while(1){f=f+1|0;b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=x;break}else g=g+1|0}}while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=m;break}g=g+1|0;f=f+1|0}while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24))break;g=g+1|0;f=f+1|0}if(d){g=h;continue c}a[f>>0]=58;g=o;while(1){f=f+1|0;b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=h;continue c}else g=g+1|0}}case 84:{g=y;while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=h;continue c}g=g+1|0;f=f+1|0}}case 72:{g=m;while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=h;continue c}f=f+1|0;g=g+1|0}}case 76:{g=w;while(1){b=a[g>>0]|0;a[f>>0]=b;if(!(b<<24>>24)){g=h;continue c}f=f+1|0;g=g+1|0}}case 92:{if(!e){a[f>>0]=92;f=f+1|0;g=h;continue c}break}default:{}}a[f>>0]=92;a[f+1>>0]=g;f=f+2|0;g=h}a[f>>0]=0;return s|0}function ow(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if(a|0){d=a;e=0;while(1){if((e|0)>=(b|0))break;if(!e)$I(c[d>>2]|0);g=c[d+8>>2]|0;if(g|0?(f=c[d+12>>2]|0,f|0):0)gb[f&127](g);d=d+56|0;e=e+1|0}$I(a)}return}function pw(d){d=d|0;var e=0;if(d|0){$I(c[d>>2]|0);e=d+72|0;if(a[d+82>>0]|0){e=c[e>>2]|0;if(e|0)FF(e,1)}else ow(c[e>>2]|0,b[d+76>>1]|0);$I(d)}return}function qw(d,e,f){d=d|0;e=e|0;f=f|0;var g=0.0,i=0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+32|0;q=u+16|0;r=u;k=c[d+16>>2]|0;s=k+12|0;t=c[s>>2]|0;c[s>>2]=e;if(!(a[f+82>>0]|0)){p=f+76|0;if((b[p>>1]|0)>=1){zD(d,0);CD(d,c[f+8>>2]|0);switch(a[f+80>>0]|0){case 116:{j=+h[f+64>>3];g=+h[f+48>>3]*.5+j;break}case 98:{j=+h[f+64>>3];g=+h[f+48>>3]*-.5+j+ +h[f+32>>3];break}default:{j=+h[f+64>>3];g=+h[f+32>>3]*.5+j}}g=g-+h[f+16>>3];o=r+8|0;h[o>>3]=g;if(b[k+260>>1]&512)h[o>>3]=g-j;m=f+72|0;n=f+56|0;i=f+40|0;e=0;while(1){if((e|0)>=(b[p>>1]|0))break;k=c[m>>2]|0;switch(a[k+(e*56|0)+48>>0]|0){case 108:{g=+h[n>>3]-+h[i>>3]*.5;break}case 114:{g=+h[i>>3]*.5+ +h[n>>3];break}default:g=+h[n>>3]}h[r>>3]=g;c[q>>2]=c[r>>2];c[q+4>>2]=c[r+4>>2];c[q+8>>2]=c[r+8>>2];c[q+12>>2]=c[r+12>>2];BD(d,q,k+(e*56|0)|0);h[o>>3]=+h[o>>3]-+h[(c[m>>2]|0)+(e*56|0)+40>>3];e=e+1|0}AD(d);i=18}}else{kF(d,c[f+72>>2]|0,f);i=18}if((i|0)==18)c[s>>2]=t;l=u;return}function rw(a,b){a=a|0;b=b|0;return nw(a,b,1)|0}function sw(a){a=a|0;return tw(a,0)|0}function tw(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;e=c[42252]|0;if(!e){c[42253]=64;e=xw(64)|0;c[42252]=e}j=d<<24>>24==0;i=0;f=0;h=b;while(1){if(!h)break;d=a[h>>0]|0;if(!(d<<24>>24))break;b=c[42253]|0;if((i|0)>(b+-8|0)){e=b<<1;c[42253]=e;e=zw(c[42252]|0,e)|0;c[42252]=e;e=e+i|0;d=a[h>>0]|0}a:do switch(d<<24>>24){case 38:{if(j?(uw(h)|0)!=0:0)k=18;else{f=5;d=87164}break}case 60:{f=4;d=87187;break}case 62:{f=4;d=87170;break}case 45:{f=5;d=87181;break}default:{if((f|0)!=0&d<<24>>24==32)if((a[f>>0]|0)==32){f=6;d=87157;break a}else{k=18;break a}switch(d<<24>>24){case 34:{f=6;d=87150;break a}case 39:{f=5;d=87175;break a}case 10:if(j){k=18;break a}else{f=5;d=87144;break a}default:{k=18;break a}}}}while(0);if((k|0)==18){k=0;d=j|d<<24>>24!=13;f=d?1:5;d=d?h:87138}g=e+f|0;b=f;while(1){if(!b)break;a[e>>0]=a[d>>0]|0;b=b+-1|0;d=d+1|0;e=e+1|0}b=h;i=f+i|0;e=g;h=h+1|0;f=b}a[e>>0]=0;return c[42252]|0}function uw(b){b=b|0;var c=0,d=0;d=b+1|0;c=a[d>>0]|0;a:do if(c<<24>>24==35){d=b+2|0;c=a[d>>0]|0;switch(c<<24>>24){case 88:case 120:break;default:{b=d;while(1){d=b+1|0;if((c+-48&255)>=10)break a;b=d;c=a[d>>0]|0}}}d=b+3|0;while(1){c=a[d>>0]|0;if((c+-48&255)>=10)switch(c<<24>>24){case 65:case 66:case 67:case 68:case 69:case 70:case 97:case 98:case 99:case 100:case 101:case 102:break;default:break a}d=d+1|0}}else while(1){b=d+1|0;if(((c&-33)+-65&255)>=26)break a;d=b;c=a[b>>0]|0}while(0);return c<<24>>24==59|0}function vw(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;d=c[42254]|0;if(!d){c[42255]=64;d=xw(64)|0;c[42254]=d;i=0}else i=0;while(1){if(!b)break;e=a[b>>0]|0;if(!(e<<24>>24))break;f=c[42255]|0;if((i|0)>(f+-8|0)){d=f<<1;c[42255]=d;d=zw(c[42254]|0,d)|0;c[42254]=d;d=d+i|0;e=a[b>>0]|0}switch(e<<24>>24){case 38:{if(!(uw(b)|0)){g=5;e=87164}else j=12;break}case 60:{g=4;e=87187;break}case 62:{g=4;e=87170;break}case 34:{g=6;e=87150;break}case 39:{g=5;e=87175;break}default:j=12}if((j|0)==12){j=0;g=1;e=b}h=d+g|0;f=g;while(1){if(!f)break;a[d>>0]=a[e>>0]|0;f=f+-1|0;e=e+1|0;d=d+1|0}i=g+i|0;d=h;b=b+1|0}a[d>>0]=0;return c[42254]|0}function ww(a){a=a|0;var b=0;if(!a)a=0;else{b=xw(a)|0;WN(b|0,0,a|0)|0;a=b}return a|0}function xw(a){a=a|0;if(a){a=_I(a)|0;if(!a){YL(96532,14,1,c[13918]|0)|0;a=0}}else a=0;return a|0}function yw(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=bJ(a,O(d,b)|0)|0;if(!((b|0)!=0&(a|0)==0)){if(b>>>0>e>>>0)WN(a+(O(e,d)|0)|0,0,O(b-e|0,d)|0)|0}else YL(96532,14,1,c[13918]|0)|0;return a|0}function zw(a,b){a=a|0;b=b|0;a=bJ(a,b)|0;if((b|0)!=0&(a|0)==0)YL(96532,14,1,c[13918]|0)|0;return a|0}function Aw(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0,m=0,n=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+80|0;r=u+40|0;q=u+32|0;n=u+24|0;m=u;s=4;t=_I(40)|0;c[t>>2]=0;f=u+68|0;g=u+64|0;if(0){o=0;ha(57,a|0,f|0,g|0);i=o;o=0;if((i|0)!=0&(p|0)!=0){j=TN(c[i>>2]|0,t|0,s|0)|0;if(!j)Ua(i|0,p|0);z=p}else j=-1;if((j|0)!=1){j=c[13918]|0;i=c[f>>2]|0;f=c[g>>2]|0;o=0;c[m>>2]=87236;c[m+4>>2]=i;c[m+8>>2]=f;c[m+12>>2]=d;c[m+16>>2]=b;aa(13,j|0,87192,m|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)!=1){o=0;ea(1);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)!=1)j=6;else{f=z;j=15}}else{f=z;j=15}}else{f=z;j=15}}else j=6;do if((j|0)==6){o=0;f=_(20,a|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){i=TN(c[g>>2]|0,t|0,s|0)|0;if(!i)Ua(g|0,p|0);z=p}else i=-1;if((i|0)!=1){if(!f){o=0;ea(2);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;break}}if((d|0)<1){o=0;ea(3);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;break}f=0;break}else{c[42256]=(e|0)>-1?e:30;t=SN(169028,1,t|0,s|0)|0;s=z;o=0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;break}f=0;j=15;break}}else{f=z;j=15}}while(0);a:do if((j|0)==15){b:while(1){if(f|0){f=2;break a}o=0;ea(4);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue}a=c[13918]|0;m=0;while(1){o=0;j=Z(1)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}if(!j)break;o=0;f=_(21,j|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){i=TN(c[g>>2]|0,t|0,s|0)|0;if(!i)Ua(g|0,p|0);z=p}else i=-1;if((i|0)==1){f=z;j=15;continue b}o=0;ga(24,j|0,f|0);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}m=m+1|0;do if(((m|0)%100|0|0)==0&0!=0){f=(m|0)%1e3|0;if((f|0)==100){o=0;$(27,87236,a|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}o=0;c[n>>2]=m;aa(13,a|0,87254,n|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}break}o=0;c[q>>2]=m;aa(13,a|0,87254,q|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){i=TN(c[g>>2]|0,t|0,s|0)|0;if(!i)Ua(g|0,p|0);z=p}else i=-1;if((i|0)==1){f=z;j=15;continue b}if(!f){o=0;$(28,10,a|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}}}while(0);if((m|0)>=(d|0))break}switch(b|0){case 1:{o=0;ea(5);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}break}case 2:{o=0;ea(6);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}break}default:{o=0;ea(7);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}o=0;ea(3);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue b}}}if(!0){f=0;break a}if((m|0)>99){o=0;$(28,10,a|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15;continue}}f=c[42296]|0;g=c[42297]|0;o=0;k=+X(1);i=o;o=0;if((i|0)!=0&(p|0)!=0){j=TN(c[i>>2]|0,t|0,s|0)|0;if(!j)Ua(i|0,p|0);z=p}else j=-1;if((j|0)==1){f=z;j=15;continue}o=0;c[r>>2]=87236;c[r+4>>2]=f;c[r+8>>2]=g;c[r+12>>2]=m;h[r+16>>3]=k;aa(13,a|0,87258,r|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,s|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){f=z;j=15}else break}f=0}while(0);$I(t|0);l=u;return f|0}function Bw(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;a=(c[a+16>>2]|0)+192|0;e=0;h=0;while(1){a=c[a>>2]|0;if(!a)break;g=c[a+16>>2]|0;f=c[g+180>>2]|0;a=0;while(1){if(!(c[f+(a<<2)>>2]|0))break;a=a+1|0;e=e+1|0}a=g+164|0;h=h+1|0}c[b>>2]=h;c[d>>2]=e;return}function Cw(b){b=b|0;var d=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;c[42299]=b;c[42306]=0;c[42297]=0;c[42296]=0;i=b+16|0;b=(c[i>>2]|0)+192|0;h=0;f=0;while(1){b=c[b>>2]|0;if(!b)break;g=c[b+16>>2]|0;a[g+157>>0]=0;h=h+1|0;c[42296]=h;d=c[g+180>>2]|0;b=0;while(1){if(!(c[d+(b<<2)>>2]|0))break;k=f+1|0;c[42297]=k;b=b+1|0;f=k}b=g+164|0}b=c[42307]|0;if(!b)b=xw(h<<2)|0;else b=zw(b,h<<2)|0;c[42307]=b;c[42308]=0;b=c[42301]|0;if(!b)b=xw(c[42296]<<2)|0;else b=zw(b,c[42296]<<2)|0;c[42301]=b;c[42300]=0;d=1;b=(c[i>>2]|0)+192|0;while(1){b=c[b>>2]|0;if(!b)break;k=b+16|0;i=c[k>>2]|0;j=i+292|0;c[j>>2]=0;i=c[i+172>>2]|0;h=d;g=0;b=0;while(1){d=c[i+(g<<2)>>2]|0;if(!d)break;f=b+1|0;c[j>>2]=f;b=c[d+16>>2]|0;c[b+160>>2]=0;c[b+164>>2]=-1;if(!h)b=0;else{l=c[d>>2]&3;b=((c[(c[(c[((l|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((l|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)|0)<(e[b+170>>1]|0|0)?0:h}h=b;g=g+1|0;b=f}b=ww((g<<2)+4|0)|0;d=c[k>>2]|0;c[d+264>>2]=b;c[d+268>>2]=0;d=c[d+180>>2]|0;b=0;do{l=b;b=b+1|0}while((c[d+(l<<2)>>2]|0)!=0);d=ww(b<<2)|0;b=c[k>>2]|0;c[b+272>>2]=d;c[b+276>>2]=0;d=h;b=b+164|0}return d|0}function Dw(){var a=0,b=0,d=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;n=o+8|0;k=o;m=AA(c[42296]|0)|0;a=(c[(c[42299]|0)+16>>2]|0)+192|0;while(1){b=c[a>>2]|0;if(!b){j=0;break}d=b+16|0;a=c[d>>2]|0;if(!(c[a+292>>2]|0)){CA(m,b);a=c[d>>2]|0}a=a+164|0}while(1){a=DA(m)|0;if(!a)break;i=a+16|0;a=c[i>>2]|0;f=a+232|0;c[f>>2]=0;d=c[a+172>>2]|0;b=0;h=0;while(1){g=c[d+(b<<2)>>2]|0;if(!g){f=0;break}g=(c[(c[(c[((c[g>>2]&3|0)==3?g:g+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)+(e[(c[g+16>>2]|0)+170>>1]|0)|0;g=(h|0)>(g|0)?h:g;c[f>>2]=g;b=b+1|0;h=g}while(1){b=c[(c[a+180>>2]|0)+(f<<2)>>2]|0;if(!b)break;d=b+-48|0;g=(c[(c[((c[b>>2]&3|0)==2?b:d)+40>>2]|0)+16>>2]|0)+292|0;h=c[g>>2]|0;c[g>>2]=h+-1;if((h|0)<2){CA(m,c[((c[b>>2]&3|0)==2?b:d)+40>>2]|0);a=c[i>>2]|0}f=f+1|0}j=j+1|0}a:do if((j|0)!=(c[42296]|0)){$l(1,87590,k)|0;a=(c[(c[42299]|0)+16>>2]|0)+192|0;while(1){b=c[a>>2]|0;if(!b)break a;d=b+16|0;a=c[d>>2]|0;if(c[a+292>>2]|0){k=En(b)|0;a=c[(c[d>>2]|0)+292>>2]|0;c[n>>2]=k;c[n+4>>2]=a;$l(3,87612,n)|0;a=c[d>>2]|0}a=a+164|0}}while(0);BA(m);l=o;return}function Ew(){var b=0,d=0,e=0;b=(c[(c[42299]|0)+16>>2]|0)+192|0;while(1){b=c[b>>2]|0;if(!b)break;e=b+16|0;b=c[e>>2]|0;d=c[b+264>>2]|0;if(d){$I(d);b=c[e>>2]|0}d=c[b+272>>2]|0;if(d){$I(d);b=c[e>>2]|0}a[b+157>>0]=0;b=b+164|0}return}function Fw(){var a=0,b=0,d=0,e=0,f=0;a=(c[(c[42299]|0)+16>>2]|0)+192|0;while(1){a=c[a>>2]|0;if(!a)break;a=c[a+16>>2]|0;c[a+280>>2]=0;a=a+164|0}f=ww(c[42296]<<2)|0;e=0;a=(c[(c[42299]|0)+16>>2]|0)+192|0;while(1){b=c[a>>2]|0;if(!b)break;d=b+16|0;a=c[d>>2]|0;if(!(c[a+280>>2]|0)){c[f+(e<<2)>>2]=Sw(b)|0;b=e+1|0;a=c[d>>2]|0}else b=e;e=b;a=a+164|0}a=Tw(f,e)|0;while(1){if((Uw(a)|0)<=1)break;Yw(a,c[(Xw(Ww(Vw(a)|0)|0)|0)+8>>2]|0)}$I(a);a=0;while(1){if((a|0)>=(e|0))break;$I(c[f+(a<<2)>>2]|0);a=a+1|0}$I(f);if((c[42300]|0)==((c[42296]|0)+-1|0)){Zw();return}else ma(87335,87365,523,87370)}function Gw(){var a=0,b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;i=c[42306]|0;f=c[42300]|0;j=c[42301]|0;k=c[42256]|0;b=0;a=0;g=i;while(1){if((g|0)>=(f|0)){h=8;break}e=c[j+(g<<2)>>2]|0;d=c[(c[e+16>>2]|0)+160>>2]|0;if((d|0)<0){if(!a)a=e;else a=(c[(c[a+16>>2]|0)+160>>2]|0)>(d|0)?e:a;b=b+1|0;if((b|0)>=(k|0))break}e=g+1|0;c[42306]=e;g=e}if((h|0)==8)if((i|0)>0){f=0;while(1){if((f|0)>=(i|0))break;d=c[j+(f<<2)>>2]|0;e=c[(c[d+16>>2]|0)+160>>2]|0;if((e|0)<0){if(!a)a=d;else a=(c[(c[a+16>>2]|0)+160>>2]|0)>(e|0)?d:a;b=b+1|0;if((b|0)>=(k|0))break}f=f+1|0}c[42306]=f}return a|0}function Hw(a){a=a|0;var b=0,d=0;b=c[a>>2]&3;d=c[((b|0)==3?a:a+48|0)+40>>2]|0;a=c[((b|0)==2?a:a+-48|0)+40>>2]|0;b=(c[(c[d+16>>2]|0)+288>>2]|0)<(c[(c[a+16>>2]|0)+288>>2]|0);a=b?d:a;c[42302]=0;c[42303]=2147483647;d=c[a+16>>2]|0;c[42304]=c[d+284>>2];c[42305]=c[d+288>>2];if(b)Rw(a);else Qw(a);return c[42302]|0}function Iw(a,b){a=a|0;b=b|0;var d=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;n=o;g=c[b>>2]&3;m=b+-48|0;j=b+48|0;k=b+16|0;g=(c[(c[(c[((g|0)==2?b:m)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((g|0)==3?b:j)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[(c[k>>2]|0)+170>>1]|0)|0;do if((g|0)>0){d=c[a>>2]&3;h=c[((d|0)==3?a:a+48|0)+40>>2]|0;i=c[h+16>>2]|0;if(((c[i+276>>2]|0)+(c[i+268>>2]|0)|0)==1){Mw(h,g);break}d=c[((d|0)==2?a:a+-48|0)+40>>2]|0;f=c[d+16>>2]|0;if(((c[f+276>>2]|0)+(c[f+268>>2]|0)|0)==1){Mw(d,0-g|0);break}if((c[i+288>>2]|0)<(c[f+288>>2]|0)){Mw(h,g);break}else{Mw(d,0-g|0);break}}while(0);d=a+16|0;f=c[(c[d>>2]|0)+160>>2]|0;g=c[b>>2]&3;g=Nw(c[((g|0)==3?b:j)+40>>2]|0,c[((g|0)==2?b:m)+40>>2]|0,f,1)|0;i=c[b>>2]&3;if((Nw(c[((i|0)==2?b:m)+40>>2]|0,c[((i|0)==3?b:j)+40>>2]|0,f,0)|0)==(g|0)){c[(c[k>>2]|0)+160>>2]=0-f;c[(c[d>>2]|0)+160>>2]=0;Ow(a,b);n=c[g+16>>2]|0;Pw(g,c[n+280>>2]|0,c[n+284>>2]|0)|0;l=o;return}else{$l(1,87296,n)|0;Ua(169028,1)}}function Jw(){var b=0,d=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;Lw();m=ww((c[42298]<<2)+4|0)|0;d=c[42298]|0;b=0;while(1){if((b|0)>(d|0))break;c[m+(b<<2)>>2]=0;b=b+1|0}b=(c[(c[42299]|0)+16>>2]|0)+192|0;d=b;while(1){d=c[d>>2]|0;if(!d)break;d=c[d+16>>2]|0;if(!(a[d+156>>0]|0)){l=m+(c[d+232>>2]<<2)|0;c[l>>2]=(c[l>>2]|0)+1}d=d+164|0}while(1){b=c[b>>2]|0;if(!b)break;l=b+16|0;b=c[l>>2]|0;if(!(a[b+156>>0]|0)){h=c[42298]|0;f=c[b+172>>2]|0;k=0;j=0;d=0;while(1){g=c[f+(d<<2)>>2]|0;if(!g)break;n=c[g+16>>2]|0;i=(c[(c[(c[((c[g>>2]&3|0)==3?g:g+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)+(e[n+170>>1]|0)|0;k=(c[n+156>>2]|0)+k|0;j=(j|0)>(i|0)?j:i;d=d+1|0}g=c[b+180>>2]|0;i=0;d=0;while(1){f=c[g+(d<<2)>>2]|0;if(!f)break;o=c[f+16>>2]|0;n=(c[(c[(c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[o+170>>1]|0)|0;i=(c[o+156>>2]|0)+i|0;h=(h|0)<(n|0)?h:n;d=d+1|0}d=(j|0)>0?j:0;if((k|0)==(i|0)){g=d;f=d;while(1){d=f+1|0;if((f|0)>=(h|0))break;g=(c[m+(d<<2)>>2]|0)<(c[m+(g<<2)>>2]|0)?d:g;f=d}o=b+232|0;n=m+(c[o>>2]<<2)|0;c[n>>2]=(c[n>>2]|0)+-1;n=m+(g<<2)|0;c[n>>2]=(c[n>>2]|0)+1;c[o>>2]=g}d=c[b+264>>2]|0;if(d){$I(d);b=c[l>>2]|0}d=c[b+272>>2]|0;if(d){$I(d);b=c[l>>2]|0}a[b+157>>0]=0}b=b+164|0}$I(m);return}function Kw(){var a=0,b=0,d=0,f=0,g=0,h=0;b=0;while(1){if((b|0)>=(c[42300]|0))break;a=c[(c[42301]|0)+(b<<2)>>2]|0;do if(((c[(c[a+16>>2]|0)+160>>2]|0)==0?(d=Hw(a)|0,d|0):0)?(f=c[d>>2]&3,f=(c[(c[(c[((f|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((f|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[(c[d+16>>2]|0)+170>>1]|0)|0,(f|0)>=2):0){h=c[a>>2]&3;g=c[((h|0)==3?a:a+48|0)+40>>2]|0;a=c[((h|0)==2?a:a+-48|0)+40>>2]|0;if((c[(c[g+16>>2]|0)+288>>2]|0)<(c[(c[a+16>>2]|0)+288>>2]|0)){Mw(g,f>>>1);break}else{Mw(a,(f|0)/-2|0);break}}while(0);b=b+1|0}Ew();return}function Lw(){var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;i=l;l=l+16|0;h=i;c[h>>2]=0;c[h>>2]=2147483647;c[42298]=-2147483647;b=(c[(c[42299]|0)+16>>2]|0)+192|0;e=b;g=2147483647;f=-2147483647;while(1){d=c[e>>2]|0;if(!d)break;e=c[d+16>>2]|0;if(!(a[e+156>>0]|0)){j=c[e+232>>2]|0;d=(g|0)<(j|0)?g:j;c[h>>2]=d;f=(f|0)>(j|0)?f:j;c[42298]=f}else d=g;e=e+164|0;g=d}if(g|0){while(1){b=c[b>>2]|0;if(!b)break;b=c[b+16>>2]|0;j=b+232|0;c[j>>2]=(c[j>>2]|0)-g;b=b+164|0}c[42298]=f-g;c[h>>2]=0}l=i;return}function Mw(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=a+16|0;a=c[f>>2]|0;e=a+232|0;c[e>>2]=(c[e>>2]|0)-b;e=0;while(1){d=c[(c[a+272>>2]|0)+(e<<2)>>2]|0;if(!d){e=0;break}if((d|0)!=(c[a+280>>2]|0)){Mw(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0,b);a=c[f>>2]|0}e=e+1|0}while(1){d=c[(c[a+264>>2]|0)+(e<<2)>>2]|0;if(!d)break;if((d|0)!=(c[a+280>>2]|0)){Mw(c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0,b);a=c[f>>2]|0}e=e+1|0}return}function Nw(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;g=(e|0)==0&1;h=0-d|0;f=c[(c[b+16>>2]|0)+288>>2]|0;b=a;while(1){a=c[b+16>>2]|0;if((c[a+284>>2]|0)<=(f|0)?(f|0)<=(c[a+288>>2]|0):0)break;a=c[a+280>>2]|0;i=a+48|0;j=(c[a+16>>2]|0)+160|0;c[j>>2]=(((b|0)==(c[((c[a>>2]&3|0)==3?a:i)+40>>2]|0)?e:g)|0?d:h)+(c[j>>2]|0);j=c[a>>2]&3;i=c[((j|0)==3?a:i)+40>>2]|0;a=c[((j|0)==2?a:a+-48|0)+40>>2]|0;b=(c[(c[i+16>>2]|0)+288>>2]|0)>(c[(c[a+16>>2]|0)+288>>2]|0)?i:a}return b|0}function Ow(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;i=a+16|0;e=(c[i>>2]|0)+164|0;c[(c[b+16>>2]|0)+164>>2]=c[e>>2];c[(c[42301]|0)+(c[e>>2]<<2)>>2]=b;c[(c[i>>2]|0)+164>>2]=-1;i=(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16|0;e=c[i>>2]|0;g=e+276|0;f=c[g>>2]|0;j=f+-1|0;c[g>>2]=j;g=e+272|0;h=0;while(1){if((h|0)>=(f|0)){k=3;break}d=c[g>>2]|0;if((c[d+(h<<2)>>2]|0)==(a|0))break;h=h+1|0}if((k|0)==3)d=c[e+272>>2]|0;c[d+(h<<2)>>2]=c[d+(j<<2)>>2];c[(c[(c[i>>2]|0)+272>>2]|0)+(j<<2)>>2]=0;i=(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)+16|0;e=c[i>>2]|0;g=e+268|0;f=c[g>>2]|0;j=f+-1|0;c[g>>2]=j;g=e+264|0;h=0;while(1){if((h|0)>=(f|0)){k=8;break}d=c[g>>2]|0;if((c[d+(h<<2)>>2]|0)==(a|0))break;h=h+1|0}if((k|0)==8)d=c[e+264>>2]|0;c[d+(h<<2)>>2]=c[d+(j<<2)>>2];c[(c[(c[i>>2]|0)+264>>2]|0)+(j<<2)>>2]=0;k=(c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)+16|0;a=c[k>>2]|0;j=c[a+272>>2]|0;a=a+276|0;i=c[a>>2]|0;c[a>>2]=i+1;c[j+(i<<2)>>2]=b;k=c[k>>2]|0;c[(c[k+272>>2]|0)+(c[k+276>>2]<<2)>>2]=0;k=(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)+16|0;i=c[k>>2]|0;j=c[i+264>>2]|0;i=i+268|0;a=c[i>>2]|0;c[i>>2]=a+1;c[j+(a<<2)>>2]=b;k=c[k>>2]|0;c[(c[k+264>>2]|0)+(c[k+268>>2]<<2)>>2]=0;return}function Pw(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;g=a+16|0;a=c[g>>2]|0;c[a+280>>2]=b;c[a+284>>2]=d;f=0;while(1){e=c[(c[a+272>>2]|0)+(f<<2)>>2]|0;if(!e){f=0;break}if((e|0)!=(b|0)){d=Pw(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,e,d)|0;a=c[g>>2]|0}f=f+1|0}while(1){e=c[(c[a+264>>2]|0)+(f<<2)>>2]|0;if(!e)break;if((e|0)!=(b|0)){d=Pw(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0,e,d)|0;a=c[g>>2]|0}f=f+1|0}c[a+288>>2]=d;return d+1|0}function Qw(a){a=a|0;var b=0,d=0,f=0,g=0,h=0,i=0,j=0;i=a+16|0;g=0;while(1){a=c[i>>2]|0;d=c[(c[a+180>>2]|0)+(g<<2)>>2]|0;if(!d){d=0;break}f=c[d+16>>2]|0;if((c[f+164>>2]|0)<0){a=c[d>>2]&3;b=c[(c[((a|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0;j=c[b+288>>2]|0;if((c[42304]|0)>(j|0)|(j|0)>(c[42305]|0)?(h=(c[b+232>>2]|0)-(c[(c[(c[((a|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[f+170>>1]|0)|0,(h|0)<(c[42303]|0)|(c[42302]|0)==0):0){c[42302]=d;c[42303]=h}}else{b=c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0;if((c[(c[b+16>>2]|0)+288>>2]|0)<(c[a+288>>2]|0))Qw(b)}g=g+1|0}while(1){b=c[(c[a+264>>2]|0)+(d<<2)>>2]|0;if(!((b|0)!=0&(c[42303]|0)>0))break;b=c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0;if((c[(c[b+16>>2]|0)+288>>2]|0)<(c[a+288>>2]|0)){Qw(b);a=c[i>>2]|0}d=d+1|0}return}function Rw(a){a=a|0;var b=0,d=0,f=0,g=0,h=0,i=0,j=0;i=a+16|0;g=0;while(1){a=c[i>>2]|0;d=c[(c[a+172>>2]|0)+(g<<2)>>2]|0;if(!d){d=0;break}f=c[d+16>>2]|0;if((c[f+164>>2]|0)<0){a=c[d>>2]&3;b=c[(c[((a|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0;j=c[b+288>>2]|0;if((c[42304]|0)>(j|0)|(j|0)>(c[42305]|0)?(h=(c[(c[(c[((a|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[b+232>>2]|0)-(e[f+170>>1]|0)|0,(h|0)<(c[42303]|0)|(c[42302]|0)==0):0){c[42302]=d;c[42303]=h}}else{b=c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0;if((c[(c[b+16>>2]|0)+288>>2]|0)<(c[a+288>>2]|0))Rw(b)}g=g+1|0}while(1){b=c[(c[a+272>>2]|0)+(d<<2)>>2]|0;if(!((b|0)!=0&(c[42303]|0)>0))break;b=c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0;if((c[(c[b+16>>2]|0)+288>>2]|0)<(c[a+288>>2]|0)){Rw(b);a=c[i>>2]|0}d=d+1|0}return}function Sw(a){a=a|0;var b=0;b=ww(16)|0;c[b>>2]=a;c[b+4>>2]=gx(a,b)|0;c[b+12>>2]=b;return b|0}function Tw(a,b){a=a|0;b=b|0;var d=0,e=0;e=ww(8)|0;c[e>>2]=a;c[e+4>>2]=b;d=0;while(1){if((d|0)>=(b|0))break;c[(c[a+(d<<2)>>2]|0)+8>>2]=d;d=d+1|0}d=(b|0)/2|0;while(1){if((d|0)<=-1)break;Yw(e,d);d=d+-1|0}return e|0}function Uw(a){a=a|0;return c[a+4>>2]|0}function Vw(a){a=a|0;var b=0,d=0,e=0,f=0;f=c[a>>2]|0;b=c[f>>2]|0;c[b+8>>2]=-1;d=a+4|0;e=(c[d>>2]|0)+-1|0;c[f>>2]=c[f+(e<<2)>>2];f=c[a>>2]|0;c[(c[f>>2]|0)+8>>2]=0;c[f+(e<<2)>>2]=b;c[d>>2]=e;Yw(a,0);return b|0}function Ww(a){a=a|0;return fx(c[a>>2]|0,0,0)|0}function Xw(a){a=a|0;var b=0,d=0,f=0,g=0,h=0,i=0;b=a+16|0;if((c[(c[b>>2]|0)+164>>2]|0)>-1)ma(87384,87365,463,87398);g=a+48|0;d=bx(c[((c[a>>2]&3|0)==3?a:g)+40>>2]|0)|0;i=a+-48|0;f=bx(c[((c[a>>2]&3|0)==2?a:i)+40>>2]|0)|0;h=c[a>>2]&3;b=(c[(c[(c[((h|0)==2?a:i)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((h|0)==3?a:g)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[(c[b>>2]|0)+170>>1]|0)|0;if((c[d+8>>2]|0)==-1)cx(c[d>>2]|0,0,b);else cx(c[f>>2]|0,0,0-b|0);dx(a);return ex(d,f)|0}function Yw(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=c[a>>2]|0;g=c[a+4>>2]|0;while(1){a=b<<1;f=a+2|0;a=a|1;if(!((a|0)<(g|0)?(c[(c[h+(a<<2)>>2]|0)+4>>2]|0)<(c[(c[h+(b<<2)>>2]|0)+4>>2]|0):0))a=b;if((f|0)>=(g|0))break;d=h+(f<<2)|0;e=c[d>>2]|0;if((f|0)==(b|0)?1:(c[e+4>>2]|0)>=(c[(c[h+(a<<2)>>2]|0)+4>>2]|0))break;i=h+(b<<2)|0;a=c[i>>2]|0;c[i>>2]=e;c[d>>2]=a;c[(c[i>>2]|0)+8>>2]=b;c[a+8>>2]=f;b=f}return}function Zw(){Pw(c[(c[(c[42299]|0)+16>>2]|0)+192>>2]|0,0,1)|0;_w(c[(c[(c[42299]|0)+16>>2]|0)+192>>2]|0,0);return}function _w(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=a+16|0;d=0;while(1){a=c[f>>2]|0;e=c[(c[a+272>>2]|0)+(d<<2)>>2]|0;if(!e){e=0;break}if((e|0)!=(b|0))_w(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,e);d=d+1|0}while(1){d=c[(c[a+264>>2]|0)+(e<<2)>>2]|0;if(!d)break;if((d|0)!=(b|0)){_w(c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0,d);a=c[f>>2]|0}e=e+1|0}if(b|0)$w(b);return}function $w(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0;b=c[a>>2]&3;d=c[((b|0)==3?a:a+48|0)+40>>2]|0;e=c[d+16>>2]|0;if((c[e+280>>2]|0)==(a|0))i=1;else{e=c[((b|0)==2?a:a+-48|0)+40>>2]|0;i=-1;d=e;e=c[e+16>>2]|0}g=c[e+180>>2]|0;b=0;f=0;while(1){h=c[g+(f<<2)>>2]|0;if(!h)break;b=(ax(h,d,i)|0)+b|0;f=f+1|0}g=c[e+172>>2]|0;e=0;while(1){f=c[g+(e<<2)>>2]|0;if(!f)break;b=(ax(f,d,i)|0)+b|0;e=e+1|0}c[(c[a+16>>2]|0)+160>>2]=b;return}function ax(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;h=c[a>>2]&3;i=(h|0)==3?a:a+48|0;e=c[i+40>>2]|0;if((e|0)==(b|0))e=c[((h|0)==2?a:a+-48|0)+40>>2]|0;g=c[b+16>>2]|0;f=c[(c[e+16>>2]|0)+288>>2]|0;if((c[g+284>>2]|0)<=(f|0)?(f|0)<=(c[g+288>>2]|0):0){f=c[a+16>>2]|0;if((c[f+164>>2]|0)>-1)e=c[f+160>>2]|0;else e=0;g=1;e=e-(c[f+156>>2]|0)|0}else{g=0;e=c[(c[a+16>>2]|0)+156>>2]|0}i=(c[((d|0)>0?((h|0)==2?a:a+-48|0):i)+40>>2]|0)==(b|0)?1:-1;return (((g?i:0-i|0)|0)<0?0-e|0:e)|0}function bx(a){a=a|0;var b=0,d=0;a=c[(c[a+16>>2]|0)+280>>2]|0;while(1){b=a+12|0;d=c[b>>2]|0;if(!((d|0)!=(a|0)&(d|0)!=0))break;a=c[d+12>>2]|0;if(!a){a=d;continue}c[b>>2]=a}return a|0}function cx(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;h=a+16|0;e=c[h>>2]|0;g=e+232|0;c[g>>2]=(c[g>>2]|0)+d;g=0;while(1){f=c[(c[e+264>>2]|0)+(g<<2)>>2]|0;if(!f){g=0;break}f=c[((c[f>>2]&3|0)==3?f:f+48|0)+40>>2]|0;if((f|0)!=(b|0)){cx(f,a,d);e=c[h>>2]|0}g=g+1|0}while(1){f=c[(c[e+272>>2]|0)+(g<<2)>>2]|0;if(!f)break;f=c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0;if((f|0)!=(b|0)){cx(f,a,d);e=c[h>>2]|0}g=g+1|0}return}function dx(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=l;l=l+32|0;d=(c[b+16>>2]|0)+164|0;if((c[d>>2]|0)>-1){$l(1,87487,h)|0;Ua(169028,1)}g=c[42300]|0;c[d>>2]=g;d=c[42301]|0;c[42300]=g+1;c[d+(g<<2)>>2]=b;d=c[b>>2]|0;g=b+48|0;e=c[((d&3|0)==3?b:g)+40>>2]|0;if(!(a[(c[e+16>>2]|0)+157>>0]|0)){f=c[42307]|0;d=c[42308]|0;c[42308]=d+1;c[f+(d<<2)>>2]=e;d=c[b>>2]|0}f=b+-48|0;e=c[((d&3|0)==2?b:f)+40>>2]|0;if(!(a[(c[e+16>>2]|0)+157>>0]|0)){i=c[42307]|0;d=c[42308]|0;c[42308]=d+1;c[i+(d<<2)>>2]=e;d=c[b>>2]|0}i=(c[((d&3|0)==3?b:g)+40>>2]|0)+16|0;d=c[i>>2]|0;a[d+157>>0]=1;e=c[d+272>>2]|0;d=d+276|0;g=c[d>>2]|0;c[d>>2]=g+1;c[e+(g<<2)>>2]=b;g=c[i>>2]|0;c[(c[g+272>>2]|0)+(c[g+276>>2]<<2)>>2]=0;i=c[i>>2]|0;if(!(c[(c[i+180>>2]|0)+((c[i+276>>2]|0)+-1<<2)>>2]|0)){$l(1,87521,h+8|0)|0;Ua(169028,1)}i=(c[((c[b>>2]&3|0)==2?b:f)+40>>2]|0)+16|0;e=c[i>>2]|0;a[e+157>>0]=1;f=c[e+264>>2]|0;e=e+268|0;g=c[e>>2]|0;c[e>>2]=g+1;c[f+(g<<2)>>2]=b;b=c[i>>2]|0;c[(c[b+264>>2]|0)+(c[b+268>>2]<<2)>>2]=0;i=c[i>>2]|0;if(!(c[(c[i+172>>2]|0)+((c[i+268>>2]|0)+-1<<2)>>2]|0)){$l(1,87556,h+16|0)|0;Ua(169028,1)}else{l=h;return}}function ex(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;while(1){g=a+12|0;d=c[g>>2]|0;if((d|0)==0|(d|0)==(a|0))break;else a=d}while(1){f=b+12|0;d=c[f>>2]|0;if((d|0)==0|(d|0)==(b|0))break;else b=d}if((a|0)!=(b|0)){e=c[a+8>>2]|0;d=c[b+8>>2]|0;do if((e|0)>-1)if((d|0)==-1)h=a;else j=10;else if((d|0)>-1)if((e|0)==-1){h=b;break}else{j=10;break}else ma(87410,87365,327,87457);while(0);if((j|0)==10)h=(c[b+4>>2]|0)<(c[a+4>>2]|0)?a:b;c[f>>2]=h;c[g>>2]=h;c[h+4>>2]=(c[b+4>>2]|0)+(c[a+4>>2]|0);if((c[h+8>>2]|0)>-1)i=h;else ma(87468,87365,335,87457)}else i=a;return i|0}function fx(a,b,d){a=a|0;b=b|0;d=d|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;l=bx(a)|0;if(d){k=c[d>>2]&3;if(((c[(c[(c[((k|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((k|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)|0)!=(e[(c[d+16>>2]|0)+170>>1]|0|0))f=3}else{d=0;f=3}a:do if((f|0)==3){k=a+16|0;j=0;while(1){f=c[k>>2]|0;i=c[(c[f+180>>2]|0)+(j<<2)>>2]|0;if(!i){j=0;break}f=i+16|0;g=i+-48|0;h=c[((c[i>>2]&3|0)==2?i:g)+40>>2]|0;do if((c[(c[f>>2]|0)+164>>2]|0)>-1){if((h|0)!=(b|0))d=fx(h,a,d)|0}else if((bx(h)|0)!=(l|0)){if(d|0?(m=c[i>>2]&3,h=c[d>>2]&3,((c[(c[(c[((m|0)==2?i:g)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((m|0)==3?i:i+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[(c[f>>2]|0)+170>>1]|0)|0)>=((c[(c[(c[((h|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((h|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[(c[d+16>>2]|0)+170>>1]|0)|0)):0)break;d=i}while(0);j=j+1|0}while(1){f=c[(c[f+172>>2]|0)+(j<<2)>>2]|0;if(!f)break a;g=f+16|0;h=f+48|0;i=c[((c[f>>2]&3|0)==3?f:h)+40>>2]|0;do if((c[(c[g>>2]|0)+164>>2]|0)>-1){if((i|0)!=(b|0))d=fx(i,a,d)|0}else if((bx(i)|0)!=(l|0)){if(d|0?(i=c[f>>2]&3,m=c[d>>2]&3,((c[(c[(c[((i|0)==2?f:f+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((i|0)==3?f:h)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[(c[g>>2]|0)+170>>1]|0)|0)>=((c[(c[(c[((m|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((m|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(e[(c[d+16>>2]|0)+170>>1]|0)|0)):0)break;d=f}while(0);j=j+1|0;f=c[k>>2]|0}}while(0);return d|0}function gx(a,b){a=a|0;b=b|0;var d=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;l=a+16|0;d=c[l>>2]|0;c[d+280>>2]=b;a=1;h=0;while(1){g=c[(c[d+172>>2]|0)+(h<<2)>>2]|0;if(!g){h=0;break}f=c[g+16>>2]|0;if(((c[f+164>>2]|0)<=-1?(i=c[g>>2]&3,j=g+48|0,k=c[(c[((i|0)==3?g:j)+40>>2]|0)+16>>2]|0,(c[k+280>>2]|0)==0):0)?((c[(c[(c[((i|0)==2?g:g+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[k+232>>2]|0)|0)==(e[f+170>>1]|0|0):0){dx(g);a=(gx(c[((c[g>>2]&3|0)==3?g:j)+40>>2]|0,b)|0)+a|0;d=c[l>>2]|0}h=h+1|0}while(1){f=c[(c[d+180>>2]|0)+(h<<2)>>2]|0;if(!f)break;g=c[f+16>>2]|0;if(((c[g+164>>2]|0)<=-1?(m=c[f>>2]&3,n=f+-48|0,o=c[(c[((m|0)==2?f:n)+40>>2]|0)+16>>2]|0,(c[o+280>>2]|0)==0):0)?((c[o+232>>2]|0)-(c[(c[(c[((m|0)==3?f:f+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)|0)==(e[g+170>>1]|0|0):0){dx(f);a=(gx(c[((c[f>>2]&3|0)==2?f:n)+40>>2]|0,b)|0)+a|0;d=c[l>>2]|0}h=h+1|0}return a|0}function hx(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;d=Jm(a,87620)|0;if(!d)d=30;else d=sM(d)|0;return Aw(a,b,c,d)|0}function ix(a){a=+a;return +((c[42184]|0)==0?a:+h[20895]-a)}function jx(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0.0,u=0;r=l;l=l+16|0;q=r;c[42309]=c[(c[(c[d+64>>2]|0)+8>>2]|0)+4>>2];kx(d);i=c[d+16>>2]|0;t=+h[i+32>>3];s=+h[i+40>>3];lx(e,87631,+h[b+352>>3]);lx(e,87638,t*.013888888888888888);lx(e,87638,s*.013888888888888888);mx(e);i=eo(d)|0;while(1){if(!i)break;g=i+16|0;if(!(a[(c[g>>2]|0)+118>>0]|0)){nx(e,87640,Xp(En(i)|0)|0);p=(c[g>>2]|0)+16|0;c[q>>2]=c[p>>2];c[q+4>>2]=c[p+4>>2];c[q+8>>2]=c[p+8>>2];c[q+12>>2]=c[p+12>>2];ox(e,q);if(!(a[(c[(c[g>>2]|0)+104>>2]|0)+82>>0]|0)){b=so(i)|0;b=px(b,c[c[(c[g>>2]|0)+104>>2]>>2]|0)|0}else b=Xp(Km(i,c[42199]|0)|0)|0;lx(e,87638,+h[(c[g>>2]|0)+32>>3]);lx(e,87638,+h[(c[g>>2]|0)+40>>3]);nx(e,87638,b);nx(e,87638,HA(i,c[42202]|0,95889)|0);nx(e,87638,c[c[(c[g>>2]|0)+8>>2]>>2]|0);nx(e,87638,HA(i,c[42193]|0,122106)|0);b=HA(i,c[42194]|0,174185)|0;if(!(a[b>>0]|0))b=HA(i,c[42193]|0,119592)|0;nx(e,87638,b);mx(e)}i=fo(d,i)|0}o=f<<24>>24==0;n=eo(d)|0;while(1){if(!n)break;m=Qm(d,n)|0;while(1){if(!m)break;if(o){f=174185;j=174185}else{j=Jm(m,96242)|0;f=Jm(m,96251)|0;f=f|0?f:174185;j=j|0?j:174185}p=m+16|0;b=c[p>>2]|0;k=c[b+8>>2]|0;a:do if(k){i=c[k+4>>2]|0;b=0;g=0;while(1){if((b|0)>=(i|0))break;u=(c[(c[k>>2]|0)+(b*48|0)+4>>2]|0)+g|0;b=b+1|0;g=u}nx(e,0,96237);qx(e,c[((c[m>>2]&3|0)==3?m:m+48|0)+40>>2]|0,j);qx(e,c[((c[m>>2]&3|0)==2?m:m+-48|0)+40>>2]|0,f);rx(e,g);f=0;while(1){b=c[p>>2]|0;g=c[b+8>>2]|0;if((f|0)>=(c[g+4>>2]|0))break a;i=c[g>>2]|0;g=c[i+(f*48|0)>>2]|0;i=c[i+(f*48|0)+4>>2]|0;b=0;while(1){if((b|0)>=(i|0))break;u=g+(b<<4)|0;c[q>>2]=c[u>>2];c[q+4>>2]=c[u+4>>2];c[q+8>>2]=c[u+8>>2];c[q+12>>2]=c[u+12>>2];ox(e,q);b=b+1|0}f=f+1|0}}while(0);if(c[b+96>>2]|0){u=so(c[((c[m>>2]&3|0)==3?m:m+48|0)+40>>2]|0)|0;nx(e,87638,px(u,c[c[(c[p>>2]|0)+96>>2]>>2]|0)|0);u=(c[(c[p>>2]|0)+96>>2]|0)+56|0;c[q>>2]=c[u>>2];c[q+4>>2]=c[u+4>>2];c[q+8>>2]=c[u+8>>2];c[q+12>>2]=c[u+12>>2];ox(e,q)}nx(e,87638,HA(m,c[42230]|0,95889)|0);nx(e,87638,HA(m,c[42221]|0,122106)|0);mx(e);m=Sm(d,m)|0}n=fo(d,n)|0}sx(87646,e);l=r;return}function kx(a){a=a|0;var b=0.0;if(c[42184]|0){a=c[a+16>>2]|0;b=+h[a+24>>3]+ +h[a+40>>3];h[20895]=b;h[20896]=b*.013888888888888888}return}function lx(a,b,c){a=a|0;b=b|0;c=+c;var d=0,e=0,f=0;f=l;l=l+1040|0;e=f;d=f+8|0;if(b|0)sx(b,a);h[e>>3]=c;qL(d,87652,e)|0;sx(d,a);l=f;return}function mx(b){b=b|0;a[174081]=10;ab[c[42309]&63](b,174081)|0;return}function nx(a,b,c){a=a|0;b=b|0;c=c|0;if(b|0)sx(b,a);sx(c,a);return}function ox(a,b){a=a|0;b=b|0;var d=0.0;lx(a,87638,+h[b>>3]*.013888888888888888);if(!(c[42184]|0))d=+h[b+8>>3];else d=+h[20895]-+h[b+8>>3];lx(a,87638,d*.013888888888888888);return}function px(a,b){a=a|0;b=b|0;var c=0;c=ap(a,b)|0;b=Xp(c)|0;cp(a,c)|0;return b|0}function qx(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if(!(a[(c[d+16>>2]|0)+118>>0]|0))d=Xp(En(d)|0)|0;else{f=so(d)|0;d=px(f,(XJ(En(d)|0,58)|0)+1|0)|0}nx(b,87638,d);if(e|0?a[e>>0]|0:0)nx(b,93017,Xp(e)|0);return}function rx(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=l;l=l+1040|0;f=d;e=d+8|0;sx(87638,a);c[f>>2]=b;qL(e,122187,f)|0;sx(e,a);l=d;return}function sx(a,b){a=a|0;b=b|0;ab[c[42309]&63](b,a)|0;return} +function FB(a,b){a=a|0;b=b|0;if((+h[a+16>>3]>=+h[b>>3]?+h[b+16>>3]>=+h[a>>3]:0)?+h[a+24>>3]>=+h[b+8>>3]:0)a=+h[b+24>>3]>=+h[a+8>>3]&1;else a=0;return a|0}function GB(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+96|0;k=n+64|0;j=n+48|0;i=n+32|0;f=n+16|0;g=n;m=a+4|0;d=c[m>>2]|0;if(!d)ma(94759,92694,1637,94767);e=c[a>>2]|0;c[g>>2]=c[e>>2];c[g+4>>2]=c[e+4>>2];c[g+8>>2]=c[e+8>>2];c[g+12>>2]=c[e+12>>2];e=1;while(1){if((e|0)>=(d|0)){h=7;break}d=(c[a>>2]|0)+(e<<4)|0;c[f>>2]=c[d>>2];c[f+4>>2]=c[d+4>>2];c[f+8>>2]=c[d+8>>2];c[f+12>>2]=c[d+12>>2];c[i>>2]=c[d>>2];c[i+4>>2]=c[d+4>>2];c[i+8>>2]=c[d+8>>2];c[i+12>>2]=c[d+12>>2];c[j>>2]=c[g>>2];c[j+4>>2]=c[g+4>>2];c[j+8>>2]=c[g+8>>2];c[j+12>>2]=c[g+12>>2];c[k>>2]=c[b>>2];c[k+4>>2]=c[b+4>>2];c[k+8>>2]=c[b+8>>2];c[k+12>>2]=c[b+12>>2];c[k+16>>2]=c[b+16>>2];c[k+20>>2]=c[b+20>>2];c[k+24>>2]=c[b+24>>2];c[k+28>>2]=c[b+28>>2];if((Zv(i,j,k)|0)!=-1){d=1;break};c[g>>2]=c[f>>2];c[g+4>>2]=c[f+4>>2];c[g+8>>2]=c[f+8>>2];c[g+12>>2]=c[f+12>>2];e=e+1|0;d=c[m>>2]|0}do if((h|0)==7){d=c[a+8>>2]|0;if(d|0?(g=a+16|0,h=c[a>>2]|0,c[i>>2]=c[g>>2],c[i+4>>2]=c[g+4>>2],c[i+8>>2]=c[g+8>>2],c[i+12>>2]=c[g+12>>2],c[j>>2]=c[h>>2],c[j+4>>2]=c[h+4>>2],c[j+8>>2]=c[h+8>>2],c[j+12>>2]=c[h+12>>2],c[k>>2]=c[b>>2],c[k+4>>2]=c[b+4>>2],c[k+8>>2]=c[b+8>>2],c[k+12>>2]=c[b+12>>2],c[k+16>>2]=c[b+16>>2],c[k+20>>2]=c[b+20>>2],c[k+24>>2]=c[b+24>>2],c[k+28>>2]=c[b+28>>2],(HB(i,j,d,k)|0)<<24>>24):0){d=1;break}d=c[a+12>>2]|0;if(d|0?(h=a+32|0,m=(c[a>>2]|0)+((c[m>>2]|0)+-1<<4)|0,c[i>>2]=c[h>>2],c[i+4>>2]=c[h+4>>2],c[i+8>>2]=c[h+8>>2],c[i+12>>2]=c[h+12>>2],c[j>>2]=c[m>>2],c[j+4>>2]=c[m+4>>2],c[j+8>>2]=c[m+8>>2],c[j+12>>2]=c[m+12>>2],c[k>>2]=c[b>>2],c[k+4>>2]=c[b+4>>2],c[k+8>>2]=c[b+8>>2],c[k+12>>2]=c[b+12>>2],c[k+16>>2]=c[b+16>>2],c[k+20>>2]=c[b+20>>2],c[k+24>>2]=c[b+24>>2],c[k+28>>2]=c[b+28>>2],(HB(i,j,d,k)|0)<<24>>24):0){d=1;break}d=0}while(0);l=n;return d|0}function HB(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0.0;m=l;l=l+160|0;g=m+144|0;f=m+128|0;n=m+96|0;i=m+64|0;j=m+32|0;k=m;o=+h[e+16>>3];c[f>>2]=c[a>>2];c[f+4>>2]=c[a+4>>2];c[f+8>>2]=c[a+8>>2];c[f+12>>2]=c[a+12>>2];c[g>>2]=c[b>>2];c[g+4>>2]=c[b+4>>2];c[g+8>>2]=c[b+8>>2];c[g+12>>2]=c[b+12>>2];St(n,f,g,1.0,d);if(((o>=+h[n>>3]?(c[f>>2]=c[a>>2],c[f+4>>2]=c[a+4>>2],c[f+8>>2]=c[a+8>>2],c[f+12>>2]=c[a+12>>2],c[g>>2]=c[b>>2],c[g+4>>2]=c[b+4>>2],c[g+8>>2]=c[b+8>>2],c[g+12>>2]=c[b+12>>2],St(i,f,g,1.0,d),+h[i+16>>3]>=+h[e>>3]):0)?(o=+h[e+24>>3],c[f>>2]=c[a>>2],c[f+4>>2]=c[a+4>>2],c[f+8>>2]=c[a+8>>2],c[f+12>>2]=c[a+12>>2],c[g>>2]=c[b>>2],c[g+4>>2]=c[b+4>>2],c[g+8>>2]=c[b+8>>2],c[g+12>>2]=c[b+12>>2],St(j,f,g,1.0,d),o>=+h[j+8>>3]):0)?(c[f>>2]=c[a>>2],c[f+4>>2]=c[a+4>>2],c[f+8>>2]=c[a+8>>2],c[f+12>>2]=c[a+12>>2],c[g>>2]=c[b>>2],c[g+4>>2]=c[b+4>>2],c[g+8>>2]=c[b+8>>2],c[g+12>>2]=c[b+12>>2],St(k,f,g,1.0,d),+h[k+24>>3]>=+h[e+8>>3]):0)f=1;else f=0;l=m;return f|0}function IB(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;g=l;l=l+16|0;f=g;a:do if((b|0)!=0?(e=a[b>>0]|0,e<<24>>24!=0):0){do switch(e<<24>>24|0){case 48:{d=2;break a}case 57:case 56:case 55:case 54:case 53:case 52:case 51:case 50:case 49:{d=10;break a}case 67:case 99:{e=b+1|0;if(!(jK(e,94782)|0)){d=4;break a}if(!(jK(e,94788)|0)){d=12;break a}break}case 70:case 102:{if(!(jK(b+1|0,94796)|0)){d=2;break a}break}case 76:case 108:{if(!(jK(b+1|0,94801)|0)){d=2;break a}break}case 78:case 110:{e=b+1|0;if(!(jK(e,94805)|0)){d=0;break a}if(!(jK(e,94809)|0)){d=2;break a}break}case 79:case 111:{if(!(jK(b+1|0,94811)|0)){d=8;break a}break}case 80:case 112:{if(!(jK(b+1|0,94816)|0)){d=6;break a}break}case 83:case 115:{if(!(jK(b+1|0,94824)|0)){d=10;break a}break}case 84:case 116:{if(!(jK(b+1|0,94830)|0)){d=10;break a}break}case 89:case 121:{if(!(jK(b+1|0,94834)|0)){d=10;break a}break}default:{}}while(0);c[f>>2]=b;$l(0,94837,f)|0}while(0);l=g;return d|0}function JB(d,f){d=d|0;f=f|0;var g=0;g=Jm(d,94878)|0;if(g)if(!(a[g>>0]|0))f=0;else f=IB(g,f)|0;d=(c[d+16>>2]|0)+136|0;b[d>>1]=f|e[d>>1];return}function KB(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=+d;e=e|0;var f=0.0,g=0.0,i=0.0,j=0.0,k=0.0,m=0,n=0,o=0.0,p=0,q=0.0,r=0,s=0.0,t=0,u=0,v=0,w=0;v=l;l=l+32|0;p=v+16|0;r=v;t=e&1;u=e&2;a:do if((c|0)==2){s=+h[a+16>>3];f=+h[a>>3];j=+h[a+24>>3];i=+h[a+8>>3];f=f-(s-f);h[p>>3]=f;h[r>>3]=s;i=i-(j-i);h[p+8>>3]=i;h[r+8>>3]=j}else{g=+h[a>>3];h[r>>3]=g;h[p>>3]=g;j=+h[a+8>>3];m=r+8|0;h[m>>3]=j;n=p+8|0;h[n>>3]=j;e=0;f=g;i=j;while(1){if((e|0)>=(c|0)){s=g;break a}w=a+(e<<4)|0;q=+h[w>>3];k=+h[(q>3];h[p>>3]=k;s=+h[a+(e<<4)+8>>3];o=+h[(s>3];h[n>>3]=o;q=+h[(q>g?w:r)>>3];h[r>>3]=q;s=+h[(s>j?w:r)+8>>3];h[m>>3]=s;e=e+1|0;f=k;i=o;g=q;j=s}}while(0);g=(s-f)*.5;q=g+f;o=(j-i)*.5;k=o+i;if(!t){f=j-k;j=d;i=+F(+j);j=+E(+j);if(!u){g=i*f-k;f=-k-o*i}else{f=i*f;g=k-f;f=f+k}h[b+8>>3]=g;h[b+24>>3]=f;d=j*(s-q);h[b>>3]=q-d;h[b+16>>3]=d+q}else{d=+C(+(o*o+g*g));h[b+8>>3]=u|0?k:-k;h[b>>3]=q;h[b+16>>3]=d*.25;h[b+24>>3]=d}l=v;return}function LB(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0;e=a+16|0;f=c[e>>2]|0;if(!(b<<24>>24)){d=+h[f+32>>3]*36.0;h[f+88>>3]=d;a=f+40|0}else{d=+h[f+40>>3]*36.0;h[f+88>>3]=d;a=f+32|0}h[f+96>>3]=d;h[(c[e>>2]|0)+80>>3]=+h[a>>3]*72.0;return}function MB(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,A=0;y=l;l=l+16|0;j=y+8|0;x=4;w=_I(40)|0;c[w>>2]=0;s=y;o=0;e=_(22,b|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;a:do if((g|0)!=1){o=0;v=_(23,e<<3|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){e=TN(c[f>>2]|0,w|0,x|0)|0;if(!e)Ua(f|0,p|0);z=p}else e=-1;if((e|0)!=1){if(!(a[174080]|0))t=0;else{o=0;e=Z(2)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){n=0;k=0;m=0;j=0;i=0;d=v;h=v;e=z;g=0;u=74;break}t=e}o=0;e=$(31,b|0,94886)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)!=1){c[42367]=0;b:do if(e|0?(i=a[e>>0]|0,i<<24>>24):0){h=e;f=i;g=0;while(1){i=h+1|0;if(!(f<<24>>24))break b;switch(f<<24>>24|0){case 99:{e=8;u=16;break}case 105:{e=18;u=16;break}case 109:{e=1;u=16;break}case 114:{e=4;u=16;break}case 115:{e=2;u=16;break}default:e=g}if((u|0)==16){u=0;e=g|e;c[42367]=e}h=i;f=a[i>>0]|0;g=e}}while(0);if(d|0){o=0;aa(11,0,94890,j|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){n=0;k=t;m=0;j=0;i=0;d=v;h=v;e=z;g=0;u=74;break}}o=0;r=$(32,b|0,0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){m=c[r+16>>2]|0;if(c[42367]&2|0){o=0;ga(25,c[13918]|0,m|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){n=0;k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break}}o=0;g=_(24,b|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){n=0;while(1){if(!g)break;o=0;e=$(33,b|0,g|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){h=TN(c[f>>2]|0,w|0,x|0)|0;if(!h)Ua(f|0,p|0);z=p}else h=-1;if((h|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}i=n;while(1){if(!e)break;if(!((c[42179]|0)==2?(c[(c[e+16>>2]|0)+8>>2]|0)!=0:0))u=32;c:do if((u|0)==32){u=0;do if(a[174080]|0){k=c[e>>2]&3;j=(c[c[((k|0)==3?e:e+48|0)+40>>2]>>2]|0)>>>4;k=(c[c[((k|0)==2?e:e+-48|0)+40>>2]>>2]|0)>>>4;if(j>>>0>k>>>0){o=0;f=aa(15,t|0,k|0,j|0)|0;h=o;o=0;if((h|0)!=0&(p|0)!=0){d=TN(c[h>>2]|0,w|0,x|0)|0;if(!d)Ua(h|0,p|0);z=p}else d=-1;if((d|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}if(f|0)break c;o=0;ha(59,t|0,k|0,j|0);f=o;o=0;if((f|0)!=0&(p|0)!=0){h=TN(c[f>>2]|0,w|0,x|0)|0;if(!h)Ua(f|0,p|0);z=p}else h=-1;if((h|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}break}else{o=0;f=aa(15,t|0,j|0,k|0)|0;h=o;o=0;if((h|0)!=0&(p|0)!=0){d=TN(c[h>>2]|0,w|0,x|0)|0;if(!d)Ua(h|0,p|0);z=p}else d=-1;if((d|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}if(f|0)break c;o=0;ha(59,t|0,j|0,k|0);f=o;o=0;if((f|0)!=0&(p|0)!=0){h=TN(c[f>>2]|0,w|0,x|0)|0;if(!h)Ua(f|0,p|0);z=p}else h=-1;if((h|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}break}}while(0);c[v+(i<<3)+4>>2]=e;o=0;d=_(25,e|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){h=TN(c[f>>2]|0,w|0,x|0)|0;if(!h)Ua(f|0,p|0);z=p}else h=-1;if((h|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}c[v+(i<<3)>>2]=d;i=i+1|0}while(0);o=0;e=$(34,b|0,e|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){h=TN(c[f>>2]|0,w|0,x|0)|0;if(!h)Ua(f|0,p|0);z=p}else h=-1;if((h|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}}o=0;g=$(35,b|0,g|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74;break a}n=i}o=0;j=_(26,n<<3|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){o=0;ja(25,v|0,n|0,8,36);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){g=c[m>>2]|0;o=0;fa(87,g+2|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){i=c[m+16>>2]|0;d=i+(g*40|0)|0;i=i+((g+1|0)*40|0)|0;q=c[13918]|0;h=0;while(1){if((h|0)>=(n|0))break;if((h|0)>0?c[42367]&16|0:0){o=0;ga(25,q|0,m|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74;break a}}e=c[v+(h<<3)+4>>2]|0;k=c[e>>2]&3;g=c[(c[(c[((k|0)==3?e:e+48|0)+40>>2]|0)+16>>2]|0)+112>>2]|0;e=c[(c[(c[((k|0)==2?e:e+-48|0)+40>>2]|0)+16>>2]|0)+112>>2]|0;if((g|0)==(e|0)){o=0;ja(26,m|0,g|0,i|0,d|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74;break a}}else{o=0;ha(60,m|0,e|0,i|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74;break a}o=0;ha(60,m|0,g|0,d|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74;break a}}o=0;e=aa(16,m|0,i|0,d|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74;break a}if(e|0){k=t;m=j;i=r;d=v;h=v;break a}e=j+(h<<3)|0;o=0;ja(27,s|0,m|0,d|0,i|0);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74;break a}g=s;k=c[g+4>>2]|0;c[e>>2]=c[g>>2];c[e+4>>2]=k;o=0;fa(88,m|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74;break a}h=h+1|0}o=0;ea(8);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){o=0;e=_(27,r|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)!=1){c[r+20>>2]=e;o=0;e=_(28,r|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)!=1){c[r+24>>2]=e;o=0;ha(61,n|0,j|0,r|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){w=SN(169472,1,w|0,x|0)|0;x=z;o=0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)!=1){k=t;m=j;i=r;d=v;h=v;e=0;g=q;u=74}else{k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74}}else{k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74}}else{k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74}}else{k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74}}else{k=t;m=j;i=r;d=v;h=v;e=z;g=q;u=74}}else{k=t;m=j;i=r;d=v;h=v;e=z;g=0;u=74}}else{k=t;m=j;i=r;d=v;h=v;e=z;g=0;u=74}}else{k=t;m=0;i=r;d=v;h=v;e=z;g=0;u=74}}else{n=0;k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74}}else{n=0;k=t;m=0;j=0;i=r;d=v;h=v;e=z;g=0;u=74}}else{n=0;k=t;m=0;j=0;i=0;d=v;h=v;e=z;g=0;u=74}}else{n=0;k=0;m=0;j=0;i=0;d=0;h=v;e=z;g=0;u=74}}else{n=0;k=0;m=0;j=0;i=0;d=0;h=0;e=z;g=0;u=74}while(0);d:while(1){if((u|0)==74){u=0;if(e|0){q=g;continue}o=0;fa(89,i|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){A=g;f=h;q=d;r=i;s=j;t=m;v=k;u=n;e=z;g=A;h=f;d=q;i=r;j=s;m=t;k=v;n=u;u=74;continue}if(c[42367]&4|0){o=0;ka(7,g|0,i|0,n|0,m|0,d|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){f=g;q=h;r=d;s=i;t=j;v=m;A=k;u=n;e=z;g=f;h=q;d=r;i=s;j=t;m=v;k=A;n=u;u=74;continue}}o=0;la(10,b|0,i|0,n|0,m|0,d|0,0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){f=g;q=h;r=d;s=i;t=j;v=m;A=k;u=n;e=z;g=f;h=q;d=r;i=s;j=t;m=v;k=A;n=u;u=74;continue}q=g}if(!(a[174080]|0))e=0;else{o=0;fa(90,k|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;g=q;u=74;continue}e=0}while(1){if((e|0)>=(n|0))break;o=0;fa(91,c[m+(e<<3)+4>>2]|0);f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,w|0,x|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;g=q;u=74;continue d}e=e+1|0}o=0;fa(91,j|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;g=q;u=74;continue}o=0;fa(92,i|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;g=q;u=74;continue}o=0;fa(91,h|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,w|0,x|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;g=q;u=74}else break}$I(w|0);l=y;return}function NB(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0;q=l;l=l+64|0;p=q+32|0;o=q+16|0;j=q;k=q+48|0;XL(95757,a)|0;XL(95768,a)|0;m=b+16|0;n=j+8|0;i=k+4|0;g=0;while(1){if((g|0)>=(c[b>>2]|0))break;d=c[m>>2]|0;e=c[d+(g*40|0)+20>>2]|0;f=c[d+(g*40|0)+24>>2]|0;if((e|0)==(f|0)){GC(j,e);d=~~+h[j>>3];e=~~+h[n>>3]}else{IC(k,(c[e>>2]&1|0)==0?e:f,d+(g*40|0)|0);d=c[k>>2]|0;e=c[i>>2]|0}c[o>>2]=g;c[o+4>>2]=d;c[o+8>>2]=e;AL(a,95788,o)|0;g=g+1|0}f=b+4|0;e=b+20|0;d=0;while(1){if((d|0)>=(c[f>>2]|0))break;o=c[e>>2]|0;b=c[o+(d*24|0)+16>>2]|0;r=+h[o+(d*24|0)>>3];c[p>>2]=c[o+(d*24|0)+12>>2];c[p+4>>2]=b;h[p+8>>3]=r;AL(a,95808,p)|0;d=d+1|0}XL(95830,a)|0;l=q;return}function OB(a){a=a|0;var b=0.0,d=0.0,e=0,f=0;f=c[a>>2]&3;e=c[(c[((f|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0;a=c[(c[((f|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0;b=+h[e+16>>3]-+h[a+16>>3];d=+h[e+24>>3]-+h[a+24>>3];return ~~(d*d+b*b)|0}function PB(a,b){a=a|0;b=b|0;return (c[a>>2]|0)-(c[b>>2]|0)|0}function QB(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+32|0;j=n;GC(n+16|0,d);k=d+32|0;m=d+36|0;g=0;while(1){if((g|0)>=(c[k>>2]|0))break;h=c[(c[m>>2]|0)+(g<<2)>>2]|0;do if(!(a[h+36>>0]|0)){i=c[h+20>>2]|0;if((i|0)==(d|0)){EC(j,h,c[h+24>>2]|0);ZC(b,f,h,0.0)|0;break}else{EC(j,h,i);ZC(b,e,h,0.0)|0;break}}while(0);g=g+1|0}c[b>>2]=(c[b>>2]|0)+2;l=n;return}function RB(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+32|0;h=k;GC(k+16|0,b);i=b+32|0;j=b+36|0;f=0;while(1){if((f|0)>=(c[i>>2]|0))break;g=c[(c[j>>2]|0)+(f<<2)>>2]|0;e=c[g+20>>2]|0;if((e|0)==(b|0))e=c[g+24>>2]|0;EC(h,g,e);ZC(a,d,g,0.0)|0;f=f+1|0}c[a>>2]=(c[a>>2]|0)+1;c[d+24>>2]=b;c[d+20>>2]=b;l=k;return}function SB(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;H=l;l=l+128|0;C=H+64|0;n=H+48|0;D=H+32|0;E=H+16|0;F=H;g=0;i=e;while(1){if(!i)break;g=g+1|0;i=c[i+8>>2]|0}B=ww((g*56|0)+-112|0)|0;c[C+52>>2]=0;c[C+48>>2]=0;A=e+8|0;e=c[A>>2]|0;i=c[e+8>>2]|0;g=c[e+20>>2]|0;if(c[g>>2]&1)g=c[e+24>>2]|0;EC(n,e,g);j=e;q=e;p=0.0;o=+h[n>>3];z=0;m=0.0;x=+h[n+8>>3];while(1){y=i+8|0;if(!(c[y>>2]|0))break;v=FC(j,i)|0;vG(d,v,c[q+12>>2]|0);t=q+36|0;u=i+36|0;if((a[t>>0]|0)==(a[u>>0]|0))if((c[y>>2]|0)==(f|0)){EC(E,i,v);e=E;G=12}else{j=q;e=z;k=x}else{GC(D,v);e=D;G=12}if((G|0)==12){G=0;w=+h[e>>3];k=+h[e+8>>3];e=a[t>>0]|0;s=e<<24>>24==0;r=(q|0)==(c[A>>2]|0);if(s){if(!(a[u>>0]|0))e=0;else e=(c[i+20>>2]|0)==(v|0)?4:2;n=v+48|0;q=g+48|0;j=g+40|0;g=r?0:p>o?4:2}else{if(e<<24>>24==(a[u>>0]|0))e=0;else e=(c[i+20>>2]|0)==(v|0)?1:3;n=v+40|0;q=g+40|0;j=g+48|0;g=r?0:m>x?1:3}HC(C,s&1,+h[j>>3],+h[q>>3],+h[n>>3],g,e);q=z+1|0;g=B+(z*56|0)|0;e=C;j=g+56|0;do{c[g>>2]=c[e>>2];g=g+4|0;e=e+4|0}while((g|0)<(j|0));if((a[t>>0]|0)!=(a[u>>0]|0)?(c[y>>2]|0)==(f|0):0){EC(F,i,v);n=(a[u>>0]|0)==0;e=v+40|0;g=v+48|0;p=+h[(n?g:e)>>3];HC(C,n&1,+h[(n?e:g)>>3],p,p,n?(o>w?4:2):x>k?1:3,0);n=z+2|0;g=B+(q*56|0)|0;e=C;j=g+56|0;do{c[g>>2]=c[e>>2];g=g+4|0;e=e+4|0}while((g|0)<(j|0));g=v;j=i;p=o;o=w;e=n;m=x}else{g=v;j=i;p=o;o=w;e=q;m=x}}v=i;i=c[y>>2]|0;q=j;z=e;x=k;j=v}i=bJ(B,z*56|0)|0;e=z+-1|0;g=0;while(1){if((g|0)>=(z|0))break;if((g|0)>0)c[i+(g*56|0)+48>>2]=i+((g+-1|0)*56|0);if((g|0)<(e|0)){G=g+1|0;c[i+(g*56|0)+52>>2]=i+(G*56|0);g=G;continue}else{g=g+1|0;continue}}c[b>>2]=z;c[b+4>>2]=i;l=H;return}function TB(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0,k=0;j=Rl(24676,c[4345]|0)|0;k=a+8|0;i=0;while(1){if((i|0)>=(c[a>>2]|0))break;b=(c[k>>2]|0)+(i*72|0)|0;if(!(c[b>>2]&4)){while(1){d=c[(c[b+36>>2]|0)+8>>2]|0;if(!d)break;d=c[d+20>>2]|0;if(!d)break;if(!(c[d>>2]&1))b=d;else break}g=ww(40)|0;c[g+36>>2]=b;h[g+8>>3]=+h[b+40>>3];f=b;d=c[b>>2]|0;while(1){c[f>>2]=d|4;d=c[c[f+36>>2]>>2]|0;if(!d)break;e=c[d+24>>2]|0;if(!e)break;d=c[e>>2]|0;if(d&1|0)break;else f=e}h[g+16>>3]=+h[f+56>>3];zC(j,g,+h[b+48>>3])}i=i+1|0}return j|0}function UB(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0,k=0;j=Rl(24676,c[4345]|0)|0;k=a+8|0;i=0;while(1){if((i|0)>=(c[a>>2]|0))break;b=(c[k>>2]|0)+(i*72|0)|0;if(!(c[b>>2]&2)){while(1){d=c[(c[b+36>>2]|0)+12>>2]|0;if(!d)break;d=c[d+20>>2]|0;if(!d)break;if(!(c[d>>2]&1))b=d;else break}g=ww(40)|0;c[g+36>>2]=b;h[g+8>>3]=+h[b+48>>3];f=b;d=c[b>>2]|0;while(1){c[f>>2]=d|2;d=c[(c[f+36>>2]|0)+4>>2]|0;if(!d)break;e=c[d+24>>2]|0;if(!e)break;d=c[e>>2]|0;if(d&1|0)break;else f=e}h[g+16>>3]=+h[f+64>>3];zC(j,g,+h[b+40>>3])}i=i+1|0}return j|0}function VB(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;j=e+20|0;i=e+24|0;e=0;while(1){if((e|0)>=(b|0))break;g=c[d+(e<<3)>>2]|0;h=c[d+(e<<3)+4>>2]|0;f=0;while(1){if((f|0)>=(g|0))break;k=h+(f*56|0)|0;yC(cC(c[((a[k>>0]|0)==0?j:i)>>2]|0,k)|0,k);f=f+1|0}e=e+1|0}return}function WB(a){a=a|0;var b=0,d=0;d=a+20|0;eC(c[d>>2]|0);b=a+24|0;eC(c[b>>2]|0);fC(c[d>>2]|0);fC(c[b>>2]|0);gC(c[d>>2]|0,a);gC(c[b>>2]|0,a);hC(c[d>>2]|0);hC(c[b>>2]|0);return}function XB(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0.0,C=0.0,D=0,E=0.0;z=l;l=l+224|0;n=z+176|0;m=z+208|0;x=z+160|0;y=z+128|0;k=z+96|0;t=z+64|0;u=z;o=z+32|0;v=u+8|0;h[v>>3]=1797693134862315708145274.0e284;h[u>>3]=1797693134862315708145274.0e284;w=u+24|0;h[w>>3]=-1797693134862315708145274.0e284;p=u+16|0;h[p>>3]=-1797693134862315708145274.0e284;XL(95005,a)|0;c[n>>2]=10;c[n+4>>2]=10;AL(a,95411,n)|0;XL(123076,a)|0;i=b+4|0;j=b+12|0;q=t+8|0;r=t+16|0;s=t+24|0;g=0;while(1){if((g|0)>=(c[i>>2]|0))break;D=(c[j>>2]|0)+(g*72|0)+40|0;c[t>>2]=c[D>>2];c[t+4>>2]=c[D+4>>2];c[t+8>>2]=c[D+8>>2];c[t+12>>2]=c[D+12>>2];c[t+16>>2]=c[D+16>>2];c[t+20>>2]=c[D+20>>2];c[t+24>>2]=c[D+24>>2];c[t+28>>2]=c[D+28>>2];C=+h[q>>3];B=+h[r>>3];A=+h[s>>3];h[k>>3]=+h[t>>3];h[k+8>>3]=C;h[k+16>>3]=B;h[k+24>>3]=A;AL(a,123095,k)|0;g=g+1|0}g=0;while(1){if((g|0)>=(d|0))break;D=c[f+(g<<3)+4>>2]|0;k=e+(g<<3)|0;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];c[n>>2]=c[u>>2];c[n+4>>2]=c[u+4>>2];c[n+8>>2]=c[u+8>>2];c[n+12>>2]=c[u+12>>2];c[n+16>>2]=c[u+16>>2];c[n+20>>2]=c[u+20>>2];c[n+24>>2]=c[u+24>>2];c[n+28>>2]=c[u+28>>2];dC(o,a,D,m,b,n);c[u>>2]=c[o>>2];c[u+4>>2]=c[o+4>>2];c[u+8>>2]=c[o+8>>2];c[u+12>>2]=c[o+12>>2];c[u+16>>2]=c[o+16>>2];c[u+20>>2]=c[o+20>>2];c[u+24>>2]=c[o+24>>2];c[u+28>>2]=c[o+28>>2];g=g+1|0}XL(95428,a)|0;i=b+8|0;g=0;while(1){if((g|0)>=(c[b>>2]|0))break;D=(c[i>>2]|0)+(g*72|0)+40|0;c[t>>2]=c[D>>2];c[t+4>>2]=c[D+4>>2];c[t+8>>2]=c[D+8>>2];c[t+12>>2]=c[D+12>>2];c[t+16>>2]=c[D+16>>2];c[t+20>>2]=c[D+20>>2];c[t+24>>2]=c[D+24>>2];c[t+28>>2]=c[D+28>>2];E=+h[t>>3];A=+h[q>>3];B=+h[r>>3];C=+h[s>>3];h[y>>3]=E;h[y+8>>3]=A;h[y+16>>3]=B;h[y+24>>3]=C;AL(a,123132,y)|0;h[u>>3]=+h[(+h[u>>3]>3];h[v>>3]=+h[(+h[v>>3]>3];h[p>>3]=+h[(+h[p>>3]>B?u:t)+16>>3];h[w>>3]=+h[(+h[w>>3]>C?u:t)+24>>3];g=g+1|0}v=~~(+h[v>>3]+10.0);y=~~(+h[p>>3]+10.0);D=~~(+h[w>>3]+10.0);c[x>>2]=~~(+h[u>>3]+10.0);c[x+4>>2]=v;c[x+8>>2]=y;c[x+12>>2]=D;AL(a,95453,x)|0;l=z;return}function YB(b,d,e,f,g,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0.0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0;N=l;l=l+112|0;F=N+88|0;E=N+72|0;M=N+32|0;I=N+16|0;J=N;K=N+56|0;L=N+40|0;G=c[13918]|0;w=(i|0)==0;x=J+8|0;y=I+8|0;v=0;m=0;n=0;o=0;p=0;i=0;while(1){if((v|0)>=(e|0))break;z=c[g+(v<<3)+4>>2]|0;A=z+48|0;u=(c[(c[((c[z>>2]&3|0)==3?z:A)+40>>2]|0)+16>>2]|0)+16|0;B=z+16|0;C=(c[B>>2]|0)+16|0;c[E>>2]=c[u>>2];c[E+4>>2]=c[u+4>>2];c[E+8>>2]=c[u+8>>2];c[E+12>>2]=c[u+12>>2];c[F>>2]=c[C>>2];c[F+4>>2]=c[C+4>>2];c[F+8>>2]=c[C+8>>2];c[F+12>>2]=c[C+12>>2];ZB(K,E,F);c[I>>2]=c[K>>2];c[I+4>>2]=c[K+4>>2];c[I+8>>2]=c[K+8>>2];c[I+12>>2]=c[K+12>>2];C=z+-48|0;u=(c[(c[((c[z>>2]&3|0)==2?z:C)+40>>2]|0)+16>>2]|0)+16|0;t=(c[B>>2]|0)+56|0;c[E>>2]=c[u>>2];c[E+4>>2]=c[u+4>>2];c[E+8>>2]=c[u+8>>2];c[E+12>>2]=c[u+12>>2];c[F>>2]=c[t>>2];c[F+4>>2]=c[t+4>>2];c[F+8>>2]=c[t+8>>2];c[F+12>>2]=c[t+12>>2];ZB(L,E,F);c[J>>2]=c[L>>2];c[J+4>>2]=c[L+4>>2];c[J+8>>2]=c[L+8>>2];c[J+12>>2]=c[L+12>>2];t=c[f+(v<<3)>>2]|0;u=c[f+(v<<3)+4>>2]|0;s=t*3|0;D=s+1|0;if((s|0)>=(n|0)){if(m|0)$I(i);p=xw(D<<4)|0;m=p;n=D;o=p;i=p}if(!(a[u>>0]|0)){k=+($B(u,d)|0);j=+h[I>>3]}else{j=+_B(u,d);k=+h[y>>3]}r=m+16|0;h[m+16>>3]=j;h[m+24>>3]=k;c[p>>2]=c[r>>2];c[p+4>>2]=c[r+4>>2];c[p+8>>2]=c[r+8>>2];c[p+12>>2]=c[r+12>>2];r=1;q=u;s=2;while(1){if((r|0)>=(t|0))break;q=u+(r*56|0)|0;if(!(a[q>>0]|0))k=+($B(q,d)|0);else j=+_B(q,d);O=m+(s+2<<4)|0;Q=m+(s+1<<4)|0;P=m+(s<<4)|0;h[P>>3]=j;h[m+(s<<4)+8>>3]=k;c[Q>>2]=c[P>>2];c[Q+4>>2]=c[P+4>>2];c[Q+8>>2]=c[P+8>>2];c[Q+12>>2]=c[P+12>>2];c[O>>2]=c[P>>2];c[O+4>>2]=c[P+4>>2];c[O+8>>2]=c[P+8>>2];c[O+12>>2]=c[P+12>>2];r=r+1|0;s=s+3|0}if(!(a[q>>0]|0)){k=+($B(q,d)|0);j=+h[J>>3]}else{j=+_B(q,d);k=+h[x>>3]}Q=m+(s<<4)|0;O=s+1|0;P=m+(O<<4)|0;h[P>>3]=j;h[m+(O<<4)+8>>3]=k;c[Q>>2]=c[P>>2];c[Q+4>>2]=c[P+4>>2];c[Q+8>>2]=c[P+8>>2];c[Q+12>>2]=c[P+12>>2];if(0>1){P=En(c[((c[z>>2]&3|0)==3?z:A)+40>>2]|0)|0;Q=En(c[((c[z>>2]&3|0)==2?z:C)+40>>2]|0)|0;c[M>>2]=P;c[M+4>>2]=Q;AL(G,94964,M)|0}Kz(z,c[((c[z>>2]&3|0)==2?z:C)+40>>2]|0,m,D,24664);if((!w?(H=c[(c[B>>2]|0)+96>>2]|0,H|0):0)?(a[H+81>>0]|0)==0:0){c[E>>2]=c[I>>2];c[E+4>>2]=c[I+4>>2];c[E+8>>2]=c[I+8>>2];c[E+12>>2]=c[I+12>>2];c[F>>2]=c[J>>2];c[F+4>>2]=c[J+4>>2];c[F+8>>2]=c[J+8>>2];c[F+12>>2]=c[J+12>>2];dA(b,z,E,F)}v=v+1|0}$I(o);l=N;return}function ZB(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;h[b>>3]=+h[b>>3]+ +h[d>>3];e=b+8|0;h[e>>3]=+h[e>>3]+ +h[d+8>>3];c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];return}function _B(a,b){a=a|0;b=b|0;var d=0.0,e=0;b=cC(c[b+24>>2]|0,a)|0;e=c[b+36>>2]|0;d=+h[e+40>>3];return +((+h[e+56>>3]-d)*(+(c[a+44>>2]|0)/+((c[b+24>>2]|0)+1|0))+d)}function $B(a,b){a=a|0;b=b|0;var d=0.0,e=0;e=cC(c[b+20>>2]|0,a)|0;b=c[e+36>>2]|0;d=+h[b+48>>3];return ~~((1.0-+(c[a+44>>2]|0)/+((c[e+24>>2]|0)+1|0))*(+h[b+64>>3]-d)+d)|0}function aC(a){a=a|0;return 0}function bC(a){a=a|0;return 0}function cC(a,b){a=a|0;b=b|0;a=bb[c[a>>2]&31](a,b+8|0,512)|0;if(!a)ma(94977,94983,423,94991);a=c[a+16>>2]|0;a=bb[c[a>>2]&31](a,b+16|0,512)|0;if(!a)ma(95002,94983,425,94991);else return a|0;return 0}function dC(b,d,e,f,g,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0.0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0.0;z=l;l=l+32|0;y=z+16|0;u=z+8|0;m=z;j=c[(c[(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0)+16>>2]|0)+112>>2]|0;t=c[f+4>>2]|0;if(!(a[t>>0]|0)){k=+h[j+56>>3];s=+h[j+40>>3];j=$B(t,g)|0;k=(s+k)*.5}else{k=+h[j+64>>3];s=+h[j+48>>3];j=~~((s+k)*.5);k=+_B(t,g)}A=~~k;p=+h[i>>3];r=+(A|0);p=p>3]=p;v=i+8|0;q=+h[v>>3];s=+(j|0);q=q>3]=q;w=i+16|0;k=+h[w>>3];r=k>r?k:r;h[w>>3]=r;x=i+24|0;k=+h[x>>3];s=k>s?k:s;h[x>>3]=s;c[m>>2]=A;c[m+4>>2]=j;AL(d,95504,m)|0;o=c[f>>2]|0;m=t;n=1;f=A;while(1){if((n|0)>=(o|0))break;m=t+(n*56|0)|0;if(!(a[m>>0]|0))j=$B(m,g)|0;else f=~~+_B(m,g);B=+(f|0);D=p>3]=D;k=+(j|0);C=q>3]=C;B=r>B?r:B;h[w>>3]=B;k=s>k?s:k;h[x>>3]=k;c[u>>2]=f;c[u+4>>2]=j;AL(d,95526,u)|0;n=n+1|0;p=D;q=C;r=B;s=k}j=c[(c[(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0)+16>>2]|0)+112>>2]|0;if(!(a[m>>0]|0)){k=+h[j+56>>3];D=+h[j+40>>3];j=$B(m,g)|0;k=(D+k)*.5}else{k=+h[j+64>>3];D=+h[j+48>>3];j=~~((D+k)*.5);k=+_B(m,g)}A=~~k;C=+(A|0);h[i>>3]=p>3]=q>3]=r>C?r:C;h[x>>3]=s>D?s:D;c[y>>2]=A;c[y+4>>2]=j;AL(d,95540,y)|0;c[b>>2]=c[i>>2];c[b+4>>2]=c[i+4>>2];c[b+8>>2]=c[i+8>>2];c[b+12>>2]=c[i+12>>2];c[b+16>>2]=c[i+16>>2];c[b+20>>2]=c[i+20>>2];c[b+24>>2]=c[i+24>>2];c[b+28>>2]=c[i+28>>2];l=z;return}function eC(a){a=a|0;var b=0;a=Pl(a)|0;while(1){if(!a)break;b=Pl(c[a+16>>2]|0)|0;while(1){if(!b)break;c[b+32>>2]=JC(c[b+24>>2]|0)|0;b=c[b>>2]|0}a=c[a>>2]|0}return}function fC(a){a=a|0;var b=0;a=Pl(a)|0;while(1){if(!a)break;b=Pl(c[a+16>>2]|0)|0;while(1){if(!b)break;if(c[b+24>>2]|0)xC(b);b=c[b>>2]|0}a=c[a>>2]|0}return}function gC(a,b){a=a|0;b=b|0;var d=0;d=Pl(a)|0;while(1){if(!d)break;a=Pl(c[d+16>>2]|0)|0;while(1){if(!a)break;lC(a,b);a=c[a>>2]|0}d=c[d>>2]|0}return}function hC(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0;e=Pl(a)|0;while(1){if(!e)break;i=e+8|0;f=Pl(c[e+16>>2]|0)|0;while(1){if(!f)break;a=f+24|0;a:do if(c[a>>2]|0){if(c[42367]&8|0)iC(f,~~+h[i>>3]);g=f+32|0;OC(c[g>>2]|0);b=c[a>>2]|0;d=f+28|0;a=0;while(1){if((a|0)>=(b|0))break a;c[(c[(c[d>>2]|0)+(a<<2)>>2]|0)+44>>2]=(c[(c[(c[g>>2]|0)+4>>2]|0)+(a*12|0)+4>>2]|0)+1;a=a+1|0}}while(0);f=c[f>>2]|0}e=c[e>>2]|0}return}function iC(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0.0,m=0.0;j=l;l=l+32|0;d=j;g=a+24|0;a:do if((c[g>>2]|0)>=2){i=c[13918]|0;m=+h[a+8>>3];k=+h[a+16>>3];c[d>>2]=b;h[d+8>>3]=m;h[d+16>>3]=k;AL(i,95561,d)|0;f=a+32|0;a=a+28|0;b=0;while(1){if((b|0)>=(c[g>>2]|0))break a;e=c[(c[(c[f>>2]|0)+4>>2]|0)+(b*12|0)+8>>2]|0;b:do if(Tl(e)|0){jC(i,c[(c[a>>2]|0)+(b<<2)>>2]|0);XL(95581,i)|0;d=bb[c[e>>2]&31](e,0,128)|0;while(1){if(!d)break b;XL(95586,i)|0;jC(i,c[(c[a>>2]|0)+(c[d>>2]<<2)>>2]|0);XL(134901,i)|0;d=bb[c[e>>2]&31](e,d,8)|0}}while(0);b=b+1|0}}while(0);l=j;return}function jC(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0.0,k=0.0,m=0.0;g=l;l=l+80|0;f=g+40|0;e=g;if(!(a[d>>0]|0)){m=+h[d+16>>3];j=+h[d+8>>3];k=+h[d+24>>3];i=kC(c[d+32>>2]|0)|0;e=kC(c[d+36>>2]|0)|0;h[f>>3]=m;h[f+8>>3]=j;h[f+16>>3]=k;h[f+24>>3]=j;c[f+32>>2]=i;c[f+36>>2]=e;AL(b,95592,f)|0}else{k=+h[d+8>>3];j=+h[d+16>>3];m=+h[d+24>>3];f=kC(c[d+32>>2]|0)|0;i=kC(c[d+36>>2]|0)|0;h[e>>3]=k;h[e+8>>3]=j;h[e+16>>3]=k;h[e+24>>3]=m;c[e+32>>2]=f;c[e+36>>2]=i;AL(b,95592,e)|0}l=g;return}function kC(a){a=a|0;switch(a|0){case 0:{a=95643;break}case 1:{a=95638;break}case 2:{a=95631;break}case 3:{a=95624;break}case 4:{a=95616;break}default:a=0}return a|0}function lC(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=l;l=l+16|0;r=w+8|0;t=w;u=c[a+32>>2]|0;v=c[a+28>>2]|0;p=a+24|0;m=r+4|0;n=t+4|0;j=0;a=c[p>>2]|0;a:while(1){q=j+1|0;if((q|0)>=(a|0))break;o=v+(j<<2)|0;k=q;while(1){if((k|0)>=(a|0)){j=q;continue a}b:do if(((NC(u,j,k)|0)==0?(NC(u,k,j)|0)==0:0)?(s=v+(k<<2)|0,mC(c[o>>2]|0,c[s>>2]|0)|0):0){f=c[o>>2]|0;a=c[f+48>>2]|0;i=c[s>>2]|0;d=c[i+48>>2]|0;e=(d|0)==0;if(a)if(e)a=1;else a=+h[a+8>>3]!=+h[d+8>>3];else a=e^1;g=a&1;nC(r,f,i,0,g);a=c[r>>2]|0;i=c[m>>2]|0;f=g^1;nC(t,c[o>>2]|0,c[s>>2]|0,1,f);d=c[t>>2]|0;e=c[n>>2]|0;switch(i|0){case -1:{oC(c[s>>2]|0,c[o>>2]|0,g,0,a,b);oC(c[s>>2]|0,c[o>>2]|0,f,1,d,b);if((e|0)!=1)break b;pC(c[o>>2]|0,c[s>>2]|0,f,b);break b}case 0:switch(e|0){case -1:{oC(c[s>>2]|0,c[o>>2]|0,g,0,a,b);oC(c[s>>2]|0,c[o>>2]|0,f,1,d,b);break b}case 0:{oC(c[o>>2]|0,c[s>>2]|0,0,g,a,b);oC(c[o>>2]|0,c[s>>2]|0,1,f,d,b);break b}case 1:{oC(c[o>>2]|0,c[s>>2]|0,0,g,a,b);oC(c[o>>2]|0,c[s>>2]|0,1,f,d,b);break b}default:break b}case 1:{oC(c[o>>2]|0,c[s>>2]|0,0,g,a,b);oC(c[o>>2]|0,c[s>>2]|0,1,f,d,b);if((e|0)!=-1)break b;pC(c[o>>2]|0,c[s>>2]|0,f,b);break b}default:break b}}while(0);k=k+1|0;a=c[p>>2]|0}}l=w;return}function mC(a,b){a=a|0;b=b|0;if(!(+h[a+8>>3]==+h[b+8>>3]))ma(95714,94983,843,95745);if((+h[a+16>>3]==+h[b+16>>3]?+h[a+24>>3]==+h[b+24>>3]:0)?(c[a+32>>2]|0)==(c[b+32>>2]|0):0)a=(c[a+36>>2]|0)==(c[b+36>>2]|0)&1;else a=0;return a|0}function nC(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0;g=0;while(1){b=qC(b,e)|0;if(!b){h=0;break}d=qC(d,f)|0;if(!d){i=6;break}if(!(mC(b,d)|0)){i=7;break}g=g+1|0}if((i|0)==6)ma(123205,94983,871,95663);else if((i|0)==7)h=sC(b,rC(b,d)|0,g+1|0,1-e|0)|0;c[a>>2]=g;c[a+4>>2]=h;return}function oC(b,d,e,f,g,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0;o=i+20|0;n=i+24|0;i=cC(c[((a[b>>0]|0)==0?o:n)>>2]|0,b)|0;LC(c[i+32>>2]|0,c[b+40>>2]|0,c[d+40>>2]|0);k=1;while(1){if((k|0)>(g|0))break;l=qC(b,e)|0;m=qC(d,f)|0;do if(!(a[b>>0]|0)){j=cC(c[n>>2]|0,l)|0;if(+h[l+8>>3]==+h[b+16>>3]){p=(c[b+32>>2]|0)==1;i=(NC(c[i+32>>2]|0,c[b+40>>2]|0,c[d+40>>2]|0)|0)!=0;b=c[j+32>>2]|0;if(p)if(i){LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}else{LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}else if(i){LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}else{LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}}else{p=(c[b+36>>2]|0)==1;i=(NC(c[i+32>>2]|0,c[b+40>>2]|0,c[d+40>>2]|0)|0)!=0;b=c[j+32>>2]|0;if(p)if(i){LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}else{LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}else if(i){LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}else{LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}}}else{j=cC(c[o>>2]|0,l)|0;if(+h[l+8>>3]==+h[b+16>>3]){p=(c[b+32>>2]|0)==2;i=(NC(c[i+32>>2]|0,c[b+40>>2]|0,c[d+40>>2]|0)|0)!=0;b=c[j+32>>2]|0;if(p)if(i){LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}else{LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}else if(i){LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}else{LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}}else{p=(c[b+36>>2]|0)==2;i=(NC(c[i+32>>2]|0,c[b+40>>2]|0,c[d+40>>2]|0)|0)!=0;b=c[j+32>>2]|0;if(p)if(i){LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}else{LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}else if(i){LC(b,c[l+40>>2]|0,c[m+40>>2]|0);i=j;break}else{LC(b,c[m+40>>2]|0,c[l+40>>2]|0);i=j;break}}}while(0);b=l;d=m;k=k+1|0}return}function pC(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0;while(1){if(!(mC(b,d)|0))break;g=qC(b,1)|0;d=qC(d,e)|0;b=g}g=c[(cC(c[((a[b>>0]|0)==0?f+20|0:f+24|0)>>2]|0,b)|0)+32>>2]|0;MC(g,c[b+40>>2]|0,c[d+40>>2]|0);return}function qC(a,b){a=a|0;b=b|0;if(!a)ma(95650,94983,798,95654);else return c[((b|0)==0?a+48|0:a+52|0)>>2]|0;return 0}function rC(b,c){b=b|0;c=c|0;var d=0,e=0,f=0;f=l;l=l+16|0;e=f;d=a[b>>0]|0;if(d<<24>>24==(a[c>>0]|0)?!(+h[b+8>>3]!=+h[c+8>>3]):0){if(!(d<<24>>24))b=tC(b,c,3,1)|0;else b=tC(b,c,4,2)|0;l=f;return b|0}$l(1,95676,e)|0;Ua(169472,1);return 0}function sC(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0;j=1;while(1){if((j|0)>(e|0))break;i=qC(b,f)|0;g=+h[i+8>>3]==+h[b+16>>3];do if(!(a[b>>0]|0))if(g){g=(c[b+32>>2]|0)==1;break}else{g=(c[b+36>>2]|0)==3;break}else if(g){g=(c[b+32>>2]|0)==4;break}else{g=(c[b+36>>2]|0)==2;break}while(0);b=i;j=j+1|0;d=g?0-d|0:d}return d|0}function tC(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0.0,k=0.0,l=0,m=0,n=0,o=0;j=+h[a+24>>3];k=+h[b+16>>3];do if(!(j>3],i=+h[b+24>>3],!(g>i)):0){if(k>2]|0;return ((d|0)==(c[b+32>>2]|0)?0:(d|0)==(e|0)?1:-1)|0}else{d=c[a+32>>2]|0;b=(d|0)==(c[b+36>>2]|0)?0:(d|0)==(e|0)?1:-1;break}if(!(j==i))if(j>2]|0)==(d|0);d=wC(c[b+32>>2]|0,c[a+32>>2]|0,d,e)|0;return (o?d:0-d|0)|0}else{o=(c[b+36>>2]|0)==(e|0);b=wC(c[a+32>>2]|0,c[b+32>>2]|0,d,e)|0;b=o?b:0-b|0;break}o=c[a+32>>2]|0;n=c[b+32>>2]|0;if((o|0)==(n|0)){b=c[b+36>>2]|0;if((c[a+36>>2]|0)==(b|0)){b=0;break}}else b=c[b+36>>2]|0;m=(n|0)==(d|0);if((n|0)==(b|0)){if(m){b=1;break}if((n|0)==(e|0)){b=-1;break}if((o|0)!=(d|0)?(c[a+36>>2]|0)!=(d|0):0){b=1;break}if((o|0)!=(e|0)?(c[a+36>>2]|0)!=(e|0):0){b=-1;break}b=0;break}f=(b|0)==(e|0);if(m&f){b=(c[a+36>>2]|0)==(e|0);if((o|0)==(d|0)){if(!b){b=-1;break}}else if(b){b=1;break}b=0;break}l=(b|0)==(d|0);if((n|0)==(e|0)&l){b=(o|0)==(e|0);if((c[a+36>>2]|0)==(d|0)){if(!b){b=-1;break}}else if(b){b=1;break}b=0;break}if(!n){if(l){b=vC(o,c[a+36>>2]|0,d)|0;break}if(f){b=0-(vC(o,c[a+36>>2]|0,e)|0)|0;break}}f=c[a+36>>2]|0;if(m&(b|0)==0){b=vC(f,o,d)|0;break}else{b=0-(vC(f,o,e)|0)|0;break}}else b=0;while(0);return b|0}function uC(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0.0,j=0.0;i=+h[a+24>>3];j=+h[b+24>>3];do if(i>2]|0;if((a|0)==(d|0)?(c[b+32>>2]|0)==(e|0):0){a=-1;break}if((a|0)==(e|0)?(c[b+32>>2]|0)==(d|0):0){a=1;break}a=0}else{f=c[b+32>>2]|0;g=(f|0)==(e|0);if(i==j)if(g){a=wC(c[a+36>>2]|0,c[b+36>>2]|0,d,e)|0;break}else{a=0-(wC(c[b+36>>2]|0,c[a+36>>2]|0,d,e)|0)|0;break}if(g?(c[b+36>>2]|0)==(e|0):0){a=-1;break}if((f|0)==(d|0)?(c[b+36>>2]|0)==(d|0):0){a=1;break}a=0}while(0);return a|0}function vC(a,b,c){a=a|0;b=b|0;c=c|0;return ((a|0)==(c|0)?((b|0)==(c|0))<<31>>31:1)|0}function wC(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if((a|0)==(d|0)){b=(a|0)==0;if(b)return 0;else b=b&1}return ((a|0)!=0|(b|0)!=(c|0))<<31>>31|0}function xC(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;g=c[a+28>>2]|0;h=c[a+24>>2]|0;d=c[a+32>>2]|0;a=0;a:while(1){e=a+1|0;if((e|0)>=(h|0))break;f=g+(a<<2)|0;b=e;while(1){if((b|0)==(h|0)){a=e;continue a}switch(rC(c[f>>2]|0,c[g+(b<<2)>>2]|0)|0){case 1:{LC(d,a,b);break}case -1:{LC(d,b,a);break}default:{}}b=b+1|0}}return}function yC(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=a+24|0;e=c[f>>2]|0;d=e+1|0;c[f>>2]=d;c[b+40>>2]=e;e=a+28|0;a=c[e>>2]|0;if(!a)a=xw(d<<2)|0;else a=zw(a,d<<2)|0;c[e>>2]=a;c[a+((c[f>>2]|0)+-1<<2)>>2]=b;return}function zC(a,b,d){a=a|0;b=b|0;d=+d;var e=0,f=0,g=0;g=l;l=l+16|0;f=g;h[f>>3]=d;e=bb[c[a>>2]&31](a,f,512)|0;if(!e){e=ww(24)|0;h[e+8>>3]=+h[f>>3];c[e+16>>2]=Rl(24712,c[4345]|0)|0;bb[c[a>>2]&31](a,e,1)|0}f=c[e+16>>2]|0;bb[c[f>>2]&31](f,b,1)|0;l=g;return}function AC(a,b,d){a=a|0;b=b|0;d=d|0;KC(c[b+32>>2]|0);$I(c[b+28>>2]|0);$I(b);return}function BC(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0.0,f=0.0;e=+h[b>>3];f=+h[c>>3];if(!(e>f))if(e>3]>=+h[c+8>>3])<<31>>31;else a=0;else a=!(+h[b+8>>3]<=+h[c+8>>3])&1;return a|0}function CC(a,b,d){a=a|0;b=b|0;d=d|0;Ll(c[b+16>>2]|0)|0;$I(b);return}function DC(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0.0,f=0.0;f=+h[b>>3];e=+h[c>>3];return (f>e?1:(f>31)|0}function EC(b,d,e){b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0,j=0;i=(a[d+36>>0]|0)!=0;j=e+40|0;do if((c[d+24>>2]|0)==(e|0)){f=+h[j>>3];if(i){g=(+h[e+64>>3]+ +h[e+48>>3])*.5;break}else{g=+h[e+48>>3];f=(+h[e+56>>3]+f)*.5;break}}else if(i){g=(+h[e+64>>3]+ +h[e+48>>3])*.5;f=+h[e+56>>3];break}else{g=+h[e+64>>3];f=(+h[e+56>>3]+ +h[j>>3])*.5;break}while(0);h[b>>3]=f;h[b+8>>3]=g;return}function FC(a,b){a=a|0;b=b|0;var d=0;d=c[a+20>>2]|0;if((d|0)!=(c[b+20>>2]|0)?(d|0)!=(c[b+24>>2]|0):0)d=c[a+24>>2]|0;return d|0}function GC(a,b){a=a|0;b=b|0;var c=0.0;c=(+h[b+64>>3]+ +h[b+48>>3])*.5;h[a>>3]=(+h[b+56>>3]+ +h[b+40>>3])*.5;h[a+8>>3]=c;return}function HC(b,d,e,f,g,i,j){b=b|0;d=d|0;e=+e;f=+f;g=+g;i=i|0;j=j|0;var k=0,l=0;a[b>>0]=d;h[b+8>>3]=e;if(f>3]=f;h[b+16>>3]=e;c[b+36>>2]=d;c[b+32>>2]=l;a[b+1>>0]=k;return}function IC(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=c[b+36>>2]|0;do if((c[e+4>>2]|0)!=(d|0)){if((c[e+12>>2]|0)==(d|0)){e=~~((+h[b+56>>3]+ +h[b+40>>3])*.5);d=~~+h[b+48>>3];break}if((c[e+8>>2]|0)==(d|0)){e=~~+h[b+40>>3];d=~~((+h[b+64>>3]+ +h[b+48>>3])*.5);break}if((c[e>>2]|0)==(d|0)){e=~~+h[b+56>>3];d=~~((+h[b+64>>3]+ +h[b+48>>3])*.5)}else{e=0;d=0}}else{e=~~((+h[b+56>>3]+ +h[b+40>>3])*.5);d=~~+h[b+64>>3]}while(0);c[a>>2]=e;c[a+4>>2]=d;return}function JC(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;d=ww(8)|0;c[d>>2]=a;e=d+4|0;c[e>>2]=ww(a*12|0)|0;b=0;while(1){if((b|0)>=(a|0))break;g=gG()|0;f=c[e>>2]|0;c[f+(b*12|0)+8>>2]=g;c[f+(b*12|0)>>2]=0;b=b+1|0}return d|0}function KC(a){a=a|0;var b=0,d=0,e=0;d=a+4|0;b=0;while(1){e=c[d>>2]|0;if((b|0)>=(c[a>>2]|0))break;Ll(c[e+(b*12|0)+8>>2]|0)|0;b=b+1|0}$I(e);$I(a);return}function LC(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=l;l=l+16|0;f=e;c[f>>2]=d;d=c[(c[a+4>>2]|0)+(b*12|0)+8>>2]|0;bb[c[d>>2]&31](d,f,1)|0;l=e;return}function MC(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=l;l=l+16|0;f=e;c[f>>2]=d;a=a+4|0;g=c[(c[a>>2]|0)+(b*12|0)+8>>2]|0;bb[c[g>>2]&31](g,f,2)|0;c[f>>2]=b;d=c[(c[a>>2]|0)+(d*12|0)+8>>2]|0;bb[c[d>>2]&31](d,f,2)|0;l=e;return}function NC(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=l;l=l+16|0;f=e;c[f>>2]=d;d=c[(c[a+4>>2]|0)+(b*12|0)+8>>2]|0;d=(bb[c[d>>2]&31](d,f,512)|0)!=0&1;l=e;return d|0}function OC(a){a=a|0;var b=0,d=0,e=0,f=0;b=c[a>>2]|0;switch(b|0){case 0:break;case 1:{c[(c[a+4>>2]|0)+4>>2]=0;break}default:{e=PC(b)|0;f=a+4|0;d=0;b=0;while(1){if((d|0)>=(c[a>>2]|0)){b=0;break}if(!(c[(c[f>>2]|0)+(d*12|0)>>2]|0))b=QC(a,d,b,e)|0;d=d+1|0}while(1){d=RC(e)|0;if((d|0)<=-1)break;c[(c[f>>2]|0)+(d*12|0)+4>>2]=b;b=b+1|0}SC(e)}}return}function PC(a){a=a|0;var b=0;b=ww(8)|0;c[b+4>>2]=ww(a<<2)|0;c[b>>2]=-1;return b|0}function QC(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;i=a+4|0;g=c[i>>2]|0;j=g+(b*12|0)|0;c[j>>2]=1;g=c[g+(b*12|0)+8>>2]|0;h=g+4|0;d=d+1|0;g=Pl(g)|0;while(1){if(!g)break;f=c[(c[h>>2]|0)+8>>2]|0;if((f|0)<0)f=c[g+8>>2]|0;else f=g+(0-f)|0;f=c[f>>2]|0;if(!(c[(c[i>>2]|0)+(f*12|0)>>2]|0))d=QC(a,f,d,e)|0;g=c[g>>2]|0}c[j>>2]=2;TC(e,b);return d+1|0}function RC(a){a=a|0;var b=0,d=0;b=c[a>>2]|0;if((b|0)==-1)a=-1;else{d=c[(c[a+4>>2]|0)+(b<<2)>>2]|0;c[a>>2]=b+-1;a=d}return a|0}function SC(a){a=a|0;$I(c[a+4>>2]|0);$I(a);return}function TC(a,b){a=a|0;b=b|0;var d=0;d=(c[a>>2]|0)+1|0;c[a>>2]=d;c[(c[a+4>>2]|0)+(d<<2)>>2]=b;return}function UC(a){a=a|0;var d=0,e=0,f=0;e=c[a>>2]|0;c[a+8>>2]=e;c[a+12>>2]=c[a+4>>2];d=a+16|0;a=0;while(1){if((a|0)>=(e|0))break;f=c[d>>2]|0;b[f+(a*40|0)+18>>1]=b[f+(a*40|0)+16>>1]|0;a=a+1|0}return}function VC(a){a=a|0;var d=0,e=0,f=0;d=c[a+8>>2]|0;c[a>>2]=d;c[a+4>>2]=c[a+12>>2];e=a+16|0;a=0;while(1){if((a|0)>=(d|0))break;f=c[e>>2]|0;b[f+(a*40|0)+16>>1]=b[f+(a*40|0)+18>>1]|0;a=a+1|0}d=d+2|0;while(1){if((a|0)>=(d|0))break;b[(c[e>>2]|0)+(a*40|0)+16>>1]=0;a=a+1|0}return}function WC(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=ww(((c[a>>2]|0)*6|0)+(b<<1)<<2)|0;c[a+20>>2]=ww((((c[a>>2]|0)*3|0)+b|0)*24|0)|0;e=c[a>>2]|0;f=a+16|0;a=0;while(1){if((a|0)>=(e|0))break;c[(c[f>>2]|0)+(a*40|0)+28>>2]=d;d=d+24|0;a=a+1|0}e=e+2|0;while(1){if((a|0)>=(e|0))break;c[(c[f>>2]|0)+(a*40|0)+28>>2]=d;d=d+(b<<2)|0;a=a+1|0}return}function XC(a){a=a|0;var b=0;b=ww(24)|0;c[b>>2]=0;c[b+16>>2]=ww(a*40|0)|0;return b|0}function YC(a){a=a|0;var b=0,d=0;d=c[a+16>>2]|0;b=c[a>>2]|0;c[d+(b*40|0)+32>>2]=b;c[a>>2]=b+1;return d+(b*40|0)|0}function ZC(a,b,d,e){a=a|0;b=b|0;d=d|0;e=+e;var f=0,g=0;g=a+4|0;f=c[g>>2]|0;c[g>>2]=f+1;g=c[a+20>>2]|0;a=g+(f*24|0)|0;c[g+(f*24|0)+12>>2]=c[b+32>>2];c[g+(f*24|0)+16>>2]=c[d+32>>2];h[a>>3]=e;c[g+(f*24|0)+8>>2]=0;_C(b,f);_C(d,f);return a|0}function _C(a,d){a=a|0;d=d|0;var e=0,f=0;e=a+16|0;f=b[e>>1]|0;c[(c[a+28>>2]|0)+(f<<16>>16<<2)>>2]=d;b[e>>1]=f+1<<16>>16;return}function $C(a){a=a|0;var b=0;b=a+16|0;$I(c[(c[b>>2]|0)+28>>2]|0);$I(c[b>>2]|0);$I(c[a+20>>2]|0);$I(a);return}function aD(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0;g=c[a>>2]|0;i=a+16|0;f=0;while(1){if((f|0)>=(g|0))break;c[(c[i>>2]|0)+(f*40|0)>>2]=-2147483648;f=f+1|0}oG();a:do if(!(rG(d)|0)){c[d+8>>2]=0;c[d>>2]=0;d=a+20|0;b:while(1){g=tG()|0;if(!g){f=0;break a}c[g>>2]=0-(c[g>>2]|0);if((g|0)==(e|0)){f=0;break a}i=g+16|0;j=g+28|0;f=0;while(1){if((f|0)>=(b[i>>1]|0))continue b;k=(c[d>>2]|0)+((c[(c[j>>2]|0)+(f<<2)>>2]|0)*24|0)|0;l=bD(a,k,g)|0;m=c[l>>2]|0;do if((m|0)<0){n=~~-(+h[k>>3]+ +(c[g>>2]|0));if((m|0)==-2147483648){c[l>>2]=n;if(rG(l)|0){f=1;break a}c[l+8>>2]=g;c[l+12>>2]=k;break}else{if((m|0)>=(n|0))break;uG(l,n);c[l+8>>2]=g;c[l+12>>2]=k;break}}while(0);f=f+1|0}}}else f=1;while(0);return f|0}function bD(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=c[b+12>>2]|0;if((e|0)==(c[d+32>>2]|0))e=c[b+16>>2]|0;return (c[a+16>>2]|0)+(e*40|0)|0}function cD(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;g=c[a>>2]|0;Kr(g,3,b)|0;b=c[g+92>>2]|0;do if(b){d=c[b+16>>2]|0;h=c[d+12>>2]|0;c[a+76>>2]=h;e=c[d+16>>2]|0;c[a+84>>2]=e;f=a+80|0;c[f>>2]=c[d>>2];c[a+88>>2]=c[b+4>>2];d=a+152|0;e=c[d>>2]|c[e>>2];c[d>>2]=e;b=c[g+80>>2]|0;if(!b){c[a+60>>2]=0;b=999;break}else{g=c[b+16>>2]|0;c[a+60>>2]=c[g+12>>2];i=c[g+16>>2]|0;c[a+68>>2]=i;c[a+72>>2]=c[b+4>>2];c[d>>2]=e|c[i>>2];c[a+64>>2]=c[((h|0)==0?f:g)>>2];b=300;break}}else b=999;while(0);return b|0}function dD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(!(jr(a)|0))if((b|0)!=0?(d=c[b>>2]|0,(d|0)!=0):0){gb[d&127](a);a=0}else a=0;else a=1;return a|0}function eD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+4>>2]|0,d|0):0)gb[d&127](a);c[(c[a>>2]|0)+24>>2]=0;rr(a);return}function fD(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0.0,g=0.0,i=0.0;e=+h[b+504>>3];f=+h[b+512>>3];i=+h[b+352>>3];if(!(c[b+360>>2]|0)){g=+h[d>>3]+e;d=d+8|0;e=f}else g=-(f+ +h[d+8>>3]);f=+h[b+528>>3]*i*(+h[d>>3]+e);h[a>>3]=+h[b+520>>3]*i*g;h[a+8>>3]=f;return}function gD(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0.0,k=0.0;f=+h[a+504>>3];g=+h[a+512>>3];i=+h[a+352>>3];j=+h[a+520>>3]*i;i=+h[a+528>>3]*i;a:do if(!(c[a+360>>2]|0)){a=0;while(1){if((a|0)>=(e|0))break a;h[d+(a<<4)>>3]=(+h[b+(a<<4)>>3]+f)*j;h[d+(a<<4)+8>>3]=(+h[b+(a<<4)+8>>3]+g)*i;a=a+1|0}}else{a=0;while(1){if((a|0)>=(e|0))break a;k=-(j*(+h[b+(a<<4)+8>>3]+g));h[d+(a<<4)+8>>3]=(+h[b+(a<<4)>>3]+f)*i;h[d+(a<<4)>>3]=k;a=a+1|0}}while(0);return d|0}function hD(a,b){a=a|0;b=b|0;var d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+8>>2]|0,d|0):0)gb[d&127](a);return}function iD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+12>>2]|0,d|0):0)gb[d&127](a);qr(a);return}function jD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+24>>2]|0,d|0):0)gb[d&127](a);return}function kD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+28>>2]|0,d|0):0)gb[d&127](a);return}function lD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+16>>2]|0,d|0):0){b=c[a+160>>2]|0;kb[d&31](a,c[(c[(c[a>>2]|0)+308>>2]|0)+(b<<2)>>2]|0,b,c[a+156>>2]|0)}return}function mD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+20>>2]|0,d|0):0)gb[d&127](a);return}function nD(a,b){a=a|0;b=b|0;var d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+32>>2]|0,d|0):0)gb[d&127](a);return}function oD(a,b){a=a|0;b=b|0;var d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+36>>2]|0,d|0):0)gb[d&127](a);return}function pD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+40>>2]|0,d|0):0)gb[d&127](a);return}function qD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+44>>2]|0,d|0):0)gb[d&127](a);return}function rD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+48>>2]|0,d|0):0)gb[d&127](a);return}function sD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+52>>2]|0,d|0):0)gb[d&127](a);return}function tD(a,b){a=a|0;b=b|0;var d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+56>>2]|0,d|0):0)gb[d&127](a);return}function uD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+60>>2]|0,d|0):0)gb[d&127](a);return}function vD(a,b){a=a|0;b=b|0;var d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+64>>2]|0,d|0):0)gb[d&127](a);return}function wD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+68>>2]|0,d|0):0)gb[d&127](a);return}function xD(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;g=c[a+60>>2]|0;if(g|0?(h=c[g+72>>2]|0,h|0):0)lb[h&7](a,b,d,e,f);return}function yD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+76>>2]|0,d|0):0)gb[d&127](a);return}function zD(a,b){a=a|0;b=b|0;var d=0,e=0;d=c[a+60>>2]|0;if(d|0?(e=c[d+80>>2]|0,e|0):0)hb[e&31](a,b);return}function AD(a){a=a|0;var b=0,d=0;b=c[a+60>>2]|0;if(b|0?(d=c[b+84>>2]|0,d|0):0)gb[d&127](a);return}function BD(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0;k=l;l=l+48|0;f=k+32|0;h=k;i=k+16|0;j=c[b+60>>2]|0;m=c[e>>2]|0;do if(m|0?a[m>>0]|0:0){m=c[b+16>>2]|0;if(m|0?(c[m+144>>2]|0)==0:0)break;if(!(c[b+152>>2]&8192)){c[f>>2]=c[d>>2];c[f+4>>2]=c[d+4>>2];c[f+8>>2]=c[d+8>>2];c[f+12>>2]=c[d+12>>2];fD(i,b,f);c[h>>2]=c[i>>2];c[h+4>>2]=c[i+4>>2];c[h+8>>2]=c[i+8>>2];c[h+12>>2]=c[i+12>>2]}else{c[h>>2]=c[d>>2];c[h+4>>2]=c[d+4>>2];c[h+8>>2]=c[d+8>>2];c[h+12>>2]=c[d+12>>2]}if(j|0?(g=c[j+88>>2]|0,g|0):0){c[f>>2]=c[h>>2];c[f+4>>2]=c[h+4>>2];c[f+8>>2]=c[h+8>>2];c[f+12>>2]=c[h+12>>2];ib[g&127](b,f,e)}}while(0);l=k;return}function CD(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;f=c[b+60>>2]|0;g=(c[b+16>>2]|0)+16|0;i=XJ(d,58)|0;h=(i|0)!=0;if(h)a[i>>0]=0;if(f|0?(DD(c[b+68>>2]|0,d,g),e=c[f+92>>2]|0,e|0):0)hb[e&31](b,g);if(h)a[i>>0]=58;return}function DD(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+32|0;g=k+16|0;j=k+8|0;i=k;c[d>>2]=b;c[d+32>>2]=5;e=SE(b)|0;f=c[a+16>>2]|0;if(!((f|0)!=0?(wM(e,f,c[a+20>>2]|0,4,37)|0)!=0:0))h=3;a:do if((h|0)==3){switch(TE(b,d,c[a+24>>2]|0)|0){case 0:break a;case 1:break;default:{$l(1,95868,g)|0;break a}}a=xw((sJ(b)|0)+16|0)|0;c[i>>2]=b;qL(a,95833,i)|0;if(Ev(a)|0){c[j>>2]=b;$l(0,95842,j)|0}$I(a)}while(0);l=k;return}function ED(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;f=c[b+60>>2]|0;g=(c[b+16>>2]|0)+56|0;i=XJ(d,58)|0;h=(i|0)!=0;if(h)a[i>>0]=0;if(f|0?(DD(c[b+68>>2]|0,d,g),e=c[f+92>>2]|0,e|0):0)hb[e&31](b,g);if(h)a[i>>0]=58;return}function FD(a,b,d,e){a=a|0;b=b|0;d=d|0;e=+e;var f=0,h=0,i=0,j=0;h=c[a+60>>2]|0;i=a+16|0;j=(c[i>>2]|0)+96|0;if(h|0?(DD(c[a+68>>2]|0,b,j),f=c[h+92>>2]|0,f|0):0)hb[f&31](a,j);j=c[i>>2]|0;c[j+136>>2]=d;g[j+140>>2]=e;return}function GD(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0;m=l;l=l+16|0;k=m;j=c[b+60>>2]|0;b=c[b+16>>2]|0;c[b+160>>2]=d;a:do if((d|0)!=0&(j|0)!=0){j=b+144|0;i=b+152|0;g=b+148|0;b=d;b:while(1){f=b+4|0;b=c[b>>2]|0;if(!b)break a;c:do switch(a[b>>0]|0){case 115:{if(!(yJ(b,95889)|0)){c[j>>2]=3;b=f;continue b}if(!(yJ(b,95910)|0)){e=115;while(1){d=b+1|0;if(!(e<<24>>24))break;b=d;e=a[d>>0]|0}h[i>>3]=+tM(d);b=f;continue b}break}case 100:{if(!(yJ(b,122119)|0)){c[j>>2]=1;b=f;continue b}if(!(yJ(b,122112)|0)){c[j>>2]=2;b=f;continue b}break}case 105:{if(yJ(b,119127)|0?yJ(b,95895)|0:0)break c;c[j>>2]=0;b=f;continue b}case 98:{if(!(yJ(b,95905)|0)){h[i>>3]=2.0;b=f;continue b}break}case 102:{if(!(yJ(b,95923)|0)){c[g>>2]=1;b=f;continue b}break}case 117:{if(!(yJ(b,95930)|0)){c[g>>2]=0;b=f;continue b}break}case 116:{if(!(yJ(b,95939)|0)){b=f;continue b}break}default:{}}while(0);c[k>>2]=b;$l(0,95947,k)|0;b=f}}while(0);l=m;return}function HD(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0;j=l;l=l+32|0;g=j;d=c[a+60>>2]|0;if((d|0?(i=d+96|0,f=c[i>>2]|0,f|0):0)?c[(c[a+16>>2]|0)+144>>2]|0:0){d=b+16|0;h[g>>3]=(+h[d>>3]+ +h[b>>3])*.5;h[g+8>>3]=(+h[b+24>>3]+ +h[b+8>>3])*.5;b=g+16|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];if(!(c[a+152>>2]&8192)){gD(a,g,g,2)|0;f=c[i>>2]|0}ib[f&127](a,g,e)}l=j;return}function ID(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+48|0;m=o;f=c[a+60>>2]|0;if((f|0?(n=f+100|0,c[n>>2]|0):0)?(k=a+16|0,j=c[k>>2]|0,c[j+144>>2]|0):0){if(!(e&4)){f=e;g=0}else{f=e&-5;e=j+16|0;g=m;h=e;i=g+40|0;do{c[g>>2]=c[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));g=e;h=j+56|0;i=g+40|0;do{c[g>>2]=c[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));g=1}if(!(c[a+152>>2]&8192)){e=d+10|0;if((c[42407]|0)<(d|0)){c[42407]=e;e=zw(c[42408]|0,e<<4)|0;c[42408]=e}else e=c[42408]|0;gD(a,b,e,d)|0;kb[c[n>>2]&31](a,e,d,f)}else kb[c[n>>2]&31](a,b,d,f);if(g|0){g=(c[k>>2]|0)+16|0;h=m;i=g+40|0;do{c[g>>2]=c[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0))}}l=o;return}function JD(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=l;l=l+64|0;f=e;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];g=f+32|0;b=b+16|0;c[g>>2]=c[b>>2];c[g+4>>2]=c[b+4>>2];c[g+8>>2]=c[b+8>>2];c[g+12>>2]=c[b+12>>2];h[f+16>>3]=+h[f>>3];h[f+24>>3]=+h[f+40>>3];h[f+48>>3]=+h[g>>3];h[f+56>>3]=+h[f+8>>3];ID(a,f,4,d);l=e;return}function KD(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0;i=c[a+60>>2]|0;do if((i|0?(j=i+104|0,h=c[j>>2]|0,h|0):0)?c[(c[a+16>>2]|0)+144>>2]|0:0){if(c[a+152>>2]&8192|0){mb[h&15](a,b,d,e,f,g&255);break}h=d+10|0;if((c[42407]|0)<(d|0)){c[42407]=h;h=zw(c[42408]|0,h<<4)|0;c[42408]=h}else h=c[42408]|0;gD(a,b,h,d)|0;mb[c[j>>2]&15](a,h,d,e,f,g&255)}while(0);return}function LD(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=c[a+60>>2]|0;do if((e|0?(g=e+108|0,f=c[g>>2]|0,f|0):0)?c[(c[a+16>>2]|0)+144>>2]|0:0){if(c[a+152>>2]&8192|0){ib[f&127](a,b,d);break}e=d+10|0;if((c[42407]|0)<(d|0)){c[42407]=e;e=zw(c[42408]|0,e<<4)|0;c[42408]=e}else e=c[42408]|0;gD(a,b,e,d)|0;ib[c[g>>2]&127](a,e,d)}while(0);return}function MD(b,d){b=b|0;d=d|0;var e=0,f=0;e=c[b+60>>2]|0;if((d|0?!((e|0)==0|(a[d>>0]|0)==0):0)?(f=c[e+112>>2]|0,f|0):0)hb[f&31](b,d);return}function ND(b,d,e,f,g,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0.0,k=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0,t=0.0,u=0.0,v=0.0,w=0.0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;F=l;l=l+112|0;B=F+64|0;E=F;n=F+96|0;x=F+48|0;y=F+32|0;C=c[b+60>>2]|0;if(!b)ma(96061,96e3,691,96011);if(!d)ma(96030,96e3,692,96011);if(!(a[d>>0]|0))ma(96035,96e3,693,96011);D=Mr(d)|0;if(!D){if((C|0)!=0&(Qy(d)|0)!=0?(m=c[C+116>>2]|0,m|0):0)lb[m&7](b,d,e,f,g&255)}else{s=b+432|0;c[B>>2]=c[s>>2];c[B+4>>2]=c[s+4>>2];c[B+8>>2]=c[s+8>>2];c[B+12>>2]=c[s+12>>2];Pr(n,D,B);s=c[n>>2]|0;m=c[n+4>>2]|0;if(!((s|0)<1&(m|0)<1)){n=E+16|0;c[n>>2]=c[e>>2];c[n+4>>2]=c[e+4>>2];c[n+8>>2]=c[e+8>>2];c[n+12>>2]=c[e+12>>2];c[E>>2]=c[e>>2];c[E+4>>2]=c[e+4>>2];c[E+8>>2]=c[e+8>>2];c[E+12>>2]=c[e+12>>2];z=E+8|0;A=E+24|0;d=1;while(1){if((d|0)>=(f|0))break;G=e+(d<<4)|0;v=+h[G>>3];h[E>>3]=+h[(+h[E>>3]>3];w=+h[e+(d<<4)+8>>3];h[z>>3]=+h[(+h[z>>3]>3];h[n>>3]=+h[(+h[n>>3]>v?n:G)>>3];h[A>>3]=+h[(+h[A>>3]>w?n:G)+8>>3];d=d+1|0}k=+h[n>>3];j=+h[E>>3];t=k-j;u=+h[A>>3];v=+h[z>>3];w=u-v;o=+(m|0);p=+(s|0);q=t/p;r=w/o;a:do switch(OD(i)|0){case 1:if(q>3]=j;k=k-t;h[n>>3]=k}if(o>3]=v+w;h[A>>3]=u-w}if(!(c[b+152>>2]&8192)){c[B>>2]=c[E>>2];c[B+4>>2]=c[E+4>>2];c[B+8>>2]=c[E+8>>2];c[B+12>>2]=c[E+12>>2];fD(x,b,B);c[E>>2]=c[x>>2];c[E+4>>2]=c[x+4>>2];c[E+8>>2]=c[x+8>>2];c[E+12>>2]=c[x+12>>2];c[B>>2]=c[n>>2];c[B+4>>2]=c[n+4>>2];c[B+8>>2]=c[n+8>>2];c[B+12>>2]=c[n+12>>2];fD(y,b,B);c[n>>2]=c[y>>2];c[n+4>>2]=c[y+4>>2];c[n+8>>2]=c[y+8>>2];c[n+12>>2]=c[y+12>>2];k=+h[n>>3];j=+h[E>>3]}if(j>k){h[E>>3]=k;h[n>>3]=j}j=+h[z>>3];k=+h[A>>3];if(j>k){h[z>>3]=k;h[A>>3]=j}if(C|0){G=c[b+72>>2]|0;c[B>>2]=c[E>>2];c[B+4>>2]=c[E+4>>2];c[B+8>>2]=c[E+8>>2];c[B+12>>2]=c[E+12>>2];c[B+16>>2]=c[E+16>>2];c[B+20>>2]=c[E+20>>2];c[B+24>>2]=c[E+24>>2];c[B+28>>2]=c[E+28>>2];QD(b,D,B,g,G)}}}l=F;return}function OD(b){b=b|0;if(a[b>>0]|0)if(jK(b,96043)|0)if(jK(b,96049)|0)if(!(jK(b,96056)|0))b=4;else b=(JA(b)|0)<<24>>24!=0&1;else b=3;else b=2;else b=0;return b|0}function PD(a,b){a=a|0;b=+b;if(c[a+60>>2]|0)h[(c[a+16>>2]|0)+152>>3]=b;return}function QD(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+176|0;k=n+8|0;j=n;h=n+40|0;if(!b)ma(96061,96065,52,96079);if(!d)ma(96091,96065,53,96079);i=c[d+8>>2]|0;if(!i)ma(96094,96065,54,96079);if(!(a[i>>0]|0))ma(96103,96065,55,96079);yK(h,c[d+28>>2]|0)|0;i=h+(sJ(h)|0)|0;a[i>>0]=58;a[i+1>>0]=0;JL(h,g)|0;if((RD(b,h)|0)==999){c[j>>2]=h;$l(0,96115,j)|0}g=c[b+92>>2]|0;if(g|0?(m=c[g>>2]|0,m|0):0){c[k>>2]=c[e>>2];c[k+4>>2]=c[e+4>>2];c[k+8>>2]=c[e+8>>2];c[k+12>>2]=c[e+12>>2];c[k+16>>2]=c[e+16>>2];c[k+20>>2]=c[e+20>>2];c[k+24>>2]=c[e+24>>2];c[k+28>>2]=c[e+28>>2];kb[m&31](b,d,k,f)}l=n;return}function RD(a,b){a=a|0;b=b|0;b=Kr(c[a>>2]|0,4,b)|0;if(!b)b=999;else{b=c[b+16>>2]|0;c[a+92>>2]=c[b+12>>2];c[a+96>>2]=c[b>>2];b=300}return b|0}function SD(a){a=a|0;return 1}function TD(b){b=b|0;var c=0;a[b+536>>0]=0;c=b+336|0;h[c>>3]=+h[c>>3]+10.0/+h[b+352>>3];a[b+537>>0]=1;return 0}function UD(b){b=b|0;var c=0;a[b+536>>0]=0;c=b+336|0;h[c>>3]=+h[c>>3]-10.0/+h[b+352>>3];a[b+537>>0]=1;return 0}function VD(b){b=b|0;var c=0;a[b+536>>0]=0;c=b+344|0;h[c>>3]=+h[c>>3]-10.0/+h[b+352>>3];a[b+537>>0]=1;return 0}function WD(b){b=b|0;var c=0;a[b+536>>0]=0;c=b+344|0;h[c>>3]=+h[c>>3]+10.0/+h[b+352>>3];a[b+537>>0]=1;return 0}function XD(b){b=b|0;var c=0;a[b+536>>0]=0;c=b+352|0;h[c>>3]=+h[c>>3]*1.1;a[b+537>>0]=1;return 0}function YD(b){b=b|0;var c=0;a[b+536>>0]=0;c=b+352|0;h[c>>3]=+h[c>>3]*.9090909090909091;a[b+537>>0]=1;return 0}function ZD(b){b=b|0;var d=0,e=0,f=0,g=0.0,i=0.0;e=b+536|0;d=(a[e>>0]|0)==0;a[e>>0]=d&1;if(d){d=c[b+448>>2]|0;e=c[b+452>>2]|0;i=+(d>>>0);g=+(e>>>0);f=i/+(d|0)>3]=(f?i:g)/+((f?d:e)|0);e=b+336|0;c[e>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;a[b+537>>0]=1}return 0}function _D(b){b=b|0;var d=0,e=0;d=c[(c[b>>2]|0)+168>>2]|0;e=b+580|0;if(!(c[e>>2]|0)){c[e>>2]=d;e=(c[d+16>>2]|0)+112|0;a[e>>0]=a[e>>0]|2;oE(b,d)}hu(b,d);a[b+540>>0]=1;return}function $D(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0,k=0;k=l;l=l+16|0;f=k;switch(d|0){case 1:{c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2];hE(b,f);nE(b);a[b+538>>0]=1;a[b+541>>0]=1;j=13;break}case 2:{a[b+538>>0]=1;a[b+541>>0]=2;j=13;break}case 3:{c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2];hE(b,f);a[b+538>>0]=1;a[b+541>>0]=3;j=13;break}case 4:{a[b+536>>0]=0;if(!(c[b+360>>2]|0)){f=b+352|0;i=+h[f>>3];d=b+336|0;h[d>>3]=(+h[e>>3]-+((c[b+448>>2]|0)>>>0)*.5)*.10000000000000009/(+h[b+520>>3]*i)+ +h[d>>3];g=+h[e+8>>3]-+((c[b+452>>2]|0)>>>0)*.5;d=b+528|0}else{f=b+352|0;i=+h[f>>3];d=b+336|0;h[d>>3]=+h[d>>3]-(+h[e+8>>3]-+((c[b+452>>2]|0)>>>0)*.5)*.10000000000000009/(+h[b+528>>3]*i);g=+h[e>>3]-+((c[b+448>>2]|0)>>>0)*.5;d=b+520|0}j=b+344|0;h[j>>3]=g*.10000000000000009/(+h[d>>3]*i)+ +h[j>>3];h[f>>3]=i*1.1;j=13;break}case 5:{a[b+536>>0]=0;j=b+352|0;i=+h[j>>3]*.9090909090909091;h[j>>3]=i;if(!(c[b+360>>2]|0)){f=b+336|0;h[f>>3]=+h[f>>3]-(+h[e>>3]-+((c[b+448>>2]|0)>>>0)*.5)*.10000000000000009/(+h[b+520>>3]*i);g=+h[e+8>>3]-+((c[b+452>>2]|0)>>>0)*.5;f=b+528|0}else{f=b+336|0;h[f>>3]=(+h[e+8>>3]-+((c[b+452>>2]|0)>>>0)*.5)*.10000000000000009/(+h[b+528>>3]*i)+ +h[f>>3];g=+h[e>>3]-+((c[b+448>>2]|0)>>>0)*.5;f=b+520|0}j=b+344|0;h[j>>3]=+h[j>>3]-g*.10000000000000009/(+h[f>>3]*i);j=13;break}default:{}}if((j|0)==13)a[b+537>>0]=1;b=b+560|0;c[b>>2]=c[e>>2];c[b+4>>2]=c[e+4>>2];c[b+8>>2]=c[e+8>>2];c[b+12>>2]=c[e+12>>2];l=k;return}function aE(b,c,d){b=b|0;c=c|0;d=d|0;a[b+538>>0]=0;a[b+541>>0]=0;return}function bE(b,d){b=b|0;d=d|0;var e=0,f=0.0,g=0.0,i=0,j=0.0,k=0;k=l;l=l+16|0;e=k;i=b+560|0;j=(+h[d>>3]-+h[i>>3])/+h[b+520>>3];g=(+h[d+8>>3]-+h[b+568>>3])/+h[b+528>>3];if(!(+B(+j)<.0001&+B(+g)<.0001)){switch(a[b+541>>0]|0){case 0:{c[e>>2]=c[d>>2];c[e+4>>2]=c[d+4>>2];c[e+8>>2]=c[d+8>>2];c[e+12>>2]=c[d+12>>2];hE(b,e);break}case 2:{f=+h[b+352>>3];if(!(c[b+360>>2]|0)){e=b+336|0;h[e>>3]=+h[e>>3]-j/f;e=b+344|0;h[e>>3]=+h[e>>3]-g/f}else{e=b+336|0;h[e>>3]=+h[e>>3]-g/f;e=b+344|0;h[e>>3]=+h[e>>3]+j/f}a[b+537>>0]=1;break}default:{}}c[i>>2]=c[d>>2];c[i+4>>2]=c[d+4>>2];c[i+8>>2]=c[d+8>>2];c[i+12>>2]=c[d+12>>2]}l=k;return}function cE(a,b,c){a=a|0;b=b|0;c=c|0;return}function dE(a){a=a|0;return}function eE(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;j=c[b>>2]|0;if(d){d=bM(d,123632)|0;if(d|0){i=fr(d,0)|0;ML(d)|0;f=5}}else{i=fr(c[13853]|0,0)|0;f=5}if((f|0)==5?i|0:0){g=j+168|0;d=c[g>>2]|0;if(d|0){f=c[j+172>>2]|0;if((f|0)!=0?(h=c[f+4>>2]|0,(h|0)!=0):0){gb[h&127](d);d=c[g>>2]|0}jw(d);mn(c[g>>2]|0)|0}To(i,0,122277,280,1);To(i,1,122241,304,1);To(i,2,122254,176,1);c[g>>2]=i;c[(c[i+16>>2]|0)+144>>2]=j;if((ms(j,i,e)|0)!=-1){c[b+580>>2]=0;c[b+576>>2]=0;a[b+537>>0]=1}}return}function fE(a,b){a=a|0;b=b|0;a=c[a>>2]|0;ms(a,c[a+168>>2]|0,b)|0;return}function gE(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;g=c[a>>2]|0;f=g+160|0;e=c[f>>2]|0;if((e|0)!=0?(c[g+164>>2]|0)==0:0){i=g+192|0;h=c[i>>2]|0;c[f>>2]=0;c[i>>2]=0;f=h}else{f=0;e=0}os(g,c[g+168>>2]|0,b,d)|0;if(e|0){i=c[a>>2]|0;c[i+160>>2]=e;c[i+192>>2]=f}return}function hE(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0.0,j=0.0,k=0.0,m=0;f=l;l=l+80|0;e=f+48|0;g=f;m=f+32|0;c[e>>2]=c[d>>2];c[e+4>>2]=c[d+4>>2];c[e+8>>2]=c[d+8>>2];c[e+12>>2]=c[d+12>>2];iE(m,b,e);k=+h[m>>3];j=+h[m+8>>3];i=1.0/+h[b+352>>3];h[g+16>>3]=i+k;h[g+24>>3]=i+j;h[g>>3]=k-i;h[g+8>>3]=j-i;d=c[(c[b>>2]|0)+168>>2]|0;c[e>>2]=c[g>>2];c[e+4>>2]=c[g+4>>2];c[e+8>>2]=c[g+8>>2];c[e+12>>2]=c[g+12>>2];c[e+16>>2]=c[g+16>>2];c[e+20>>2]=c[g+20>>2];c[e+24>>2]=c[g+24>>2];c[e+28>>2]=c[g+28>>2];d=jE(d,e)|0;e=b+576|0;if((d|0)!=(c[e>>2]|0)){kE(b);c[e>>2]=d;lE(b);a[b+537>>0]=1}l=f;return}function iE(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0.0,g=0.0,i=0;if(!(c[b+360>>2]|0)){e=+h[b+352>>3];f=+h[d+8>>3];g=e;i=b+528|0;e=+h[d>>3]/(+h[b+520>>3]*e)-+h[b+504>>3]}else{e=+h[b+352>>3];f=-+h[d>>3];g=e;i=b+520|0;e=+h[d+8>>3]/(+h[b+528>>3]*e)-+h[b+504>>3]}g=f/(+h[i>>3]*g)-+h[b+512>>3];h[a>>3]=e;h[a+8>>3]=g;return}function jE(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=l;l=l+32|0;f=g;e=eo(a)|0;a:while(1){if(!e){e=9;break}d=Qm(a,e)|0;while(1){if(!d)break;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];c[f+16>>2]=c[b+16>>2];c[f+20>>2]=c[b+20>>2];c[f+24>>2]=c[b+24>>2];c[f+28>>2]=c[b+28>>2];if((EB(d,f)|0)<<24>>24){e=6;break a}d=Sm(a,d)|0}e=fo(a,e)|0}do if((e|0)!=6)if((e|0)==9){d=go(a)|0;while(1){if(!d)break;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];c[f+16>>2]=c[b+16>>2];c[f+20>>2]=c[b+20>>2];c[f+24>>2]=c[b+24>>2];c[f+28>>2]=c[b+28>>2];if((BB(d,f)|0)<<24>>24){e=12;break}d=ho(a,d)|0}if((e|0)==12)break;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];c[f+16>>2]=c[b+16>>2];c[f+20>>2]=c[b+20>>2];c[f+24>>2]=c[b+24>>2];c[f+28>>2]=c[b+28>>2];d=mE(a,f)|0;if(!d){d=a;break}else break}while(0);l=g;return d|0}function kE(b){b=b|0;var d=0;d=c[b+576>>2]|0;a:do if(d|0)switch(Do(d)|0){case 0:{d=(c[d+16>>2]|0)+112|0;a[d>>0]=a[d>>0]&-2;break a}case 1:{d=(c[d+16>>2]|0)+117|0;a[d>>0]=a[d>>0]&-2;break a}case 2:{d=(c[d+16>>2]|0)+115|0;a[d>>0]=a[d>>0]&-2;break a}default:break a}while(0);c[b+584>>2]=0;return}function lE(b){b=b|0;var d=0,e=0;e=b+584|0;d=c[e>>2]|0;if(d|0){$I(d);c[e>>2]=0}d=c[b+576>>2]|0;a:do if(d|0)switch(Do(d)|0){case 0:{b=(c[d+16>>2]|0)+112|0;a[b>>0]=a[b>>0]|1;b=zm(d,0,96229,0)|0;if(!b)break a;c[e>>2]=rw(Km(d,b)|0,d)|0;break a}case 1:{b=(c[d+16>>2]|0)+117|0;a[b>>0]=a[b>>0]|1;b=zm(so(d)|0,1,96229,0)|0;if(!b)break a;c[e>>2]=rw(Km(d,b)|0,d)|0;break a}case 2:{b=(c[d+16>>2]|0)+115|0;a[b>>0]=a[b>>0]|1;b=zm(so(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)|0,2,96229,0)|0;if(!b)break a;c[e>>2]=rw(Km(d,b)|0,d)|0;break a}default:break a}while(0);return}function mE(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0.0,o=0.0;m=l;l=l+32|0;e=m;g=c[a+16>>2]|0;i=c[g+180>>2]|0;j=g+184|0;d=1;while(1){if((d|0)>(i|0)){k=4;break}f=c[(c[j>>2]|0)+(d<<2)>>2]|0;c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];c[e+8>>2]=c[b+8>>2];c[e+12>>2]=c[b+12>>2];c[e+16>>2]=c[b+16>>2];c[e+20>>2]=c[b+20>>2];c[e+24>>2]=c[b+24>>2];c[e+28>>2]=c[b+28>>2];f=mE(f,e)|0;if(!f)d=d+1|0;else{a=f;break}}do if((k|0)==4){o=+h[g+24>>3];n=+h[g+40>>3];if(((+h[b+16>>3]>=+h[g+16>>3]?+h[g+32>>3]>=+h[b>>3]:0)?+h[b+24>>3]>=o:0)?n>=+h[b+8>>3]:0)break;a=0}while(0);l=m;return a|0}function nE(b){b=b|0;var d=0,e=0,f=0;f=b+580|0;d=c[f>>2]|0;a:do if(d|0)switch(Do(d)|0){case 0:{e=(c[d+16>>2]|0)+112|0;a[e>>0]=a[e>>0]&-7|4;break a}case 1:{e=(c[d+16>>2]|0)+117|0;a[e>>0]=a[e>>0]&-7|4;break a}case 2:{e=(c[d+16>>2]|0)+115|0;a[e>>0]=a[e>>0]&-7|4;break a}default:break a}while(0);d=b+588|0;e=c[d>>2]|0;if(e|0){$I(e);c[d>>2]=0}d=c[b+576>>2]|0;c[f>>2]=d;b:do if(d|0)switch(Do(d)|0){case 0:{f=(c[d+16>>2]|0)+112|0;a[f>>0]=a[f>>0]|2;oE(b,d);break b}case 1:{f=(c[d+16>>2]|0)+117|0;a[f>>0]=a[f>>0]|2;pE(b,d);break b}case 2:{f=(c[d+16>>2]|0)+115|0;a[f>>0]=a[f>>0]|2;qE(b,d);break b}default:break b}while(0);return}function oE(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=a+592|0;do if((to(b)|0)==(b|0))if(!(rn(b)|0)){Fr(d,0,96286);break}else{Fr(d,0,96278);break}else Fr(d,0,96292);while(0);Fr(d,1,En(b)|0);c[a+596>>2]=2;f=a+604|0;d=0;e=2;while(1){d=Em(b,0,d)|0;if(!d)break;Fr(f,e,c[d+8>>2]|0);Fr(f,e+1|0,Km(b,d)|0);Fr(f,e+2|0,0);e=e+3|0}c[a+608>>2]=e;d=zm(b,0,96264,0)|0;if(!d){d=zm(b,0,96269,0)|0;if(d|0)g=11}else g=11;if((g|0)==11)c[a+588>>2]=rw(Km(b,d)|0,b)|0;return}function pE(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;f=a+592|0;Fr(f,0,96273);Fr(f,1,En(b)|0);c[a+596>>2]=2;f=a+604|0;g=to(so(b)|0)|0;e=2;d=0;while(1){d=Em(g,1,d)|0;if(!d)break;Fr(f,e,c[d+8>>2]|0);Fr(f,e|1,Km(b,d)|0);e=e+2|0}c[a+608>>2]=e;d=zm(so(b)|0,1,96264,0)|0;if(!d){d=zm(so(b)|0,1,96269,0)|0;if(d|0)h=6}else h=6;if((h|0)==6)c[a+588>>2]=rw(Km(b,d)|0,b)|0;return}function qE(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;h=a+592|0;Fr(h,0,96237);k=b+48|0;Fr(h,1,En(c[((c[b>>2]&3|0)==3?b:k)+40>>2]|0)|0);k=(rn(so(c[((c[b>>2]&3|0)==3?b:k)+40>>2]|0)|0)|0)!=0;Fr(h,3,k?122546:122549);k=b+-48|0;Fr(h,4,En(c[((c[b>>2]&3|0)==2?b:k)+40>>2]|0)|0);c[a+596>>2]=7;i=a+604|0;j=to(so(c[((c[b>>2]&3|0)==2?b:k)+40>>2]|0)|0)|0;g=7;d=0;a:while(1){while(1){d=Em(j,2,d)|0;if(!d)break a;e=d+8|0;f=c[e>>2]|0;if(!(yJ(f,96242)|0)){l=5;break}if(!(yJ(f,96251)|0)){l=7;break}if(yJ(f,96260)|0)break;Fr(h,6,Km(b,d)|0)}if((l|0)==5){l=0;Fr(h,2,Km(b,d)|0)}else if((l|0)==7){l=0;Fr(h,5,Km(b,d)|0)}Fr(i,g,c[e>>2]|0);Fr(i,g+1|0,Km(b,d)|0);g=g+2|0}c[a+608>>2]=g;d=zm(so(c[((c[b>>2]&3|0)==2?b:k)+40>>2]|0)|0,2,96264,0)|0;if(!d){d=zm(so(c[((c[b>>2]&3|0)==2?b:k)+40>>2]|0)|0,2,96269,0)|0;if(d|0)l=13}else l=13;if((l|0)==13)c[a+588>>2]=rw(Km(b,d)|0,b)|0;return}function rE(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;g=sE(a,b,c[d>>2]|0)|0;d=c[d+4>>2]|0;while(1){f=c[d+4>>2]|0;if(!f)break;b=0;while(1){e=c[f+(b*20|0)+4>>2]|0;if(!e)break;Ir(a,c[d>>2]|0,e,c[f+(b*20|0)+8>>2]|0,g,f+(b*20|0)|0)|0;b=b+1|0}d=d+8|0}return}function sE(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=xw(12)|0;if(!b)b=0;else b=HL(b)|0;c[e+4>>2]=b;c[e+8>>2]=HL(d)|0;d=a+100|0;c[e>>2]=c[d>>2];c[d>>2]=e;return e|0}function tE(b,c){b=b|0;c=c|0;uE(b);a[b+44>>0]=0;vE(b)|0;uA(b)|0;return}function uE(b){b=b|0;var d=0,e=0;d=c[b+32>>2]|0;a:do if(d|0)while(1){e=c[d>>2]|0;if(!e)break a;if((a[e>>0]|0)==103?iL(e,96301)|0:0)rE(b,0,c[d+4>>2]|0);d=d+8|0}while(0);return}function vE(a){a=a|0;var b=0;b=Kr(a,2,96314)|0;if(!b)a=999;else{c[a+148>>2]=c[(c[b+16>>2]|0)+12>>2];a=300}return a|0}function wE(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;a=c[a+148>>2]|0;if((a|0)!=0?(e=c[a>>2]|0,(e|0)!=0):0)a=ab[e&63](b,d)|0;else a=0;return a|0}function xE(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;return (c[b>>2]|0)-(c[d>>2]|0)|0}function yE(a){a=a|0;var b=0.0,d=0.0;a=c[a+16>>2]|0;d=+h[a+16>>3];b=+h[a+24>>3];return (zE(~~(d>b?d:b)>>>0)|0)+1|0}function zE(a){a=a|0;var b=0,c=0;if(!a)a=-1;else{c=a>>>0>65535;a=c?a>>>16:a;c=c?16:0;b=a>>>0>255;a=b?a>>>8:a;c=b?c|8:c;b=a>>>0>15;a=b?a>>>4:a;c=b?c|4:c;b=a>>>0>3;a=(b?c|2:c)+((b?a>>>2:a)>>>0>1&1)|0}return a|0}function AE(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0;r=l;l=l+32|0;q=r;p=BE(b,d,e,f,g)|0;e=CE(p)|0;if((e|0)>=0){n=q+16|0;o=q+24|0;m=q+8|0;k=g+32|0;e=0;g=0;while(1){if((g|0)>=(d|0))break;f=b+(g*40|0)+32|0;do if(c[f>>2]|0){DE(q,p,b+(g*40|0)|0);i=+h[n>>3];j=+h[o>>3];if(!(c[q>>2]|0)){a[(c[f>>2]|0)+36>>0]=1;break}if(+h[m>>3]==0.0){f=c[f>>2]|0;h[f+16>>3]=i;h[f+24>>3]=j;a[f+36>>0]=1;break}if((a[k>>0]|0)==1){f=c[f>>2]|0;h[f+16>>3]=i;h[f+24>>3]=j;a[f+36>>0]=1}else e=1}while(0);g=g+1|0}EE(p)}l=r;return e|0}function BE(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;g=ww(28)|0;j=Rl(24896,c[4348]|0)|0;h=g+20|0;c[h>>2]=j;do if(j){j=kH()|0;c[g+24>>2]=j;if(!j){YL(96532,14,1,c[13918]|0)|0;i=6;break}else{c[g>>2]=a;c[g+4>>2]=b;c[g+8>>2]=d;c[g+12>>2]=e;c[g+16>>2]=f;break}}else{YL(96532,14,1,c[13918]|0)|0;i=6}while(0);if((i|0)==6){a=c[h>>2]|0;if(a|0)Ll(a)|0;a=c[g+24>>2]|0;if(a|0)mH(a)|0;$I(g);g=0}return g|0}function CE(a){a=a|0;var b=0;b=NE(a)|0;if((b|0)>=0){OE(a);PE(a);b=Ll(c[a+20>>2]|0)|0}return b|0}function DE(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0,g=0,i=0.0,j=0,k=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0.0,L=0,M=0;M=l;l=l+464|0;J=M+416|0;L=M+400|0;G=M+384|0;m=M+352|0;n=M+320|0;o=M+288|0;p=M+256|0;r=M+224|0;s=M+192|0;t=M+160|0;u=M+128|0;v=M+96|0;x=M+64|0;y=M+32|0;H=M;z=c[d+32>>2]|0;e=+h[z>>3];C=d+16|0;A=(e*2.0+ +h[C>>3])*.125;D=z+8|0;I=d+24|0;i=+h[I>>3];K=(+h[D>>3]*2.0+i)*.5;if(!z)ma(96325,96335,445,96345);f=J;g=f+36|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));B=z+16|0;h[B>>3]=+h[d>>3]-e;E=d+8|0;F=z+24|0;h[F>>3]=i+ +h[E>>3];FE(m,b,d,J);j=c[m>>2]|0;f=c[m+4>>2]|0;e=+h[m+8>>3];m=m+16|0;c[L>>2]=c[m>>2];c[L+4>>2]=c[m+4>>2];c[L+8>>2]=c[m+8>>2];c[L+12>>2]=c[m+12>>2];a:do if(!j){c[a>>2]=0;c[a+4>>2]=f;h[a+8>>3]=e;a=a+16|0;c[a>>2]=c[L>>2];c[a+4>>2]=c[L+4>>2];c[a+8>>2]=c[L+8>>2];c[a+12>>2]=c[L+12>>2]}else{h[F>>3]=+h[E>>3];FE(n,b,d,J);g=c[n>>2]|0;m=c[n+4>>2]|0;i=+h[n+8>>3];n=n+16|0;c[G>>2]=c[n>>2];c[G+4>>2]=c[n+4>>2];c[G+8>>2]=c[n+8>>2];c[G+12>>2]=c[n+12>>2];if(!g){c[a>>2]=0;c[a+4>>2]=m;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break}if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];f=m;e=i}else g=j;h[F>>3]=+h[E>>3]-+h[D>>3];FE(o,b,d,J);m=c[o>>2]|0;j=c[o+4>>2]|0;i=+h[o+8>>3];o=o+16|0;c[G>>2]=c[o>>2];c[G+4>>2]=c[o+4>>2];c[G+8>>2]=c[o+8>>2];c[G+12>>2]=c[o+12>>2];if(!m){c[a>>2]=0;c[a+4>>2]=j;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break}if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];f=j;e=i}else m=g;h[B>>3]=+h[d>>3];h[F>>3]=+h[I>>3]+ +h[E>>3];FE(p,b,d,J);g=c[p>>2]|0;j=c[p+4>>2]|0;i=+h[p+8>>3];p=p+16|0;c[G>>2]=c[p>>2];c[G+4>>2]=c[p+4>>2];c[G+8>>2]=c[p+8>>2];c[G+12>>2]=c[p+12>>2];if(!g){c[a>>2]=0;c[a+4>>2]=j;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break}if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];m=g;f=j;e=i}h[F>>3]=+h[E>>3]-+h[D>>3];FE(r,b,d,J);g=c[r>>2]|0;j=c[r+4>>2]|0;i=+h[r+8>>3];r=r+16|0;c[G>>2]=c[r>>2];c[G+4>>2]=c[r+4>>2];c[G+8>>2]=c[r+8>>2];c[G+12>>2]=c[r+12>>2];if(!g){c[a>>2]=0;c[a+4>>2]=j;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break}if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];m=g;f=j;e=i}h[B>>3]=+h[C>>3]+ +h[d>>3];h[F>>3]=+h[I>>3]+ +h[E>>3];FE(s,b,d,J);g=c[s>>2]|0;j=c[s+4>>2]|0;i=+h[s+8>>3];s=s+16|0;c[G>>2]=c[s>>2];c[G+4>>2]=c[s+4>>2];c[G+8>>2]=c[s+8>>2];c[G+12>>2]=c[s+12>>2];if(!g){c[a>>2]=0;c[a+4>>2]=j;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break}if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];m=g;f=j;e=i}h[F>>3]=+h[E>>3];FE(t,b,d,J);g=c[t>>2]|0;j=c[t+4>>2]|0;i=+h[t+8>>3];t=t+16|0;c[G>>2]=c[t>>2];c[G+4>>2]=c[t+4>>2];c[G+8>>2]=c[t+8>>2];c[G+12>>2]=c[t+12>>2];if(!g){c[a>>2]=0;c[a+4>>2]=j;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break}if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];m=g;f=j;e=i}h[F>>3]=+h[E>>3]-+h[D>>3];FE(u,b,d,J);g=c[u>>2]|0;j=c[u+4>>2]|0;i=+h[u+8>>3];u=u+16|0;c[G>>2]=c[u>>2];c[G+4>>2]=c[u+4>>2];c[G+8>>2]=c[u+8>>2];c[G+12>>2]=c[u+12>>2];if(!g){c[a>>2]=0;c[a+4>>2]=j;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break}if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];f=j;e=i}else g=m;j=(c[J+28>>2]|0)==0;do if(!(c[J+24>>2]|0))if(j){if(c[J+32>>2]|0){w=38;break}if(!((c[J+12>>2]|0)==0&(c[J>>2]|0)==0))w=38}else w=46;else if(j)w=38;else w=46;while(0);b:do if((w|0)==38)if(!(c[J+32>>2]|0)){h[B>>3]=+h[d>>3]-+h[z>>3];p=v+4|0;r=v+8|0;s=v+16|0;m=F;j=E;i=+h[I>>3];c:while(1){while(1){h[m>>3]=+h[j>>3]+i;if(!(+h[B>>3]<=+h[C>>3]+ +h[d>>3])){w=46;break b}FE(v,b,d,J);n=c[v>>2]|0;o=c[p>>2]|0;k=+h[r>>3];c[G>>2]=c[s>>2];c[G+4>>2]=c[s+4>>2];c[G+8>>2]=c[s+8>>2];c[G+12>>2]=c[s+12>>2];if(!n)break c;if(k>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];m=B;j=B;i=A;g=n;f=o;e=k}c[a>>2]=0;c[a+4>>2]=o;h[a+8>>3]=k;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break a}else w=46;while(0);d:do if((w|0)==46)if((c[J+12>>2]|0)==0&(c[J>>2]|0)==0){h[B>>3]=+h[d>>3]-+h[z>>3];k=+h[E>>3];n=x+4|0;o=x+8|0;p=x+16|0;i=k;k=+h[I>>3]+k;while(1){h[F>>3]=k;if(!(k>=i-+h[D>>3]))break d;FE(x,b,d,J);j=c[x>>2]|0;m=c[n>>2]|0;i=+h[o>>3];c[G>>2]=c[p>>2];c[G+4>>2]=c[p+4>>2];c[G+8>>2]=c[p+8>>2];c[G+12>>2]=c[p+12>>2];if(!j)break;if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];g=j;f=m;e=i}i=+h[E>>3];k=+h[F>>3]-K}c[a>>2]=0;c[a+4>>2]=m;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break a}while(0);i=+h[d>>3];k=+h[C>>3]+i;h[B>>3]=k;q=+h[D>>3];h[F>>3]=+h[E>>3]-q;j=c[J+4>>2]|0;do if(!(c[J+8>>2]|0)){m=c[J>>2]|0;if(!((j|0)==0&(m|0)==0)){w=59;break}if(c[J+20>>2]|0){j=0;m=0;w=59;break}if(c[J+32>>2]|0){j=0;m=0;w=59}}else{m=c[J>>2]|0;w=59}while(0);e:do if((w|0)==59){f:do if((j|0)==0&(m|0)==0){h[B>>3]=k;p=y+4|0;r=y+8|0;s=y+16|0;m=F;j=E;i=q;g:while(1){while(1){h[m>>3]=+h[j>>3]-i;i=+h[d>>3];if(!(+h[B>>3]>=i-+h[z>>3]))break f;FE(y,b,d,J);n=c[y>>2]|0;o=c[p>>2]|0;k=+h[r>>3];c[G>>2]=c[s>>2];c[G+4>>2]=c[s+4>>2];c[G+8>>2]=c[s+8>>2];c[G+12>>2]=c[s+12>>2];if(!n)break g;if(k>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];m=B;j=B;i=A;g=n;f=o;e=k}c[a>>2]=0;c[a+4>>2]=o;h[a+8>>3]=k;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break a}while(0);if(c[J+20>>2]|0)break;if(c[J+32>>2]|0)break;h[B>>3]=+h[C>>3]+i;i=+h[E>>3];n=H+4|0;o=H+8|0;p=H+16|0;k=i;i=i-+h[D>>3];while(1){h[F>>3]=i;if(!(i<=+h[I>>3]+k))break e;FE(H,b,d,J);j=c[H>>2]|0;m=c[n>>2]|0;i=+h[o>>3];c[G>>2]=c[p>>2];c[G+4>>2]=c[p+4>>2];c[G+8>>2]=c[p+8>>2];c[G+12>>2]=c[p+12>>2];if(!j)break;if(i>2]=c[G>>2];c[L+4>>2]=c[G+4>>2];c[L+8>>2]=c[G+8>>2];c[L+12>>2]=c[G+12>>2];g=j;f=m;e=i}k=+h[E>>3];i=+h[F>>3]+K}c[a>>2]=0;c[a+4>>2]=m;h[a+8>>3]=i;a=a+16|0;c[a>>2]=c[G>>2];c[a+4>>2]=c[G+4>>2];c[a+8>>2]=c[G+8>>2];c[a+12>>2]=c[G+12>>2];break a}while(0);c[a>>2]=g;c[a+4>>2]=f;h[a+8>>3]=e;a=a+16|0;c[a>>2]=c[L>>2];c[a+4>>2]=c[L+4>>2];c[a+8>>2]=c[L+8>>2];c[a+12>>2]=c[L+12>>2]}while(0);l=M;return}function EE(a){a=a|0;mH(c[a+24>>2]|0)|0;$I(a);return}function FE(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0.0,j=0,k=0,m=0,n=0.0,o=0,p=0,q=0,r=0.0,s=0,t=0;t=l;l=l+48|0;q=t+32|0;s=t+16|0;p=t;g=c[e+32>>2]|0;if(!g)ma(96325,96335,382,96354);o=g+16|0;c[p>>2]=c[o>>2];c[p+4>>2]=c[o+4>>2];c[p+8>>2]=c[o+8>>2];c[p+12>>2]=c[o+12>>2];o=d+4|0;m=0;g=0;while(1){if((m|0)>=(c[o>>2]|0))break;j=c[d>>2]|0;k=j+(m*40|0)|0;do if((k|0)!=(e|0)){if(+h[j+(m*40|0)+16>>3]>0.0?+h[j+(m*40|0)+24>>3]>0.0:0)break;g=g+((GE(e,k)|0)!=0&1)|0}while(0);m=m+1|0}HE(e,q);m=c[d+24>>2]|0;m=oH(m,c[m>>2]|0,q)|0;if(!m){c[b>>2]=g;h[b+8>>3]=0.0;s=b+16|0;c[s>>2]=c[p>>2];c[s+4>>2]=c[p+4>>2];c[s+8>>2]=c[p+8>>2];c[s+12>>2]=c[p+12>>2]}else{k=m;i=0.0;while(1){if(!k)break;j=c[(c[k+4>>2]|0)+16>>2]|0;if((j|0)!=(e|0)){IE(j,s);n=+JE(q,s);if(n>0.0){g=g+1|0;i=+KE(e,j,q,n,f)+i}d=c[j+32>>2]|0;if(((d|0)!=0?(a[d+36>>0]|0)!=0:0)?(HE(j,s),r=+JE(q,s),r>0.0):0){g=g+1|0;i=+LE(e,j,q,r,f)+i}}k=c[k>>2]|0}jH(m);c[b>>2]=g;h[b+8>>3]=i;s=b+16|0;c[s>>2]=c[p>>2];c[s+4>>2]=c[p+4>>2];c[s+8>>2]=c[p+8>>2];c[s+12>>2]=c[p+12>>2]}l=t;return}function GE(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0.0,g=0.0;a=c[a+32>>2]|0;if(+h[b+16>>3]==0.0?+h[b+24>>3]==0.0:0){if((((a|0)!=0?(d=+h[b>>3],e=+h[a+16>>3],d>e):0)?d<+h[a>>3]+e:0)?(f=+h[b+8>>3],g=+h[a+24>>3],f>g):0)a=f<+h[a+8>>3]+g&1;else a=0;return a|0}ma(96391,96335,219,96428);return 0}function HE(a,b){a=a|0;b=b|0;var d=0.0,e=0.0;a=c[a+32>>2]|0;e=+h[a+16>>3];c[b>>2]=~~e;d=+h[a+24>>3];c[b+4>>2]=~~d;c[b+8>>2]=~~(+h[a>>3]+e);c[b+12>>2]=~~(+h[a+8>>3]+d);return}function IE(a,b){a=a|0;b=b|0;var d=0.0,e=0.0;e=+h[a>>3];c[b>>2]=~~e;d=+h[a+8>>3];c[b+4>>2]=~~d;c[b+8>>2]=~~(+h[a+16>>3]+e);c[b+12>>2]=~~(+h[a+24>>3]+d);return}function JE(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;i=c[a+8>>2]|0;j=c[b>>2]|0;if((((i|0)>=(j|0)?(k=c[a>>2]|0,l=c[b+8>>2]|0,(k|0)<=(l|0)):0)?(e=c[a+12>>2]|0,f=c[b+4>>2]|0,(e|0)>=(f|0)):0)?(g=c[a+4>>2]|0,h=c[b+12>>2]|0,(g|0)<=(h|0)):0)d=(+(c[((e|0)<(h|0)?a:b)+12>>2]|0)-+(c[((g|0)>(f|0)?a:b)+4>>2]|0))*(+(c[((i|0)<(l|0)?a:b)+8>>2]|0)-+(c[((k|0)>(j|0)?a:b)>>2]|0));else d=0.0;return +d}function KE(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=+e;f=f|0;var g=0.0,h=0.0,i=0,j=0;j=l;l=l+16|0;i=j;a=ME(a,b)|0;f=f+(((a|0)<0?5:a)<<2)|0;a=c[f>>2]|0;if(!a){c[f>>2]=b;g=e}else{IE(a,i);g=+JE(d,i);g=g>e?g:0.0;a=c[f>>2]|0;if((c[a+32>>2]|0)!=0?(HE(a,i),h=+JE(d,i),h>e):0)g=h>g?h:g;if(!(g>0.0)){c[f>>2]=b;g=e}}l=j;return +g}function LE(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=+e;f=f|0;var g=0.0,h=0.0,i=0,j=0;j=l;l=l+16|0;i=j;a=ME(a,b)|0;f=f+(((a|0)<0?5:a)<<2)|0;a=c[f>>2]|0;if(!a){c[f>>2]=b;g=e}else{IE(a,i);g=+JE(d,i);g=g>e?g:0.0;a=c[f>>2]|0;if((c[a+32>>2]|0)!=0?(HE(a,i),h=+JE(d,i),h>e):0)g=h>g?h:g;if(!(g>0.0)){c[f>>2]=b;g=e}}l=j;return +g}function ME(b,d){b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0.0,k=0.0;e=c[b+32>>2]|0;f=c[d+32>>2]|0;if((e|0)==(f|0))ma(96370,96335,276,96380);do if((a[e+36>>0]|0)!=0?(a[f+36>>0]|0)!=0:0){j=+h[b>>3];if(j==0.0?+h[b+8>>3]==0.0:0){e=-1;break}k=+h[d>>3];i=+h[d+8>>3];if(!(k==0.0&i==0.0)){g=+h[b+8>>3];if(ij?2:1;break}e=kg){if(e){e=6;break}e=k>j?8:7;break}if(!e)if(k>j)e=5;else e=-1;else e=3}else e=-1}else e=-1;while(0);return e|0}function NE(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;k=l;l=l+32|0;d=k+24|0;e=k+16|0;f=k;g=yE(a)|0;h=a+4|0;i=e+4|0;j=a+20|0;b=0;while(1){if((b|0)>=(c[h>>2]|0)){b=0;break}m=ww(32)|0;o=(c[a>>2]|0)+(b*40|0)|0;n=m+12|0;c[m+28>>2]=o;QE(f,o);c[n>>2]=c[f>>2];c[n+4>>2]=c[f+4>>2];c[n+8>>2]=c[f+8>>2];c[n+12>>2]=c[f+12>>2];n=c[n>>2]|0;c[e>>2]=(((c[m+20>>2]|0)-n|0)/2|0)+n;n=c[m+16>>2]|0;c[i>>2]=(((c[m+24>>2]|0)-n|0)/2|0)+n;c[d>>2]=c[e>>2];c[d+4>>2]=c[e+4>>2];c[m+8>>2]=RE(d,g)|0;n=c[j>>2]|0;if(!(bb[c[n>>2]&31](n,m,1)|0)){b=-1;break}else b=b+1|0}l=k;return b|0}function OE(a){a=a|0;var b=0,d=0,e=0;d=a+20|0;e=c[d>>2]|0;b=a+24|0;a=bb[c[e>>2]&31](e,0,128)|0;while(1){if(!a)break;e=c[b>>2]|0;pH(e,a+12|0,c[a+28>>2]|0,e,0)|0;e=c[d>>2]|0;a=bb[c[e>>2]&31](e,a,8)|0}return}function PE(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;e=a+20|0;f=Tl(c[e>>2]|0)|0;d=0;while(1){if(!(Tl(c[e>>2]|0)|0))break;g=c[e>>2]|0;a=c[(c[g+8>>2]|0)+4>>2]|0;if(!a){h=8;break}b=c[(c[g+4>>2]|0)+8>>2]|0;if((b|0)<0)a=c[a+8>>2]|0;else a=a+(0-b)|0;if(!a){h=8;break}bb[c[g>>2]&31](g,a,4096)|0;$I(a);d=d+1|0}if((h|0)==8)ma(96441,96335,616,96444);if((f|0)==(d|0))return;else ma(96456,96335,623,96444)}function QE(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0.0,g=0.0,i=0,j=0,k=0,l=0.0;d=c[b+32>>2]|0;if(!d){e=0.0;f=0.0}else{e=+h[d>>3];f=+h[d+8>>3]}l=+h[b>>3];k=~~+A(+(l-e));g=+h[b+8>>3];j=~~+A(+(g-f));i=~~+N(+(l+e+ +h[b+16>>3]));if((i|0)==2147483647)ma(96468,96335,264,96495);d=~~+N(+(g+f+ +h[b+24>>3]));if((d|0)==2147483647)ma(96505,96335,266,96495);else{c[a>>2]=k;c[a+4>>2]=j;c[a+8>>2]=i;c[a+12>>2]=d;return}}function RE(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;f=0;e=c[a>>2]|0;d=c[a+4>>2]|0;while(1){a=b+-1|0;if((b|0)<=0)break;i=e>>>a&1;b=d>>>a&1;g=b+-1|0;h=g&(e^d);g=g&0-i;f=i<<1|f<<2|i^b;b=a;e=h^e^g;d=h^d^g}return f|0}function SE(b){b=b|0;var d=0,e=0,f=0,g=0;d=sJ(b)|0;if(d>>>0>=(c[42409]|0)>>>0){d=d+11|0;c[42409]=d;d=zw(c[42410]|0,d)|0;c[42410]=d;if(!d)d=0;else e=4}else{d=c[42410]|0;e=4}if((e|0)==4){g=d;while(1){e=a[b>>0]|0;if(!(e<<24>>24))break;f=e&255;if(lK(f)|0)e=(kK(f)|0)&255;a[g>>0]=e;g=g+1|0;b=b+1|0}a[g>>0]=0}return d|0}function TE(b,e,f){b=b|0;e=e|0;f=f|0;var g=0.0,i=0,j=0.0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0.0;F=l;l=l+144|0;s=F+96|0;p=F+80|0;v=F+124|0;t=F+72|0;w=F+64|0;x=F+56|0;C=F+48|0;D=F+40|0;E=F+32|0;y=F+24|0;z=F+16|0;A=F+8|0;B=F;i=F+120|0;m=F+116|0;n=F+112|0;o=F+108|0;c[e+32>>2]=f;r=b;while(1)if((a[r>>0]|0)==32)r=r+1|0;else break;c[o>>2]=255;b=a[r>>0]|0;a:do if(b<<24>>24==35){c[p>>2]=i;c[p+4>>2]=m;c[p+8>>2]=n;c[p+12>>2]=o;if((dM(r,96547,p)|0)<=2){b=a[r>>0]|0;q=12;break}switch(f|0){case 0:{G=+((c[i>>2]|0)>>>0)*.00392156862745098;h[C>>3]=G;g=+((c[m>>2]|0)>>>0)*.00392156862745098;h[D>>3]=g;j=+((c[n>>2]|0)>>>0)*.00392156862745098;h[E>>3]=j;k=+((c[o>>2]|0)>>>0)*.00392156862745098;UE(G,g,j,t,w,x);h[e>>3]=+h[t>>3];h[e+8>>3]=+h[w>>3];h[e+16>>3]=+h[x>>3];h[e+24>>3]=k;b=0;break a}case 1:{a[e>>0]=c[i>>2];a[e+1>>0]=c[m>>2];a[e+2>>0]=c[n>>2];a[e+3>>0]=c[o>>2];b=0;break a}case 3:{j=+((c[i>>2]|0)>>>0)*.00392156862745098;h[C>>3]=j;k=+((c[m>>2]|0)>>>0)*.00392156862745098;h[D>>3]=k;G=+((c[n>>2]|0)>>>0)*.00392156862745098;h[E>>3]=G;VE(j,k,G,y,z,A,B);a[e>>0]=~~+h[y>>3]*255;a[e+1>>0]=~~+h[z>>3]*255;a[e+2>>0]=~~+h[A>>3]*255;a[e+3>>0]=~~+h[B>>3]*255;b=0;break a}case 2:{c[e>>2]=(((c[i>>2]|0)*65535|0)>>>0)/255|0;c[e+4>>2]=(((c[m>>2]|0)*65535|0)>>>0)/255|0;c[e+8>>2]=(((c[n>>2]|0)*65535|0)>>>0)/255|0;c[e+12>>2]=(((c[o>>2]|0)*65535|0)>>>0)/255|0;b=0;break a}case 4:{h[e>>3]=+((c[i>>2]|0)>>>0)*.00392156862745098;h[e+8>>3]=+((c[m>>2]|0)>>>0)*.00392156862745098;h[e+16>>3]=+((c[n>>2]|0)>>>0)*.00392156862745098;h[e+24>>3]=+((c[o>>2]|0)>>>0)*.00392156862745098;b=0;break a}default:{b=0;break a}}}else q=12;while(0);b:do if((q|0)==12){if(!(b<<24>>24!=46?((b&255)+-48|0)>>>0>=10:0)){b=sJ(r)|0;if(b>>>0>=(c[42411]|0)>>>0){b=b+11|0;c[42411]=b;b=zw(c[42412]|0,b)|0;c[42412]=b;if(!b){b=-1;break}}else b=c[42412]|0;m=b;i=r;c:while(1){n=i+1|0;i=a[i>>0]|0;switch(i<<24>>24){case 0:break c;case 44:{i=32;break}default:{}}a[m>>0]=i;m=m+1|0;i=n}a[m>>0]=0;c[s>>2]=t;c[s+4>>2]=w;c[s+8>>2]=x;if((dM(b,96561,s)|0)==3){k=+h[t>>3];k=k<1.0?k:1.0;k=k>0.0?k:0.0;h[t>>3]=k;j=+h[w>>3];j=j<1.0?j:1.0;j=j>0.0?j:0.0;h[w>>3]=j;g=+h[x>>3];g=g<1.0?g:1.0;g=g>0.0?g:0.0;h[x>>3]=g;switch(f|0){case 0:{h[e>>3]=k;h[e+8>>3]=j;h[e+16>>3]=g;h[e+24>>3]=1.0;b=0;break b}case 1:{WE(k,j,g,C,D,E);a[e>>0]=~~(+h[C>>3]*255.0);a[e+1>>0]=~~(+h[D>>3]*255.0);a[e+2>>0]=~~(+h[E>>3]*255.0);a[e+3>>0]=-1;b=0;break b}case 3:{WE(k,j,g,C,D,E);VE(+h[C>>3],+h[D>>3],+h[E>>3],y,z,A,B);a[e>>0]=~~+h[y>>3]*255;a[e+1>>0]=~~+h[z>>3]*255;a[e+2>>0]=~~+h[A>>3]*255;a[e+3>>0]=~~+h[B>>3]*255;b=0;break b}case 2:{WE(k,j,g,C,D,E);c[e>>2]=~~(+h[C>>3]*65535.0);c[e+4>>2]=~~(+h[D>>3]*65535.0);c[e+8>>2]=~~(+h[E>>3]*65535.0);c[e+12>>2]=65535;b=0;break b}case 4:{WE(k,j,g,C,D,E);h[e>>3]=+h[C>>3];h[e+8>>3]=+h[D>>3];h[e+16>>3]=+h[E>>3];h[e+24>>3]=1.0;b=0;break b}default:{b=0;break b}}}}i=XE(r)|0;c[v>>2]=i;if(!i)b=-1;else{b=c[42413]|0;if(!(((b|0)!=0?(u=c[b>>2]|0,(a[u>>0]|0)==(a[i>>0]|0)):0)?(yJ(u,i)|0)==0:0)){b=wM(v,24932,2491,12,38)|0;c[42413]=b;if(!b)switch(f|0){case 0:{c[e>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;c[e+16>>2]=0;c[e+20>>2]=0;h[e+24>>3]=1.0;b=1;break b}case 1:{a[e+2>>0]=0;a[e+1>>0]=0;a[e>>0]=0;a[e+3>>0]=-1;b=1;break b}case 3:{c[e>>2]=0;b=1;break b}case 2:{c[e+8>>2]=0;c[e+4>>2]=0;c[e>>2]=0;c[e+12>>2]=65535;b=1;break b}case 4:{c[e>>2]=0;c[e+4>>2]=0;c[e+8>>2]=0;c[e+12>>2]=0;c[e+16>>2]=0;c[e+20>>2]=0;h[e+24>>3]=1.0;b=1;break b}default:{b=1;break b}}}switch(f|0){case 0:{h[e>>3]=+(d[b+4>>0]|0)*.00392156862745098;h[e+8>>3]=+(d[b+5>>0]|0)*.00392156862745098;h[e+16>>3]=+(d[b+6>>0]|0)*.00392156862745098;h[e+24>>3]=+(d[b+10>>0]|0)*.00392156862745098;b=0;break b}case 1:{a[e>>0]=a[b+7>>0]|0;a[e+1>>0]=a[b+8>>0]|0;a[e+2>>0]=a[b+9>>0]|0;a[e+3>>0]=a[b+10>>0]|0;b=0;break b}case 3:{j=+(d[b+7>>0]|0)*.00392156862745098;h[C>>3]=j;k=+(d[b+8>>0]|0)*.00392156862745098;h[D>>3]=k;G=+(d[b+9>>0]|0)*.00392156862745098;h[E>>3]=G;VE(j,k,G,y,z,A,B);a[e>>0]=~~+h[y>>3]*255;a[e+1>>0]=~~+h[z>>3]*255;a[e+2>>0]=~~+h[A>>3]*255;a[e+3>>0]=~~+h[B>>3]*255;b=0;break b}case 2:{c[e>>2]=(d[b+7>>0]|0)*257;c[e+4>>2]=(d[b+8>>0]|0)*257;c[e+8>>2]=(d[b+9>>0]|0)*257;c[e+12>>2]=(d[b+10>>0]|0)*257;b=0;break b}case 4:{h[e>>3]=+(d[b+7>>0]|0)*.00392156862745098;h[e+8>>3]=+(d[b+8>>0]|0)*.00392156862745098;h[e+16>>3]=+(d[b+9>>0]|0)*.00392156862745098;h[e+24>>3]=+(d[b+10>>0]|0)*.00392156862745098;b=0;break b}default:{b=0;break b}}}}while(0);l=F;return b|0}function UE(a,b,c,d,e,f){a=+a;b=+b;c=+c;d=d|0;e=e|0;f=f|0;var g=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0;i=bc?b:c;m=ma?a:i);g=i/m;if(m>0.0)if(g>0.0){j=(m-a)/i;k=(m-b)/i;l=(m-c)/i;do if(!(m==a)){if(m==b){a=j+2.0-l;break}if(m==c)a=k+4.0-j;else a=0.0}else a=(b-c)/i;while(0);a=a*60.0;if(a<0.0)a=a+360.0}else a=0.0;else{g=0.0;a=0.0}h[d>>3]=a*.002777777777777778;h[f>>3]=m;h[e>>3]=g;return}function VE(a,b,c,d,e,f,g){a=+a;b=+b;c=+c;d=d|0;e=e|0;f=f|0;g=g|0;h[d>>3]=1.0-a;h[e>>3]=1.0-b;h[f>>3]=1.0-c;b=+h[d>>3];c=+h[e>>3];c=b>3]=c;b=+h[f>>3];c=b>3]=c;h[d>>3]=+h[d>>3]-c;h[e>>3]=+h[e>>3]-+h[g>>3];h[f>>3]=+h[f>>3]-+h[g>>3];return}function WE(a,b,c,d,e,f){a=+a;b=+b;c=+c;d=d|0;e=e|0;f=f|0;var g=0.0,i=0.0,j=0.0,k=0,l=0;a:do if(!(b<=0.0)){i=!(a>=1.0)?a*6.0:0.0;l=~~i;i=i-+(l|0);a=(1.0-b)*c;j=(1.0-i*b)*c;b=(1.0-(1.0-i)*b)*c;switch(l|0){case 0:{g=a;i=b;a=c;k=8;break a}case 1:{g=a;i=c;a=j;k=8;break a}case 2:{g=b;i=c;k=8;break a}case 3:{g=c;i=j;k=8;break a}case 4:{g=c;i=a;a=b;k=8;break a}case 5:{g=j;i=a;a=c;k=8;break a}default:break a}}else{g=c;i=c;a=c;k=8}while(0);if((k|0)==8){h[d>>3]=a;h[e>>3]=i;h[f>>3]=g}return}function XE(b){b=b|0;var d=0,e=0;d=a[b>>0]|0;if(((d<<24>>24!=98?(e=b+1|0,!(d<<24>>24==119|(WJ(e,122058,4)|0)==0)):0)?!(d<<24>>24==108|(WJ(e,122063,4)|0)==0):0)?(WJ(e,122068,8)|0)!=0:0){do if(d<<24>>24==47){d=XJ(e,47)|0;if(!d)b=e;else{if((a[e>>0]|0)!=47){e=(qK(122077,e,4)|0)==0;b=e?d+1|0:b;break}d=c[42414]|0;if((d|0?a[d>>0]|0:0)?qK(122077,d,3)|0:0){b=ZE(d,b+2|0)|0;break}b=b+2|0}}else{d=c[42414]|0;if(((d|0)!=0?(a[d>>0]|0)!=0:0)?(qK(122077,d,3)|0)!=0:0)b=ZE(d,b)|0}while(0);b=SE(b)|0}return b|0}function YE(a,b){a=a|0;b=b|0;return jK(c[a>>2]|0,c[b>>2]|0)|0}function ZE(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;f=l;l=l+16|0;e=f;g=sJ(a)|0;g=(sJ(b)|0)+g|0;d=g+13|0;if((g+3|0)>>>0<(c[42415]|0)>>>0)d=c[42416]|0;else{c[42415]=d;d=zw(c[42416]|0,d)|0;c[42416]=d}c[e>>2]=a;c[e+4>>2]=b;qL(d,122082,e)|0;l=f;return c[42416]|0}function _E(a){a=a|0;c[42414]=a;return}function $E(a,b,c,d,e){a=a|0;b=+b;c=+c;d=+d;e=+e;var f=0,g=0;f=l;l=l+208|0;g=f;aF(g,+h[a>>3],+h[a+8>>3],b,c,d,e);a=bF(g)|0;l=f;return a|0}function aF(a,b,c,d,e,f,g){a=a|0;b=+b;c=+c;d=+d;e=+e;f=+f;g=+g;var i=0,j=0;h[a>>3]=b;h[a+8>>3]=c;j=a+16|0;h[j>>3]=d;i=a+24|0;h[i>>3]=e;h[a+32>>3]=0.0;c=+K(+(+F(+f)/e),+(+E(+f)/d));h[a+56>>3]=c;e=+K(+(+F(+g)/e),+(+E(+g)/d));h[a+40>>3]=1.0;h[a+48>>3]=0.0;e=e-+A(+((e-c)*.15915494309189535))*6.283185307179586;h[a+64>>3]=g-f>3.141592653589793&e-c<3.141592653589793?e+6.283185307179586:e;hF(a);iF(a);jF(a);g=+h[j>>3];g=(g-+h[i>>3])/g;h[a+168>>3]=g;h[a+176>>3]=(2.0-g)*g;g=1.0-g;h[a+184>>3]=g;h[a+192>>3]=g*g;return}function bF(a){a=a|0;var b=0,c=0.0,d=0,e=0.0,f=0.0,g=0.0,i=0.0,j=0,k=0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0;q=ww(8)|0;f=+h[a+56>>3];e=+h[a+64>>3]-f;p=1;b=0;while(1){o=e/+(p|0);if(!(b<<24>>24==0&(p|0)<1024))break;a:do if(!(o<=1.5707963267948966))b=0;else{c=f;d=0;b=1;while(1){if(!(b<<24>>24!=0&(d|0)<(p|0)))break a;n=c+o;b=+cF(a,c,n)<=1.0e-05&1;c=n;d=d+1|0}}while(0);p=p<<1}i=+E(+f);u=+F(+f);d=a+16|0;s=+h[d>>3];v=s*i;j=a+24|0;c=+h[j>>3];g=c*u;i=c*i;c=+h[a>>3];k=a+40|0;t=+h[k>>3];l=a+48|0;r=+h[l>>3];e=t*v+c-r*g;m=a+8|0;n=+h[m>>3];g=r*v+t*g+n;s=-(u*s);dF(q,c,n);eF(q,e,g);n=+G(+(o*.5));n=+F(+o)*.3333333333333333*(+C(+(n*n*3.0+4.0))+-1.0);c=f;f=g;g=r*s+t*i;i=t*s-r*i;b=0;while(1){if((b|0)>=(p|0))break;r=c+o;u=+E(+r);v=+F(+r);x=+h[d>>3];z=x*u;w=+h[j>>3];t=w*v;u=w*u;w=+h[k>>3];y=+h[l>>3];s=w*z+ +h[a>>3]-y*t;t=y*z+w*t+ +h[m>>3];x=-(v*x);v=w*x-y*u;u=y*x+w*u;fF(q,e+i*n,f+g*n,s-v*n,t-u*n,s,t);c=r;e=s;f=t;g=u;i=v;b=b+1|0}gF(q);return q|0}function cF(a,b,c){a=a|0;b=+b;c=+c;var d=0.0,e=0.0,f=0.0,g=0.0,i=0.0;d=c+b;i=+h[a+16>>3];e=+h[a+24>>3]/i;g=+E(+d);f=+E(+(d*2.0));d=+E(+(d*3.0));a=e<.25?10328:10584;return +(((e*.001+4.98)*e+.207)/(e+.0067)*i*+L(+(((+h[a+32>>3]*e+ +h[a+40>>3])*e+ +h[a+48>>3])/(+h[a+56>>3]+e)*g+((+h[a>>3]*e+ +h[a+8>>3])*e+ +h[a+16>>3])/(+h[a+24>>3]+e)+((+h[a+64>>3]*e+ +h[a+72>>3])*e+ +h[a+80>>3])/(+h[a+88>>3]+e)*f+((+h[a+96>>3]*e+ +h[a+104>>3])*e+ +h[a+112>>3])/(+h[a+120>>3]+e)*d+(((+h[a+160>>3]*e+ +h[a+168>>3])*e+ +h[a+176>>3])/(+h[a+184>>3]+e)*g+((+h[a+128>>3]*e+ +h[a+136>>3])*e+ +h[a+144>>3])/(+h[a+152>>3]+e)+((+h[a+192>>3]*e+ +h[a+200>>3])*e+ +h[a+208>>3])/(+h[a+216>>3]+e)*f+((+h[a+224>>3]*e+ +h[a+232>>3])*e+ +h[a+240>>3])/(+h[a+248>>3]+e)*d)*(c-b))))}function dF(a,b,d){a=a|0;b=+b;d=+d;var e=0;c[42417]=100;e=ww(1600)|0;c[a>>2]=e;h[e>>3]=b;h[e+8>>3]=d;c[a+4>>2]=1;return}function eF(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0;f=c[a>>2]|0;e=(c[a+4>>2]|0)+-1|0;fF(a,+h[f+(e<<4)>>3],+h[f+(e<<4)+8>>3],b,d,b,d);return}function fF(a,b,d,e,f,g,i){a=a|0;b=+b;d=+d;e=+e;f=+f;g=+g;i=+i;var j=0,k=0,l=0,m=0;l=a+4|0;j=c[l>>2]|0;k=c[42417]|0;if((j+3|0)<(k|0))a=c[a>>2]|0;else{c[42417]=k<<1;j=bJ(c[a>>2]|0,k<<5)|0;c[a>>2]=j;a=j;j=c[l>>2]|0}h[a+(j<<4)>>3]=b;m=j+1|0;h[a+(j<<4)+8>>3]=d;h[a+(m<<4)>>3]=e;k=j+2|0;h[a+(m<<4)+8>>3]=f;h[a+(k<<4)>>3]=g;c[l>>2]=j+3;h[a+(k<<4)+8>>3]=i;return}function gF(a){a=a|0;var b=0;b=c[a>>2]|0;eF(a,+h[b>>3],+h[b+8>>3]);c[a>>2]=bJ(c[a>>2]|0,c[a+4>>2]<<4)|0;c[42417]=0;return}function hF(a){a=a|0;var b=0.0,c=0.0,d=0.0,e=0.0;d=+h[a+16>>3];b=+h[a+24>>3];b=+C(+(d*d-b*b));d=b*+h[a+40>>3];b=b*+h[a+48>>3];e=+h[a>>3];h[a+104>>3]=e-d;c=+h[a+8>>3];h[a+112>>3]=c-b;h[a+120>>3]=e+d;h[a+128>>3]=c+b;return}function iF(a){a=a|0;var b=0.0,c=0.0,d=0.0,e=0.0,f=0.0,g=0.0,i=0.0,j=0.0;d=+h[a+16>>3];i=+h[a+56>>3];j=+E(+i)*d;b=+h[a+24>>3];i=+F(+i)*b;g=+h[a+64>>3];d=+E(+g)*d;b=+F(+g)*b;g=+h[a>>3];c=+h[a+40>>3];e=+h[a+48>>3];h[a+72>>3]=c*j+g-e*i;f=+h[a+8>>3];h[a+80>>3]=e*j+f+c*i;h[a+88>>3]=g+c*d-e*b;h[a+96>>3]=f+e*d+c*b;return}function jF(a){a=a|0;var b=0.0,c=0.0,d=0.0,e=0.0,f=0.0,g=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0;k=+h[a+24>>3];l=+h[a+16>>3];e=k/l;m=+h[a+48>>3];n=+B(+m)<.1;j=+h[a+40>>3];do if(n){b=m/j;c=+J(+(b*e));d=-c;if(j<0.0){b=+J(+(b/e));e=d;d=3.141592653589793-c;c=4.71238898038469-b;b=1.5707963267948966-b;break}else{b=+J(+(b/e));e=-3.141592653589793-c;c=1.5707963267948966-b;b=-1.5707963267948966-b;break}}else{b=j/m;c=+J(+(b/e));d=c+1.5707963267948966;if(m<0.0){b=+J(+(b*e));e=c+-1.5707963267948966;c=b+3.141592653589793;break}else{b=+J(+(b*e));e=d;d=c+4.71238898038469;c=b;b=b+-3.141592653589793;break}}while(0);g=+h[a+56>>3];e=e-+A(+((e-g)*.15915494309189535))*6.283185307179586;b=b-+A(+((b-g)*.15915494309189535))*6.283185307179586;f=d-+A(+((d-g)*.15915494309189535))*6.283185307179586;g=c-+A(+((c-g)*.15915494309189535))*6.283185307179586;i=+h[a+64>>3];if(!(e<=i)){e=+h[a+72>>3];c=+h[a+88>>3];c=e>3]-k*+F(+e)*m;h[a+136>>3]=c;if(!(b<=i)){e=+h[a+80>>3];d=+h[a+96>>3];d=e>3]+ +F(+b)*k*j;h[a+144>>3]=d;if(!(f<=i)){f=+h[a+72>>3];b=+h[a+88>>3];b=f>b?f:b}else b=+E(+f)*l*j+ +h[a>>3]-k*+F(+f)*m;h[a+152>>3]=b-c;if(!(g<=i)){m=+h[a+80>>3];b=+h[a+96>>3];b=m>b?m:b}else b=+E(+g)*l*m+ +h[a+8>>3]+ +F(+g)*k*j;h[a+160>>3]=b-d;return}function kF(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0,j=0,k=0.0,m=0,n=0;n=l;l=l+80|0;m=n;lF(b);k=+h[e+56>>3];g=+h[e+64>>3];switch(a[e+80>>0]|0){case 116:{g=(+h[e+48>>3]-+mF(d))*.5+g;f=4;break}case 98:{g=g-(+h[e+48>>3]-+mF(d))*.5;f=4;break}default:{}}if((f|0)==4)g=g+-1.0;h[m>>3]=k;h[m+8>>3]=g;c[m+20>>2]=c[e+8>>2];c[m+16>>2]=c[e+4>>2];h[m+32>>3]=+h[e+16>>3];j=b+16|0;f=Jm(c[(c[j>>2]|0)+8>>2]|0,122089)|0;e=m+56|0;c[e>>2]=f;i=m+60|0;c[i>>2]=c[(c[j>>2]|0)+212>>2];j=m+64|0;a[j>>0]=0;if(!((f|0)!=0?(a[f>>0]|0)!=0:0))c[e>>2]=122100;if((a[d+4>>0]|0)==1){e=c[d>>2]|0;GD(b,c[(c[b>>2]|0)+336>>2]|0);f=c[e+24>>2]|0;if(!f)CD(b,122106);else CD(b,f);oF(b,e,m);if(a[j>>0]|0)$I(c[i>>2]|0)}else nF(b,c[d>>2]|0,m);pF(b);l=n;return}function lF(a){a=a|0;var d=0,e=0,f=0;d=Wt(a)|0;e=c[d>>2]|0;a=c[e+4>>2]|0;c[d+4>>2]=a;c[d+12>>2]=c[e+12>>2];switch(a|0){case 2:{a=e+8|0;f=6;break}case 0:{a=e+8|0;f=6;break}case 1:{a=e+8|0;f=6;break}case 3:{a=e+8|0;f=6;break}default:{}}if((f|0)==6)c[d+8>>2]=c[a>>2];c[d+208>>2]=c[e+208>>2];c[d+228>>2]=c[e+228>>2];c[d+244>>2]=c[e+244>>2];f=d+260|0;b[f>>1]=b[f>>1]&-2|b[e+260>>1]&1;return}function mF(b){b=b|0;var d=0.0,e=0,f=0;switch(a[b+4>>0]|0){case 1:{e=c[b>>2]|0;b=e+72|0;e=e+56|0;f=5;break}case 3:{e=c[b>>2]|0;b=e+24|0;e=e+8|0;f=5;break}case 2:{e=c[b>>2]|0;b=e+32|0;e=e+16|0;f=5;break}default:d=0.0}if((f|0)==5)d=+h[b>>3]-+h[e>>3];return +d}function nF(d,e,f){d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0.0,p=0.0,q=0,r=0,s=0;n=l;l=l+96|0;j=n+64|0;i=n+32|0;g=n+16|0;k=n;m=b[e+4>>1]|0;if(m<<16>>16>=1){r=e+8|0;p=+h[e+24>>3];o=+h[r>>3];h[k>>3]=(o+p)*.5+ +h[f>>3];h[k+8>>3]=(+h[e+16>>3]+ +h[e+32>>3])*.5+ +h[f+8>>3];q=c[e>>2]|0;s=f+16|0;f=a[e+6>>0]|0;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[g+8>>2]=c[k+8>>2];c[g+12>>2]=c[k+12>>2];c[i>>2]=c[s>>2];c[i+4>>2]=c[s+4>>2];c[i+8>>2]=c[s+8>>2];c[i+12>>2]=c[s+12>>2];c[i+16>>2]=c[s+16>>2];c[i+20>>2]=c[s+20>>2];c[i+24>>2]=c[s+24>>2];c[i+28>>2]=c[s+28>>2];c[j>>2]=c[r>>2];c[j+4>>2]=c[r+4>>2];c[j+8>>2]=c[r+8>>2];c[j+12>>2]=c[r+12>>2];c[j+16>>2]=c[r+16>>2];c[j+20>>2]=c[r+20>>2];c[j+24>>2]=c[r+24>>2];c[j+28>>2]=c[r+28>>2];BF(d,m<<16>>16,q,g,(p-o)*.5,i,j,f)}l=n;return}function oF(e,f,g){e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0.0,n=0.0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;y=l;l=l+176|0;t=y+96|0;v=y+64|0;w=y+136|0;p=y;q=y+128|0;r=f+48|0;c[v>>2]=c[r>>2];c[v+4>>2]=c[r+4>>2];c[v+8>>2]=c[r+8>>2];c[v+12>>2]=c[r+12>>2];c[v+16>>2]=c[r+16>>2];c[v+20>>2]=c[r+20>>2];c[v+24>>2]=c[r+24>>2];c[v+28>>2]=c[r+28>>2];m=+h[g>>3];n=+h[g+8>>3];r=f+84|0;i=c[r>>2]|0;if(!(c[f>>2]|0))x=(c[f+8>>2]|0)!=0;else x=1;u=f+108|0;j=c[u>>2]|0;if(j|0)qF(g,j,167296);h[v>>3]=+h[v>>3]+m;s=v+16|0;h[s>>3]=+h[s>>3]+m;s=v+8|0;h[s>>3]=+h[s>>3]+n;s=v+24|0;h[s>>3]=+h[s>>3]+n;if(x?(c[e+152>>2]&4|0)==0:0){c[t>>2]=c[v>>2];c[t+4>>2]=c[v+4>>2];c[t+8>>2]=c[v+8>>2];c[t+12>>2]=c[v+12>>2];c[t+16>>2]=c[v+16>>2];c[t+20>>2]=c[v+20>>2];c[t+24>>2]=c[v+24>>2];c[t+28>>2]=c[v+28>>2];s=rF(e,g,f,t,w)|0}else s=0;o=f+42|0;j=b[o>>1]|0;if(!(j&32)){k=c[f+20>>2]|0;if(k){j=sF(e,k,c[f+28>>2]|0,j&65535,q)|0;if(!(b[o>>1]&4)){c[t>>2]=c[v>>2];c[t+4>>2]=c[v+4>>2];c[t+8>>2]=c[v+8>>2];c[t+12>>2]=c[v+12>>2];c[t+16>>2]=c[v+16>>2];c[t+20>>2]=c[v+20>>2];c[t+24>>2]=c[v+24>>2];c[t+28>>2]=c[v+28>>2];JD(e,t,j)}else{o=d[f+33>>0]|0;c[t>>2]=c[v>>2];c[t+4>>2]=c[v+4>>2];c[t+8>>2]=c[v+8>>2];c[t+12>>2]=c[v+12>>2];c[t+16>>2]=c[v+16>>2];c[t+20>>2]=c[v+20>>2];c[t+24>>2]=c[v+24>>2];c[t+28>>2]=c[v+28>>2];zy(e,tF(p,t,o)|0,4,4,j)}$I(c[q>>2]|0)}while(1){j=c[i>>2]|0;if(!j)break;uF(e,j,g);i=i+4|0}i=c[r>>2]|0;PD(e,1.0);j=f+24|0;while(1){k=i+4|0;i=c[i>>2]|0;if(!i)break;if(!(a[i+100>>0]|0)){i=k;continue}vF(e,i,g,c[j>>2]|0,c[k>>2]|0);i=k}if(a[f+33>>0]|0){c[t>>2]=c[v>>2];c[t+4>>2]=c[v+4>>2];c[t+8>>2]=c[v+8>>2];c[t+12>>2]=c[v+12>>2];c[t+16>>2]=c[v+16>>2];c[t+20>>2]=c[v+20>>2];c[t+24>>2]=c[v+24>>2];c[t+28>>2]=c[v+28>>2];wF(e,f,t)}}if(s|0)xF(e,w);if((x?c[e+152>>2]&4|0:0)?(c[t>>2]=c[v>>2],c[t+4>>2]=c[v+4>>2],c[t+8>>2]=c[v+8>>2],c[t+12>>2]=c[v+12>>2],c[t+16>>2]=c[v+16>>2],c[t+20>>2]=c[v+20>>2],c[t+24>>2]=c[v+24>>2],c[t+28>>2]=c[v+28>>2],rF(e,g,f,t,w)|0):0)xF(e,w);if(c[u>>2]|0)yF(g,167296);l=y;return}function pF(a){a=a|0;var b=0;b=c[a+16>>2]|0;c[b+208>>2]=0;c[b+228>>2]=0;c[b+244>>2]=0;c[b+212>>2]=0;Xt(a);return}function qF(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0,g=0,i=0;i=a+16|0;f=c[i>>2]|0;if(f|0){if(!(c[b>>2]|0)){f=0;g=d}else{c[d>>2]=f;f=c[b>>2]|0;g=i}c[g>>2]=f}f=c[a+20>>2]|0;if(f|0){g=b+4|0;if(!(c[g>>2]|0)){f=0;g=d}else{c[d+4>>2]=f;f=c[g>>2]|0;g=i}c[g+4>>2]=f}e=+h[a+32>>3];if(e>=0.0){f=b+16|0;if(!(+h[f>>3]>=0.0))e=-1.0;else{h[d+16>>3]=e;e=+h[f>>3];d=i}h[d+16>>3]=e}return}function rF(d,e,f,g,h){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+224|0;n=u+8|0;k=u;t=u+40|0;j=u+184|0;i=u+56|0;m=c[d+16>>2]|0;o=m+208|0;c[h>>2]=c[o>>2];p=m+228|0;c[h+4>>2]=c[p>>2];q=m+244|0;c[h+8>>2]=c[q>>2];r=m+212|0;c[h+12>>2]=c[r>>2];s=m+260|0;a[h+16>>0]=(b[s>>1]<<15&65535)<<16>>16>>15;h=c[f+16>>2]|0;if((h|0)!=0?(a[h>>0]|0)!=0:0)i=0;else{dm(t,128,i);i=e+60|0;h=c[i>>2]|0;if(!h){h=HL(Zt(d,c[m+8>>2]|0,t)|0)|0;c[i>>2]=h;a[e+64>>0]=1}gm(t,h)|0;i=c[42418]|0;c[42418]=i+1;c[k>>2]=i;qL(j,122183,k)|0;gm(t,j)|0;i=t+4|0;h=c[i>>2]|0;if(h>>>0>=(c[t+8>>2]|0)>>>0){em(t,1)|0;h=c[i>>2]|0}a[h>>0]=0;h=c[t>>2]|0;c[i>>2]=h;i=1}h=Yt(d,0,c[f>>2]|0,c[f+12>>2]|0,c[f+8>>2]|0,h,c[m+8>>2]|0)|0;if(i)hm(t);do if(h|0){if((c[o>>2]|0)==0?(b[s>>1]&1)==0:0)break;c[n>>2]=c[g>>2];c[n+4>>2]=c[g+4>>2];c[n+8>>2]=c[g+8>>2];c[n+12>>2]=c[g+12>>2];c[n+16>>2]=c[g+16>>2];c[n+20>>2]=c[g+20>>2];c[n+24>>2]=c[g+24>>2];c[n+28>>2]=c[g+28>>2];eu(d,n);xD(d,c[o>>2]|0,c[p>>2]|0,c[q>>2]|0,c[r>>2]|0)}while(0);l=u;return h|0}function sF(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var h=0.0,i=0,j=0;j=l;l=l+16|0;i=j;if(!((yv(b,f,i)|0)<<24>>24)){ED(a,b);b=1}else{ED(a,c[f>>2]|0);b=c[f+4>>2]|0;h=+g[i>>2];if(!b)FD(a,122106,d,h);else FD(a,b,d,h);b=e>>>1&1|2}CD(a,122171);l=j;return b|0}function tF(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0.0,g=0.0,i=0.0,j=0.0;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];e=a+32|0;b=b+16|0;c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];c[e+8>>2]=c[b+8>>2];c[e+12>>2]=c[b+12>>2];if((d|0)>1){j=+(d|0)*.5;i=+h[a>>3]+j;h[a>>3]=i;d=a+8|0;g=+h[d>>3]+j;h[d>>3]=g;f=+h[e>>3]-j;h[e>>3]=f;e=a+40|0;j=+h[e>>3]-j;h[e>>3]=j}else{f=+h[e>>3];g=+h[a+8>>3];i=+h[a>>3];j=+h[a+40>>3]}h[a+16>>3]=f;h[a+24>>3]=g;h[a+48>>3]=i;h[a+56>>3]=j;return a|0}function uF(e,f,g){e=e|0;f=f|0;g=g|0;var i=0,j=0.0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;v=l;l=l+176|0;r=v+96|0;s=v+136|0;t=v+64|0;p=v;q=v+128|0;u=f+48|0;c[t>>2]=c[u>>2];c[t+4>>2]=c[u+4>>2];c[t+8>>2]=c[u+8>>2];c[t+12>>2]=c[u+12>>2];c[t+16>>2]=c[u+16>>2];c[t+20>>2]=c[u+20>>2];c[t+24>>2]=c[u+24>>2];c[t+28>>2]=c[u+28>>2];j=+h[g>>3];k=+h[g+8>>3];if(!(c[f>>2]|0))u=(c[f+8>>2]|0)!=0;else u=1;h[t>>3]=+h[t>>3]+j;o=t+16|0;h[o>>3]=+h[o>>3]+j;o=t+8|0;h[o>>3]=+h[o>>3]+k;o=t+24|0;h[o>>3]=+h[o>>3]+k;if(u?(c[e+152>>2]&4|0)==0:0){c[r>>2]=c[t>>2];c[r+4>>2]=c[t+4>>2];c[r+8>>2]=c[t+8>>2];c[r+12>>2]=c[t+12>>2];c[r+16>>2]=c[t+16>>2];c[r+20>>2]=c[t+20>>2];c[r+24>>2]=c[t+24>>2];c[r+28>>2]=c[t+28>>2];o=rF(e,g,f,r,s)|0}else o=0;n=f+42|0;i=b[n>>1]|0;a:do if(!(i&32)){m=c[f+20>>2]|0;if(m|0){i=sF(e,m,c[f+28>>2]|0,i&65535,q)|0;if(!(b[n>>1]&4)){c[r>>2]=c[t>>2];c[r+4>>2]=c[t+4>>2];c[r+8>>2]=c[t+8>>2];c[r+12>>2]=c[t+12>>2];c[r+16>>2]=c[t+16>>2];c[r+20>>2]=c[t+20>>2];c[r+24>>2]=c[t+24>>2];c[r+28>>2]=c[t+28>>2];JD(e,r,i)}else{n=d[f+33>>0]|0;c[r>>2]=c[t>>2];c[r+4>>2]=c[t+4>>2];c[r+8>>2]=c[t+8>>2];c[r+12>>2]=c[t+12>>2];c[r+16>>2]=c[t+16>>2];c[r+20>>2]=c[t+20>>2];c[r+24>>2]=c[t+24>>2];c[r+28>>2]=c[t+28>>2];zy(e,tF(p,r,n)|0,4,4,i)}$I(c[q>>2]|0)}if(a[f+33>>0]|0){c[r>>2]=c[t>>2];c[r+4>>2]=c[t+4>>2];c[r+8>>2]=c[t+8>>2];c[r+12>>2]=c[t+12>>2];c[r+16>>2]=c[t+16>>2];c[r+20>>2]=c[t+20>>2];c[r+24>>2]=c[t+24>>2];c[r+28>>2]=c[t+28>>2];wF(e,f,r)}i=f+88|0;switch(a[f+92>>0]|0){case 1:{oF(e,c[i>>2]|0,g);break a}case 3:{AF(e,c[i>>2]|0,g);break a}default:{nF(e,c[i>>2]|0,g);break a}}}while(0);if(o|0)xF(e,s);if((u?c[e+152>>2]&4|0:0)?(c[r>>2]=c[t>>2],c[r+4>>2]=c[t+4>>2],c[r+8>>2]=c[t+8>>2],c[r+12>>2]=c[t+12>>2],c[r+16>>2]=c[t+16>>2],c[r+20>>2]=c[t+20>>2],c[r+24>>2]=c[t+24>>2],c[r+28>>2]=c[t+28>>2],rF(e,g,f,r,s)|0):0)xF(e,s);l=v;return}function vF(f,g,i,j,k){f=f|0;g=g|0;i=i|0;j=j|0;k=k|0;var m=0.0,n=0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0.0,y=0,z=0,A=0,B=0,C=0;A=l;l=l+32|0;y=A+16|0;z=A;r=+h[i>>3];x=+h[i+8>>3];q=(j|0)==0?122106:j;ED(f,q);CD(f,q);t=+h[g+48>>3];o=+h[g+56>>3];u=+h[g+64>>3];p=+h[g+72>>3];s=t+r;r=u+r;x=o+x;q=g+100|0;i=a[q>>0]|0;if((i&1)!=0?(n=c[g+96>>2]|0,((e[g+80>>1]|0)+(e[g+84>>1]|0)|0)<(c[n+104>>2]|0)):0){i=b[g+86>>1]|0;do if(i<<16>>16)if(((e[g+82>>1]|0)+(i&65535)|0)==(c[n+100>>2]|0)){B=a[n+32>>0]|0;C=(B<<24>>24)/2|0;j=(C<<24>>24)+(d[n+33>>0]|0)|0;i=j;j=j&255;m=x-+(C<<24>>24);n=B;break}else{n=a[n+32>>0]|0;i=0;j=((n<<24>>24)/2|0)<<24>>24;m=x;break}else{C=a[n+32>>0]|0;j=((C<<24>>24)/2|0)<<24>>24;i=j+(d[n+33>>0]|0)|0;m=x;n=C}while(0);h[z+8>>3]=m-+(j|0);h[z>>3]=r+ +(((n<<24>>24)/2|0)<<24>>24);c[y>>2]=c[z>>2];c[y+4>>2]=c[z+4>>2];c[y+8>>2]=c[z+8>>2];c[y+12>>2]=c[z+12>>2];zF(f,y,0.0,p-o+ +(i&255|0)+ +(n<<24>>24));i=a[q>>0]|0}if(i&2?(v=b[g+86>>1]|0,w=c[g+96>>2]|0,((e[g+82>>1]|0)+(v&65535)|0)<(c[w+100>>2]|0)):0){i=b[g+84>>1]|0;do if(!(i<<16>>16)){i=a[w+32>>0]|0;C=(i<<24>>24)/2|0;n=(C<<24>>24)+(d[w+33>>0]|0)|0;j=n&255;n=n&255;m=+(C<<24>>24);h[z>>3]=s-m-+(n|0);if((c[w+104>>2]|0)==(e[g+80>>1]|0)){j=n<<1&255;break}if((k|0)!=0?(b[k+86>>1]|0)!=v<<16>>16:0)j=~~(+(j&255)-u+ +h[w+64>>3]-m)&255}else{if(((e[g+80>>1]|0)+(i&65535)|0)==(c[w+104>>2]|0)){i=a[w+32>>0]|0;C=(i<<24>>24)/2|0;j=(C&255)+(d[w+33>>0]|0)&255;h[z>>3]=s-+(C<<24>>24);break}i=a[w+32>>0]|0;m=+(((i<<24>>24)/2|0)<<24>>24);h[z>>3]=s-m;if((k|0)!=0?(b[k+86>>1]|0)!=v<<16>>16:0)j=~~(+h[w+64>>3]-u-m)&255;else j=0}while(0);h[z+8>>3]=x-+(((i<<24>>24)/2|0)<<24>>24);c[y>>2]=c[z>>2];c[y+4>>2]=c[z+4>>2];c[y+8>>2]=c[z+8>>2];c[y+12>>2]=c[z+12>>2];zF(f,y,u-t+ +(j&255)+ +(i<<24>>24),0.0)}l=A;return}function wF(e,f,g){e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0.0;p=l;l=l+160|0;o=p+112|0;n=p;j=p+144|0;m=c[f+24>>2]|0;CD(e,(m|0)==0?122106:m);m=f+42|0;i=b[m>>1]|0;if(!(i&384))GD(e,c[(c[e>>2]|0)+336>>2]|0);else{c[j+4>>2]=0;c[j>>2]=0;i=i&65535;if(!(i&256)){if(i&128|0){i=122112;k=4}}else{i=122119;k=4}if((k|0)==4)c[j>>2]=i;GD(e,j)}k=f+33|0;PD(e,+(d[k>>0]|0));a:do if(!(b[m>>1]&4)){i=b[f+36>>1]&15360;if(!(i<<16>>16)){i=a[k>>0]|0;if((i&255)>1){q=+(i&255)*.5;h[g>>3]=+h[g>>3]+q;n=g+8|0;h[n>>3]=+h[n>>3]+q;n=g+16|0;h[n>>3]=+h[n>>3]-q;n=g+24|0;h[n>>3]=+h[n>>3]-q};c[o>>2]=c[g>>2];c[o+4>>2]=c[g+4>>2];c[o+8>>2]=c[g+8>>2];c[o+12>>2]=c[g+12>>2];c[o+16>>2]=c[g+16>>2];c[o+20>>2]=c[g+20>>2];c[o+24>>2]=c[g+24>>2];c[o+28>>2]=c[g+28>>2];JD(e,o,0);break}j=n+16|0;m=d[k>>0]|0;c[o>>2]=c[g>>2];c[o+4>>2]=c[g+4>>2];c[o+8>>2]=c[g+8>>2];c[o+12>>2]=c[g+12>>2];c[o+16>>2]=c[g+16>>2];c[o+20>>2]=c[g+20>>2];c[o+24>>2]=c[g+24>>2];c[o+28>>2]=c[g+28>>2];tF(j,o,m)|0;do switch(((i&65535)+-1024|0)>>>10&4194303|0){case 7:{LD(e,j,2);break a}case 3:{LD(e,n+32|0,2);break a}case 1:{LD(e,n+48|0,2);break a}case 0:{g=n+64|0;c[n>>2]=c[g>>2];c[n+4>>2]=c[g+4>>2];c[n+8>>2]=c[g+8>>2];c[n+12>>2]=c[g+12>>2];LD(e,n,2);break a}case 11:{LD(e,j,3);break a}case 5:{LD(e,n+32|0,3);break a}case 2:{g=n+80|0;c[g>>2]=c[j>>2];c[g+4>>2]=c[j+4>>2];c[g+8>>2]=c[j+8>>2];c[g+12>>2]=c[j+12>>2];LD(e,n+48|0,3);break a}case 8:{g=n+64|0;c[n>>2]=c[g>>2];c[n+4>>2]=c[g+4>>2];c[n+8>>2]=c[g+8>>2];c[n+12>>2]=c[g+12>>2];LD(e,n,3);break a}case 13:{LD(e,j,4);break a}case 6:{g=n+80|0;c[g>>2]=c[j>>2];c[g+4>>2]=c[j+4>>2];c[g+8>>2]=c[j+8>>2];c[g+12>>2]=c[j+12>>2];LD(e,n+32|0,4);break a}case 10:{g=n+80|0;c[g>>2]=c[j>>2];c[g+4>>2]=c[j+4>>2];c[g+8>>2]=c[j+8>>2];c[g+12>>2]=c[j+12>>2];g=n+96|0;o=n+32|0;c[g>>2]=c[o>>2];c[g+4>>2]=c[o+4>>2];c[g+8>>2]=c[o+8>>2];c[g+12>>2]=c[o+12>>2];LD(e,n+48|0,4);break a}case 12:{g=n+64|0;c[n>>2]=c[g>>2];c[n+4>>2]=c[g+4>>2];c[n+8>>2]=c[g+8>>2];c[n+12>>2]=c[g+12>>2];LD(e,n,4);break a}case 9:{LD(e,j,2);LD(e,n+48|0,2);break a}case 4:{g=n+64|0;c[n>>2]=c[g>>2];c[n+4>>2]=c[g+4>>2];c[n+8>>2]=c[g+8>>2];c[n+12>>2]=c[g+12>>2];LD(e,n,2);LD(e,n+32|0,2);break a}default:break a}while(0)}else{m=d[k>>0]|0;c[o>>2]=c[g>>2];c[o+4>>2]=c[g+4>>2];c[o+8>>2]=c[g+8>>2];c[o+12>>2]=c[g+12>>2];c[o+16>>2]=c[g+16>>2];c[o+20>>2]=c[g+20>>2];c[o+24>>2]=c[g+24>>2];c[o+28>>2]=c[g+28>>2];zy(e,tF(n,o,m)|0,4,4,0)}while(0);l=p;return}function xF(d,e){d=d|0;e=e|0;var f=0,g=0,h=0;h=c[d+16>>2]|0;f=h+208|0;if((c[f>>2]|0)==0?(b[h+260>>1]&1)==0:0)d=0;else{yD(d);d=c[f>>2]|0}if((d|0)!=(c[e>>2]|0)){$I(d);c[f>>2]=c[e>>2]}d=h+228|0;f=c[d>>2]|0;g=e+4|0;if((f|0)!=(c[g>>2]|0)){$I(f);c[d>>2]=c[g>>2]}d=h+244|0;f=c[d>>2]|0;g=e+8|0;if((f|0)!=(c[g>>2]|0)){$I(f);c[d>>2]=c[g>>2]}d=h+212|0;f=c[d>>2]|0;g=e+12|0;if((f|0)!=(c[g>>2]|0)){$I(f);c[d>>2]=c[g>>2]}h=h+260|0;b[h>>1]=b[h>>1]&-2|a[e+16>>0]&1;return}function yF(a,b){a=a|0;b=b|0;var d=0.0,e=0;e=c[b>>2]|0;if(e|0)c[a+16>>2]=e;e=c[b+4>>2]|0;if(e|0)c[a+20>>2]=e;d=+h[b+16>>3];if(d>=0.0)h[a+32>>3]=d;return}function zF(a,b,d,e){a=a|0;b=b|0;d=+d;e=+e;var f=0,g=0,i=0;f=l;l=l+64|0;g=f+32|0;i=f;c[i>>2]=c[b>>2];c[i+4>>2]=c[b+4>>2];c[i+8>>2]=c[b+8>>2];c[i+12>>2]=c[b+12>>2];h[i+16>>3]=+h[b>>3]+d;h[i+24>>3]=+h[b+8>>3]+e;c[g>>2]=c[i>>2];c[g+4>>2]=c[i+4>>2];c[g+8>>2]=c[i+8>>2];c[g+12>>2]=c[i+12>>2];c[g+16>>2]=c[i+16>>2];c[g+20>>2]=c[i+20>>2];c[g+24>>2]=c[i+24>>2];c[g+28>>2]=c[i+28>>2];JD(a,g,1);l=f;return}function AF(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0.0,k=0.0,m=0.0,n=0.0;i=l;l=l+64|0;g=i;k=+h[e>>3];n=k+ +h[d>>3];m=+h[e+8>>3];j=m+ +h[d+8>>3];k=k+ +h[d+16>>3];m=m+ +h[d+24>>3];h[g>>3]=k;h[g+8>>3]=m;h[g+32>>3]=n;h[g+40>>3]=j;h[g+16>>3]=n;h[g+24>>3]=m;h[g+48>>3]=k;h[g+56>>3]=j;f=c[d+36>>2]|0;if(!f)f=c[e+56>>2]|0;e=c[d+32>>2]|0;if(!e)ma(122126,122134,623,122146);if(!(a[e>>0]|0))ma(122160,122134,624,122146);else{ND(b,e,g,4,1,f);l=i;return}}function BF(d,e,f,g,i,j,k,m){d=d|0;e=e|0;f=f|0;g=g|0;i=+i;j=j|0;k=k|0;m=m|0;var n=0.0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0.0,J=0,K=0,L=0,M=0.0,N=0.0,O=0,P=0,Q=0,R=0;R=l;l=l+128|0;K=R+104|0;O=R+48|0;P=R+16|0;L=R;J=L;c[J>>2]=0;c[J+4>>2]=0;M=+h[g>>3];N=M-i;I=M+i;J=L+8|0;h[J>>3]=(+h[k+24>>3]-+h[k+8>>3])*.5+ +h[g+8>>3];zD(d,1);D=P+16|0;E=P+4|0;F=P+24|0;G=O+4|0;H=O+16|0;s=(m|0)==0;t=O+24|0;u=O+8|0;v=O+32|0;w=O+40|0;x=O+48|0;y=j+16|0;z=j+4|0;A=P+8|0;q=0;while(1){if((q|0)>=(e|0))break;switch(a[f+(q*24|0)+6>>0]|0){case 108:{i=N;break}case 114:{i=I-+h[f+(q*24|0)+8>>3];break}default:i=M-+h[f+(q*24|0)+8>>3]*.5}h[g>>3]=i;B=f+(q*24|0)+16|0;h[J>>3]=+h[J>>3]-+h[B>>3];C=f+(q*24|0)+4|0;p=c[f+(q*24|0)>>2]|0;r=0;while(1){if((r|0)>=(b[C>>1]|0))break;o=p+4|0;m=c[o>>2]|0;if(m){h[D>>3]=+h[(+h[m+16>>3]>0.0?m:j)+16>>3];c[P>>2]=c[((c[m>>2]|0)==0?j:m)>>2];k=c[((c[m+4>>2]|0)==0?j:m)+4>>2]|0;c[E>>2]=k;m=c[m+24>>2]&127;if(!m)Q=12;else m=c[F>>2]&-128|m}else{h[D>>3]=+h[y>>3];c[P>>2]=c[j>>2];k=c[z>>2]|0;c[E>>2]=k;Q=12}if((Q|0)==12){Q=0;m=c[F>>2]&-128}c[F>>2]=m;CD(d,k);c[O>>2]=c[p>>2];c[G>>2]=P;h[H>>3]=+h[p+16>>3];if(s)n=1.0;else n=+h[p+24>>3];h[t>>3]=n;c[A>>2]=c[(c[o>>2]|0)+8>>2];c[u>>2]=c[p+8>>2];o=p+32|0;h[v>>3]=+h[o>>3];h[w>>3]=+h[B>>3];a[x>>0]=108;h[L>>3]=i;c[K>>2]=c[L>>2];c[K+4>>2]=c[L+4>>2];c[K+8>>2]=c[L+8>>2];c[K+12>>2]=c[L+12>>2];BD(d,K,O);n=+h[o>>3]+i;h[g>>3]=n;p=p+56|0;r=r+1|0;i=n}q=q+1|0}AD(d);l=R;return}function CF(a){a=a|0;$I(c[a>>2]|0);$I(c[a+4>>2]|0);$I(c[a+8>>2]|0);$I(c[a+16>>2]|0);$I(c[a+12>>2]|0);$I(c[a+20>>2]|0);$I(c[a+24>>2]|0);return}function DF(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;if(a|0){j=a+4|0;e=0;g=c[a>>2]|0;while(1){if((e|0)>=(b[j>>1]|0))break;k=g+4|0;d=0;f=c[g>>2]|0;while(1){if((d|0)>=(b[k>>1]|0))break;$I(c[f>>2]|0);h=c[f+8>>2]|0;if(h|0?(i=c[f+12>>2]|0,i|0):0)gb[i&127](h);d=d+1|0;f=f+56|0}e=e+1|0;g=g+24|0}d=c[a>>2]|0;if(d|0)$I(d);$I(a)}return}function EF(a){a=a|0;$I(c[a+32>>2]|0);$I(a);return}function FF(b,d){b=b|0;d=d|0;switch(a[b+4>>0]|0){case 1:{GF(c[b>>2]|0);break}case 3:{EF(c[b>>2]|0);break}default:DF(c[b>>2]|0)}if(d|0)$I(b);return}function GF(a){a=a|0;var b=0,d=0,e=0;e=a+84|0;if((c[a+100>>2]|0)==-1)Ll(c[e>>2]|0)|0;else{b=c[e>>2]|0;$I(c[a+92>>2]|0);$I(c[a+96>>2]|0);while(1){d=c[b>>2]|0;if(!d)break;HF(d);b=b+4|0}$I(c[e>>2]|0)}CF(a);$I(a);return}function HF(a){a=a|0;FF(a+88|0,0);CF(a);$I(a);return}function IF(b,e,f){b=b|0;e=e|0;f=f|0;var g=0;b=c[(c[(c[b+16>>2]|0)+104>>2]|0)+72>>2]|0;if((a[b+4>>0]|0)!=2?(g=JF(c[b>>2]|0,e)|0,(g|0)!=0):0){c[f>>2]=d[g+35>>0];b=g+48|0}else b=0;return b|0}function JF(a,b){a=a|0;b=b|0;var d=0,e=0;d=c[a+4>>2]|0;if(!((d|0)!=0?(jK(d,b)|0)==0:0))e=3;a:do if((e|0)==3){d=c[a+84>>2]|0;while(1){a=c[d>>2]|0;if(!a){a=0;break a}a=KF(a,b)|0;if(!a)d=d+4|0;else break}}while(0);return a|0}function KF(b,d){b=b|0;d=d|0;var e=0;e=c[b+4>>2]|0;if(!((e|0)!=0?(jK(e,d)|0)==0:0))if((a[b+92>>0]|0)==1)b=JF(c[b+88>>2]|0,d)|0;else b=0;return b|0}function LF(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return 0}function MF(d){d=d|0;var f=0.0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;p=d+92|0;c[p>>2]=ww((c[d+100>>2]<<2)+4|0)|0;n=ww((c[d+104>>2]<<2)+4|0)|0;c[d+96>>2]=n;o=d+32|0;m=c[d+84>>2]|0;while(1){l=c[m>>2]|0;if(!l)break;d=b[l+82>>1]|0;f=+h[l+72>>3];if(d<<16>>16==1)i=~~f;else{i=~~((f-+(O((a[o>>0]|0)+-1|0,(d&65535)+-1|0)|0))/+(d&65535));i=(i|0)>1?i:1}j=b[l+80>>1]|0;f=+h[l+64>>3];if(j<<16>>16==1)k=~~f;else{k=~~((f-+(O((a[o>>0]|0)+-1|0,(j&65535)+-1|0)|0))/+(j&65535));k=(k|0)>1?k:1}q=e[l+86>>1]|0;g=(d&65535)+q|0;d=q;while(1){if((d|0)>=(g|0))break;q=(c[p>>2]|0)+(d<<2)|0;r=c[q>>2]|0;c[q>>2]=(r|0)>(i|0)?r:i;d=d+1|0}d=e[l+84>>1]|0;g=(j&65535)+d|0;while(1){if((d|0)>=(g|0))break;r=n+(d<<2)|0;q=c[r>>2]|0;c[r>>2]=(q|0)>(k|0)?q:k;d=d+1|0}m=m+4|0}return}function NF(a){a=a|0;var b=0,d=0;d=l;l=l+16|0;b=d;if(a>>>0<21)a=c[54824+(a<<2)>>2]|0;else{c[b>>2]=a;qL(174085,122187,b)|0;a=174085}l=d;return a|0}function OF(a,b,d){a=a|0;b=b|0;d=d|0;var f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;k=a+104|0;l=a+100|0;j=d+16|0;f=0;g=0;while(1){if((f|0)>(c[k>>2]|0))break;i=oo(d,NF(f)|0,1)|0;Oo(i,122241,304,1)|0;m=i+16|0;c[(c[m>>2]|0)+176>>2]=0;o=ww((c[l>>2]<<2)+4|0)|0;n=c[m>>2]|0;c[n+172>>2]=o;c[n+184>>2]=0;n=ww((c[l>>2]<<2)+4|0)|0;c[(c[m>>2]|0)+180>>2]=n;if(!g)c[(c[j>>2]|0)+192>>2]=i;else c[(c[g+16>>2]|0)+164>>2]=i;f=f+1|0;g=i}j=b+16|0;f=0;g=0;while(1){if((f|0)>(c[l>>2]|0))break;i=oo(b,NF(f)|0,1)|0;Oo(i,122241,304,1)|0;o=i+16|0;c[(c[o>>2]|0)+176>>2]=0;m=ww((c[k>>2]<<2)+4|0)|0;n=c[o>>2]|0;c[n+172>>2]=m;c[n+184>>2]=0;n=ww((c[k>>2]<<2)+4|0)|0;c[(c[o>>2]|0)+180>>2]=n;if(!g)c[(c[j>>2]|0)+192>>2]=i;else c[(c[g+16>>2]|0)+164>>2]=i;f=f+1|0;g=i}f=c[a+84>>2]|0;while(1){g=c[f>>2]|0;if(!g)break;o=g+84|0;n=oo(d,NF(e[o>>1]|0)|0,0)|0;o=oo(d,NF((e[g+80>>1]|0)+(e[o>>1]|0)|0)|0,0)|0;PF(d,n,o,~~+h[g+64>>3]);o=g+86|0;n=oo(b,NF(e[o>>1]|0)|0,0)|0;o=oo(b,NF((e[g+82>>1]|0)+(e[o>>1]|0)|0)|0,0)|0;PF(b,n,o,~~+h[g+72>>3]);f=f+4|0}QF(d);QF(b);return}function PF(a,d,f,g){a=a|0;d=d|0;f=f|0;g=g|0;var h=0,i=0;h=bn(a,d,f,0,0)|0;if(!h){i=bn(a,d,f,0,1)|0;Oo(i,122254,176,1)|0;b[(c[i+16>>2]|0)+170>>1]=g;d=d+16|0;a=c[d>>2]|0;h=c[a+180>>2]|0;if(!h)a=xw((c[a+184>>2]<<2)+8|0)|0;else a=zw(h,(c[a+184>>2]<<2)+8|0)|0;g=c[d>>2]|0;c[g+180>>2]=a;g=g+184|0;h=c[g>>2]|0;c[g>>2]=h+1;c[a+(h<<2)>>2]=i;d=c[d>>2]|0;c[(c[d+180>>2]|0)+(c[d+184>>2]<<2)>>2]=0;d=f+16|0;a=c[d>>2]|0;h=c[a+172>>2]|0;if(!h)a=xw((c[a+176>>2]<<2)+8|0)|0;else a=zw(h,(c[a+176>>2]<<2)+8|0)|0;g=c[d>>2]|0;c[g+172>>2]=a;g=g+176|0;f=c[g>>2]|0;c[g>>2]=f+1;c[a+(f<<2)>>2]=i;i=c[d>>2]|0;c[(c[i+172>>2]|0)+(c[i+176>>2]<<2)>>2]=0}else{i=(c[h+16>>2]|0)+170|0;f=e[i>>1]|0;b[i>>1]=(f|0)>(g|0)?f:g}return}function QF(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0;d=c[(c[a+16>>2]|0)+192>>2]|0;while(1){f=d+16|0;h=c[(c[f>>2]|0)+164>>2]|0;if(!h)break;if(bn(a,d,h,0,0)|0){d=h;continue}g=bn(a,d,h,0,1)|0;Oo(g,122254,176,1)|0;b[(c[g+16>>2]|0)+170>>1]=0;d=c[f>>2]|0;e=c[d+180>>2]|0;if(!e)d=xw((c[d+184>>2]<<2)+8|0)|0;else d=zw(e,(c[d+184>>2]<<2)+8|0)|0;i=c[f>>2]|0;c[i+180>>2]=d;i=i+184|0;e=c[i>>2]|0;c[i>>2]=e+1;c[d+(e<<2)>>2]=g;f=c[f>>2]|0;c[(c[f+180>>2]|0)+(c[f+184>>2]<<2)>>2]=0;f=h+16|0;d=c[f>>2]|0;e=c[d+172>>2]|0;if(!e)d=xw((c[d+176>>2]<<2)+8|0)|0;else d=zw(e,(c[d+176>>2]<<2)+8|0)|0;e=c[f>>2]|0;c[e+172>>2]=d;e=e+176|0;i=c[e>>2]|0;c[e>>2]=i+1;c[d+(i<<2)>>2]=g;d=c[f>>2]|0;c[(c[d+172>>2]|0)+(c[d+176>>2]<<2)>>2]=0;d=h}return}function RF(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;g=a+92|0;e=0;f=0;b=c[(c[(c[b+16>>2]|0)+192>>2]|0)+16>>2]|0;while(1){b=c[b+164>>2]|0;if(!b)break;b=c[b+16>>2]|0;h=b+232|0;c[(c[g>>2]|0)+(f<<2)>>2]=(c[h>>2]|0)-e;e=c[h>>2]|0;f=f+1|0}a=a+96|0;e=0;f=0;b=c[(c[(c[d+16>>2]|0)+192>>2]|0)+16>>2]|0;while(1){b=c[b+164>>2]|0;if(!b)break;b=c[b+16>>2]|0;h=b+232|0;c[(c[a>>2]|0)+(f<<2)>>2]=(c[h>>2]|0)-e;e=c[h>>2]|0;f=f+1|0}return}function SF(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;g=h+4|0;d=h;c[d>>2]=c[4411];e=c[b+100>>2]|0;if((e|0)!=1?(f=b+104|0,(c[f>>2]|0)!=1):0){c[b+92>>2]=ww((e<<2)+4|0)|0;c[b+96>>2]=ww((c[f>>2]<<2)+4|0)|0;a[g>>0]=a[d>>0]|0;a[g+1>>0]=a[d+1>>0]|0;a[g+2>>0]=a[d+2>>0]|0;a[g+3>>0]=a[d+3>>0]|0;f=hn(122267,g,0)|0;a[g>>0]=a[d>>0]|0;a[g+1>>0]=a[d+1>>0]|0;a[g+2>>0]=a[d+2>>0]|0;a[g+3>>0]=a[d+3>>0]|0;g=hn(122272,g,0)|0;Oo(f,122277,280,1)|0;Oo(g,122277,280,1)|0;OF(b,f,g);hx(f,2,2147483647)|0;hx(g,2,2147483647)|0;RF(b,f,g);TF(f,g)}else MF(b);l=h;return}function TF(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=(c[b+16>>2]|0)+192|0;while(1){d=c[d>>2]|0;if(!d)break;f=d+16|0;d=c[f>>2]|0;e=c[d+172>>2]|0;if(e){$I(e);d=c[f>>2]|0}e=c[d+180>>2]|0;if(e){$I(e);d=c[f>>2]|0}d=d+164|0}mn(a)|0;mn(b)|0;return}function UF(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0;p=l;l=l+272|0;n=p+104|0;o=p+136|0;j=p+72|0;k=p;g=p+144|0;c[k+48>>2]=b;switch(Do(b)|0){case 0:{e=c[b+60>>2]|0;break}case 1:{e=so(b)|0;break}case 2:{e=so(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0;break}default:{}}i=k+52|0;c[i>>2]=e;m=c[e+60>>2]|0;h[k+32>>3]=+h[d+16>>3];c[k+16>>2]=c[d+4>>2];c[k+20>>2]=c[d+8>>2];c[k+40>>2]=0;f=cI(c[d>>2]|0,o,k)|0;if(!f){dm(n,128,g);a[d+82>>0]=0;e=HL(VF(b,n)|0)|0;c[d>>2]=e;if((c[d+12>>2]|0)==1)e=zB(e)|0;else e=wB(e,c[i>>2]|0)|0;$I(c[d>>2]|0);c[d>>2]=e;kw(c[(c[m+16>>2]|0)+144>>2]|0,d);hm(n);e=c[o>>2]|0}else{e=f+4|0;if((a[e>>0]|0)==1){if((c[(c[f>>2]|0)+24>>2]|0)==0?WF(b)|0:0){i=HL(WF(b)|0)|0;c[(c[f>>2]|0)+24>>2]=i}m=XF(m,c[f>>2]|0,0,k)|0;c[o>>2]=c[o>>2]|m;m=c[f>>2]|0;r=+h[m+64>>3]*.5;q=+h[m+72>>3]*.5;YF(j,-r,-q,r,q);m=c[f>>2]|0;c[n>>2]=c[j>>2];c[n+4>>2]=c[j+4>>2];c[n+8>>2]=c[j+8>>2];c[n+12>>2]=c[j+12>>2];c[n+16>>2]=c[j+16>>2];c[n+20>>2]=c[j+20>>2];c[n+24>>2]=c[j+24>>2];c[n+28>>2]=c[j+28>>2];ZF(m,n,15)}else{_F(c[(c[m+16>>2]|0)+144>>2]|0,c[f>>2]|0,k);n=c[f>>2]|0;q=+h[n+24>>3]*.5;r=+h[n+32>>3]*.5;YF(j,-q,-r,q,r);n=(c[f>>2]|0)+8|0;c[n>>2]=c[j>>2];c[n+4>>2]=c[j+4>>2];c[n+8>>2]=c[j+8>>2];c[n+12>>2]=c[j+12>>2];c[n+16>>2]=c[j+16>>2];c[n+20>>2]=c[j+20>>2];c[n+24>>2]=c[j+24>>2];c[n+28>>2]=c[j+28>>2]}h[d+24>>3]=+h[j+16>>3]-+h[j>>3];h[d+32>>3]=+h[j+24>>3]-+h[j+8>>3];c[d+72>>2]=f;if((a[e>>0]|0)==1){$I(c[d>>2]|0);c[d>>2]=HL(122290)|0}e=c[o>>2]|0}l=p;return e|0}function VF(b,d){b=b|0;d=d|0;var e=0;a:do switch(Do(b)|0){case 0:{gm(d,En(b)|0)|0;break}case 1:{gm(d,En(b)|0)|0;break}case 2:{gm(d,En(c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0)|0;e=b+-48|0;gm(d,En(c[((c[b>>2]&3|0)==2?b:e)+40>>2]|0)|0)|0;if(!(rn(so(c[((c[b>>2]&3|0)==2?b:e)+40>>2]|0)|0)|0)){gm(d,122549)|0;break a}else{gm(d,122546)|0;break a}}default:{}}while(0);e=d+4|0;b=c[e>>2]|0;if(b>>>0>=(c[d+8>>2]|0)>>>0){em(d,1)|0;b=c[e>>2]|0}a[b>>0]=0;d=c[d>>2]|0;c[e>>2]=d;return d|0}function WF(b){b=b|0;var c=0,d=0;c=Jm(b,122531)|0;if(!((c|0)!=0?(a[c>>0]|0)!=0:0))d=3;do if((d|0)==3){c=Jm(b,122540)|0;if(c|0?a[c>>0]|0:0)break;c=0}while(0);return c|0}function XF(f,g,i,j){f=f|0;g=g|0;i=i|0;j=j|0;var k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=l;l=l+16|0;u=w+8|0;t=w;v=g+108|0;k=c[v>>2]|0;if(k|0)qF(j,k,167328);c[g+80>>2]=i;k=cG(f,g,j)|0;r=g+36|0;f=b[r>>1]|0;if(!(f&128))a[g+32>>0]=2;i=g+33|0;if(!(f&32))a[i>>0]=1;SF(g);n=c[g+104>>2]|0;p=a[g+32>>0]|0;f=O(n+1|0,p)|0;o=d[i>>0]<<1;q=c[g+100>>2]|0;p=O(q+1|0,p)|0;m=g+96|0;f=o+f|0;i=0;while(1){if((i|0)>=(n|0))break;f=(c[(c[m>>2]|0)+(i<<2)>>2]|0)+f|0;i=i+1|0}n=g+92|0;i=p+o|0;m=0;while(1){if((m|0)>=(q|0))break;i=(c[(c[n>>2]|0)+(m<<2)>>2]|0)+i|0;m=m+1|0}n=g+38|0;do if(b[r>>1]&1){r=b[n>>1]|0;m=r&65535;if(r<<16>>16?(s=b[g+40>>1]|0,s<<16>>16):0){if(!((f|0)>(m|0)|(i|0)>(s&65535|0))){i=0;f=0;break}$l(0,122331,t)|0;k=1;i=0;f=0;break}$l(0,122365,u)|0;k=1}while(0);u=e[n>>1]|0;h[g+64>>3]=+(((f|0)>(u|0)?f:u)|0);u=e[g+40>>1]|0;h[g+72>>3]=+(((i|0)>(u|0)?i:u)|0);if(c[v>>2]|0)yF(j,167328);l=w;return k|0}function YF(a,b,c,d,e){a=a|0;b=+b;c=+c;d=+d;e=+e;h[a>>3]=b;h[a+8>>3]=c;h[a+16>>3]=d;h[a+24>>3]=e;return}function ZF(e,f,g){e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0.0,n=0.0,o=0,p=0,q=0.0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0.0,K=0;I=l;l=l+64|0;G=I+32|0;H=I;E=c[e+84>>2]|0;k=c[e+80>>2]|0;if((k|0?(i=c[k+24>>2]|0,i|0):0)?(j=e+24|0,(c[j>>2]|0)==0):0)c[j>>2]=HL(i)|0;F=e+48|0;i=f+16|0;n=+h[i>>3];m=+h[f>>3];k=~~(n-m-+(~~+h[e+64>>3]|0));if((k|0)<=-1)ma(122298,122134,1761,122308);o=f+24|0;y=+h[o>>3];p=f+8|0;q=+h[p>>3];r=+(~~+h[e+72>>3]|0);s=~~(y-q-r);if((s|0)<=-1)ma(122321,122134,1764,122308);t=b[e+36>>1]|0;j=t&65535;a:do if(j&1){b:do if((k|0)>0)switch(j&6){case 4:{h[i>>3]=m+r;break b}case 2:{J=+(k|0);h[i>>3]=n+J;m=m+J;h[f>>3]=m;break b}default:{J=+(k>>>1|0);m=m+J;h[f>>3]=m;h[i>>3]=n-J;break b}}while(0);if((s|0)>0)switch(t&24){case 16:{y=q+r;h[o>>3]=y;s=0;i=0;break a}case 8:{J=+(s|0);y=y+J;h[o>>3]=y;h[p>>3]=q+J;s=0;i=0;break a}default:{J=+(s>>>1|0);h[p>>3]=q+J;y=y-J;h[o>>3]=y;s=0;i=0;break a}}else{s=0;i=0}}else i=k;while(0);n=+(d[e+33>>0]|0);C=e+32|0;u=a[C>>0]|0;q=+(u<<24>>24);D=e+104|0;k=c[D>>2]|0;t=(i|0)/(k|0)|0;o=i-(O(t,k)|0)|0;o=~~(((o|0)>-1?.5:-.5)+ +(o|0));B=e+96|0;p=u<<24>>24;i=~~(m+n+q);j=0;while(1){if((j|0)>(k|0))break;A=(c[B>>2]|0)+(j<<2)|0;k=c[A>>2]|0;c[A>>2]=i;i=i+t+((j|0)<(o|0)&1)+k+p|0;j=j+1|0;k=c[D>>2]|0}A=e+100|0;k=c[A>>2]|0;t=(s|0)/(k|0)|0;p=s-(O(t,k)|0)|0;p=~~(((p|0)>-1?.5:-.5)+ +(p|0));z=e+92|0;o=u<<24>>24;i=~~(y-n-q);j=0;while(1){if((j|0)>(k|0))break;x=(c[z>>2]|0)+(j<<2)|0;k=c[x>>2]|0;c[x>>2]=i;i=i-t+(((j|0)<(p|0))<<31>>31)-k-o|0;j=j+1|0;k=c[A>>2]|0}u=(g|0)==0;v=H+16|0;w=H+24|0;x=H+8|0;i=E;while(1){o=c[i>>2]|0;if(!o)break;k=b[o+84>>1]|0;if(u){j=0;p=b[o+80>>1]|0;s=b[o+86>>1]|0;t=b[o+82>>1]|0}else{j=k<<16>>16==0?8:0;s=b[o+86>>1]|0;j=s<<16>>16==0?j|4:j;p=b[o+80>>1]|0;t=b[o+82>>1]|0;j=(((p&65535)+(k&65535)|0)==(c[D>>2]|0)?j|2:j)|((t&65535)+(s&65535)|0)==(c[A>>2]|0)}K=c[B>>2]|0;k=k&65535;h[H>>3]=+(c[K+(k<<2)>>2]|0);E=a[C>>0]|0;h[v>>3]=+((c[K+((p&65535)+k<<2)>>2]|0)-E|0);p=c[z>>2]|0;h[w>>3]=+(c[p+((s&65535)<<2)>>2]|0);h[x>>3]=+((c[p+((t&65535)+(s&65535)<<2)>>2]|0)+E|0);c[G>>2]=c[H>>2];c[G+4>>2]=c[H+4>>2];c[G+8>>2]=c[H+8>>2];c[G+12>>2]=c[H+12>>2];c[G+16>>2]=c[H+16>>2];c[G+20>>2]=c[H+20>>2];c[G+24>>2]=c[H+24>>2];c[G+28>>2]=c[H+28>>2];$F(o,G,j&g);i=i+4|0}a[e+35>>0]=g;c[F>>2]=c[f>>2];c[F+4>>2]=c[f+4>>2];c[F+8>>2]=c[f+8>>2];c[F+12>>2]=c[f+12>>2];c[F+16>>2]=c[f+16>>2];c[F+20>>2]=c[f+20>>2];c[F+24>>2]=c[f+24>>2];c[F+28>>2]=c[f+28>>2];l=I;return}function _F(d,e,f){d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0.0,k=0.0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0.0,Q=0.0,R=0.0;O=l;l=l+112|0;H=O+48|0;I=O+16|0;J=O;c[I>>2]=0;c[I+4>>2]=0;c[I+8>>2]=0;c[I+12>>2]=0;c[I+16>>2]=0;c[I+20>>2]=0;c[I+24>>2]=0;c[I+28>>2]=0;K=e+4|0;L=f+16|0;M=f+32|0;N=I+16|0;r=b[K>>1]|0;n=r<<16>>16;g=0;j=-1.0;m=0;while(1){if((m|0)>=(n|0)){g=1;break}i=c[e>>2]|0;if((b[i+(m*24|0)+4>>1]|0)>1){g=0;break}i=c[(c[i+(m*24|0)>>2]|0)+4>>2]|0;if(!i){k=+h[M>>3];h[N>>3]=k;i=L}else{if(c[i+24>>2]&127|0){g=0;break}k=+h[(+h[i+16>>3]>0.0?i:L)+16>>3];h[N>>3]=k;i=(c[i>>2]|0)==0?L:i}i=c[i>>2]|0;c[I>>2]=i;if(!(j==-1.0)){if(k!=j){g=0;break}}else j=k;if(g){if(yJ(i,g)|0){g=0;break}}else g=i;m=m+1|0}a[e+6>>0]=g;E=f+48|0;F=f+20|0;G=I+4|0;w=f+40|0;x=I+24|0;y=d+144|0;z=H+4|0;v=J+8|0;A=H+16|0;B=H+24|0;C=H+8|0;D=H+12|0;f=(g|0)==0;j=0.0;s=0.0;t=0.0;u=0.0;n=0;g=r;while(1){if((n|0)>=(g<<16>>16|0))break;k=0.0;q=0.0;m=0;p=0.0;j=0.0;i=c[e>>2]|0;while(1){if((m|0)>=(b[i+(n*24|0)+4>>1]|0))break;c[H>>2]=rw(c[(c[i+(n*24|0)>>2]|0)+(m*56|0)>>2]|0,c[E>>2]|0)|0;i=(c[e>>2]|0)+(n*24|0)|0;g=c[(c[i>>2]|0)+(m*56|0)+4>>2]|0;if(!g){h[N>>3]=+h[M>>3];c[I>>2]=c[L>>2];c[G>>2]=c[F>>2];c[x>>2]=c[x>>2]&-128|c[w>>2]&127}else{g=c[g+24>>2]&127;if(!g)g=c[w>>2]&127;c[x>>2]=c[x>>2]&-128|g;r=c[(c[i>>2]|0)+(m*56|0)+4>>2]|0;h[N>>3]=+h[(+h[r+16>>3]>0.0?r:L)+16>>3];c[I>>2]=c[((c[r>>2]|0)==0?L:r)>>2];c[G>>2]=c[((c[r+4>>2]|0)==0?L:r)+4>>2]}i=c[y>>2]|0;c[z>>2]=bb[c[i>>2]&31](i,I,1)|0;qA(J,d,H);Q=+h[J>>3];o=+h[v>>3];$I(c[(c[(c[e>>2]|0)+(n*24|0)>>2]|0)+(m*56|0)>>2]|0);i=c[e>>2]|0;r=c[i+(n*24|0)>>2]|0;c[r+(m*56|0)>>2]=c[H>>2];h[r+(m*56|0)+32>>3]=Q;h[r+(m*56|0)+16>>3]=+h[A>>3];h[r+(m*56|0)+24>>3]=+h[B>>3];c[r+(m*56|0)+4>>2]=c[z>>2];c[r+(m*56|0)+8>>2]=c[C>>2];c[r+(m*56|0)+12>>2]=c[D>>2];P=+h[N>>3];R=+h[B>>3];k=R>k?R:k;q=Q+q;m=m+1|0;p=P>p?P:p;j=o>j?o:j}h[i+(n*24|0)+8>>3]=q;g=(n|0)==0;do if(f)if(g){o=p;k=p-k;g=i;break}else{o=p;k=t-u+p-k;g=i+(n*24|0)|0;break}else{o=j;k=g?p:j;g=i+(n*24|0)|0}while(0);h[g+16>>3]=k;s=q>s?q:s;t=o+t;u=+h[i+(n*24|0)+16>>3]+u;n=n+1|0;g=b[K>>1]|0}h[e+24>>3]=s;h[e+32>>3]=g<<16>>16==1?j:t;l=O;return}function $F(e,f,g){e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0.0,A=0.0;y=l;l=l+64|0;v=y+32|0;x=y;j=e+24|0;if((c[j>>2]|0)==0?(i=c[(c[e+96>>2]|0)+24>>2]|0,i|0):0)c[j>>2]=HL(i)|0;t=e+36|0;w=b[t>>1]|0;i=w&65535;a:do if(i&1){k=+h[e+64>>3];q=+h[e+72>>3];j=f+16|0;m=+h[j>>3];o=+h[f>>3];n=m-o-k;b:do if(n>0.0)switch(i&6){case 4:{m=o+k;h[j>>3]=m;k=o;break b}case 2:{m=n+m;h[j>>3]=m;k=o+n;h[f>>3]=k;break b}default:{p=n*.5;k=p+o;h[f>>3]=k;m=m-p;h[j>>3]=m;break b}}else k=o;while(0);i=f+24|0;p=+h[i>>3];j=f+8|0;n=+h[j>>3];o=p-n-q;if(o>0.0)switch(w&24){case 16:{o=n+q;h[i>>3]=o;break a}case 8:{q=o+p;h[i>>3]=q;n=n+o;h[j>>3]=n;o=q;break a}default:{o=o*.5;n=o+n;h[j>>3]=n;o=p-o;h[i>>3]=o;break a}}else o=p}else{k=+h[f>>3];n=+h[f+8>>3];m=+h[f+16>>3];o=+h[f+24>>3]}while(0);s=e+48|0;c[s>>2]=c[f>>2];c[s+4>>2]=c[f+4>>2];c[s+8>>2]=c[f+8>>2];c[s+12>>2]=c[f+12>>2];c[s+16>>2]=c[f+16>>2];c[s+20>>2]=c[f+20>>2];c[s+24>>2]=c[f+24>>2];c[s+28>>2]=c[f+28>>2];a[e+35>>0]=g;A=+(d[e+33>>0]|0);z=+(d[e+34>>0]|0);p=k+A+z;h[x>>3]=p;q=n+A+z;s=x+8|0;h[s>>3]=q;n=m-A-z;f=x+16|0;h[f>>3]=n;o=o-A-z;r=x+24|0;h[r>>3]=o;j=e+88|0;switch(a[e+92>>0]|0){case 1:{w=c[j>>2]|0;c[v>>2]=c[x>>2];c[v+4>>2]=c[x+4>>2];c[v+8>>2]=c[x+8>>2];c[v+12>>2]=c[x+12>>2];c[v+16>>2]=c[x+16>>2];c[v+20>>2]=c[x+20>>2];c[v+24>>2]=c[x+24>>2];c[v+28>>2]=c[x+28>>2];ZF(w,v,g);break}case 3:{i=c[j>>2]|0;k=+h[i+24>>3];m=n-p-+h[i+16>>3];c:do if(m>0.0)switch(w&6){case 4:{h[f>>3]=n-m;break c}case 2:{h[x>>3]=m+p;break c}default:break c}while(0);k=o-q-k;d:do if(k>0.0)switch(w&24){case 16:{h[r>>3]=o-k;break d}case 8:{h[s>>3]=k+q;break d}default:break d}while(0);c[v>>2]=c[x>>2];c[v+4>>2]=c[x+4>>2];c[v+8>>2]=c[x+8>>2];c[v+12>>2]=c[x+12>>2];c[v+16>>2]=c[x+16>>2];c[v+20>>2]=c[x+20>>2];c[v+24>>2]=c[x+24>>2];c[v+28>>2]=c[x+28>>2];aG(i,v);break}default:{i=c[j>>2]|0;k=+h[i+32>>3];m=n-p-+h[i+24>>3];e:do if(m>0.0?(u=w&6,u<<16>>16!=6):0)switch(u&7){case 4:{h[f>>3]=n-m;break e}case 2:{h[x>>3]=m+p;break e}default:{A=m*.5;h[x>>3]=A+p;h[f>>3]=n-A;break e}}while(0);k=o-q-k;f:do if(k>0.0)switch(w&24){case 16:{h[r>>3]=o-k;break f}case 8:{h[s>>3]=k+q;break f}default:{A=k*.5;h[s>>3]=A+q;h[r>>3]=o-A;break f}}while(0);w=i+8|0;c[w>>2]=c[x>>2];c[w+4>>2]=c[x+4>>2];c[w+8>>2]=c[x+8>>2];c[w+12>>2]=c[x+12>>2];c[w+16>>2]=c[x+16>>2];c[w+20>>2]=c[x+20>>2];c[w+24>>2]=c[x+24>>2];c[w+28>>2]=c[x+28>>2];x=b[t>>1]&768;bG(c[j>>2]|0,(x&1023)==512?108:(x&1023)==256?114:110)}}l=y;return}function aG(a,b){a=a|0;b=b|0;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];c[a+16>>2]=c[b+16>>2];c[a+20>>2]=c[b+20>>2];c[a+24>>2]=c[b+24>>2];c[a+28>>2]=c[b+28>>2];return}function bG(d,e){d=d|0;e=e|0;var f=0,g=0,h=0;g=b[d+4>>1]|0;f=0;while(1){if((f|0)>=(g|0))break;h=(c[d>>2]|0)+(f*24|0)+6|0;if(!(a[h>>0]|0))a[h>>0]=e;f=f+1|0}return}function cG(d,f,g){d=d|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;l=f+84|0;t=c[l>>2]|0;u=xx()|0;v=gG()|0;i=0;h=0;k=Pl(t)|0;while(1){if(!k)break;j=Pl(c[k+8>>2]|0)|0;while(1){if(!j)break;j=c[j>>2]|0;i=i+1|0}h=h+1|0;if(a[k+12>>0]|0)kG(v,h);k=c[k>>2]|0}h=ww((i<<2)+4|0)|0;c[l>>2]=h;i=0;j=0;k=0;q=0;r=Pl(t)|0;while(1){if(!r)break;s=q&65535;p=0;o=Pl(c[r+8>>2]|0)|0;while(1){if(!o)break;n=c[o+8>>2]|0;c[h>>2]=n;k=dG(d,n,f,g)|0|k;l=eG(u,q,p,n)|0;b[n+86>>1]=s;b[n+84>>1]=l;l=l+(e[n+80>>1]|0)|0;m=q+(e[n+82>>1]|0)|0;if(lG(v,m)|0){p=n+100|0;a[p>>0]=a[p>>0]|2}p=l;h=h+4|0;o=c[o>>2]|0;i=(l|0)>(i|0)?l:i;j=(m|0)>(j|0)?m:j}q=q+1|0;r=c[r>>2]|0}c[f+100>>2]=j;c[f+104>>2]=i;Ll(t)|0;Ll(v)|0;Ax(u);return k|0}function dG(f,g,i,j){f=f|0;g=g|0;i=i|0;j=j|0;var k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0;u=l;l=l+16|0;t=u+8|0;s=u;c[g+96>>2]=i;q=g+36|0;o=b[q>>1]|0;if(!(o&64)){if(!(b[i+36>>1]&64))n=2;else n=a[i+34>>0]|0;a[g+34>>0]=n}if(!(o&32)){n=a[i+88>>0]|0;if(n<<24>>24<=-1)if(!(b[i+36>>1]&32))n=1;else n=a[i+33>>0]|0;a[g+33>>0]=n}n=g+88|0;p=g+92|0;switch(a[p>>0]|0){case 1:{o=XF(f,c[n>>2]|0,g,j)|0;i=c[n>>2]|0;n=o;o=i+64|0;i=i+72|0;break}case 3:{o=fG(c[n>>2]|0,j)|0;i=c[n>>2]|0;n=o;o=i+16|0;i=i+24|0;break}default:{_F(c[(c[f+16>>2]|0)+144>>2]|0,c[n>>2]|0,j);i=c[n>>2]|0;n=0;o=i+24|0;i=i+32|0}}k=+((d[g+33>>0]|0)+(d[g+34>>0]|0)<<1|0);m=+h[o>>3]+k;k=+h[i>>3]+k;i=g+38|0;do if(b[q>>1]&1){o=b[i>>1]|0;if(o<<16>>16?(r=b[g+40>>1]|0,r<<16>>16):0){if(!(m>+(o&65535)|k>+(r&65535))){m=0.0;k=0.0;break}if((a[p>>0]|0)==3){m=0.0;k=0.0;break}$l(0,122416,s)|0;n=1;m=0.0;k=0.0;break}$l(0,122449,t)|0;n=1}while(0);v=+(e[i>>1]|0);h[g+64>>3]=m>v?m:v;m=+(e[g+40>>1]|0);h[g+72>>3]=k>m?k:m;l=u;return n|0}function eG(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var f=0,g=0,h=0,i=0,j=0;j=d+80|0;i=(e[j>>1]|0)+-1|0;h=0;a:while(1){f=c;while(1){if(h)break a;g=i+f|0;while(1){if((g|0)<(f|0)){c=f;h=1;continue a}if(Fx(a,g,b)|0)break;g=g+-1|0}f=g+1|0}}h=d+82|0;f=c;while(1){if((f|0)<(c+(e[j>>1]|0)|0))g=b;else break;while(1){if((g|0)>=((e[h>>1]|0)+b|0))break;Dx(a,f,g);g=g+1|0}f=f+1|0}return c|0}function fG(b,d){b=b|0;d=d|0;var e=0.0,f=0.0,g=0,i=0,j=0,k=0,m=0;m=l;l=l+16|0;j=m;i=m+8|0;d=d+52|0;g=b+32|0;Qr(i,c[d>>2]|0,c[g>>2]|0);k=c[i>>2]|0;i=c[i+4>>2]|0;if((i&k|0)==-1){c[j>>2]=c[g>>2];$l(1,122499,j)|0;d=1;f=0.0;e=0.0}else{a[(c[(c[d>>2]|0)+16>>2]|0)+114>>0]=1;d=0;f=+(i|0);e=+(k|0)}c[b>>2]=0;c[b+4>>2]=0;c[b+8>>2]=0;c[b+12>>2]=0;h[b+16>>3]=e;h[b+24>>3]=f;l=m;return d|0}function gG(){return Rl(54908,c[4345]|0)|0}function hG(a,b,d){a=a|0;b=b|0;d=d|0;d=ww(12)|0;c[d>>2]=c[b>>2];return d|0}function iG(a,b,c){a=a|0;b=b|0;c=c|0;$I(b);return}function jG(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;b=c[b>>2]|0;e=c[d>>2]|0;return ((b|0)>(e|0)?1:((b|0)<(e|0))<<31>>31)|0}function kG(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=b;bb[c[a>>2]&31](a,e,1)|0;l=d;return}function lG(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=b;b=(bb[c[a>>2]&31](a,e,512)|0)!=0&1;l=d;return b|0}function mG(a){a=a|0;var b=0;if(!(c[42419]|0)){b=ww((a<<2)+4|0)|0;c[42419]=b;c[b>>2]=169680;c[42430]=a}c[42431]=0;return}function nG(){$I(c[42419]|0);c[42419]=0;c[42431]=0;return}function oG(){c[42431]=0;return}function pG(){var a=0,b=0,d=0;b=c[42431]|0;d=c[42419]|0;a=1;while(1){if((a|0)>(b|0)){a=5;break}if((c[(c[d+(a<<2)>>2]|0)+4>>2]|0)==(a|0))a=a+1|0;else{a=4;break}}if((a|0)==4)ma(123205,122552,59,122558);else if((a|0)==5)return}function qG(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;f=c[42419]|0;g=c[f+(a<<2)>>2]|0;h=c[g>>2]|0;while(1){b=(a|0)/2|0;d=c[f+(b<<2)>>2]|0;e=f+(a<<2)|0;if((c[d>>2]|0)>=(h|0))break;c[e>>2]=d;c[d+4>>2]=a;a=b}c[e>>2]=g;c[g+4>>2]=a;return}function rG(a){a=a|0;var b=0,d=0;d=l;l=l+16|0;b=c[42431]|0;if((b|0)==(c[42430]|0)){$l(1,122566,d)|0;a=1}else{b=b+1|0;c[42431]=b;c[(c[42419]|0)+(b<<2)>>2]=a;qG(b);pG();a=0}l=d;return a|0}function sG(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;e=c[42419]|0;f=c[e+(a<<2)>>2]|0;g=c[f>>2]|0;h=c[42431]|0;i=(h|0)/2|0;while(1){if((a|0)>(i|0))break;d=a<<1;b=c[e+(d<<2)>>2]|0;if((d|0)<(h|0)){l=d|1;j=c[e+(l<<2)>>2]|0;k=(c[b>>2]|0)<(c[j>>2]|0);d=k?l:d;b=k?j:b}if((g|0)>=(c[b>>2]|0))break;c[e+(a<<2)>>2]=b;c[b+4>>2]=a;a=d}c[e+(a<<2)>>2]=f;c[f+4>>2]=a;return}function tG(){var a=0,b=0,d=0,e=0;b=c[42431]|0;if(!b)a=0;else{e=c[42419]|0;d=e+4|0;a=c[d>>2]|0;c[d>>2]=c[e+(b<<2)>>2];b=b+-1|0;c[42431]=b;if(b|0)sG(1);pG()}return a|0}function uG(a,b){a=a|0;b=b|0;c[a>>2]=b;qG(c[a+4>>2]|0);pG();return}function vG(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;m=b+16|0;j=c[m>>2]|0;j=(a[j+((c[e+12>>2]|0)*40|0)+36>>0]|0)!=(a[j+((c[e+16>>2]|0)*40|0)+36>>0]|0);k=~~((+h[d+64>>3]+-3.0-+h[d+48>>3])*.5);l=~~((+h[d+56>>3]+-3.0-+h[d+40>>3])*.5);g=(k|0)<(l|0)?k:l;n=d+4|0;f=0;while(1){b=c[n>>2]|0;if((f|0)>=(b|0)){g=f;break}i=c[d+8+(f<<2)>>2]|0;o=c[m>>2]|0;if((a[o+((c[i+12>>2]|0)*40|0)+36>>0]|0)==(a[o+((c[i+16>>2]|0)*40|0)+36>>0]|0)){g=f;break}wG(i,g);f=f+1|0}while(1){if((g|0)>=(b|0))break;f=c[d+8+(g<<2)>>2]|0;if(j|(f|0)==(e|0)){wG(f,a[(c[m>>2]|0)+((c[f+12>>2]|0)*40|0)+36>>0]|0?k:l);b=c[n>>2]|0}g=g+1|0}return}function wG(a,b){a=a|0;b=b|0;var d=0,e=0;d=a+8|0;e=c[d>>2]|0;c[d>>2]=e+1;if((e|0)>=(b|0)){c[d>>2]=0;h[a>>3]=+h[a>>3]+16384.0}return}function xG(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0,A=0.0,B=0.0,C=0,D=0,E=0.0;x=l;l=l+112|0;u=x+64|0;t=x+96|0;m=x+32|0;v=x;w=ww(28)|0;b=nn(a)|0;s=w+4|0;c[s>>2]=b;b=ww(b*72|0)|0;r=w+12|0;c[r>>2]=b;e=v+8|0;h[e>>3]=1797693134862315708145274.0e284;h[v>>3]=1797693134862315708145274.0e284;f=v+24|0;h[f>>3]=-1797693134862315708145274.0e284;g=v+16|0;h[g>>3]=-1797693134862315708145274.0e284;i=m+16|0;j=m+8|0;k=m+24|0;d=eo(a)|0;n=1797693134862315708145274.0e284;o=1797693134862315708145274.0e284;p=-1797693134862315708145274.0e284;q=-1797693134862315708145274.0e284;while(1){if(!d)break;C=d+16|0;D=c[C>>2]|0;z=(+h[D+96>>3]+ +h[D+88>>3])*.5;z=z<1.0?1.0:z;y=+h[D+80>>3]*.5;y=y<1.0?1.0:y;E=+h[D+16>>3];B=E-z;h[m>>3]=B;z=E+z;h[i>>3]=z;E=+h[D+24>>3];A=E-y;h[j>>3]=A;y=E+y;h[k>>3]=y;B=+h[(n>3];h[v>>3]=B;A=+h[(o>3];h[e>>3]=A;z=+h[(p>z?v:m)+16>>3];h[g>>3]=z;y=+h[(q>y?v:m)+24>>3];h[f>>3]=y;D=b+40|0;c[D>>2]=c[m>>2];c[D+4>>2]=c[m+4>>2];c[D+8>>2]=c[m+8>>2];c[D+12>>2]=c[m+12>>2];c[D+16>>2]=c[m+16>>2];c[D+20>>2]=c[m+20>>2];c[D+24>>2]=c[m+24>>2];c[D+28>>2]=c[m+28>>2];c[b>>2]=c[b>>2]|1;c[(c[C>>2]|0)+112>>2]=b;b=b+72|0;d=fo(a,d)|0;n=B;o=A;p=z;q=y}h[v>>3]=n+-36.0;h[e>>3]=o+-36.0;h[g>>3]=p+36.0;h[f>>3]=q+36.0;D=c[r>>2]|0;f=c[s>>2]|0;c[u>>2]=c[v>>2];c[u+4>>2]=c[v+4>>2];c[u+8>>2]=c[v+8>>2];c[u+12>>2]=c[v+12>>2];c[u+16>>2]=c[v+16>>2];c[u+20>>2]=c[v+20>>2];c[u+24>>2]=c[v+24>>2];c[u+28>>2]=c[v+28>>2];f=HG(D,f,t,u)|0;if(c[42367]&1|0){r=c[r>>2]|0;C=c[s>>2]|0;D=c[t>>2]|0;c[u>>2]=c[v>>2];c[u+4>>2]=c[v+4>>2];c[u+8>>2]=c[v+8>>2];c[u+12>>2]=c[v+12>>2];c[u+16>>2]=c[v+16>>2];c[u+20>>2]=c[v+20>>2];c[u+24>>2]=c[v+24>>2];c[u+28>>2]=c[v+28>>2];yG(r,C,u,f,D)}e=w+8|0;c[e>>2]=ww((c[t>>2]|0)*72|0)|0;c[w>>2]=c[t>>2];d=c[t>>2]|0;b=0;while(1){if((b|0)>=(d|0))break;D=(c[e>>2]|0)+(b*72|0)+40|0;C=f+(b<<5)|0;c[D>>2]=c[C>>2];c[D+4>>2]=c[C+4>>2];c[D+8>>2]=c[C+8>>2];c[D+12>>2]=c[C+12>>2];c[D+16>>2]=c[C+16>>2];c[D+20>>2]=c[C+20>>2];c[D+24>>2]=c[C+24>>2];c[D+28>>2]=c[C+28>>2];b=b+1|0}$I(f);c[u>>2]=c[v>>2];c[u+4>>2]=c[v+4>>2];c[u+8>>2]=c[v+8>>2];c[u+12>>2]=c[v+12>>2];c[u+16>>2]=c[v+16>>2];c[u+20>>2]=c[v+20>>2];c[u+24>>2]=c[v+24>>2];c[u+28>>2]=c[v+28>>2];c[w+16>>2]=zG(w,u)|0;l=x;return w|0}function yG(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0.0,i=0,j=0,k=0.0,m=0.0,n=0.0,o=0,p=0,q=0,r=0,s=0,t=0.0,u=0.0,v=0.0;q=l;l=l+128|0;p=q+96|0;o=q+64|0;j=q+32|0;r=q+16|0;s=q;m=+h[d+16>>3];n=+h[d>>3];k=+h[d+24>>3];g=+h[d+8>>3];i=c[13918]|0;XL(122581,i)|0;c[s>>2]=10;c[s+4>>2]=10;c[s+8>>2]=~~(m+10.0-n);c[s+12>>2]=~~(k+10.0-g);AL(i,123011,s)|0;h[r>>3]=10.0-n;h[r+8>>3]=10.0-g;AL(i,123059,r)|0;XL(123076,i)|0;d=0;while(1){if((d|0)>=(b|0))break;v=+h[a+(d*72|0)+48>>3];u=+h[a+(d*72|0)+56>>3];t=+h[a+(d*72|0)+64>>3];h[j>>3]=+h[a+(d*72|0)+40>>3];h[j+8>>3]=v;h[j+16>>3]=u;h[j+24>>3]=t;AL(i,123095,j)|0;d=d+1|0}XL(123113,i)|0;d=0;while(1){if((d|0)>=(f|0))break;t=+h[e+(d<<5)+8>>3];u=+h[e+(d<<5)+16>>3];v=+h[e+(d<<5)+24>>3];h[o>>3]=+h[e+(d<<5)>>3];h[o+8>>3]=t;h[o+16>>3]=u;h[o+24>>3]=v;AL(i,123132,o)|0;d=d+1|0}XL(123150,i)|0;h[p>>3]=n;h[p+8>>3]=g;h[p+16>>3]=m;h[p+24>>3]=k;AL(i,123132,p)|0;XL(122897,i)|0;l=q;return}function zG(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0;A=l;l=l+32|0;t=A+16|0;k=A;w=c[a>>2]|0;y=XC(w<<2|2)|0;z=Rl(54944,c[4345]|0)|0;v=Rl(54980,c[4345]|0)|0;w=ww(w<<7)|0;f=ww(c[a>>2]<<4)|0;x=a+8|0;g=b+16|0;i=k+8|0;j=b+24|0;m=b+8|0;d=0;while(1){if((d|0)>=(c[a>>2]|0))break;n=c[x>>2]|0;o=n+(d*72|0)|0;c[n+(d*72|0)+32>>2]=4;p=n+(d*72|0)+36|0;c[p>>2]=f+(d<<2<<2);q=n+(d*72|0)+40|0;e=+h[n+(d*72|0)+56>>3];if(e<+h[g>>3]){h[k>>3]=e;h[i>>3]=+h[n+(d*72|0)+48>>3];c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[t+8>>2]=c[k+8>>2];c[t+12>>2]=c[k+12>>2];s=AG(y,z,t,w,1)|0;c[s+20>>2]=o;c[c[p>>2]>>2]=s}e=+h[n+(d*72|0)+64>>3];if(e<+h[j>>3]){h[k>>3]=+h[q>>3];h[i>>3]=e;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[t+8>>2]=c[k+8>>2];c[t+12>>2]=c[k+12>>2];s=AG(y,v,t,w,0)|0;c[s+20>>2]=o;c[(c[p>>2]|0)+4>>2]=s}if(+h[q>>3]>+h[b>>3]){c[t>>2]=c[q>>2];c[t+4>>2]=c[q+4>>2];c[t+8>>2]=c[q+8>>2];c[t+12>>2]=c[q+12>>2];s=AG(y,z,t,w,1)|0;c[s+24>>2]=o;c[(c[p>>2]|0)+8>>2]=s}if(+h[n+(d*72|0)+48>>3]>+h[m>>3]){c[t>>2]=c[q>>2];c[t+4>>2]=c[q+4>>2];c[t+8>>2]=c[q+8>>2];c[t+12>>2]=c[q+12>>2];s=AG(y,v,t,w,0)|0;c[s+24>>2]=o;c[(c[p>>2]|0)+12>>2]=s}d=d+1|0}o=ww(c[y>>2]<<2)|0;r=a+4|0;s=a+12|0;p=t+8|0;m=0;q=0;n=0;while(1){d=c[r>>2]|0;if((n|0)>=(d|0)){b=0;break}g=c[s>>2]|0;i=g+(n*72|0)|0;j=g+(n*72|0)+36|0;c[j>>2]=o+(m<<2);b=g+(n*72|0)+40|0;c[t>>2]=c[b>>2];c[t+4>>2]=c[b+4>>2];c[t+8>>2]=c[b+8>>2];c[t+12>>2]=c[b+12>>2];b=g+(n*72|0)+56|0;k=g+(n*72|0)+32|0;d=bb[c[v>>2]&31](v,t,512)|0;while(1){if(!d)break;if(!(+h[d+8>>3]<+h[b>>3]))break;C=c[d>>2]|0;B=c[j>>2]|0;f=c[k>>2]|0;c[k>>2]=f+1;c[B+(f<<2)>>2]=C;c[(c[d>>2]|0)+24>>2]=i;d=bb[c[v>>2]&31](v,d,8)|0}f=g+(n*72|0)+64|0;d=bb[c[z>>2]&31](z,t,512)|0;while(1){if(!d){u=20;break}e=+h[f>>3];if(!(+h[d+16>>3]>2]|0;B=c[j>>2]|0;C=c[k>>2]|0;c[k>>2]=C+1;c[B+(C<<2)>>2]=b;c[(c[d>>2]|0)+24>>2]=i;d=bb[c[z>>2]&31](z,d,8)|0}if((u|0)==20){u=0;e=+h[f>>3]}h[p>>3]=e;b=g+(n*72|0)+56|0;d=bb[c[v>>2]&31](v,t,512)|0;while(1){if(!d){u=25;break}e=+h[b>>3];if(!(+h[d+8>>3]>2]|0;B=c[j>>2]|0;C=c[k>>2]|0;c[k>>2]=C+1;c[B+(C<<2)>>2]=D;c[(c[d>>2]|0)+20>>2]=i;d=bb[c[v>>2]&31](v,d,8)|0}if((u|0)==25){u=0;e=+h[b>>3]}h[t>>3]=e;h[p>>3]=+h[g+(n*72|0)+48>>3];d=bb[c[z>>2]&31](z,t,512)|0;while(1){if(!d)break;if(!(+h[d+16>>3]<+h[f>>3]))break;B=c[d>>2]|0;C=c[j>>2]|0;D=c[k>>2]|0;c[k>>2]=D+1;c[C+(D<<2)>>2]=B;c[(c[d>>2]|0)+20>>2]=i;d=bb[c[z>>2]&31](z,d,8)|0}D=c[k>>2]|0;m=D+m|0;q=(D|0)>(q|0)?D:q;n=n+1|0}while(1){if((b|0)>=(d|0))break;BG((c[s>>2]|0)+(b*72|0)|0);b=b+1|0;d=c[r>>2]|0}d=c[y>>2]|0;D=c[y+16>>2]|0;c[D+(d*40|0)+32>>2]=d;d=d+1|0;c[D+(d*40|0)+32>>2]=d;WC(y,q);d=0;while(1){if((d|0)>=(c[a>>2]|0))break;CG((c[x>>2]|0)+(d*72|0)|0,y);d=d+1|0}Ll(z)|0;Ll(v)|0;$I(w);DG(y);UC(y);l=A;return y|0}function AG(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0;h=bb[c[d>>2]&31](d,e,512)|0;do if(!h){b=YC(b)|0;if(!f)ma(122994,122942,291,123001);else{h=c[b+32>>2]|0;i=f+(h<<5)|0;f=f+(h<<5)+8|0;c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2];c[i>>2]=b;a[b+36>>0]=g;bb[c[d>>2]&31](d,i,1)|0;break}}else i=h;while(0);return c[i>>2]|0}function BG(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0;a:do if((+h[b+64>>3]+-3.0-+h[b+48>>3])*.5<2.0){i=c[b+32>>2]|0;j=b+36|0;g=0;while(1){if((g|0)>=(i|0))break a;d=c[(c[j>>2]|0)+(g<<2)>>2]|0;b:do if(a[d+36>>0]|0){f=c[d+20>>2]|0;if((f|0)==(b|0)){e=c[d+24>>2]|0;d=e;e=c[e>>2]|0;do{c[d>>2]=e|8;d=c[c[d+36>>2]>>2]|0;if(!d)break b;d=c[d+24>>2]|0;e=c[d>>2]|0}while(!(e&1|0))}else{e=f;d=c[f>>2]|0;do{c[e>>2]=d|8;d=c[(c[e+36>>2]|0)+8>>2]|0;if(!d)break b;e=c[d+20>>2]|0;d=c[e>>2]|0}while(!(d&1|0))}}while(0);g=g+1|0}}while(0);c:do if((+h[b+56>>3]+-3.0-+h[b+40>>3])*.5<2.0){i=c[b+32>>2]|0;j=b+36|0;g=0;while(1){if((g|0)>=(i|0))break c;d=c[(c[j>>2]|0)+(g<<2)>>2]|0;d:do if(!(a[d+36>>0]|0)){f=c[d+20>>2]|0;if((f|0)==(b|0)){e=c[d+24>>2]|0;d=e;e=c[e>>2]|0;do{c[d>>2]=e|16;d=c[(c[d+36>>2]|0)+4>>2]|0;if(!d)break d;d=c[d+24>>2]|0;e=c[d>>2]|0}while(!(e&1|0))}else{e=f;d=c[f>>2]|0;do{c[e>>2]=d|16;d=c[(c[e+36>>2]|0)+12>>2]|0;if(!d)break d;e=c[d+20>>2]|0;d=c[e>>2]|0}while(!(d&1|0))}}while(0);g=g+1|0}}while(0);return}function CG(a,b){a=a|0;b=b|0;var d=0,e=0,f=0.0,g=0.0,i=0.0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0;g=+h[a+56>>3]-+h[a+40>>3];i=+h[a+64>>3]-+h[a+48>>3];f=(i+g)*.5+500.0;if((i+-3.0)*.5<2.0){l=(c[a>>2]&8|0)==0;f=l?16384.0:f;p=l?16384.0:g}else p=g;if((g+-3.0)*.5<2.0){l=(c[a>>2]&16|0)==0;i=l?16384.0:i;f=l?16384.0:f}l=a+36|0;d=c[l>>2]|0;e=c[d+8>>2]|0;if((e|0)!=0?(j=c[d+4>>2]|0,(j|0)!=0):0){j=ZC(b,e,j,f)|0;e=a+4|0;d=c[e>>2]|0;c[e>>2]=d+1;c[a+8+(d<<2)>>2]=j;d=c[l>>2]|0}e=c[d+4>>2]|0;if((e|0)!=0?(k=c[d>>2]|0,(k|0)!=0):0){k=ZC(b,e,k,f)|0;j=a+4|0;d=c[j>>2]|0;c[j>>2]=d+1;c[a+8+(d<<2)>>2]=k;d=c[l>>2]|0}e=c[d+8>>2]|0;if((e|0)!=0?(m=c[d+12>>2]|0,(m|0)!=0):0){m=ZC(b,e,m,f)|0;k=a+4|0;d=c[k>>2]|0;c[k>>2]=d+1;c[a+8+(d<<2)>>2]=m;d=c[l>>2]|0}e=c[d+12>>2]|0;if((e|0)!=0?(n=c[d>>2]|0,(n|0)!=0):0){n=ZC(b,e,n,f)|0;m=a+4|0;d=c[m>>2]|0;c[m>>2]=d+1;c[a+8+(d<<2)>>2]=n;d=c[l>>2]|0}e=c[d+4>>2]|0;if((e|0)!=0?(o=c[d+12>>2]|0,(o|0)!=0):0){o=ZC(b,e,o,i)|0;n=a+4|0;d=c[n>>2]|0;c[n>>2]=d+1;c[a+8+(d<<2)>>2]=o;d=c[l>>2]|0}e=c[d+8>>2]|0;if(e|0?(q=c[d>>2]|0,q|0):0){b=ZC(b,e,q,p)|0;o=a+4|0;q=c[o>>2]|0;c[o>>2]=q+1;c[a+8+(q<<2)>>2]=b}return}function DG(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+16|0;i=j+8|0;h=j;f=a+16|0;g=c[13918]|0;e=0;while(1){if((e|0)>=(c[a>>2]|0)){b=10;break}b=c[f>>2]|0;d=b+(e*40|0)+20|0;if((c[d>>2]|0)==0?(c[h>>2]=e,AL(g,122907,h)|0,(c[d>>2]|0)==0):0){b=5;break}b=b+(e*40|0)+24|0;if((c[b>>2]|0)==0?(c[i>>2]=e,AL(g,122959,i)|0,(c[b>>2]|0)==0):0){b=8;break}e=e+1|0}if((b|0)==5)ma(122929,122942,311,122949);else if((b|0)==8)ma(122981,122942,313,122949);else if((b|0)==10){l=j;return}}function EG(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0.0,f=0.0;e=+h[b+8>>3];f=+h[c+8>>3];if(!(e>f))if(!(e>3];e=+h[c>>3];if(f>e)a=1;else a=(f>31}else a=-1;else a=1;return a|0}function FG(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0.0,f=0.0;e=+h[b>>3];f=+h[c>>3];if(!(e>f))if(!(e>3];e=+h[c+8>>3];if(f>e)a=1;else a=(f>31}else a=-1;else a=1;return a|0}function GG(a){a=a|0;var b=0,d=0;d=a+8|0;$I(c[(c[d>>2]|0)+36>>2]|0);b=a+12|0;$I(c[(c[b>>2]|0)+36>>2]|0);$I(c[d>>2]|0);$I(c[b>>2]|0);$C(c[a+16>>2]|0);Ll(c[a+20>>2]|0)|0;Ll(c[a+24>>2]|0)|0;$I(a);return}function HG(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;p=l;l=l+32|0;h=p;i=b<<2;f=i+4|0;i=i+5|0;o=xw(i*56|0)|0;i=ww(i<<2)|0;g=f*5|1;j=xw(g*72|0)|0;m=g<<5;k=ww(m)|0;m=ww(m)|0;c[h>>2]=c[e>>2];c[h+4>>2]=c[e+4>>2];c[h+8>>2]=c[e+8>>2];c[h+12>>2]=c[e+12>>2];c[h+16>>2]=c[e+16>>2];c[h+20>>2]=c[e+20>>2];c[h+24>>2]=c[e+24>>2];c[h+28>>2]=c[e+28>>2];IG(a,b,h,o,0);zM(173);JG(f,i);TG(f,o,i,g,j)|0;n=KG(f,o,j,0,k)|0;c[h>>2]=c[e>>2];c[h+4>>2]=c[e+4>>2];c[h+8>>2]=c[e+8>>2];c[h+12>>2]=c[e+12>>2];c[h+16>>2]=c[e+16>>2];c[h+20>>2]=c[e+20>>2];c[h+24>>2]=c[e+24>>2];c[h+28>>2]=c[e+28>>2];IG(a,b,h,o,1);JG(f,i);TG(f,o,i,g,j)|0;f=KG(f,o,j,1,m)|0;g=ww(O(n<<5,f)|0)|0;b=0;a=0;while(1){if((b|0)>=(f|0))break;h=m+(b<<5)|0;e=0;while(1){if((e|0)>=(n|0))break;q=a+((LG(g+(a<<5)|0,h,k+(e<<5)|0)|0)!=0&1)|0;e=e+1|0;a=q}b=b+1|0}q=zw(g,a<<5)|0;$I(o);$I(i);$I(j);$I(k);$I(m);c[d>>2]=a;l=p;return q|0}function IG(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0;j=l;l=l+96|0;h=j+64|0;i=j;c[h>>2]=c[d>>2];c[h+4>>2]=c[d+4>>2];c[h+8>>2]=c[d+8>>2];c[h+12>>2]=c[d+12>>2];c[h+16>>2]=c[d+16>>2];c[h+20>>2]=c[d+20>>2];c[h+24>>2]=c[d+24>>2];c[h+28>>2]=c[d+28>>2];RG(h,f,1,i);d=SG(e,1,i)|0;g=0;while(1){if((g|0)>=(b|0))break;k=a+(g*72|0)+40|0;c[h>>2]=c[k>>2];c[h+4>>2]=c[k+4>>2];c[h+8>>2]=c[k+8>>2];c[h+12>>2]=c[k+12>>2];c[h+16>>2]=c[k+16>>2];c[h+20>>2]=c[k+20>>2];c[h+24>>2]=c[k+24>>2];c[h+28>>2]=c[k+28>>2];RG(h,f,0,i);d=SG(e,d,i)|0;g=g+1|0}l=j;return}function JG(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;d=0;while(1){if((d|0)>(a|0))break;c[b+(d<<2)>>2]=d;d=d+1|0}g=a+1|0;d=1;while(1){if((d|0)>(a|0))break;h=~~(+BM()*+(g-d|0)+ +(d|0));e=b+(d<<2)|0;f=b+(h<<2)|0;if((d|0)!=(h|0)){h=c[e>>2]|0;c[e>>2]=c[f>>2];c[f>>2]=h}d=d+1|0}return}function KG(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;g=a*5|0;j=g+1|0;l=ww(j<<2)|0;c[42432]=ww(j<<4)|0;c[42433]=ww((a*56|0)+56|0)|0;j=ww(a<<2)|0;c[42434]=j;k=0;while(1){if((k|0)>(g|0))break;if(MG(d+(k*72|0)|0,b)|0)break;k=k+1|0}h=c[42432]|0;i=c[42433]|0;g=1;while(1){if((g|0)>(a|0))break;c[h+(g<<4)+8>>2]=c[b+(g*56|0)+48>>2];m=b+(g*56|0)+44|0;c[h+(g<<4)+4>>2]=c[m>>2];c[h+(g<<4)>>2]=g;n=i+(g*56|0)|0;o=b+(g*56|0)|0;c[n>>2]=c[o>>2];c[n+4>>2]=c[o+4>>2];c[n+8>>2]=c[o+8>>2];c[n+12>>2]=c[o+12>>2];c[i+(g*56|0)+16>>2]=c[m>>2];c[i+(g*56|0)+32>>2]=g;c[i+(g*56|0)+48>>2]=1;g=g+1|0}c[42435]=a;c[42436]=0;c[j>>2]=1;g=c[d+(k*72|0)+40>>2]|0;if((g|0)<=0){g=c[d+(k*72|0)+48>>2]|0;if((g|0)>0)g=NG(l,f,0,b,d,0,k,g,e,2)|0;else g=0}else g=NG(l,f,0,b,d,0,k,g,e,1)|0;$I(l);$I(c[42432]|0);$I(c[42433]|0);$I(c[42434]|0);return g|0}function LG(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0.0,g=0.0;g=+h[(+h[b>>3]>+h[c>>3]?b:c)>>3];f=+h[(+h[b+16>>3]<+h[c+16>>3]?b:c)+16>>3];h[a+16>>3]=f;h[a>>3]=g;e=+h[(+h[b+8>>3]>+h[c+8>>3]?b:c)+8>>3];d=+h[(+h[b+24>>3]<+h[c+24>>3]?b:c)+24>>3];h[a+24>>3]=d;h[a+8>>3]=e;return !(g>=f)&!(e>=d)&1|0}function MG(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0;f=c[a+4>>2]|0;do if((c[a+68>>2]|0)!=2?!((f|0)<1|(c[a>>2]|0)<1):0){if(!((c[a+40>>2]|0)<1?(c[a+44>>2]|0)<1:0)){if((c[a+48>>2]|0)>=1){a=0;break}if((c[a+52>>2]|0)>=1){a=0;break}}d=+h[b+(f*56|0)+24>>3];e=+h[b+(f*56|0)+8>>3];if(!(d>e+1.0e-07))if(d>3]>+h[b+(f*56|0)>>3]&1;else a=1}else a=0;while(0);return a|0}function NG(a,b,d,e,f,g,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;k=k|0;l=l|0;var m=0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0.0,J=0,K=0.0,L=0,M=0,N=0,O=0,P=0;D=(k|0)==0;C=i;a:while(1){y=f+(C*72|0)|0;if((C|0)<1)break;i=a+(C<<2)|0;if(c[i>>2]|0)break;c[i>>2]=1;v=f+(C*72|0)+8|0;t=f+(C*72|0)+16|0;p=+h[t>>3];w=f+(C*72|0)+24|0;x=f+(C*72|0)+32|0;o=+h[x>>3];if((p>o?(A=c[y>>2]|0,I=+h[e+(A*56|0)>>3],I==+h[e+(A*56|0)+16>>3]):0)?(A=c[f+(C*72|0)+4>>2]|0,K=+h[e+(A*56|0)>>3],K==+h[e+(A*56|0)+16>>3]):0){i=b+(d<<5)|0;if(D){h[i>>3]=I;q=p;p=K}else{h[i>>3]=o;q=-I;o=-K}h[b+(d<<5)+8>>3]=o;h[b+(d<<5)+16>>3]=p;h[b+(d<<5)+24>>3]=q;d=d+1|0}i=f+(C*72|0)+40|0;z=c[i>>2]|0;do if((z|0)<1?(L=f+(C*72|0)+44|0,(c[L>>2]|0)<1):0){i=f+(C*72|0)+48|0;n=f+(C*72|0)+52|0;if((c[i>>2]|0)>0?(M=c[n>>2]|0,(M|0)>0):0){m=c[f+(M*72|0)>>2]|0;l=c[y>>2]|0;if((M|0)==(j|0)){l=OG(g,l,m)|0;d=NG(a,b,d,e,f,g,c[n>>2]|0,C,k,1)|0;g=l;l=1;break}else{l=OG(g,m,l)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,1)|0;g=l;i=n;l=1;break}}d=NG(a,b,d,e,f,g,z,C,k,2)|0;d=NG(a,b,d,e,f,g,c[L>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,1)|0;i=n;l=1}else P=19;while(0);do if((P|0)==19){P=0;A=f+(C*72|0)+48|0;r=c[A>>2]|0;if((r|0)<1?(N=f+(C*72|0)+52|0,(c[N>>2]|0)<1):0){n=f+(C*72|0)+44|0;if((z|0)>0?(O=c[n>>2]|0,(O|0)>0):0){m=c[f+(C*72|0)+4>>2]|0;l=c[f+(z*72|0)+4>>2]|0;if((O|0)==(j|0)){l=OG(g,l,m)|0;d=NG(a,b,d,e,f,g,c[n>>2]|0,C,k,2)|0;g=l;l=2;break}else{l=OG(g,m,l)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;g=l;i=n;l=2;break}}d=NG(a,b,d,e,f,g,z,C,k,2)|0;d=NG(a,b,d,e,f,g,c[n>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;i=N;l=1;break}u=f+(C*72|0)+44|0;s=c[u>>2]|0;m=(s|0)>0;if((z|0)>0){if(m){if((r|0)>0?(E=f+(C*72|0)+52|0,F=c[E>>2]|0,(F|0)>0):0){n=c[f+(F*72|0)>>2]|0;m=c[f+(z*72|0)+4>>2]|0;if(!((l|0)==2&(F|0)==(j|0))?!((l|0)==1&(s|0)==(j|0)):0){l=OG(g,n,m)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[u>>2]|0,C,k,2)|0;g=l;i=E;l=1;break}l=OG(g,m,n)|0;d=NG(a,b,d,e,f,g,c[u>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[E>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[i>>2]|0,C,k,2)|0;g=l;i=A;l=1;break}m=c[y>>2]|0;if(+B(+(+h[x>>3]-+h[e+(m*56|0)+24>>3]))<=1.0e-07?+B(+(+h[w>>3]-+h[e+(m*56|0)+16>>3]))<=1.0e-07:0){n=c[f+(z*72|0)+4>>2]|0;m=c[e+(m*56|0)+44>>2]|0;if((l|0)==1&(z|0)==(j|0)){l=OG(g,m,n)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,l,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[u>>2]|0,C,k,2)|0;g=l;i=f+(C*72|0)+52|0;l=1;break}else{l=OG(g,n,m)|0;d=NG(a,b,d,e,f,g,c[u>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+52>>2]|0,C,k,1)|0;g=l;l=2;break}}n=c[f+(C*72|0)+4>>2]|0;m=c[f+(z*72|0)+4>>2]|0;if((l|0)==1&(s|0)==(j|0)){l=OG(g,m,n)|0;d=NG(a,b,d,e,f,g,c[u>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,l,c[f+(C*72|0)+52>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[A>>2]|0,C,k,1)|0;g=l;l=2;break}else{l=OG(g,n,m)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+52>>2]|0,C,k,1)|0;g=l;i=u;l=2;break}}}else if(!m)break a;if((r|0)>0?(G=f+(C*72|0)+52|0,H=c[G>>2]|0,(H|0)>0):0){n=c[y>>2]|0;if(+B(+(+h[t>>3]-+h[e+(n*56|0)+8>>3]))<=1.0e-07?+B(+(+h[v>>3]-+h[e+(n*56|0)>>3]))<=1.0e-07:0){m=c[f+(H*72|0)>>2]|0;if((l|0)==2&(r|0)==(j|0)){l=OG(g,m,n)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[i>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,l,c[f+(C*72|0)+44>>2]|0,C,k,2)|0;g=l;i=G;l=1;break}else{l=OG(g,n,m)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+44>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[G>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;g=l;i=A;l=1;break}}m=c[f+(H*72|0)>>2]|0;n=c[e+((c[f+(C*72|0)+4>>2]|0)*56|0)+44>>2]|0;if((l|0)==2&(H|0)==(j|0)){l=OG(g,n,m)|0;d=NG(a,b,d,e,f,g,c[G>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[f+(C*72|0)+44>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,l,c[i>>2]|0,C,k,2)|0;g=l;i=A;l=1;break}else{l=OG(g,m,n)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+44>>2]|0,C,k,2)|0;g=l;i=G;l=1;break}}o=+h[t>>3];n=c[y>>2]|0;if(((+B(+(o-+h[e+(n*56|0)+8>>3]))<=1.0e-07?+B(+(+h[v>>3]-+h[e+(n*56|0)>>3]))<=1.0e-07:0)?(J=c[f+(C*72|0)+4>>2]|0,+B(+(+h[x>>3]-+h[e+(J*56|0)+8>>3]))<=1.0e-07):0)?+B(+(+h[w>>3]-+h[e+(J*56|0)>>3]))<=1.0e-07:0)if((l|0)==1){l=OG(g,n,J)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+44>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,l,c[f+(C*72|0)+52>>2]|0,C,k,1)|0;g=l;i=A;l=1;break}else{l=OG(g,J,n)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+52>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[i>>2]|0,C,k,2)|0;g=l;i=f+(C*72|0)+44|0;l=2;break}j=c[f+(C*72|0)+4>>2]|0;if(((+B(+(o-+h[e+(j*56|0)+24>>3]))<=1.0e-07?+B(+(+h[v>>3]-+h[e+(j*56|0)+16>>3]))<=1.0e-07:0)?+B(+(+h[x>>3]-+h[e+(n*56|0)+24>>3]))<=1.0e-07:0)?+B(+(+h[w>>3]-+h[e+(n*56|0)+16>>3]))<=1.0e-07:0){m=c[e+(j*56|0)+44>>2]|0;j=c[e+(n*56|0)+44>>2]|0;if((l|0)==1){l=OG(g,j,m)|0;d=NG(a,b,d,e,f,g,c[i>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+44>>2]|0,C,k,2)|0;d=NG(a,b,d,e,f,l,c[f+(C*72|0)+52>>2]|0,C,k,1)|0;g=l;i=A;l=1;break}else{l=OG(g,m,j)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+52>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,l,c[i>>2]|0,C,k,2)|0;g=l;i=f+(C*72|0)+44|0;l=2;break}}d=NG(a,b,d,e,f,g,z,C,k,2)|0;d=NG(a,b,d,e,f,g,c[A>>2]|0,C,k,1)|0;d=NG(a,b,d,e,f,g,c[f+(C*72|0)+44>>2]|0,C,k,2)|0;i=f+(C*72|0)+52|0;l=1}while(0);j=C;C=c[i>>2]|0}return d|0}function OG(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0;f=l;l=l+16|0;r=f+4|0;i=f;e=(c[42436]|0)+1|0;c[42436]=e;m=c[42433]|0;PG(b,d,r,i);r=c[r>>2]|0;h=c[m+(b*56|0)+32+(r<<2)>>2]|0;i=c[m+(d*56|0)+32+(c[i>>2]<<2)>>2]|0;n=c[42435]|0;g=n+1|0;n=n+2|0;c[42435]=n;q=c[42432]|0;c[q+(g<<4)>>2]=b;c[q+(n<<4)>>2]=d;o=q+(h<<4)+4|0;p=q+(g<<4)+4|0;c[p>>2]=c[o>>2];c[q+(c[o>>2]<<4)+8>>2]=g;c[q+(g<<4)+8>>2]=n;c[q+(n<<4)+4>>2]=g;j=q+(i<<4)+8|0;c[q+(n<<4)+8>>2]=c[j>>2];c[q+(c[j>>2]<<4)+4>>2]=n;c[o>>2]=i;c[j>>2]=h;j=m+(b*56|0)+48|0;o=c[j>>2]|0;i=m+(d*56|0)+48|0;k=c[i>>2]|0;c[m+(b*56|0)+16+(r<<2)>>2]=d;c[m+(b*56|0)+32+(o<<2)>>2]=g;c[m+(b*56|0)+16+(o<<2)>>2]=c[q+(c[p>>2]<<4)>>2];c[m+(d*56|0)+32+(k<<2)>>2]=n;c[m+(d*56|0)+16+(k<<2)>>2]=b;c[j>>2]=(c[j>>2]|0)+1;c[i>>2]=(c[i>>2]|0)+1;d=c[42434]|0;c[d+(a<<2)>>2]=h;c[d+(e<<2)>>2]=g;l=f;return e|0}function PG(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0.0,h=0,i=0,j=0.0,k=0.0,l=0,m=0,n=0;l=c[42433]|0;m=l+(a*56|0)|0;n=l+(b*56|0)|0;f=0;g=-4.0;i=0;while(1){if((i|0)==4)break;h=c[l+(a*56|0)+16+(i<<2)>>2]|0;if((h|0)>=1?(j=+QG(m,l+(h*56|0)|0,n),j>g):0){f=i;g=j}i=i+1|0}c[d>>2]=f;f=0;i=0;g=-4.0;while(1){if((i|0)==4)break;h=c[l+(b*56|0)+16+(i<<2)>>2]|0;if((h|0)>=1?(k=+QG(n,l+(h*56|0)|0,m),k>g):0){f=i;g=k}i=i+1|0}c[e>>2]=f;return}function QG(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0.0,g=0.0,i=0.0;g=+h[a>>3];i=+h[b>>3]-g;d=+h[a+8>>3];f=+h[b+8>>3]-d;g=+h[c>>3]-g;d=+h[c+8>>3]-d;e=d*f+g*i;if(!(d*i-g*f>=0.0))d=-e/(+C(+(d*d+g*g))*+C(+(f*f+i*i)))+-2.0;else d=e/(+C(+(d*d+g*g))*+C(+(f*f+i*i)));return +d}function RG(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0,l=0.0;c[e>>2]=c[a>>2];c[e+4>>2]=c[a+4>>2];c[e+8>>2]=c[a+8>>2];c[e+12>>2]=c[a+12>>2];i=e+32|0;j=a+16|0;c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];c[i+8>>2]=c[j+8>>2];c[i+12>>2]=c[j+12>>2];if(!d){f=a+8|0;g=j;i=a+24|0;d=a}else{f=a+24|0;g=a;i=a+8|0;d=j}k=+h[g>>3];l=+h[i>>3];h[e+16>>3]=+h[d>>3];h[e+24>>3]=l;h[e+48>>3]=k;h[e+56>>3]=+h[f>>3];a:do if(b|0){d=0;while(1){if((d|0)==4)break a;j=e+(d<<4)+8|0;l=+h[j>>3];b=e+(d<<4)|0;h[j>>3]=+h[b>>3];h[b>>3]=-l;d=d+1|0}}while(0);return}function SG(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;h=b+3|0;i=b+1|0;j=b+2|0;k=a+(b*56|0)+44|0;l=a+(h*56|0)+44|0;e=0;f=b;while(1){if((f|0)>(h|0))break;do if((f|0)!=(b|0))if((f|0)==(h|0)){c[l>>2]=b;g=j;break}else{c[a+(f*56|0)+44>>2]=f+1;g=f+-1|0;break}else{c[k>>2]=i;g=h}while(0);c[a+(f*56|0)+48>>2]=g;c[a+(f*56|0)+32>>2]=0;n=a+(f*56|0)|0;m=d+(e<<4)|0;c[n>>2]=c[m>>2];c[n+4>>2]=c[m+4>>2];c[n+8>>2]=c[m+8>>2];c[n+12>>2]=c[m+12>>2];VN(a+(g*56|0)+16|0,m|0,16)|0;e=e+1|0;f=f+1|0}return b+4|0}function TG(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0;c[42437]=e<<1;c[42438]=e;k=ww(e*80|0)|0;c[42439]=1;c[42440]=1;WN(f|0,0,e*72|0)|0;g=UG(c[d+4>>2]|0,b,f,k)|0;e=1;while(1){if((e|0)>(a|0))break;c[b+(e*56|0)+40>>2]=g;c[b+(e*56|0)+36>>2]=g;e=e+1|0}j=VG(a)|0;g=2;i=1;while(1){if((i|0)>(j|0))break;e=WG(a,i+-1|0)|0;h=WG(a,i)|0;while(1){if((e|0)>=(h|0)){e=1;break}XG(c[d+(g<<2)>>2]|0,b,f,k);e=e+1|0;g=g+1|0}while(1){if((e|0)>(a|0))break;YG(e,b,f,k);e=e+1|0}i=i+1|0}e=WG(a,j)|0;while(1){if((e|0)>=(a|0))break;XG(c[d+(g<<2)>>2]|0,b,f,k);g=g+1|0;e=e+1|0}$I(k);return c[42439]|0}function UG(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;f=bH()|0;c[e+(f*40|0)>>2]=2;s=e+(f*40|0)+8|0;k=b+(a*56|0)|0;l=b+(a*56|0)+16|0;fH(s,k,l);n=bH()|0;c[e+(f*40|0)+36>>2]=n;c[e+(n*40|0)>>2]=3;c[e+(n*40|0)+28>>2]=f;j=bH()|0;c[e+(f*40|0)+32>>2]=j;c[e+(j*40|0)>>2]=2;r=e+(j*40|0)+8|0;gH(r,k,l);c[e+(j*40|0)+28>>2]=f;l=bH()|0;c[e+(j*40|0)+32>>2]=l;c[e+(l*40|0)>>2]=3;c[e+(l*40|0)+28>>2]=j;k=bH()|0;c[e+(j*40|0)+36>>2]=k;c[e+(k*40|0)>>2]=1;c[e+(k*40|0)+4>>2]=a;c[e+(k*40|0)+28>>2]=j;j=bH()|0;c[e+(k*40|0)+32>>2]=j;c[e+(j*40|0)>>2]=3;c[e+(j*40|0)+28>>2]=k;g=bH()|0;c[e+(k*40|0)+36>>2]=g;c[e+(g*40|0)>>2]=3;c[e+(g*40|0)+28>>2]=k;k=aH(d)|0;i=aH(d)|0;m=aH(d)|0;o=aH(d)|0;p=d+(k*72|0)+8|0;q=d+(i*72|0)+8|0;t=d+(o*72|0)+24|0;c[t>>2]=c[s>>2];c[t+4>>2]=c[s+4>>2];c[t+8>>2]=c[s+8>>2];c[t+12>>2]=c[s+12>>2];VN(q|0,s|0,16)|0;c[p>>2]=c[q>>2];c[p+4>>2]=c[q+4>>2];c[p+8>>2]=c[q+8>>2];c[p+12>>2]=c[q+12>>2];p=d+(k*72|0)+24|0;q=d+(i*72|0)+24|0;s=d+(m*72|0)+8|0;c[s>>2]=c[r>>2];c[s+4>>2]=c[r+4>>2];c[s+8>>2]=c[r+8>>2];c[s+12>>2]=c[r+12>>2];VN(q|0,r|0,16)|0;c[p>>2]=c[q>>2];c[p+4>>2]=c[q+4>>2];c[p+8>>2]=c[q+8>>2];c[p+12>>2]=c[q+12>>2];h[d+(o*72|0)+16>>3]=1073741824.0;h[d+(o*72|0)+8>>3]=1073741824.0;h[d+(m*72|0)+32>>3]=-1073741824.0;h[d+(m*72|0)+24>>3]=-1073741824.0;c[d+(i*72|0)>>2]=a;c[d+(k*72|0)+4>>2]=a;c[d+(i*72|0)+40>>2]=o;c[d+(k*72|0)+40>>2]=o;c[d+(i*72|0)+48>>2]=m;c[d+(k*72|0)+48>>2]=m;c[d+(m*72|0)+40>>2]=k;c[d+(o*72|0)+48>>2]=k;c[d+(m*72|0)+44>>2]=i;c[d+(o*72|0)+52>>2]=i;c[d+(k*72|0)+56>>2]=j;c[d+(i*72|0)+56>>2]=g;c[d+(m*72|0)+56>>2]=l;c[d+(o*72|0)+56>>2]=n;c[d+(i*72|0)+68>>2]=1;c[d+(k*72|0)+68>>2]=1;c[d+(o*72|0)+68>>2]=1;c[d+(m*72|0)+68>>2]=1;c[e+(n*40|0)+24>>2]=o;c[e+(l*40|0)+24>>2]=m;c[e+(j*40|0)+24>>2]=k;c[e+(g*40|0)+24>>2]=i;c[b+(a*56|0)+32>>2]=1;return f|0}function VG(a){a=a|0;var b=0.0;b=+(a|0);a=0;while(1){if(!(b>=1.0))break;b=+DJ(b);a=a+1|0}return a+-1|0}function WG(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;d=+(a|0);c=d;a=0;while(1){if((a|0)>=(b|0))break;c=+DJ(c);a=a+1|0}return ~~+N(+(d/c))|0}function XG(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0;W=l;l=l+96|0;S=W+32|0;f=W+16|0;T=W;s=S;k=b+(a*56|0)|0;r=s+56|0;do{c[s>>2]=c[k>>2];s=s+4|0;k=k+4|0}while((s|0)<(r|0));U=S+16|0;V=S+24|0;i=+h[V>>3];H=S+8|0;j=+h[H>>3];do if(!(i>j+1.0e-07)){if(!(i>3]>+h[S>>3]:0){G=4;break}G=($G(a,b,1)|0)==0;f=c[S+36>>2]|0;if(G){n=0;G=7}else{f=ZG(S,U,f,b,e)|0;G=20}}else G=4;while(0);if((G|0)==4){c[f>>2]=c[S>>2];c[f+4>>2]=c[S+4>>2];c[f+8>>2]=c[S+8>>2];c[f+12>>2]=c[S+12>>2];c[S>>2]=c[U>>2];c[S+4>>2]=c[U+4>>2];c[S+8>>2]=c[U+8>>2];c[S+12>>2]=c[U+12>>2];c[U>>2]=c[f>>2];c[U+4>>2]=c[f+4>>2];c[U+8>>2]=c[f+8>>2];c[U+12>>2]=c[f+12>>2];E=S+36|0;F=c[E>>2]|0;G=S+40|0;f=c[G>>2]|0;c[E>>2]=f;c[G>>2]=F;if(!($G(a,b,2)|0)){n=1;G=7}else{f=ZG(S,U,f,b,e)|0;G=19}}if((G|0)==7){m=ZG(S,U,f,b,e)|0;f=aH(d)|0;c[d+(f*72|0)+68>>2]=1;s=d+(f*72|0)|0;k=d+(m*72|0)|0;r=s+72|0;do{c[s>>2]=c[k>>2];s=s+4|0;k=k+4|0}while((s|0)<(r|0));q=+h[H>>3];h[d+(f*72|0)+16>>3]=q;h[d+(m*72|0)+32>>3]=q;q=+h[S>>3];h[d+(f*72|0)+8>>3]=q;h[d+(m*72|0)+24>>3]=q;c[d+(m*72|0)+48>>2]=f;c[d+(m*72|0)+52>>2]=0;c[d+(f*72|0)+40>>2]=m;c[d+(f*72|0)+44>>2]=0;g=c[d+(f*72|0)+48>>2]|0;if((g|0)>0){k=d+(g*72|0)+40|0;if((c[k>>2]|0)==(m|0))c[k>>2]=f;g=d+(g*72|0)+44|0;if((c[g>>2]|0)==(m|0))c[g>>2]=f}g=c[d+(f*72|0)+52>>2]|0;if((g|0)>0){k=d+(g*72|0)+40|0;if((c[k>>2]|0)==(m|0))c[k>>2]=f;g=d+(g*72|0)+44|0;if((c[g>>2]|0)==(m|0))c[g>>2]=f}E=bH()|0;G=bH()|0;F=d+(m*72|0)+56|0;D=c[F>>2]|0;c[e+(D*40|0)>>2]=2;C=e+(D*40|0)+8|0;c[C>>2]=c[S>>2];c[C+4>>2]=c[S+4>>2];c[C+8>>2]=c[S+8>>2];c[C+12>>2]=c[S+12>>2];c[e+(D*40|0)+4>>2]=a;c[e+(D*40|0)+32>>2]=G;c[e+(D*40|0)+36>>2]=E;c[e+(E*40|0)>>2]=3;c[e+(E*40|0)+24>>2]=m;c[e+(E*40|0)+28>>2]=D;c[e+(G*40|0)>>2]=3;c[e+(G*40|0)+24>>2]=f;c[e+(G*40|0)+28>>2]=D;c[F>>2]=E;c[d+(f*72|0)+56>>2]=G;if(n)G=19;else G=20}if((G|0)==19)if(!($G(a,b,1)|0)){g=1;G=21}else{g=1;G=32}else if((G|0)==20)if(!($G(a,b,2)|0)){g=0;G=21}else{g=0;G=32}if((G|0)==21){o=ZG(U,S,c[S+40>>2]|0,b,e)|0;n=aH(d)|0;c[d+(n*72|0)+68>>2]=1;s=d+(n*72|0)|0;k=d+(o*72|0)|0;r=s+72|0;do{c[s>>2]=c[k>>2];s=s+4|0;k=k+4|0}while((s|0)<(r|0));q=+h[V>>3];h[d+(n*72|0)+16>>3]=q;h[d+(o*72|0)+32>>3]=q;q=+h[U>>3];h[d+(n*72|0)+8>>3]=q;h[d+(o*72|0)+24>>3]=q;c[d+(o*72|0)+48>>2]=n;c[d+(o*72|0)+52>>2]=0;c[d+(n*72|0)+40>>2]=o;c[d+(n*72|0)+44>>2]=0;k=c[d+(n*72|0)+48>>2]|0;if((k|0)>0){m=d+(k*72|0)+40|0;if((c[m>>2]|0)==(o|0))c[m>>2]=n;k=d+(k*72|0)+44|0;if((c[k>>2]|0)==(o|0))c[k>>2]=n}k=c[d+(n*72|0)+52>>2]|0;if((k|0)>0){m=d+(k*72|0)+40|0;if((c[m>>2]|0)==(o|0))c[m>>2]=n;k=d+(k*72|0)+44|0;if((c[k>>2]|0)==(o|0))c[k>>2]=n}D=bH()|0;F=bH()|0;E=d+(o*72|0)+56|0;C=c[E>>2]|0;c[e+(C*40|0)>>2]=2;A=e+(C*40|0)+8|0;c[A>>2]=c[U>>2];c[A+4>>2]=c[U+4>>2];c[A+8>>2]=c[U+8>>2];c[A+12>>2]=c[U+12>>2];c[e+(C*40|0)+4>>2]=a;c[e+(C*40|0)+32>>2]=F;c[e+(C*40|0)+36>>2]=D;c[e+(D*40|0)>>2]=3;c[e+(D*40|0)+24>>2]=o;c[e+(D*40|0)+28>>2]=C;c[e+(F*40|0)>>2]=3;c[e+(F*40|0)+24>>2]=n;c[e+(F*40|0)+28>>2]=C;c[E>>2]=D;c[d+(n*72|0)+56>>2]=F;F=f;f=0}else if((G|0)==32){F=f;o=ZG(U,S,c[S+40>>2]|0,b,e)|0;f=1}a:do if((F|0)>0){D=d+(o*72|0)+24|0;E=d+(o*72|0)+32|0;C=(f|0)!=0;y=g?b+(a*56|0)+48|0:b+(a*56|0)+44|0;z=T+8|0;g=0;f=0;x=F;b:while(1){k=d+(x*72|0)|0;v=d+(x*72|0)+24|0;if(!(cH(v,D)|0))break a;m=d+(x*72|0)+56|0;u=c[m>>2]|0;n=bH()|0;p=bH()|0;c[e+(u*40|0)>>2]=1;c[e+(u*40|0)+4>>2]=a;c[e+(u*40|0)+32>>2]=n;c[e+(u*40|0)+36>>2]=p;c[e+(n*40|0)>>2]=3;c[e+(n*40|0)+24>>2]=x;c[e+(n*40|0)+28>>2]=u;c[e+(p*40|0)>>2]=3;w=aH(d)|0;c[e+(p*40|0)+24>>2]=w;A=d+(w*72|0)|0;c[d+(w*72|0)+68>>2]=1;c[e+(p*40|0)+28>>2]=u;g=(x|0)==(F|0)?w:g;u=d+(x*72|0)+32|0;if(+B(+(+h[u>>3]-+h[E>>3]))<=1.0e-07?+B(+(+h[v>>3]-+h[D>>3]))<=1.0e-07:0)f=w;s=A;r=s+72|0;do{c[s>>2]=c[k>>2];s=s+4|0;k=k+4|0}while((s|0)<(r|0));c[m>>2]=n;c[d+(w*72|0)+56>>2]=p;t=d+(x*72|0)+48|0;m=d+(x*72|0)+52|0;k=(c[m>>2]|0)<1;do if((c[t>>2]|0)<1){if(k)break b;s=d+(x*72|0)+40|0;k=c[s>>2]|0;do if((k|0)>0?(M=d+(x*72|0)+44|0,N=c[M>>2]|0,(N|0)>0):0){r=d+(x*72|0)+60|0;k=c[r>>2]|0;if((k|0)<=0){c[d+(w*72|0)+40>>2]=N;c[d+(w*72|0)+44>>2]=-1;c[M>>2]=-1;c[d+(N*72|0)+48>>2]=w;break}if((c[d+(x*72|0)+64>>2]|0)==1){c[d+(w*72|0)+40>>2]=N;c[M>>2]=-1;c[d+(w*72|0)+44>>2]=k;c[d+((c[s>>2]|0)*72|0)+48>>2]=x;p=w;n=N}else{c[d+(w*72|0)+44>>2]=-1;t=d+(w*72|0)+40|0;c[t>>2]=c[M>>2];n=c[s>>2]|0;c[M>>2]=n;c[s>>2]=k;c[d+(k*72|0)+48>>2]=x;p=x;k=c[t>>2]|0}c[d+(n*72|0)+48>>2]=p;c[d+(k*72|0)+48>>2]=w;c[d+(w*72|0)+60>>2]=0;c[r>>2]=0}else G=77;while(0);do if((G|0)==77){G=0;n=d+(k*72|0)+48|0;p=c[n>>2]|0;k=d+(k*72|0)+52|0;if((p|0)>0?(c[k>>2]|0)>0:0){k=c[d+(p*72|0)+4>>2]|0;if((k|0)>0?(_G(k,b,U)|0)==0:0){c[d+(w*72|0)+44>>2]=-1;c[d+(x*72|0)+44>>2]=-1;c[s>>2]=-1;c[d+((c[d+(w*72|0)+40>>2]|0)*72|0)+52>>2]=w;break}c[d+(x*72|0)+44>>2]=-1;c[d+(w*72|0)+44>>2]=-1;c[d+(w*72|0)+40>>2]=-1;c[d+((c[s>>2]|0)*72|0)+48>>2]=x;break}c[n>>2]=x;c[k>>2]=w}while(0);if(+B(+(+h[u>>3]-+h[E>>3]))<=1.0e-07?C&+B(+(+h[v>>3]-+h[D>>3]))<=1.0e-07:0){k=c[y>>2]|0;if((k|0)>0?(_G(k,b,S)|0)!=0:0){c[d+((c[m>>2]|0)*72|0)+40>>2]=x;n=d+(w*72|0)+52|0;k=w}else{c[d+((c[d+(w*72|0)+52>>2]|0)*72|0)+44>>2]=w;n=m;k=x}c[n>>2]=-1;c[d+(k*72|0)+48>>2]=-1;k=c[m>>2]|0;break}k=c[m>>2]|0;m=d+(k*72|0)+40|0;n=c[m>>2]|0;p=d+(k*72|0)+44|0;if((n|0)>0?(O=c[p>>2]|0,P=(n|0)==(x|0),(O|0)>0):0){c[d+(k*72|0)+60>>2]=P?O:n;c[d+(k*72|0)+64>>2]=P?1:2}c[m>>2]=x;c[p>>2]=w}else{if(!k){i=+h[u>>3];j=+h[H>>3];q=i-j;if(!(+B(+q)<=1.0e-07)){h[z>>3]=i;i=+h[S>>3];h[T>>3]=(+h[U>>3]-i)*(q/(+h[V>>3]-j))+i;s=(dH(T,v)|0)!=0}else s=+h[v>>3]>+h[S>>3];r=d+(x*72|0)+40|0;k=c[r>>2]|0;do if((k|0)>0?(Q=d+(x*72|0)+44|0,R=c[Q>>2]|0,(R|0)>0):0){p=d+(x*72|0)+60|0;k=c[p>>2]|0;if((k|0)<=0){c[d+(w*72|0)+40>>2]=R;c[d+(w*72|0)+44>>2]=-1;c[Q>>2]=-1;c[d+(R*72|0)+48>>2]=w;break}if((c[d+(x*72|0)+64>>2]|0)==1){c[d+(w*72|0)+40>>2]=R;c[Q>>2]=-1;c[d+(w*72|0)+44>>2]=k;c[d+((c[r>>2]|0)*72|0)+48>>2]=x;n=w;m=R}else{c[d+(w*72|0)+44>>2]=-1;X=d+(w*72|0)+40|0;c[X>>2]=c[Q>>2];m=c[r>>2]|0;c[Q>>2]=m;c[r>>2]=k;c[d+(k*72|0)+48>>2]=x;n=x;k=c[X>>2]|0}c[d+(m*72|0)+48>>2]=n;c[d+(k*72|0)+48>>2]=w;c[d+(w*72|0)+60>>2]=0;c[p>>2]=0}else G=106;while(0);do if((G|0)==106){G=0;m=d+(k*72|0)+48|0;n=c[m>>2]|0;k=d+(k*72|0)+52|0;if((n|0)>0?(c[k>>2]|0)>0:0){k=c[d+(n*72|0)+4>>2]|0;if((k|0)>0?(_G(k,b,U)|0)==0:0){c[d+(w*72|0)+44>>2]=-1;c[d+(x*72|0)+44>>2]=-1;c[r>>2]=-1;c[d+((c[d+(w*72|0)+40>>2]|0)*72|0)+52>>2]=w;break}c[d+(x*72|0)+44>>2]=-1;c[d+(w*72|0)+44>>2]=-1;c[d+(w*72|0)+40>>2]=-1;c[d+((c[r>>2]|0)*72|0)+48>>2]=x;break}c[m>>2]=x;c[k>>2]=w}while(0);if(+B(+(+h[u>>3]-+h[E>>3]))<=1.0e-07?C&+B(+(+h[v>>3]-+h[D>>3]))<=1.0e-07:0){k=c[t>>2]|0;c[d+(k*72|0)+40>>2]=x;c[d+(k*72|0)+44>>2]=-1;k=d+(x*72|0)+52|0;X=c[k>>2]|0;c[d+(X*72|0)+40>>2]=w;c[d+(X*72|0)+44>>2]=-1;c[d+(w*72|0)+48>>2]=X;c[d+(w*72|0)+52>>2]=-1;c[k>>2]=-1;k=-1}else G=116;do if((G|0)==116){G=0;k=c[t>>2]|0;c[d+(k*72|0)+40>>2]=x;m=d+(k*72|0)+44|0;if(s){c[m>>2]=w;X=d+(x*72|0)+52|0;v=c[X>>2]|0;c[d+(v*72|0)+40>>2]=w;c[d+(v*72|0)+44>>2]=-1;c[X>>2]=-1;break}else{c[m>>2]=-1;k=d+(x*72|0)+52|0;X=c[k>>2]|0;c[d+(X*72|0)+40>>2]=x;c[d+(X*72|0)+44>>2]=w;c[d+(w*72|0)+48>>2]=X;c[d+(w*72|0)+52>>2]=-1;k=c[k>>2]|0;break}}while(0);break}s=d+(x*72|0)+40|0;k=c[s>>2]|0;do if((k|0)>0?(I=d+(x*72|0)+44|0,J=c[I>>2]|0,(J|0)>0):0){r=d+(x*72|0)+60|0;k=c[r>>2]|0;if((k|0)<=0){c[d+(w*72|0)+40>>2]=J;c[d+(w*72|0)+44>>2]=-1;c[I>>2]=-1;c[d+(J*72|0)+48>>2]=w;break}if((c[d+(x*72|0)+64>>2]|0)==1){c[d+(w*72|0)+40>>2]=J;c[I>>2]=-1;c[d+(w*72|0)+44>>2]=k;c[d+((c[s>>2]|0)*72|0)+48>>2]=x;p=w;n=J}else{c[d+(w*72|0)+44>>2]=-1;X=d+(w*72|0)+40|0;c[X>>2]=c[I>>2];n=c[s>>2]|0;c[I>>2]=n;c[s>>2]=k;c[d+(k*72|0)+48>>2]=x;p=x;k=c[X>>2]|0}c[d+(n*72|0)+48>>2]=p;c[d+(k*72|0)+48>>2]=w;c[d+(w*72|0)+60>>2]=0;c[r>>2]=0}else G=51;while(0);do if((G|0)==51){G=0;n=d+(k*72|0)+48|0;p=c[n>>2]|0;k=d+(k*72|0)+52|0;if((p|0)>0?(c[k>>2]|0)>0:0){k=c[d+(p*72|0)+4>>2]|0;if((k|0)>0?(_G(k,b,U)|0)==0:0){c[d+(w*72|0)+44>>2]=-1;c[d+(x*72|0)+44>>2]=-1;c[s>>2]=-1;c[d+((c[d+(w*72|0)+40>>2]|0)*72|0)+52>>2]=w;break}c[d+(x*72|0)+44>>2]=-1;c[d+(w*72|0)+44>>2]=-1;c[d+(w*72|0)+40>>2]=-1;c[d+((c[s>>2]|0)*72|0)+48>>2]=x;break}c[n>>2]=x;c[k>>2]=w}while(0);if(+B(+(+h[u>>3]-+h[E>>3]))<=1.0e-07?C&+B(+(+h[v>>3]-+h[D>>3]))<=1.0e-07:0){k=c[y>>2]|0;if((k|0)>0?(_G(k,b,S)|0)!=0:0){c[d+((c[t>>2]|0)*72|0)+40>>2]=x;m=d+(w*72|0)+52|0;k=w}else{c[d+((c[d+(w*72|0)+48>>2]|0)*72|0)+44>>2]=w;k=x}c[m>>2]=-1;c[d+(k*72|0)+48>>2]=-1;k=c[t>>2]|0;break}k=c[t>>2]|0;m=d+(k*72|0)+40|0;n=c[m>>2]|0;p=d+(k*72|0)+44|0;if((n|0)>0?(K=c[p>>2]|0,L=(n|0)==(x|0),(K|0)>0):0){c[d+(k*72|0)+60>>2]=L?K:n;c[d+(k*72|0)+64>>2]=L?1:2}c[m>>2]=x;c[p>>2]=w}while(0);c[A>>2]=a;c[d+(x*72|0)+4>>2]=a;if((k|0)>0)x=k;else break a}YL(123235,19,1,c[13918]|0)|0}else{g=0;f=0}while(0);eH(a,F,o,1,d,e);eH(a,g,f,2,d,e);c[b+(a*56|0)+32>>2]=1;l=W;return}function YG(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;if(!(c[b+(a*56|0)+32>>2]|0)){f=b+(a*56|0)|0;g=b+(a*56|0)+16|0;h=b+(a*56|0)+36|0;c[h>>2]=c[d+((ZG(f,g,c[h>>2]|0,b,e)|0)*72|0)+56>>2];a=b+(a*56|0)+40|0;c[a>>2]=c[d+((ZG(g,f,c[a>>2]|0,b,e)|0)*72|0)+56>>2]}return}function ZG(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0.0,i=0,j=0.0,k=0.0,l=0.0,m=0.0,n=0.0,o=0,p=0.0,q=0,r=0;o=a+8|0;q=b+8|0;a:while(1){b:do switch(c[f+(d*40|0)>>2]|0){case 3:{r=3;break a}case 2:{g=+h[o>>3];i=f+(d*40|0)+8|0;j=+h[f+(d*40|0)+16>>3];k=j+1.0e-07;do if(!(g>k)){l=j+-1.0e-07;if(!(g>3]>+h[i>>3]:0)break;if(+B(+(g-j))<=1.0e-07?(m=+h[i>>3],+B(+(+h[a>>3]-m))<=1.0e-07):0){g=+h[q>>3];do if(!(g>k)){if(!(g>3]>m:0)break;d=f+(d*40|0)+32|0;break b}while(0);d=f+(d*40|0)+36|0;break b}d=f+(d*40|0)+32|0;break b}while(0);d=f+(d*40|0)+36|0;break}case 1:{g=+h[o>>3];i=c[f+(d*40|0)+4>>2]|0;if(+B(+(g-+h[e+(i*56|0)+8>>3]))<=1.0e-07?(n=+h[a>>3],+B(+(n-+h[e+(i*56|0)>>3]))<=1.0e-07):0)j=n;else r=19;do if((r|0)==19){r=0;if(+B(+(g-+h[e+(i*56|0)+24>>3]))<=1.0e-07?(p=+h[a>>3],+B(+(p-+h[e+(i*56|0)+16>>3]))<=1.0e-07):0){j=p;break}if(!(_G(i,e,a)|0)){d=f+(d*40|0)+36|0;break b}else{d=f+(d*40|0)+32|0;break b}}while(0);if(!(+B(+(g-+h[q>>3]))<=1.0e-07))if(!(_G(i,e,b)|0)){d=f+(d*40|0)+36|0;break b}else{d=f+(d*40|0)+32|0;break b}else if(+h[b>>3]>2]|0}if((r|0)==3)return c[f+(d*40|0)+24>>2]|0;else if((r|0)==31){YL(123169,35,1,c[13918]|0)|0;ma(123205,123207,349,123219)}return 0}function _G(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0,g=0.0,i=0,j=0,k=0.0;f=b+(a*56|0)+16|0;g=+h[b+(a*56|0)+24>>3];i=b+(a*56|0)|0;e=+h[b+(a*56|0)+8>>3];do if(!(g>e+1.0e-07)){if(!(g>3]>+h[i>>3]:0){j=4;break}d=+h[c+8>>3];if(+B(+(g-d))<=1.0e-07){d=+h[c>>3]<+h[f>>3]?1.0:-1.0;break}if(!(+B(+(e-d))<=1.0e-07)){k=+h[f>>3];d=(+h[i>>3]-k)*(d-g)-(+h[c>>3]-k)*(e-g);break}else{d=+h[c>>3]<+h[i>>3]?1.0:-1.0;break}}else j=4;while(0);do if((j|0)==4){d=+h[c+8>>3];if(+B(+(g-d))<=1.0e-07){d=+h[c>>3]<+h[f>>3]?1.0:-1.0;break}if(!(+B(+(e-d))<=1.0e-07)){k=+h[i>>3];d=(+h[f>>3]-k)*(d-e)-(+h[c>>3]-k)*(g-e);break}else{d=+h[c>>3]<+h[i>>3]?1.0:-1.0;break}}while(0);return d>0.0|0}function $G(a,b,d){a=a|0;b=b|0;d=d|0;return c[b+((c[((d|0)==1?b+(a*56|0)+48|0:b+(a*56|0)+44|0)>>2]|0)*56|0)+32>>2]|0}function aH(a){a=a|0;var b=0,d=0,e=0;e=l;l=l+16|0;d=e;b=c[42439]|0;if((b|0)<(c[42438]|0)){c[a+(b*72|0)>>2]=-1;c[a+(b*72|0)+4>>2]=-1;c[a+(b*72|0)+68>>2]=1;c[42439]=b+1;l=e;return b|0}else{e=c[13918]|0;c[d>>2]=b;AL(e,123294,d)|0;ma(123205,123207,88,123332)}return 0}function bH(){var a=0;a=c[42440]|0;if((a|0)<(c[42437]|0)){c[42440]=a+1;return a|0}else{YL(123255,30,1,c[13918]|0)|0;ma(123205,123207,72,123286)}return 0}function cH(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;c=+h[a+8>>3];d=+h[b+8>>3];if(!(c>d+1.0e-07))if(c>3]>=+h[b>>3]&1;else a=1;return a|0}function dH(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;c=+h[a+8>>3];d=+h[b+8>>3];if(!(cd+1.0e-07)a=0;else a=+h[a>>3]<+h[b>>3]&1;else a=1;return a|0}function eH(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;q=f+(d*72|0)+24|0;p=(e|0)==1;a:while(1){o=f+(b*72|0)+24|0;j=f+(b*72|0)+48|0;k=f+(b*72|0)+52|0;l=f+(b*72|0)|0;m=f+(b*72|0)+4|0;n=f+(b*72|0)+56|0;if((b|0)<=0)break;while(1){if(!(cH(o,q)|0))break a;d=c[j>>2]|0;e=(d|0)>0;do if(p){if(e?(c[f+(d*72|0)+4>>2]|0)==(a|0):0)break;d=c[k>>2]|0;if((d|0)<=0){b=d;continue a}if((c[f+(d*72|0)+4>>2]|0)!=(a|0)){b=d;continue a}}else{if(e?(c[f+(d*72|0)>>2]|0)==(a|0):0)break;d=c[k>>2]|0;if((d|0)<=0){b=d;continue a}if((c[f+(d*72|0)>>2]|0)!=(a|0)){b=d;continue a}}while(0);if((c[l>>2]|0)!=(c[f+(d*72|0)>>2]|0)){b=d;continue a}if((c[m>>2]|0)!=(c[f+(d*72|0)+4>>2]|0)){b=d;continue a}r=c[f+(d*72|0)+56>>2]|0;e=c[g+(r*40|0)+28>>2]|0;h=g+(e*40|0)+32|0;i=c[n>>2]|0;if((c[h>>2]|0)==(r|0))c[h>>2]=i;else c[g+(e*40|0)+36>>2]=i;e=c[f+(d*72|0)+48>>2]|0;c[j>>2]=e;do if((e|0)>0){h=f+(e*72|0)+40|0;if((c[h>>2]|0)==(d|0)){c[h>>2]=b;break}e=f+(e*72|0)+44|0;if((c[e>>2]|0)==(d|0))c[e>>2]=b}while(0);e=c[f+(d*72|0)+52>>2]|0;c[k>>2]=e;do if((e|0)>0){h=f+(e*72|0)+40|0;if((c[h>>2]|0)==(d|0)){c[h>>2]=b;break}e=f+(e*72|0)+44|0;if((c[e>>2]|0)==(d|0))c[e>>2]=b}while(0);r=f+(d*72|0)+24|0;c[o>>2]=c[r>>2];c[o+4>>2]=c[r+4>>2];c[o+8>>2]=c[r+8>>2];c[o+12>>2]=c[r+12>>2];c[f+(d*72|0)+68>>2]=2}}return}function fH(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0.0;e=+h[b+8>>3];f=+h[d+8>>3];do if(!(e>f+1.0e-07)){if(!(+B(+(e-f))<=1.0e-07)){c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];break}if(+h[b>>3]>+h[d>>3]+1.0e-07){c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];break}else{c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];break}}else{c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2]}while(0);return}function gH(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0.0;e=+h[b+8>>3];f=+h[d+8>>3];do if(!(e>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];break}if(+h[b>>3]<+h[d>>3]){c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];break}else{c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];break}}else{c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2]}while(0);return}function hH(a){a=a|0;var b=0;b=ww(8)|0;if(b|0){c[b+4>>2]=a;c[b>>2]=0}return b|0}function iH(a,b){a=a|0;b=b|0;if(b){b=hH(b)|0;c[b>>2]=a;a=b}return a|0}function jH(a){a=a|0;var b=0;do{b=a;a=c[a>>2]|0;$I(b)}while((a|0)!=0);return}function kH(){var a=0;a=ww(1992)|0;if(a|0)c[a>>2]=lH(a)|0;return a|0}function lH(a){a=a|0;var b=0;b=rH(a)|0;c[b+4>>2]=0;a=a+1972|0;c[a>>2]=(c[a>>2]|0)+1;return b|0}function mH(a){a=a|0;nH(a,c[a>>2]|0);$I(c[a>>2]|0);$I(a);return 0}function nH(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;g=a+1980|0;h=a+1912|0;i=a+1936|0;a:do if((c[b+4>>2]|0)>0){d=0;while(1){if((d|0)==64)break a;e=b+8+(d*20|0)+16|0;f=c[e>>2]|0;if(f|0?(nH(a,f),$I(c[e>>2]|0),xH(b,d),c[g>>2]=(c[g>>2]|0)+-1,c[h>>2]|0):0)c[i>>2]=(c[i>>2]|0)+1;d=d+1|0}}else{d=0;while(1){if((d|0)==64)break a;if(c[b+8+(d*20|0)+16>>2]|0?(xH(b,d),c[g>>2]=(c[g>>2]|0)+-1,c[h>>2]|0):0)c[i>>2]=(c[i>>2]|0)+1;d=d+1|0}}while(0);return}function oH(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;if(!b)ma(123690,123340,194,123348);e=c[b+4>>2]|0;if((e|0)<=-1)ma(123360,123340,195,123348);if(!d)ma(123632,123340,196,123348);i=a+1952|0;c[i>>2]=(c[i>>2]|0)+1;a:do if((e|0)>0){i=0;e=0;while(1){if((i|0)==64)break a;f=b+8+(i*20|0)+16|0;if((c[f>>2]|0)!=0?(CH(d,b+8+(i*20|0)|0)|0)!=0:0){g=oH(a,c[f>>2]|0,d)|0;if(!e)e=g;else{f=e;while(1){h=c[f>>2]|0;if(!h)break;else f=h}c[f>>2]=g}}i=i+1|0}}else{g=0;e=0;while(1){if((g|0)==64)break a;f=b+8+(g*20|0)|0;if((c[b+8+(g*20|0)+16>>2]|0)!=0?(CH(d,f)|0)!=0:0)e=iH(e,f)|0;g=g+1|0}}while(0);return e|0}function pH(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;p=l;l=l+64|0;k=p+52|0;m=p+32|0;n=p+16|0;o=p;c[k>>2]=0;if(!((b|0)!=0&(e|0)!=0))ma(123546,123340,247,123374);if((f|0)>-1?(j=c[e>>2]|0,(c[j+4>>2]|0)>=(f|0)):0){g=0;while(1){if((g|0)>=2)break;if((c[b+(g<<2)>>2]|0)>(c[b+(g+2<<2)>>2]|0)){h=8;break}else g=g+1|0}if((h|0)==8)ma(123421,123340,250,123374);i=a+1912|0;g=a+1908|0;h=c[g>>2]|0;if(c[i>>2]|0){q=h|0?a+1924|0:a+1916|0;c[q>>2]=(c[q>>2]|0)+1}if(!h){q=a+1964|0;c[q>>2]=(c[q>>2]|0)+1}if(!(qH(a,b,d,j,k,f)|0))g=0;else{if(c[i>>2]|0){q=c[g>>2]|0?a+1948|0:a+1944|0;c[q>>2]=(c[q>>2]|0)+1}g=rH(a)|0;q=a+1976|0;c[q>>2]=(c[q>>2]|0)+1;q=c[e>>2]|0;c[g+4>>2]=(c[q+4>>2]|0)+1;uH(n,q);c[m>>2]=c[n>>2];c[m+4>>2]=c[n+4>>2];c[m+8>>2]=c[n+8>>2];c[m+12>>2]=c[n+12>>2];q=m+16|0;c[q>>2]=c[e>>2];wH(a,m,g,0)|0;uH(o,c[k>>2]|0);c[m>>2]=c[o>>2];c[m+4>>2]=c[o+4>>2];c[m+8>>2]=c[o+8>>2];c[m+12>>2]=c[o+12>>2];c[q>>2]=c[k>>2];wH(a,m,g,0)|0;c[e>>2]=g;g=a+1980|0;c[g>>2]=(c[g>>2]|0)+2;g=1}l=p;return g|0}ma(123386,123340,248,123374);return 0}function qH(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;q=l;l=l+80|0;m=q+52|0;n=q+48|0;o=q+32|0;p=q+16|0;k=q;c[n>>2]=0;if(!((b|0)!=0&(e|0)!=0&(f|0)!=0))ma(123464,123340,311,123478);if((g|0)>-1?(i=e+4|0,h=c[i>>2]|0,(h|0)>=(g|0)):0){if(c[a+1912>>2]|0){h=c[a+1908>>2]|0?a+1948|0:a+1944|0;c[h>>2]=(c[h>>2]|0)+1;h=c[i>>2]|0}do if((h|0)>(g|0)){i=vH(b,e)|0;h=e+8+(i*20|0)+16|0;i=e+8+(i*20|0)|0;if(!(qH(a,b,d,c[h>>2]|0,n,g)|0)){BH(o,b,i);c[i>>2]=c[o>>2];c[i+4>>2]=c[o+4>>2];c[i+8>>2]=c[o+8>>2];c[i+12>>2]=c[o+12>>2];j=0;break}else{uH(p,c[h>>2]|0);c[i>>2]=c[p>>2];c[i+4>>2]=c[p+4>>2];c[i+8>>2]=c[p+8>>2];c[i+12>>2]=c[p+12>>2];j=c[n>>2]|0;c[m+16>>2]=j;uH(k,j);c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];c[m+8>>2]=c[k+8>>2];c[m+12>>2]=c[k+12>>2];j=a+1980|0;c[j>>2]=(c[j>>2]|0)+1;j=wH(a,m,e,f)|0;break}}else if((h|0)==(g|0)){c[m>>2]=c[b>>2];c[m+4>>2]=c[b+4>>2];c[m+8>>2]=c[b+8>>2];c[m+12>>2]=c[b+12>>2];c[m+16>>2]=d;j=a+1980|0;c[j>>2]=(c[j>>2]|0)+1;j=wH(a,m,e,f)|0;break}else ma(123523,123340,341,123478);while(0);l=q;return j|0}ma(123491,123340,312,123478);return 0}function rH(a){a=a|0;a=a+1968|0;c[a>>2]=(c[a>>2]|0)+1;a=_I(1288)|0;sH(a);return a|0}function sH(a){a=a|0;var b=0;c[a>>2]=0;c[a+4>>2]=-1;b=0;while(1){if((b|0)==64)break;tH(a+8+(b*20|0)|0);b=b+1|0}return}function tH(a){a=a|0;yH(a);c[a+16>>2]=0;return}function uH(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+32|0;g=i+16|0;h=i;if(!b)ma(123690,123529,99,123536);yH(g);d=1;f=0;while(1){if((f|0)==64)break;do if(c[b+8+(f*20|0)+16>>2]|0){e=b+8+(f*20|0)|0;if(!d){BH(h,g,e);c[g>>2]=c[h>>2];c[g+4>>2]=c[h+4>>2];c[g+8>>2]=c[h+8>>2];c[g+12>>2]=c[h+12>>2];d=0;break}else{c[g>>2]=c[e>>2];c[g+4>>2]=c[e+4>>2];c[g+8>>2]=c[e+8>>2];c[g+12>>2]=c[e+12>>2];d=0;break}}while(0);f=f+1|0}c[a>>2]=c[g>>2];c[a+4>>2]=c[g+4>>2];c[a+8>>2]=c[g+8>>2];c[a+12>>2]=c[g+12>>2];l=i;return}function vH(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;k=l;l=l+32|0;i=k+16|0;j=k;if(!((a|0)!=0&(b|0)!=0))ma(123546,123529,125,123553);d=0;e=0;f=0;g=1;h=0;while(1){if((h|0)==64)break;if(c[b+8+(h*20|0)+16>>2]|0){n=b+8+(h*20|0)|0;p=AH(n)|0;BH(j,a,n);c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];c[i+8>>2]=c[j+8>>2];c[i+12>>2]=c[j+12>>2];n=(AH(i)|0)-p|0;m=(g|0)!=0|(n|0)<(f|0);o=m|(p|0)<(e|0)&(n|0)==(f|0);d=o?h:d;e=o?p:e;f=o?n:f;g=m?0:g}h=h+1|0}l=k;return d|0}function wH(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;if(!b)ma(123712,123529,167,123564);if(!d)ma(123690,123529,168,123564);do if((c[d>>2]|0)<64){a=0;while(1){if((a|0)>=64){e=10;break}if(!(c[d+8+(a*20|0)+16>>2]|0)){e=8;break}a=a+1|0}if((e|0)==8){f=d+8+(a*20|0)|0;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];c[f+16>>2]=c[b+16>>2];f=0;g=d;break}else if((e|0)==10)ma(123574,123529,178,123564)}else{if(c[a+1912>>2]|0){h=c[a+1908>>2]|0?a+1948|0:a+1944|0;c[h>>2]=(c[h>>2]|0)+1}if(!e)ma(123587,123529,187,123564);else{DH(a,d,b,e);f=1;g=(c[d+4>>2]|0)==0?a+1972|0:a+1976|0;break}}while(0);c[g>>2]=(c[g>>2]|0)+1;return f|0}function xH(a,b){a=a|0;b=b|0;if(!((a|0)!=0&b>>>0<64))ma(123591,123529,201,123619);if(!(c[a+8+(b*20|0)+16>>2]|0))ma(124113,123529,202,123619);else{tH(a+8+(b*20|0)|0);c[a>>2]=(c[a>>2]|0)+-1;return}}function yH(a){a=a|0;var b=0;b=0;while(1){if((b|0)==4)break;c[a+(b<<2)>>2]=0;b=b+1|0}return}function zH(a){a=a|0;var b=0,d=0,e=0;e=l;l=l+16|0;d=e;c[d>>2]=1;c[d+8>>2]=-1;b=1;while(1){if((b|0)==2)break;c[d+(b+2<<2)>>2]=0;c[d+(b<<2)>>2]=0;b=b+1|0}c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];l=e;return}function AH(a){a=a|0;var b=0,d=0,e=0;if(!a)ma(123632,123634,128,123646);a:do if((c[a>>2]|0)>(c[a+8>>2]|0))b=0;else{b=1;d=0;while(1){if((d|0)==2)break a;e=O(c[a+(d+2<<2)>>2]|0,b)|0;b=e-(c[a+(d<<2)>>2]|0)|0;d=d+1|0}}while(0);return b|0}function BH(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;g=l;l=l+16|0;f=g;if(!((b|0)!=0&(d|0)!=0))ma(123655,123634,195,123663);do if((c[b>>2]|0)>(c[b+8>>2]|0)){c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2]}else{if((c[d>>2]|0)>(c[d+8>>2]|0)){c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];break}else e=0;while(1){if((e|0)==2)break;j=c[b+(e<<2)>>2]|0;h=c[d+(e<<2)>>2]|0;c[f+(e<<2)>>2]=(j|0)<(h|0)?j:h;h=e+2|0;j=c[b+(h<<2)>>2]|0;i=c[d+(h<<2)>>2]|0;c[f+(h<<2)>>2]=(j|0)>(i|0)?j:i;e=e+1|0}c[a>>2]=c[f>>2];c[a+4>>2]=c[f+4>>2];c[a+8>>2]=c[f+8>>2];c[a+12>>2]=c[f+12>>2]}while(0);l=g;return}function CH(a,b){a=a|0;b=b|0;var d=0,e=0;if((a|0)!=0&(b|0)!=0)d=0;else ma(123675,123634,216,123682);while(1){if((d|0)>=2){d=1;break}e=d+2|0;if((c[a+(d<<2)>>2]|0)>(c[b+(e<<2)>>2]|0)){d=0;break}if((c[b+(d<<2)>>2]|0)>(c[a+(e<<2)>>2]|0)){d=0;break}else d=d+1|0}return d|0}function DH(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,h=0,i=0,j=0;if(!b)ma(123690,123692,40,123702);if(!d)ma(123712,123692,41,123702);j=a+1912|0;if(c[j>>2]|0){i=c[a+1908>>2]|0?a+1932|0:a+1928|0;c[i>>2]=(c[i>>2]|0)+1}h=b+4|0;i=c[h>>2]|0;EH(a,b,d);d=a+1324|0;FH(a);f=AH(a+1852|0)|0;f=(AH(a+1868|0)|0)+f|0;if(c[j>>2]|0?(f|0)!=0&(c[a+1908>>2]|0)==0:0){j=a+1960|0;g[j>>2]=+((c[a+1320>>2]|0)>>>0)/+(f|0)+ +g[j>>2]}j=rH(a)|0;c[e>>2]=j;c[h>>2]=i;c[j+4>>2]=i;GH(a,b,j,d);if(((c[c[e>>2]>>2]|0)+(c[b>>2]|0)|0)==65)return;else ma(123714,123692,86,123702)}function EH(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;h=l;l=l+16|0;g=h;if(!b)ma(123690,123692,106,124101);if(!d)ma(123712,123692,107,124101);else e=0;while(1){if((e|0)>=64)break;if(!(c[b+8+(e*20|0)+16>>2]|0)){f=7;break}j=b+8+(e*20|0)|0;i=a+4+(e*20|0)|0;c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];c[i+8>>2]=c[j+8>>2];c[i+12>>2]=c[j+12>>2];c[i+16>>2]=c[j+16>>2];e=e+1|0}if((f|0)==7)ma(124113,123692,111,124101);e=a+4|0;j=a+1284|0;c[j>>2]=c[d>>2];c[j+4>>2]=c[d+4>>2];c[j+8>>2]=c[d+8>>2];c[j+12>>2]=c[d+12>>2];c[j+16>>2]=c[d+16>>2];d=a+1304|0;c[d>>2]=c[e>>2];c[d+4>>2]=c[e+4>>2];c[d+8>>2]=c[e+8>>2];c[d+12>>2]=c[e+12>>2];e=1;while(1){if((e|0)==65)break;BH(g,d,a+4+(e*20|0)|0);c[d>>2]=c[g>>2];c[d+4>>2]=c[g+4>>2];c[d+8>>2]=c[g+8>>2];c[d+12>>2]=c[g+12>>2];e=e+1|0}c[a+1320>>2]=AH(d)|0;sH(b);l=h;return}function FH(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;u=l;l=l+48|0;i=u+32|0;k=u+16|0;m=u;HH(a);IH(a);q=a+1844|0;s=a+1848|0;t=a+1892|0;n=a+1852|0;o=a+1884|0;p=a+1868|0;j=a+1888|0;f=0;e=0;while(1){d=c[q>>2]|0;b=c[s>>2]|0;if((b+d|0)>=65)break;h=65-(c[t>>2]|0)|0;if((d|0)<(h|0)&(b|0)<(h|0)){g=-1;h=0}else{r=12;break}while(1){if((h|0)==65)break;if(!(c[a+1584+(h<<2)>>2]|0)){v=a+4+(h*20|0)|0;BH(k,v,n);c[i>>2]=c[k>>2];c[i+4>>2]=c[k+4>>2];c[i+8>>2]=c[k+8>>2];c[i+12>>2]=c[k+12>>2];b=AH(i)|0;d=c[o>>2]|0;BH(m,v,p);c[i>>2]=c[m>>2];c[i+4>>2]=c[m+4>>2];c[i+8>>2]=c[m+8>>2];c[i+12>>2]=c[m+12>>2];v=AH(i)|0;b=v-(c[j>>2]|0)+(d-b)|0;d=(b|0)>-1;b=d?b:0-b|0;d=(d^1)&1;if((b|0)<=(g|0))if((b|0)==(g|0)){v=(c[a+1844+(d<<2)>>2]|0)<(c[a+1844+(f<<2)>>2]|0);b=g;d=v?d:f;e=v?h:e}else{b=g;d=f}else e=h}else{b=g;d=f}g=b;h=h+1|0;f=d}JH(a,e,f)}if((r|0)==12){b=(d|0)>=(65-(c[t>>2]|0)|0)&1;d=0;while(1){if((d|0)==65)break;if(!(c[a+1584+(d<<2)>>2]|0))JH(a,d,b);d=d+1|0}d=c[q>>2]|0;b=c[s>>2]|0}if((b+d|0)!=65)ma(123857,123692,210,123943);v=c[t>>2]|0;if((d|0)<(v|0)|(b|0)<(v|0))ma(123954,123692,212,123943);else{l=u;return}}function GH(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;if(!b)ma(123690,123692,297,123754);if(!d)ma(123764,123692,298,123754);if(!e)ma(123766,123692,299,123754);else f=0;while(1){if((f|0)>=65){e=14;break}e=c[a+1324+(f<<2)>>2]|0;if(e>>>0>=2){e=9;break}switch(e|0){case 0:{wH(a,a+4+(f*20|0)|0,b,0)|0;break}case 1:{wH(a,a+4+(f*20|0)|0,d,0)|0;break}default:{}}f=f+1|0}if((e|0)==9)ma(123768,123692,303,123754);else if((e|0)==14)return}function HH(a){a=a|0;var b=0,d=0,e=0,f=0;d=l;l=l+16|0;e=d;c[a+1848>>2]=0;c[a+1844>>2]=0;b=a+1852|0;f=a+1868|0;zH(e);c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2];c[b>>2]=c[e>>2];c[b+4>>2]=c[e+4>>2];c[b+8>>2]=c[e+8>>2];c[b+12>>2]=c[e+12>>2];c[a+1888>>2]=0;c[a+1884>>2]=0;b=0;while(1){if((b|0)==65)break;c[a+1584+(b<<2)>>2]=0;c[a+1324+(b<<2)>>2]=-1;b=b+1|0}l=d;return}function IH(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0;o=l;l=l+304|0;k=o+32|0;m=o+16|0;n=o;b=0;while(1){if((b|0)==65)break;c[k+(b<<2)>>2]=AH(a+4+(b*20|0)|0)|0;b=b+1|0}b=0;d=0;e=0;g=0;a:while(1){if((g|0)==64)break;i=g+1|0;j=a+4+(g*20|0)|0;h=k+(g<<2)|0;f=i;while(1){if((f|0)==65){g=i;continue a}BH(n,j,a+4+(f*20|0)|0);c[m>>2]=c[n>>2];c[m+4>>2]=c[n+4>>2];c[m+8>>2]=c[n+8>>2];c[m+12>>2]=c[n+12>>2];p=AH(m)|0;p=p-(c[h>>2]|0)-(c[k+(f<<2)>>2]|0)|0;q=p>>>0>e>>>0;r=q?f:b;f=f+1|0;b=r;d=q?g:d;e=q?p:e}}JH(a,d,0);JH(a,b,1);l=o;return}function JH(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;e=a+1584+(b<<2)|0;if(c[e>>2]|0)ma(124057,123692,257,124092);c[a+1324+(b<<2)>>2]=d;c[e>>2]=1;g=a+1844+(d<<2)|0;f=a+1852+(d<<4)|0;e=a+4+(b*20|0)|0;if(!(c[g>>2]|0)){c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];c[f+8>>2]=c[e+8>>2];c[f+12>>2]=c[e+12>>2]}else{BH(h,e,f);c[f>>2]=c[h>>2];c[f+4>>2]=c[h+4>>2];c[f+8>>2]=c[h+8>>2];c[f+12>>2]=c[h+12>>2]}c[a+1884+(d<<2)>>2]=AH(f)|0;c[g>>2]=(c[g>>2]|0)+1;l=i;return}function KH(){var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=l;l=l+1200|0;r=t+800|0;g=t;c[42441]=0;c[42442]=-2;f=r;i=200;n=g;p=0;q=0;o=r;a:while(1){b[o>>1]=p;if((f+(i<<1)+-2|0)>>>0>o>>>0)k=i;else{m=o-f>>1;e=m+1|0;if(i>>>0>9999){s=95;break}k=i<<1;k=k>>>0<1e4?k:1e4;h=_I(k*6|3)|0;if(h){UN(h|0,f|0,e<<1|0)|0;i=h+(k>>>1<<2)|0;UN(i|0,n|0,e<<2|0)|0;if((f|0)==(r|0)){e=0;f=h}else{$I(f);e=0;f=h}}else{e=4;i=n}j=(e|0)==0;h=f+(m<<1)|0;switch((j?((f+(k<<1)+-2|0)>>>0>h>>>0?0:9):e)&15){case 9:{e=1;s=96;break a}case 4:{s=95;break a}case 0:{g=j?i+(m<<2)|0:g;n=i;o=j?h:o;break}default:{e=0;break a}}}if((p|0)==31){e=0;s=96;break}e=b[58358+(p<<1)>>1]|0;j=e<<16>>16;do if(e<<16>>16!=-82){h=c[42442]|0;if((h|0)==-2){h=hI()|0;c[42442]=h}if((h|0)>=1)if(h>>>0<296)i=d[124132+h>>0]|0;else i=2;else{c[42442]=0;i=0}h=i+j|0;if(h>>>0<=271?(i|0)==(a[124428+h>>0]|0):0){p=a[124700+h>>0]|0;e=p<<24>>24;if(p<<24>>24<1){h=0-e|0;s=23;break}else{c[42442]=-2;g=g+4|0;c[g>>2]=0;j=(q|0)==0?0:q+-1|0;h=o;break}}else s=22}else s=22;while(0);if((s|0)==22){s=0;p=a[124972+p>>0]|0;h=p&255;if(!(p<<24>>24)){h=c[42442]|0;b:do switch(q|0){case 0:{c[42441]=(c[42441]|0)+1;dI(125369);h=o;break}case 3:if((h|0)<1)if(!h){e=1;s=96;break a}else{h=o;break b}else{c[42442]=-2;h=o;break b}default:h=o}while(0);while(1){if(e<<16>>16==8)break;if((h|0)==(f|0)){e=1;s=96;break a}e=h+-2|0;g=g+-4|0;h=e;e=b[58358+(b[e>>1]<<1)>>1]|0}g=g+4|0;c[g>>2]=0;e=1;j=3}else s=23}do if((s|0)==23){s=0;j=d[125088+h>>0]|0;e=c[g+(1-j<<2)>>2]|0;do switch(h|0){case 4:{s=26;break a}case 2:{c[42443]=LH(c[g+-4>>2]|0,2)|0;break}case 3:{c[42443]=LH(c[g+-4>>2]|0,1)|0;break}case 5:{e=NH()|0;break}case 8:{OH(c[42444]|0);break}case 9:{PH(c[g>>2]|0);break}case 18:{QH(c[g>>2]|0);break}case 19:{RH();break}case 20:{QH(c[g>>2]|0);break}case 21:{RH();break}case 22:{QH(c[g>>2]|0);break}case 23:{RH();break}case 24:{QH(c[g>>2]|0);break}case 25:{RH();break}case 26:{QH(c[g>>2]|0);break}case 27:{RH();break}case 28:{QH(c[g>>2]|0);break}case 29:{RH();break}case 30:{QH(c[g>>2]|0);break}case 31:{RH();break}case 32:{QH(c[g>>2]|0);break}case 33:{RH();break}case 34:{e=c[g+-4>>2]|0;break}case 35:{e=c[g>>2]|0;break}case 38:{e=c[42444]|0;i=c[e+4>>2]|0;if(i>>>0>=(c[e+8>>2]|0)>>>0){em(e,1)|0;i=c[42444]|0;e=i;i=c[i+4>>2]|0}a[i>>0]=0;p=c[e>>2]|0;c[e+4>>2]=p;if(SH(p)|0){s=51;break a}c[(c[g>>2]|0)+80>>2]=c[42445];e=Rl(55016,c[4344]|0)|0;c[(c[g>>2]|0)+84>>2]=e;c[42445]=c[g>>2];c[(c[g>>2]|0)+108>>2]=c[c[42446]>>2];e=c[g>>2]|0;break}case 39:{e=c[42444]|0;i=c[e+4>>2]|0;if(i>>>0>=(c[e+8>>2]|0)>>>0){em(e,1)|0;i=c[42444]|0;e=i;i=c[i+4>>2]|0}a[i>>0]=0;p=c[e>>2]|0;c[e+4>>2]=p;if(SH(p)|0){s=56;break a}e=c[42445]|0;c[42445]=c[e+80>>2];break}case 40:{e=c[g>>2]|0;break}case 41:{e=c[g+-4>>2]|0;break}case 42:{e=c[g+-4>>2]|0;break}case 43:{e=c[g+-4>>2]|0;break}case 44:{e=c[g+-4>>2]|0;break}case 45:{e=c[g+-4>>2]|0;break}case 48:{e=c[g>>2]|0;break}case 49:{e=c[g>>2]|0;break}case 50:{a[(c[g+-8>>2]|0)+12>>0]=1;e=c[g>>2]|0;break}case 51:{TH();break}case 52:{e=UH()|0;break}case 53:{e=c[g>>2]|0;break}case 54:{e=c[g>>2]|0;break}case 55:{e=(c[g+-8>>2]|0)+100|0;a[e>>0]=a[e>>0]|1;e=c[g>>2]|0;break}case 56:{VH(c[g+-4>>2]|0,c[g>>2]|0,1);break}case 57:{e=c[g+-12>>2]|0;break}case 58:{VH(c[g+-4>>2]|0,c[g>>2]|0,2);break}case 59:{e=c[g+-12>>2]|0;break}case 60:{VH(c[g+-4>>2]|0,c[g>>2]|0,3);break}case 61:{e=c[g+-12>>2]|0;break}case 62:{VH(c[g>>2]|0,NH()|0,2);break}case 63:{e=c[g+-8>>2]|0;break}case 64:{e=c[g+-4>>2]|0;break}case 65:{e=c[g>>2]|0;break}default:{}}while(0);i=0-j|0;p=g+(i<<2)|0;i=o+(i<<1)|0;g=p+4|0;c[p+4>>2]=e;e=(d[125260+h>>0]|0)+-41|0;p=b[i>>1]|0;h=p+(b[58590+(e<<1)>>1]|0)|0;if(h>>>0<272?(a[124428+h>>0]|0)==(p|0):0){e=a[124700+h>>0]|0;j=q;h=i;break}e=a[125330+e>>0]|0;j=q;h=i}while(0);i=k;p=e;q=j;o=h+2|0}if((s|0)==26){MH();e=1;s=96}else if((s|0)==51){dI(125158);MH();e=1;s=96}else if((s|0)==56){dI(125209);MH();e=1;s=96}else if((s|0)==95){dI(125382);e=2;s=96}if((s|0)==96)if((f|0)!=(r|0))$I(f);l=t;return e|0}function LH(b,d){b=b|0;d=d|0;var e=0;e=ww(8)|0;a[e+4>>0]=d;c[e>>2]=b;return e|0}function MH(){var a=0,b=0;a=c[42445]|0;b=c[42443]|0;if(b|0){FF(b,1);c[42443]=0}c[13767]=62;while(1){if(!a)break;b=c[a+80>>2]|0;ZH(a);a=b}c[13767]=51;c[13776]=63;b=c[42448]|0;bb[c[b>>2]&31](b,0,64)|0;c[13776]=51;c[13785]=64;b=c[42449]|0;bb[c[b>>2]&31](b,0,64)|0;c[13785]=51;aI();return}function NH(){var a=0,d=0,e=0,f=0,g=0,h=0;e=c[42449]|0;f=ww(40)|0;if(Tl(c[42448]|0)|0)PH(0);a=Tl(e)|0;b[f+4>>1]=a;a:do if(!a)a=e;else{c[f>>2]=ww(a*24|0)|0;a=0;d=bb[c[e>>2]&31](e,0,128)|0;while(1){if(!d){a=e;break a}g=(c[f>>2]|0)+(a*24|0)|0;h=d+8|0;c[g>>2]=c[h>>2];c[g+4>>2]=c[h+4>>2];c[g+8>>2]=c[h+8>>2];c[g+12>>2]=c[h+12>>2];c[g+16>>2]=c[h+16>>2];c[g+20>>2]=c[h+20>>2];a=a+1|0;d=bb[c[e>>2]&31](e,d,8)|0}}while(0);bb[c[a>>2]&31](e,0,64)|0;return f|0}function OH(b){b=b|0;var d=0,e=0,f=0;e=ww(64)|0;f=b+4|0;d=c[f>>2]|0;if(d>>>0>=(c[b+8>>2]|0)>>>0){em(b,1)|0;d=c[f>>2]|0}a[d>>0]=0;b=c[b>>2]|0;c[f>>2]=b;c[e+8>>2]=HL(b)|0;c[e+12>>2]=c[c[42446]>>2];f=c[42448]|0;bb[c[f>>2]&31](f,e,1)|0;return}function PH(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;i=ww(32)|0;j=c[42448]|0;e=Tl(j)|0;k=i+8|0;a[i+14>>0]=d;a:do if(!e){c[k>>2]=ww(56)|0;b[i+12>>1]=1;h=HL(174185)|0;k=c[k>>2]|0;c[k>>2]=h;c[k+4>>2]=c[c[42446]>>2]}else{b[i+12>>1]=e;c[k>>2]=ww(e*56|0)|0;d=0;e=Pl(j)|0;while(1){if(!e)break a;f=(c[k>>2]|0)+(d*56|0)|0;g=e+8|0;h=f+56|0;do{c[f>>2]=c[g>>2];f=f+4|0;g=g+4|0}while((f|0)<(h|0));d=d+1|0;e=c[e>>2]|0}}while(0);bb[c[j>>2]&31](j,0,64)|0;k=c[42449]|0;bb[c[k>>2]&31](k,i,1)|0;return}function QH(a){a=a|0;var b=0,d=0.0,e=0,f=0,g=0,i=0,j=0;j=l;l=l+32|0;g=j;i=ww(8)|0;f=c[c[42446]>>2]|0;c[g>>2]=c[a>>2];c[g+4>>2]=c[a+4>>2];c[g+8>>2]=c[a+8>>2];c[g+12>>2]=c[a+12>>2];c[g+16>>2]=c[a+16>>2];c[g+20>>2]=c[a+20>>2];c[g+24>>2]=c[a+24>>2];c[g+28>>2]=c[a+28>>2];if(f|0){a=g+4|0;if((c[a>>2]|0)==0?(b=c[f+4>>2]|0,b|0):0)c[a>>2]=b;a=g+16|0;if(+h[a>>3]<0.0?(d=+h[f+16>>3],d>=0.0):0)h[a>>3]=d;if((c[g>>2]|0)==0?(e=c[f>>2]|0,e|0):0)c[g>>2]=e;a=c[f+24>>2]&127;if(a|0){f=g+24|0;e=c[f>>2]|0;c[f>>2]=e&127|a|e&-128}}f=c[(c[42447]|0)+144>>2]|0;c[i>>2]=bb[c[f>>2]&31](f,g,1)|0;c[i+4>>2]=c[42446];c[42446]=i;l=j;return}function RH(){var a=0,b=0;b=c[42446]|0;a=c[b+4>>2]|0;$I(b);c[42446]=a;return}function SH(b){b=b|0;var c=0;while(1){c=a[b>>0]|0;if(!(c<<24>>24)){b=0;break}if(c<<24>>24==32)b=b+1|0;else{b=1;break}}return b|0}function TH(){var b=0,d=0,e=0;e=Rl(55052,c[4344]|0)|0;b=c[42445]|0;d=ww(16)|0;c[d+8>>2]=e;if(a[b+112>>0]&2)a[d+12>>0]=1;e=c[b+84>>2]|0;bb[c[e>>2]&31](e,d,1)|0;return}function UH(){var a=0;a=c[(c[42445]|0)+84>>2]|0;return bb[c[a>>2]&31](a,0,256)|0}function VH(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;g=ww(16)|0;f=c[42445]|0;h=c[f+84>>2]|0;h=c[(bb[c[h>>2]&31](h,0,256)|0)+8>>2]|0;c[g+8>>2]=b;bb[c[h>>2]&31](h,g,1)|0;a[b+92>>0]=e;if(a[f+112>>0]&1)a[b+100>>0]=1;c[b+88>>2]=d;return}function WH(a,b,c){a=a|0;b=b|0;c=c|0;$I(b);return}function XH(a,b,d){a=a|0;b=b|0;d=d|0;Ll(c[b+8>>2]|0)|0;$I(b);return}function YH(a,b,d){a=a|0;b=b|0;d=d|0;bI(c[b+8>>2]|0);$I(b);return}function ZH(a){a=a|0;Ll(c[a+84>>2]|0)|0;CF(a);$I(a);return}function _H(a,b,d){a=a|0;b=b|0;d=d|0;$I(c[b+8>>2]|0);$I(b);return}function $H(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0,h=0;g=d+12|0;a=b[g>>1]|0;if(a<<16>>16){h=d+8|0;e=0;f=c[h>>2]|0;while(1){if((e|0)>=(a<<16>>16|0))break;$I(c[f>>2]|0);e=e+1|0;f=f+56|0;a=b[g>>1]|0}$I(c[h>>2]|0)}$I(d);return}function aI(){var a=0,b=0;a=c[42446]|0;while(1){b=c[a+4>>2]|0;if(!b)break;$I(a);a=b}return}function bI(b){b=b|0;var d=0;d=b+88|0;switch(a[b+92>>0]|0){case 1:{ZH(c[d>>2]|0);break}case 2:{DF(c[d>>2]|0);break}default:{}}CF(b);$I(b);return}function cI(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;f=l;l=l+160|0;e=f+8|0;g=f;c[g>>2]=0;c[g+4>>2]=0;c[42446]=g;c[42445]=0;c[42443]=0;c[42447]=c[(c[(c[d+52>>2]|0)+16>>2]|0)+144>>2];c[42448]=Rl(55088,c[4344]|0)|0;c[42449]=Rl(55124,c[4344]|0)|0;dm(e,128,f+24|0);c[42444]=e;if(!(fI(a,e,d)|0)){KH()|0;c[b>>2]=gI()|0;a=c[42443]|0}else{c[b>>2]=2;a=0}Ll(c[42448]|0)|0;Ll(c[42449]|0)|0;c[42448]=0;c[42449]=0;c[42446]=0;hm(e);l=f;return a|0}function dI(b){b=b|0;var d=0,e=0;e=l;l=l+16|0;d=e;if(!(a[169800]|0)){a[169800]=1;c[d>>2]=b;c[d+4>>2]=0;$l(1,125399,d)|0;eI()}else{l=e;return}}function eI(){Ta()}function fI(a,b,d){a=a|0;b=b|0;d=d|0;a=l;l=l+16|0;if(!(c[42451]|0)){$l(0,125415,a)|0;c[42451]=(c[42451]|0)+1}l=a;return 1}function gI(){return 1}function hI(){return -1}function iI(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+64|0;m=u+48|0;k=u+32|0;s=4;j=_I(40)|0;c[j>>2]=0;n=u+16|0;q=u;r=c[d>>2]|0;i=c[d+4>>2]|0;s=SN(169808,1,j|0,s|0)|0;j=z;o=0;d=o;o=0;if((d|0)!=0&(p|0)!=0){g=TN(c[d>>2]|0,s|0,j|0)|0;if(!g)Ua(d|0,p|0);z=p}else g=-1;if((g|0)==1)d=z;else d=0;while(1){if(d|0){d=-1;break}o=0;c[m>>2]=c[e>>2];c[m+4>>2]=c[e+4>>2];c[m+8>>2]=c[e+8>>2];c[m+12>>2]=c[e+12>>2];ga(26,n|0,m|0);d=o;o=0;if((d|0)!=0&(p|0)!=0){g=TN(c[d>>2]|0,s|0,j|0)|0;if(!g)Ua(d|0,p|0);z=p}else g=-1;if((g|0)==1){d=z;continue};c[e>>2]=c[n>>2];c[e+4>>2]=c[n+4>>2];c[e+8>>2]=c[n+8>>2];c[e+12>>2]=c[n+12>>2];h=e+16|0;o=0;c[m>>2]=c[h>>2];c[m+4>>2]=c[h+4>>2];c[m+8>>2]=c[h+8>>2];c[m+12>>2]=c[h+12>>2];ga(26,q|0,m|0);d=o;o=0;if((d|0)!=0&(p|0)!=0){g=TN(c[d>>2]|0,s|0,j|0)|0;if(!g)Ua(d|0,p|0);z=p}else g=-1;if((g|0)==1){d=z;continue};c[h>>2]=c[q>>2];c[h+4>>2]=c[q+4>>2];c[h+8>>2]=c[q+8>>2];c[h+12>>2]=c[q+12>>2];c[42491]=0;o=0;fa(93,4);d=o;o=0;if((d|0)!=0&(p|0)!=0){g=TN(c[d>>2]|0,s|0,j|0)|0;if(!g)Ua(d|0,p|0);z=p}else g=-1;if((g|0)==1){d=z;continue}g=c[42492]|0;d=c[42491]|0;c[42491]=d+1;d=g+(d<<4)|0;c[d>>2]=c[r>>2];c[d+4>>2]=c[r+4>>2];c[d+8>>2]=c[r+8>>2];c[d+12>>2]=c[r+12>>2];o=0;c[k>>2]=c[e>>2];c[k+4>>2]=c[e+4>>2];c[k+8>>2]=c[e+8>>2];c[k+12>>2]=c[e+12>>2];c[m>>2]=c[h>>2];c[m+4>>2]=c[h+4>>2];c[m+8>>2]=c[h+8>>2];c[m+12>>2]=c[h+12>>2];d=da(1,a|0,b|0,r|0,i|0,k|0,m|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){h=TN(c[g>>2]|0,s|0,j|0)|0;if(!h)Ua(g|0,p|0);z=p}else h=-1;if((h|0)==1)d=z;else{t=8;break}}if((t|0)==8)if((d|0)==-1)d=-1;else{c[f+4>>2]=c[42491];c[f>>2]=c[42492];d=0}$I(s|0);l=u;return d|0}function jI(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0.0,g=0.0,i=0.0;d=+h[b>>3];e=b+8|0;f=+h[e>>3];i=f*f+d*d;g=+C(+i);if(i>1.0e-06){h[b>>3]=d/g;h[e>>3]=f/g};c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];return}function kI(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+32|0;e=f+16|0;d=f;if((c[42495]|0)<(a|0)){b=c[42492]|0;if(!b){e=_I(a<<4)|0;c[42492]=e;if(!e){e=c[13918]|0;c[d>>2]=125476;c[d+4>>2]=531;c[d+8>>2]=125611;AL(e,125484,d)|0;Ua(169808,1)}}else{d=bJ(b,a<<4)|0;c[42492]=d;if(!d){d=c[13918]|0;c[e>>2]=125476;c[e+4>>2]=537;c[e+8>>2]=125629;AL(d,125484,e)|0;Ua(169808,1)}}c[42495]=a}l=f;return}function lI(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0.0,k=0,m=0.0,n=0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0.0,U=0.0,V=0.0,W=0.0;R=l;l=l+336|0;J=R+320|0;I=R+304|0;w=R+144|0;q=R+128|0;G=R+112|0;H=R+96|0;Q=R+80|0;A=R+64|0;C=R+48|0;K=R+32|0;L=R+16|0;M=R;x=R+288|0;y=R+272|0;z=R+256|0;B=R+240|0;D=R+224|0;E=R+208|0;N=R+192|0;O=R+176|0;P=R+160|0;i=c[42494]|0;do if((c[42493]|0)<(e|0)){if(!i){i=_I(e*40|0)|0;c[42494]=i;if(!i){i=-1;break}}else{i=bJ(i,e*40|0)|0;c[42494]=i;if(!i){i=-1;break}}c[42493]=e;k=6}else k=6;while(0);if((k|0)==6){h[i>>3]=0.0;k=1;j=0.0;while(1){if((k|0)>=(e|0))break;n=d+(k<<4)|0;F=d+(k+-1<<4)|0;c[I>>2]=c[n>>2];c[I+4>>2]=c[n+4>>2];c[I+8>>2]=c[n+8>>2];c[I+12>>2]=c[n+12>>2];c[J>>2]=c[F>>2];c[J+4>>2]=c[F+4>>2];c[J+8>>2]=c[F+8>>2];c[J+12>>2]=c[F+12>>2];v=+mI(I,J)+j;h[i+(k*40|0)>>3]=v;k=k+1|0;j=v}F=e+-1|0;n=i+(F*40|0)|0;k=1;while(1){if((k|0)>=(e|0))break;S=i+(k*40|0)|0;h[S>>3]=+h[S>>3]/+h[n>>3];k=k+1|0}k=0;while(1){if((k|0)>=(e|0))break;S=i+(k*40|0)+8|0;n=i+(k*40|0)|0;v=+nI(+h[n>>3]);c[J>>2]=c[f>>2];c[J+4>>2]=c[f+4>>2];c[J+8>>2]=c[f+8>>2];c[J+12>>2]=c[f+12>>2];oI(x,J,v);c[S>>2]=c[x>>2];c[S+4>>2]=c[x+4>>2];c[S+8>>2]=c[x+8>>2];c[S+12>>2]=c[x+12>>2];S=i+(k*40|0)+24|0;v=+pI(+h[n>>3]);c[J>>2]=c[g>>2];c[J+4>>2]=c[g+4>>2];c[J+8>>2]=c[g+8>>2];c[J+12>>2]=c[g+12>>2];oI(y,J,v);c[S>>2]=c[y>>2];c[S+4>>2]=c[y+4>>2];c[S+8>>2]=c[y+8>>2];c[S+12>>2]=c[y+12>>2];k=k+1|0}c[I>>2]=c[f>>2];c[I+4>>2]=c[f+4>>2];c[I+8>>2]=c[f+8>>2];c[I+12>>2]=c[f+12>>2];c[J>>2]=c[g>>2];c[J+4>>2]=c[g+4>>2];c[J+8>>2]=c[g+8>>2];c[J+12>>2]=c[g+12>>2];qI(d,e,i,I,J,G,A,H,C);c[q>>2]=c[G>>2];c[q+4>>2]=c[G+4>>2];c[q+8>>2]=c[G+8>>2];c[q+12>>2]=c[G+12>>2];c[w>>2]=c[A>>2];c[w+4>>2]=c[A+4>>2];c[w+8>>2]=c[A+8>>2];c[w+12>>2]=c[A+12>>2];c[I>>2]=c[H>>2];c[I+4>>2]=c[H+4>>2];c[I+8>>2]=c[H+8>>2];c[I+12>>2]=c[H+12>>2];c[J>>2]=c[C>>2];c[J+4>>2]=c[C+4>>2];c[J+8>>2]=c[C+8>>2];c[J+12>>2]=c[C+12>>2];if(!(rI(a,b,q,w,I,J,d,e)|0)){c[J>>2]=c[A>>2];c[J+4>>2]=c[A+4>>2];c[J+8>>2]=c[A+8>>2];c[J+12>>2]=c[A+12>>2];oI(z,J,.3333333333333333);c[I>>2]=c[G>>2];c[I+4>>2]=c[G+4>>2];c[I+8>>2]=c[G+8>>2];c[I+12>>2]=c[G+12>>2];c[J>>2]=c[z>>2];c[J+4>>2]=c[z+4>>2];c[J+8>>2]=c[z+8>>2];c[J+12>>2]=c[z+12>>2];sI(B,I,J);v=+h[B>>3];u=+h[B+8>>3];c[J>>2]=c[C>>2];c[J+4>>2]=c[C+4>>2];c[J+8>>2]=c[C+8>>2];c[J+12>>2]=c[C+12>>2];oI(D,J,.3333333333333333);c[I>>2]=c[H>>2];c[I+4>>2]=c[H+4>>2];c[I+8>>2]=c[H+8>>2];c[I+12>>2]=c[H+12>>2];c[J>>2]=c[D>>2];c[J+4>>2]=c[D+4>>2];c[J+8>>2]=c[D+8>>2];c[J+12>>2]=c[D+12>>2];tI(E,I,J);t=+h[E>>3];p=+h[E+8>>3];q=c[42494]|0;r=+h[G>>3];s=+h[H>>3];o=+h[G+8>>3];m=+h[H+8>>3];n=Q+8|0;i=-1;j=-1.0;k=1;while(1){if((k|0)>=(F|0))break;T=+h[q+(k*40|0)>>3];U=+uI(T);V=+nI(T);W=+pI(T);T=+vI(T);h[Q>>3]=V*v+r*U+W*t+s*T;h[n>>3]=W*p+V*u+o*U+m*T;S=d+(k<<4)|0;c[I>>2]=c[Q>>2];c[I+4>>2]=c[Q+4>>2];c[I+8>>2]=c[Q+8>>2];c[I+12>>2]=c[Q+12>>2];c[J>>2]=c[S>>2];c[J+4>>2]=c[S+4>>2];c[J+8>>2]=c[S+8>>2];c[J+12>>2]=c[S+12>>2];T=+mI(I,J);S=T>j;i=S?k:i;j=S?T:j;k=k+1|0}S=d+(i<<4)|0;Q=d+(i+-1<<4)|0;c[I>>2]=c[S>>2];c[I+4>>2]=c[S+4>>2];c[I+8>>2]=c[S+8>>2];c[I+12>>2]=c[S+12>>2];c[J>>2]=c[Q>>2];c[J+4>>2]=c[Q+4>>2];c[J+8>>2]=c[Q+8>>2];c[J+12>>2]=c[Q+12>>2];tI(N,I,J);c[J>>2]=c[N>>2];c[J+4>>2]=c[N+4>>2];c[J+8>>2]=c[N+8>>2];c[J+12>>2]=c[N+12>>2];jI(L,J);Q=i+1|0;N=d+(Q<<4)|0;c[I>>2]=c[N>>2];c[I+4>>2]=c[N+4>>2];c[I+8>>2]=c[N+8>>2];c[I+12>>2]=c[N+12>>2];c[J>>2]=c[S>>2];c[J+4>>2]=c[S+4>>2];c[J+8>>2]=c[S+8>>2];c[J+12>>2]=c[S+12>>2];tI(O,I,J);c[J>>2]=c[O>>2];c[J+4>>2]=c[O+4>>2];c[J+8>>2]=c[O+8>>2];c[J+12>>2]=c[O+12>>2];jI(M,J);c[I>>2]=c[L>>2];c[I+4>>2]=c[L+4>>2];c[I+8>>2]=c[L+8>>2];c[I+12>>2]=c[L+12>>2];c[J>>2]=c[M>>2];c[J+4>>2]=c[M+4>>2];c[J+8>>2]=c[M+8>>2];c[J+12>>2]=c[M+12>>2];sI(P,I,J);c[J>>2]=c[P>>2];c[J+4>>2]=c[P+4>>2];c[J+8>>2]=c[P+8>>2];c[J+12>>2]=c[P+12>>2];jI(K,J);c[I>>2]=c[f>>2];c[I+4>>2]=c[f+4>>2];c[I+8>>2]=c[f+8>>2];c[I+12>>2]=c[f+12>>2];c[J>>2]=c[K>>2];c[J+4>>2]=c[K+4>>2];c[J+8>>2]=c[K+8>>2];c[J+12>>2]=c[K+12>>2];lI(a,b,d,Q,I,J)|0;c[I>>2]=c[K>>2];c[I+4>>2]=c[K+4>>2];c[I+8>>2]=c[K+8>>2];c[I+12>>2]=c[K+12>>2];c[J>>2]=c[g>>2];c[J+4>>2]=c[g+4>>2];c[J+8>>2]=c[g+8>>2];c[J+12>>2]=c[g+12>>2];lI(a,b,S,e-i|0,I,J)|0;i=0}else i=0}l=R;return i|0}function mI(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;c=+h[b>>3]-+h[a>>3];d=+h[b+8>>3]-+h[a+8>>3];return +(+C(+(d*d+c*c)))}function nI(a){a=+a;var b=0.0;b=1.0-a;return +(b*b*(a*3.0))}function oI(a,b,d){a=a|0;b=b|0;d=+d;var e=0;h[b>>3]=+h[b>>3]*d;e=b+8|0;h[e>>3]=+h[e>>3]*d;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];return}function pI(a){a=+a;return +(a*a*3.0*(1.0-a))}function qI(a,b,d,e,f,g,i,j,k){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;k=k|0;var m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0.0,x=0.0,y=0.0,z=0.0,A=0.0,B=0,C=0,D=0,E=0,F=0,G=0,H=0.0,I=0.0,J=0,K=0,L=0,M=0;G=l;l=l+128|0;B=G+112|0;v=G+80|0;u=G;r=G+96|0;s=G+64|0;t=G+48|0;C=G+32|0;D=G+16|0;E=a+(b+-1<<4)|0;q=0;w=0.0;x=0.0;y=0.0;z=0.0;A=0.0;while(1){if((q|0)>=(b|0))break;K=d+(q*40|0)+8|0;c[v>>2]=c[K>>2];c[v+4>>2]=c[K+4>>2];c[v+8>>2]=c[K+8>>2];c[v+12>>2]=c[K+12>>2];c[B>>2]=c[K>>2];c[B+4>>2]=c[K+4>>2];c[B+8>>2]=c[K+8>>2];c[B+12>>2]=c[K+12>>2];H=+BI(v,B)+x;J=d+(q*40|0)+24|0;c[v>>2]=c[K>>2];c[v+4>>2]=c[K+4>>2];c[v+8>>2]=c[K+8>>2];c[v+12>>2]=c[K+12>>2];c[B>>2]=c[J>>2];c[B+4>>2]=c[J+4>>2];c[B+8>>2]=c[J+8>>2];c[B+12>>2]=c[J+12>>2];p=+BI(v,B)+A;c[v>>2]=c[J>>2];c[v+4>>2]=c[J+4>>2];c[v+8>>2]=c[J+8>>2];c[v+12>>2]=c[J+12>>2];c[B>>2]=c[J>>2];c[B+4>>2]=c[J+4>>2];c[B+8>>2]=c[J+8>>2];c[B+12>>2]=c[J+12>>2];o=+BI(v,B)+y;L=a+(q<<4)|0;M=d+(q*40|0)|0;I=+CI(+h[M>>3]);c[B>>2]=c[a>>2];c[B+4>>2]=c[a+4>>2];c[B+8>>2]=c[a+8>>2];c[B+12>>2]=c[a+12>>2];oI(s,B,I);I=+DI(+h[M>>3]);c[B>>2]=c[E>>2];c[B+4>>2]=c[E+4>>2];c[B+8>>2]=c[E+8>>2];c[B+12>>2]=c[E+12>>2];oI(t,B,I);c[v>>2]=c[s>>2];c[v+4>>2]=c[s+4>>2];c[v+8>>2]=c[s+8>>2];c[v+12>>2]=c[s+12>>2];c[B>>2]=c[t>>2];c[B+4>>2]=c[t+4>>2];c[B+8>>2]=c[t+8>>2];c[B+12>>2]=c[t+12>>2];sI(r,v,B);c[v>>2]=c[L>>2];c[v+4>>2]=c[L+4>>2];c[v+8>>2]=c[L+8>>2];c[v+12>>2]=c[L+12>>2];c[B>>2]=c[r>>2];c[B+4>>2]=c[r+4>>2];c[B+8>>2]=c[r+8>>2];c[B+12>>2]=c[r+12>>2];tI(u,v,B);c[v>>2]=c[K>>2];c[v+4>>2]=c[K+4>>2];c[v+8>>2]=c[K+8>>2];c[v+12>>2]=c[K+12>>2];c[B>>2]=c[u>>2];c[B+4>>2]=c[u+4>>2];c[B+8>>2]=c[u+8>>2];c[B+12>>2]=c[u+12>>2];I=+BI(v,B)+w;c[v>>2]=c[J>>2];c[v+4>>2]=c[J+4>>2];c[v+8>>2]=c[J+8>>2];c[v+12>>2]=c[J+12>>2];c[B>>2]=c[u>>2];c[B+4>>2]=c[u+4>>2];c[B+8>>2]=c[u+8>>2];c[B+12>>2]=c[u+12>>2];q=q+1|0;w=I;x=H;y=o;z=+BI(v,B)+z;A=p}o=y*x-A*A;p=o>=0.0?o:-o;if(!(p>=1.0e-06?(m=(y*w-A*z)/o,n=(x*z-A*w)/o,!(p<1.0e-06|m<=0.0|n<=0.0)):0))F=6;if((F|0)==6){c[v>>2]=c[a>>2];c[v+4>>2]=c[a+4>>2];c[v+8>>2]=c[a+8>>2];c[v+12>>2]=c[a+12>>2];c[B>>2]=c[E>>2];c[B+4>>2]=c[E+4>>2];c[B+8>>2]=c[E+8>>2];c[B+12>>2]=c[E+12>>2];m=+mI(v,B)*.3333333333333333;n=m};c[g>>2]=c[a>>2];c[g+4>>2]=c[a+4>>2];c[g+8>>2]=c[a+8>>2];c[g+12>>2]=c[a+12>>2];c[B>>2]=c[e>>2];c[B+4>>2]=c[e+4>>2];c[B+8>>2]=c[e+8>>2];c[B+12>>2]=c[e+12>>2];oI(C,B,m);c[i>>2]=c[C>>2];c[i+4>>2]=c[C+4>>2];c[i+8>>2]=c[C+8>>2];c[i+12>>2]=c[C+12>>2];c[j>>2]=c[E>>2];c[j+4>>2]=c[E+4>>2];c[j+8>>2]=c[E+8>>2];c[j+12>>2]=c[E+12>>2];c[B>>2]=c[f>>2];c[B+4>>2]=c[f+4>>2];c[B+8>>2]=c[f+8>>2];c[B+12>>2]=c[f+12>>2];oI(D,B,n);c[k>>2]=c[D>>2];c[k+4>>2]=c[D+4>>2];c[k+8>>2]=c[D+8>>2];c[k+12>>2]=c[D+12>>2];l=G;return}function rI(a,b,d,e,f,g,i,j){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;j=j|0;var k=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0.0,s=0.0,t=0,u=0.0,v=0,w=0.0,x=0,y=0.0,z=0,A=0,B=0,C=0,D=0.0,E=0;C=l;l=l+64|0;B=C;z=(j|0)==2;y=+h[d>>3];u=+h[d+8>>3];v=B+8|0;w=+h[e>>3];x=B+16|0;p=+h[e+8>>3];q=B+24|0;r=+h[f>>3];s=+h[g>>3];t=B+32|0;o=+h[f+8>>3];n=+h[g+8>>3];e=B+40|0;f=B+48|0;g=B+56|0;d=1;k=4.0;m=4.0;while(1){h[B>>3]=y;h[v>>3]=u;D=m*.3333333333333333;h[x>>3]=D*w+y;h[q>>3]=D*p+u;D=k*.3333333333333333;h[t>>3]=r-D*s;h[e>>3]=o-D*n;h[f>>3]=r;h[g>>3]=o;if(d?(D=+wI(B,4),D<+wI(i,j)+-.001):0){d=0;break}if(xI(a,b,B)|0){A=5;break}if(m==0.0&k==0.0){A=9;break}E=m>.01;d=0;k=E?k*.5:0.0;m=E?m*.5:0.0}a:do if((A|0)==5){kI((c[42491]|0)+4|0);e=c[42492]|0;d=1;while(1){if((d|0)==4){d=1;break a}E=c[42491]|0;h[e+(E<<4)>>3]=+h[B+(d<<4)>>3];D=+h[B+(d<<4)+8>>3];c[42491]=E+1;h[e+(E<<4)+8>>3]=D;d=d+1|0}}else if((A|0)==9)if(z){kI((c[42491]|0)+4|0);e=c[42492]|0;d=1;while(1){if((d|0)==4){d=1;break a}E=c[42491]|0;h[e+(E<<4)>>3]=+h[B+(d<<4)>>3];D=+h[B+(d<<4)+8>>3];c[42491]=E+1;h[e+(E<<4)+8>>3]=D;d=d+1|0}}else d=0;while(0);l=C;return d|0}function sI(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;h[b>>3]=+h[b>>3]+ +h[d>>3];e=b+8|0;h[e>>3]=+h[e>>3]+ +h[d+8>>3];c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];return}function tI(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;h[b>>3]=+h[b>>3]-+h[d>>3];e=b+8|0;h[e>>3]=+h[e>>3]-+h[d+8>>3];c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];return}function uI(a){a=+a;a=1.0-a;return +(a*a*a)}function vI(a){a=+a;return +(a*a*a)}function wI(a,b){a=a|0;b=b|0;var c=0.0,d=0,e=0.0,f=0.0,g=0;c=0.0;d=1;while(1){if((d|0)>=(b|0))break;g=d+-1|0;e=+h[a+(d<<4)>>3]-+h[a+(g<<4)>>3];f=+h[a+(d<<4)+8>>3]-+h[a+(g<<4)+8>>3];c=+C(+(f*f+e*e))+c;d=d+1|0}return +c}function xI(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0.0,w=0,x=0.0,y=0,z=0,A=0,B=0,C=0,D=0.0,E=0.0;C=l;l=l+64|0;t=C+32|0;u=C;w=u+16|0;y=d+16|0;z=d+32|0;A=d+48|0;B=d+8|0;g=d+24|0;i=d+40|0;j=d+56|0;k=u+8|0;m=u+24|0;f=0;a:while(1){if((f|0)>=(b|0)){e=1;break}n=a+(f<<5)|0;c[u>>2]=c[n>>2];c[u+4>>2]=c[n+4>>2];c[u+8>>2]=c[n+8>>2];c[u+12>>2]=c[n+12>>2];n=a+(f<<5)+16|0;c[w>>2]=c[n>>2];c[w+4>>2]=c[n+4>>2];c[w+8>>2]=c[n+8>>2];c[w+12>>2]=c[n+12>>2];n=yI(d,u,t)|0;b:do if((n|0)!=4){o=+h[u>>3];p=+h[k>>3];q=+h[w>>3];r=+h[m>>3];e=0;while(1){if((e|0)>=(n|0))break b;s=+h[t+(e<<3)>>3];if((!(s<1.0e-06|s>.999999)?(x=s*s*s,E=s*3.0,D=1.0-s,s=E*s*D,v=D*D,E=v*E,D=v*D,v=+h[y>>3]*E+ +h[d>>3]*D+ +h[z>>3]*s+ +h[A>>3]*x,x=+h[g>>3]*E+ +h[B>>3]*D+ +h[i>>3]*s+ +h[j>>3]*x,s=v-o,D=x-p,!(D*D+s*s<.001)):0)?(E=v-q,D=x-r,!(D*D+E*E<.001)):0){e=0;break a}e=e+1|0}}while(0);f=f+1|0}l=C;return e|0}function yI(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0,j=0.0,k=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0;v=l;l=l+96|0;s=v+48|0;t=v+24|0;k=v;u=v+80|0;p=+h[b>>3];g=+h[b+16>>3]-p;q=+h[b+8>>3];j=+h[b+24>>3]-q;c[u>>2]=0;a:do if(!(g==0.0)){j=j/g;m=a+16|0;n=a+32|0;o=a+48|0;zI(+h[a+8>>3]-+h[a>>3]*j,+h[a+24>>3]-+h[m>>3]*j,+h[a+40>>3]-+h[n>>3]*j,+h[a+56>>3]-+h[o>>3]*j,s);h[s>>3]=j*p-q+ +h[s>>3];e=VI(s,t)|0;if((e|0)==4)b=4;else{f=s+8|0;i=s+16|0;k=s+24|0;g=1.0/g;b=0;while(1){if((b|0)>=(e|0))break;j=+h[t+(b<<3)>>3];if(j>=0.0&j<=1.0?(zI(+h[a>>3],+h[m>>3],+h[n>>3],+h[o>>3],s),q=(+h[s>>3]-p+((+h[k>>3]*j+ +h[i>>3])*j+ +h[f>>3])*j)*g,q>=0.0&q<=1.0):0)AI(j,d,u);b=b+1|0}b=c[u>>2]|0}}else{zI(+h[a>>3],+h[a+16>>3],+h[a+32>>3],+h[a+48>>3],s);h[s>>3]=+h[s>>3]-p;r=VI(s,t)|0;if(!(j==0.0)){if((r|0)==4){b=4;break}m=a+8|0;n=a+24|0;o=a+40|0;e=a+56|0;f=s+8|0;i=s+16|0;k=s+24|0;g=1.0/j;b=0;while(1){if((b|0)>=(r|0))break;j=+h[t+(b<<3)>>3];if(j>=0.0&j<=1.0?(zI(+h[m>>3],+h[n>>3],+h[o>>3],+h[e>>3],s),p=(+h[s>>3]-q+((+h[k>>3]*j+ +h[i>>3])*j+ +h[f>>3])*j)*g,p>=0.0&p<=1.0):0)AI(j,d,u);b=b+1|0}b=c[u>>2]|0;break}zI(+h[a+8>>3],+h[a+24>>3],+h[a+40>>3],+h[a+56>>3],s);h[s>>3]=+h[s>>3]-q;i=VI(s,k)|0;b=(i|0)==4;b:do if((r|0)==4){if(b){b=4;break a}else b=0;while(1){if((b|0)>=(i|0))break b;AI(+h[k+(b<<3)>>3],d,u);b=b+1|0}}else{if(b){b=0;while(1){if((b|0)>=(r|0))break b;AI(+h[t+(b<<3)>>3],d,u);b=b+1|0}}else e=0;while(1){if((e|0)>=(r|0))break b;f=t+(e<<3)|0;b=0;while(1){if((b|0)>=(i|0))break;g=+h[f>>3];if(g==+h[k+(b<<3)>>3])AI(g,d,u);b=b+1|0}e=e+1|0}}while(0);b=c[u>>2]|0}while(0);l=v;return b|0}function zI(a,b,c,d,e){a=+a;b=+b;c=+c;d=+d;e=e|0;h[e+24>>3]=d-a+(b-c)*3.0;h[e+16>>3]=(c+a)*3.0-b*6.0;h[e+8>>3]=(b-a)*3.0;h[e>>3]=a;return}function AI(a,b,d){a=+a;b=b|0;d=d|0;var e=0;if(a>=0.0&a<=1.0){e=c[d>>2]|0;h[b+(e<<3)>>3]=a;c[d>>2]=e+1}return}function BI(a,b){a=a|0;b=b|0;return +(+h[b+8>>3]*+h[a+8>>3]+ +h[b>>3]*+h[a>>3])}function CI(a){a=+a;var b=0.0;b=1.0-a;return +(b*b*(b+a*3.0))}function DI(a){a=+a;return +(a*a*((1.0-a)*3.0+a))} +function tx(d,f,g){d=d|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0.0,n=0,o=0.0,p=0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0;Y=l;l=l+2288|0;W=Y+208|0;V=Y+192|0;U=Y+176|0;T=Y+160|0;S=Y+144|0;R=Y+128|0;P=Y+112|0;O=Y+96|0;N=Y+80|0;M=Y+64|0;L=Y+56|0;K=Y+48|0;X=Y+32|0;Q=Y+24|0;J=Y;G=Y+1264|0;H=Y+224|0;I=d+16|0;C=(e[(c[I>>2]|0)+178>>1]|0)>2;Gv(1);kx(d);dm(H,1024,Y+240|0);uB(d,1,87657,174185)|0;uB(d,1,87661,174185)|0;c[42191]=uB(d,1,96043,174185)|0;c[42190]=uB(d,1,96049,174185)|0;uB(d,2,87657,174185)|0;i=a[(c[I>>2]|0)+113>>0]|0;if(i&16){uB(d,1,87667,174185)|0;i=a[(c[I>>2]|0)+113>>0]|0}if(i&1){uB(d,2,87671,174185)|0;i=a[(c[I>>2]|0)+113>>0]|0}if(i&32){uB(d,2,87667,174185)|0;i=a[(c[I>>2]|0)+113>>0]|0}if(i&2){uB(d,2,87674,174185)|0;i=a[(c[I>>2]|0)+113>>0]|0}if(i&4){uB(d,2,87682,174185)|0;i=a[(c[I>>2]|0)+113>>0]|0}if(!(i&8)){v=0;w=0;x=0}else{x=uB(d,0,87671,174185)|0;w=uB(d,0,87690,174185)|0;v=uB(d,0,87697,174185)|0}z=uB(d,0,87705,174185)|0;A=H+4|0;B=H+8|0;u=0;i=0;y=eo(d)|0;while(1){if(!y)break;t=y+16|0;k=c[t>>2]|0;o=+h[k+16>>3];j=(c[42184]|0)==0;if(C){if(j)m=+h[k+24>>3];else m=+h[20895]-+h[k+24>>3];q=+h[(c[k+132>>2]|0)+16>>3]*72.0;h[J>>3]=o;h[J+8>>3]=m;h[J+16>>3]=q;qL(G,87708,J)|0;gm(H,G)|0;j=3;while(1){if((j|0)>=(e[(c[I>>2]|0)+178>>1]|0))break;h[Q>>3]=+h[(c[(c[t>>2]|0)+132>>2]|0)+(j<<3)>>3]*72.0;qL(G,87723,Q)|0;gm(H,G)|0;j=j+1|0}j=c[A>>2]|0;if(j>>>0>=(c[B>>2]|0)>>>0){em(H,1)|0;j=c[A>>2]|0}a[j>>0]=0;s=c[H>>2]|0;c[A>>2]=s;Lm(y,87657,s)|0;s=y}else{if(j)m=+h[k+24>>3];else m=+h[20895]-+h[k+24>>3];h[X>>3]=o;h[X+8>>3]=m;qL(G,87729,X)|0;Lm(y,87657,G)|0;s=y}h[K>>3]=+h[(c[t>>2]|0)+80>>3]*.013888888888888888;qL(G,87652,K)|0;Dm(s,c[42190]|0,G)|0;j=c[t>>2]|0;h[L>>3]=(+h[j+96>>3]+ +h[j+88>>3])*.013888888888888888;qL(G,87652,L)|0;Dm(s,c[42191]|0,G)|0;j=c[t>>2]|0;k=c[j+108>>2]|0;if((k|0)!=0?(a[k+81>>0]|0)!=0:0){q=+h[k+64>>3];q=(c[42184]|0)==0?q:+h[20895]-q;h[M>>3]=+h[k+56>>3];h[M+8>>3]=q;qL(G,87729,M)|0;Lm(s,87667,G)|0;j=c[t>>2]|0}if(yJ(c[c[j+8>>2]>>2]|0,91264)|0){if(c[42215]|0?(Py(y)|0)<<24>>24:0){k=c[(c[t>>2]|0)+12>>2]|0;r=k+8|0;j=c[r>>2]|0;if((j|0)<3){j=Jm(s,87739)|0;if(!j)j=8;else j=sM(j)|0;j=(j|0)<3?8:j}p=k+44|0;q=1.0/+(j|0);n=0;while(1){if((n|0)>=(j|0))break;if((n|0)>0){k=c[A>>2]|0;if(k>>>0>=(c[B>>2]|0)>>>0){em(H,1)|0;k=c[A>>2]|0}c[A>>2]=k+1;a[k>>0]=32}if((c[r>>2]|0)>2){k=c[p>>2]|0;if(!(c[42184]|0))m=+h[k+(n<<4)+8>>3]*.013888888888888888;else m=+h[20896]-+h[k+(n<<4)+8>>3]*.013888888888888888;h[N>>3]=+h[k+(n<<4)>>3]*.013888888888888888;h[N+8>>3]=m;qL(G,87752,N)|0}else{k=c[t>>2]|0;m=q*+(n|0)*6.283185307179586;o=+h[k+32>>3]*.5*+E(+m);if(!(c[42184]|0))m=+h[k+40>>3]*.5*+F(+m);else m=+h[20896]-+h[k+40>>3]*.5*+F(+m);h[O>>3]=o;h[O+8>>3]=m;qL(G,87752,O)|0}gm(H,G)|0;n=n+1|0}k=c[42215]|0;j=c[A>>2]|0;if(j>>>0>=(c[B>>2]|0)>>>0){em(H,1)|0;j=c[A>>2]|0}a[j>>0]=0;t=c[H>>2]|0;c[A>>2]=t;Dm(s,k,t)|0}}else{ux(y,c[j+12>>2]|0,H);im(H)|0;j=c[A>>2]|0;if(j>>>0>=(c[B>>2]|0)>>>0){em(H,1)|0;j=c[A>>2]|0}a[j>>0]=0;t=c[H>>2]|0;c[A>>2]=t;Lm(s,87661,t)|0}a:do if((c[42182]|0)>0){t=Qm(d,y)|0;j=u;while(1){if(!t)break a;s=t+16|0;k=c[s>>2]|0;do if((a[k+112>>0]|0)!=6?(D=c[k+8>>2]|0,(D|0)!=0):0){r=0;k=D;while(1){if((r|0)>=(c[k+4>>2]|0))break;if((r|0)>0){k=c[A>>2]|0;if(k>>>0>=(c[B>>2]|0)>>>0){em(H,1)|0;k=c[A>>2]|0}c[A>>2]=k+1;a[k>>0]=59;k=c[(c[s>>2]|0)+8>>2]|0}k=c[k>>2]|0;if(c[k+(r*48|0)+8>>2]|0){if(!(c[42184]|0))m=+h[k+(r*48|0)+24>>3];else m=+h[20895]-+h[k+(r*48|0)+24>>3];h[P>>3]=+h[k+(r*48|0)+16>>3];h[P+8>>3]=m;qL(G,87762,P)|0;gm(H,G)|0;i=1;k=c[c[(c[s>>2]|0)+8>>2]>>2]|0}if(c[k+(r*48|0)+12>>2]|0){if(!(c[42184]|0))m=+h[k+(r*48|0)+40>>3];else m=+h[20895]-+h[k+(r*48|0)+40>>3];h[R>>3]=+h[k+(r*48|0)+32>>3];h[R+8>>3]=m;qL(G,87775,R)|0;gm(H,G)|0;j=1}p=0;while(1){k=c[(c[s>>2]|0)+8>>2]|0;n=c[k>>2]|0;if((p|0)>=(c[n+(r*48|0)+4>>2]|0))break;if((p|0)>0){k=c[A>>2]|0;if(k>>>0>=(c[B>>2]|0)>>>0){em(H,1)|0;k=c[A>>2]|0}c[A>>2]=k+1;a[k>>0]=32;k=c[c[(c[s>>2]|0)+8>>2]>>2]|0}else k=n;u=c[k+(r*48|0)>>2]|0;q=+h[u+(p<<4)+8>>3];q=(c[42184]|0)==0?q:+h[20895]-q;h[S>>3]=+h[u+(p<<4)>>3];h[S+8>>3]=q;qL(G,87729,S)|0;gm(H,G)|0;p=p+1|0}r=r+1|0}k=c[A>>2]|0;if(k>>>0>=(c[B>>2]|0)>>>0){em(H,1)|0;k=c[A>>2]|0}a[k>>0]=0;k=c[H>>2]|0;c[A>>2]=k;Lm(t,87657,k)|0;k=c[s>>2]|0;n=c[k+96>>2]|0;if(n){q=+h[n+64>>3];q=(c[42184]|0)==0?q:+h[20895]-q;h[T>>3]=+h[n+56>>3];h[T+8>>3]=q;qL(G,87729,T)|0;Lm(t,87671,G)|0;k=c[s>>2]|0}n=c[k+108>>2]|0;do if(n){if(!(a[n+81>>0]|0))break;q=+h[n+64>>3];q=(c[42184]|0)==0?q:+h[20895]-q;h[U>>3]=+h[n+56>>3];h[U+8>>3]=q;qL(G,87729,U)|0;Lm(t,87667,G)|0;k=c[s>>2]|0}while(0);n=c[k+100>>2]|0;if(n){q=+h[n+64>>3];q=(c[42184]|0)==0?q:+h[20895]-q;h[V>>3]=+h[n+56>>3];h[V+8>>3]=q;qL(G,87729,V)|0;Lm(t,87674,G)|0;k=c[s>>2]|0}k=c[k+104>>2]|0;if(!k)break;q=+h[k+64>>3];q=(c[42184]|0)==0?q:+h[20895]-q;h[W>>3]=+h[k+56>>3];h[W+8>>3]=q;qL(G,87729,W)|0;Lm(t,87682,G)|0}while(0);t=Sm(d,t)|0}}else j=u;while(0);u=j;y=fo(d,y)|0}vx(d,z,x,w,v);hm(H);if(b[(c[I>>2]|0)+136>>1]&1)oB(d);c[f>>2]=i;c[g>>2]=u;Gv(0);l=Y;return}function ux(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0.0,g=0.0,i=0.0,j=0,k=0,m=0,n=0,o=0.0;n=l;l=l+1056|0;k=n;j=n+32|0;m=b+48|0;if(!(c[m>>2]|0)){e=c[a+16>>2]|0;i=+h[e+16>>3];if(!(c[42184]|0)){g=+h[e+24>>3];f=g+ +h[b+24>>3];g=g+ +h[b+40>>3]}else{g=+h[e+24>>3];f=+h[20895]-+h[b+24>>3]-g;g=+h[20895]-+h[b+40>>3]-g}o=i+ +h[b+32>>3];h[k>>3]=i+ +h[b+16>>3];h[k+8>>3]=f;h[k+16>>3]=o;h[k+24>>3]=g;qL(j,87813,k)|0;gm(d,j)|0}b=b+56|0;e=0;while(1){if((e|0)>=(c[m>>2]|0))break;ux(a,c[(c[b>>2]|0)+(e<<2)>>2]|0,d);e=e+1|0}l=n;return}function vx(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0.0;s=l;l=l+1088|0;o=s+56|0;q=s+48|0;p=s+32|0;j=s;n=s+64|0;r=b+16|0;i=c[r>>2]|0;if(!(c[42184]|0)){k=+h[i+24>>3];m=+h[i+40>>3]}else{m=+h[20895];k=m-+h[i+24>>3];m=m-+h[i+40>>3]}t=+h[i+32>>3];h[j>>3]=+h[i+16>>3];h[j+8>>3]=k;h[j+16>>3]=t;h[j+24>>3]=m;qL(n,87788,j)|0;Dm(b,d,n)|0;i=c[(c[r>>2]|0)+12>>2]|0;if((i|0)!=0?(a[c[i>>2]>>0]|0)!=0:0){t=+h[i+64>>3];t=(c[42184]|0)==0?t:+h[20895]-t;h[p>>3]=+h[i+56>>3];h[p+8>>3]=t;qL(n,87729,p)|0;Dm(b,e,n)|0;i=c[(c[r>>2]|0)+12>>2]|0;t=+h[i+32>>3];h[q>>3]=+h[i+24>>3]*.013888888888888888;qL(n,87808,q)|0;Dm(b,f,n)|0;h[o>>3]=t*.013888888888888888;qL(n,87808,o)|0;Dm(b,g,n)|0;i=1}else i=1;while(1){j=c[r>>2]|0;if((i|0)>(c[j+180>>2]|0))break;vx(c[(c[j+184>>2]|0)+(i<<2)>>2]|0,d,e,f,g);i=i+1|0}l=s;return}function wx(a){a=a|0;var b=0;b=l;l=l+16|0;tx(a,b,b+4|0);l=b;return}function xx(){return Rl(19796,c[4345]|0)|0}function yx(a,b,c){a=a|0;b=b|0;c=c|0;$I(b);return}function zx(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=c[b>>2]|0;e=c[d>>2]|0;if((a|0)<=(e|0))if((a|0)<(e|0))a=-1;else{b=c[b+4>>2]|0;d=c[d+4>>2]|0;return ((b|0)>(d|0)?1:((b|0)<(d|0))<<31>>31)|0}else a=1;return a|0}function Ax(a){a=a|0;Ll(a)|0;return}function Bx(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];b=Cx(e)|0;if((bb[c[a>>2]&31](a,b,1)|0)!=(b|0))$I(b);l=d;return}function Cx(a){a=a|0;var b=0,d=0,e=0;b=ww(16)|0;e=a;d=c[e+4>>2]|0;a=b+8|0;c[a>>2]=c[e>>2];c[a+4>>2]=d;return b|0}function Dx(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=l;l=l+16|0;f=e+8|0;g=e;c[g>>2]=b;c[g+4>>2]=d;c[f>>2]=c[g>>2];c[f+4>>2]=c[g+4>>2];b=Cx(f)|0;if((bb[c[a>>2]&31](a,b,1)|0)!=(b|0))$I(b);l=e;return}function Ex(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=l;l=l+16|0;e=d;g=b;f=c[g+4>>2]|0;b=e+8|0;c[b>>2]=c[g>>2];c[b+4>>2]=f;b=(bb[c[a>>2]&31](a,e,4)|0)!=0&1;l=d;return b|0}function Fx(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=l;l=l+16|0;f=e;c[f+8>>2]=b;c[f+12>>2]=d;d=(bb[c[a>>2]&31](a,f,4)|0)!=0&1;l=e;return d|0}function Gx(a){a=a|0;return Tl(a)|0}function Hx(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;d=ww((Tl(a)|0)<<3)|0;b=d;a=Pl(a)|0;while(1){if(!a)break;g=a+8|0;f=c[g+4>>2]|0;e=b;c[e>>2]=c[g>>2];c[e+4>>2]=f;b=b+8|0;a=c[a>>2]|0}return d|0}function Ix(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0.0,g=0.0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=l;l=l+160|0;q=t+144|0;d=t+48|0;j=t+128|0;k=t+112|0;m=t+96|0;n=t+80|0;o=t+32|0;p=t+16|0;r=t;s=a+16|0;a=c[s>>2]|0;e=+h[a+16>>3];f=+h[a+24>>3];g=+h[a+32>>3];i=+h[a+40>>3];if((b+-1|0)>>>0<2){Jx(j,e,i);c[q>>2]=c[j>>2];c[q+4>>2]=c[j+4>>2];c[q+8>>2]=c[j+8>>2];c[q+12>>2]=c[j+12>>2];Kx(d,q);p=d+16|0;Jx(k,g,f);c[q>>2]=c[k>>2];c[q+4>>2]=c[k+4>>2];c[q+8>>2]=c[k+8>>2];c[q+12>>2]=c[k+12>>2];Kx(m,q);c[p>>2]=c[m>>2];c[p+4>>2]=c[m+4>>2];c[p+8>>2]=c[m+8>>2];c[p+12>>2]=c[m+12>>2]}else{Jx(n,e,f);c[q>>2]=c[n>>2];c[q+4>>2]=c[n+4>>2];c[q+8>>2]=c[n+8>>2];c[q+12>>2]=c[n+12>>2];Kx(d,q);n=d+16|0;Jx(o,g,i);c[q>>2]=c[o>>2];c[q+4>>2]=c[o+4>>2];c[q+8>>2]=c[o+8>>2];c[q+12>>2]=c[o+12>>2];Kx(p,q);c[n>>2]=c[p>>2];c[n+4>>2]=c[p+4>>2];c[n+8>>2]=c[p+8>>2];c[n+12>>2]=c[p+12>>2]}a=(c[s>>2]|0)+16|0;c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];c[a+16>>2]=c[d+16>>2];c[a+20>>2]=c[d+20>>2];c[a+24>>2]=c[d+24>>2];c[a+28>>2]=c[d+28>>2];a=c[(c[s>>2]|0)+12>>2]|0;if(!a)a=1;else{a=a+56|0;c[q>>2]=c[a>>2];c[q+4>>2]=c[a+4>>2];c[q+8>>2]=c[a+8>>2];c[q+12>>2]=c[a+12>>2];Kx(r,q);c[a>>2]=c[r>>2];c[a+4>>2]=c[r+4>>2];c[a+8>>2]=c[r+8>>2];c[a+12>>2]=c[r+12>>2];a=1}while(1){d=c[s>>2]|0;if((a|0)>(c[d+180>>2]|0))break;Ix(c[(c[d+184>>2]|0)+(a<<2)>>2]|0,b);a=a+1|0}l=t;return}function Jx(a,b,c){a=a|0;b=+b;c=+c;h[a>>3]=b;h[a+8>>3]=c;return}function Kx(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=l;l=l+32|0;g=d+16|0;e=d;f=(c[42310]|0)*90|0;c[g>>2]=c[b>>2];c[g+4>>2]=c[b+4>>2];c[g+8>>2]=c[b+8>>2];c[g+12>>2]=c[b+12>>2];bw(e,g,f);c[b>>2]=c[e>>2];c[b+4>>2]=c[e+4>>2];c[b+8>>2]=c[e+8>>2];c[b+12>>2]=c[e+12>>2];h[b>>3]=+h[b>>3]-+h[20897];e=b+8|0;h[e>>3]=+h[e>>3]-+h[20898];c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];l=d;return}function Lx(b,d){b=b|0;d=d|0;var e=0,f=0.0,g=0,i=0,j=0.0,k=0.0,m=0,n=0.0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=l;l=l+1168|0;s=w+144|0;v=w+96|0;u=w+64|0;t=w+48|0;o=w+32|0;p=w+16|0;q=w;c[t>>2]=0;c[t+4>>2]=0;c[t+8>>2]=0;c[t+12>>2]=0;r=b+16|0;m=c[(c[r>>2]|0)+116>>2]|0;c[42310]=m&3;m=m&1;a[174083]=m;if(!(m<<24>>24))Nx(b);else Mx(b);Ox(b);m=c[r>>2]|0;e=c[m+12>>2]|0;do if(e|0?(a[e+81>>0]|0)==0:0){g=e+24|0;c[t>>2]=c[g>>2];c[t+4>>2]=c[g+4>>2];c[t+8>>2]=c[g+8>>2];c[t+12>>2]=c[g+12>>2];n=+h[t>>3]+16.0;h[t>>3]=n;g=t+8|0;f=+h[g>>3]+8.0;h[g>>3]=f;g=(a[m+275>>0]&1)!=0;if(a[174083]|0){if(g){i=m+32|0;h[i>>3]=+h[i>>3]+f}else{i=m+16|0;h[i>>3]=+h[i>>3]-f}g=m+40|0;f=+h[g>>3];i=m+24|0;j=+h[i>>3];k=f-j;if(!(n>k))break;n=(n-k)*.5;h[i>>3]=j-n;h[g>>3]=f+n;break}i=(c[42310]|0)==0;do if(g)if(i){i=m+40|0;h[i>>3]=+h[i>>3]+f;break}else{i=m+24|0;h[i>>3]=+h[i>>3]-f;break}else if(i){i=m+24|0;h[i>>3]=+h[i>>3]-f;break}else{i=m+40|0;h[i>>3]=+h[i>>3]+f;break}while(0);g=m+32|0;f=+h[g>>3];i=m+16|0;j=+h[i>>3];k=f-j;if(n>k){n=(n-k)*.5;h[i>>3]=j-n;h[g>>3]=f+n}}while(0);if(d){switch(c[42310]|0){case 0:{q=m+16|0;c[41794]=c[q>>2];c[41795]=c[q+4>>2];c[41796]=c[q+8>>2];c[41797]=c[q+12>>2];break}case 1:{Jx(o,-+h[m+40>>3],+h[m+16>>3]);c[41794]=c[o>>2];c[41795]=c[o+4>>2];c[41796]=c[o+8>>2];c[41797]=c[o+12>>2];break}case 2:{Jx(p,+h[m+16>>3],-+h[m+40>>3]);c[41794]=c[p>>2];c[41795]=c[p+4>>2];c[41796]=c[p+8>>2];c[41797]=c[p+12>>2];break}case 3:{Jx(q,+h[m+24>>3],+h[m+16>>3]);c[41794]=c[q>>2];c[41795]=c[q+4>>2];c[41796]=c[q+8>>2];c[41797]=c[q+12>>2];break}default:{}}Px(b);e=c[(c[r>>2]|0)+12>>2]|0}if(e|0?(a[e+81>>0]|0)==0:0){c[s>>2]=c[t>>2];c[s+4>>2]=c[t+4>>2];c[s+8>>2]=c[t+8>>2];c[s+12>>2]=c[t+12>>2];Qx(b,s)}if(!0){l=w;return}if(!(a[174083]|0)){n=+h[20898];k=+h[20897];h[v>>3]=n;h[v+8>>3]=k;h[v+16>>3]=n;h[v+24>>3]=k;h[v+32>>3]=-k;h[v+40>>3]=-n;qL(s,88049,v)|0}else{k=+h[20897];n=+h[20898];h[u>>3]=k;h[u+8>>3]=n;h[u+16>>3]=k;h[u+24>>3]=n;qL(s,87834,u)|0}HL(s)|0;Ta()}function Mx(b){b=b|0;var d=0,e=0.0,f=0.0,g=0,i=0,j=0;j=b+16|0;if(((to(b)|0)!=(b|0)?(g=c[j>>2]|0,i=c[g+12>>2]|0,(i|0)!=0):0)?(a[i+81>>0]|0)==0:0){d=a[g+275>>0]|0;if(!(d&1)){f=+h[g+16>>3]+ +h[g+96>>3]*.5;b=g+104|0}else{f=+h[g+32>>3]-+h[g+64>>3]*.5;b=g+72|0}e=+h[b>>3];b=d<<24>>24;do if(!(b&4))if(!(b&2)){e=(+h[g+40>>3]+ +h[g+24>>3])*.5;break}else{e=+h[g+40>>3]-e*.5;break}else e=+h[g+24>>3]+e*.5;while(0);h[i+56>>3]=f;h[i+64>>3]=e;a[(c[(c[j>>2]|0)+12>>2]|0)+81>>0]=1;b=1}else b=1;while(1){d=c[j>>2]|0;if((b|0)>(c[d+180>>2]|0))break;Mx(c[(c[d+184>>2]|0)+(b<<2)>>2]|0);b=b+1|0}return}function Nx(b){b=b|0;var d=0,e=0.0,f=0.0,g=0.0,i=0,j=0,k=0;k=b+16|0;if(((to(b)|0)!=(b|0)?(i=c[k>>2]|0,j=c[i+12>>2]|0,(j|0)!=0):0)?(a[j+81>>0]|0)==0:0){d=a[i+275>>0]|0;if(!(d&1)){g=+h[i+24>>3]+ +h[i+56>>3]*.5;b=i+48|0}else{g=+h[i+40>>3]-+h[i+88>>3]*.5;b=i+80|0}f=+h[b>>3];b=d<<24>>24;do if(!(b&4)){e=+h[i+16>>3];if(!(b&2)){e=(+h[i+32>>3]+e)*.5;break}else{e=e+f*.5;break}}else e=+h[i+32>>3]-f*.5;while(0);h[j+56>>3]=e;h[j+64>>3]=g;a[(c[(c[k>>2]|0)+12>>2]|0)+81>>0]=1;b=1}else b=1;while(1){d=c[k>>2]|0;if((b|0)>(c[d+180>>2]|0))break;Nx(c[(c[d+184>>2]|0)+(b<<2)>>2]|0);b=b+1|0}return}function Ox(e){e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0;S=l;l=l+544|0;L=S+504|0;R=S+416|0;Q=S+376|0;K=S+352|0;J=S+312|0;I=S+288|0;H=S+248|0;M=S+200|0;B=S+152|0;O=S+96|0;p=S+488|0;C=S+456|0;D=S+424|0;E=S+384|0;F=S+360|0;G=S+320|0;w=S+296|0;x=S+256|0;y=S+232|0;z=S+168|0;A=S+136|0;f=S+56|0;N=S+16|0;P=S;o=e+16|0;u=c[o>>2]|0;g=b[u+136>>1]&14;u=d[u+113>>0]|0;if(!((u&54|0)==0?(u&1|0)==0|(c[42183]|0)!=0:0)){u=g<<16>>16==0;n=eo(e)|0;h=0;j=0;i=0;while(1){if(!n)break;g=c[(c[n+16>>2]|0)+108>>2]|0;do if(g)if(!(a[g+81>>0]|0)){i=i+1|0;break}else{h=h+1|0;break}while(0);m=Qm(e,n)|0;g=j;while(1){if(!m)break;k=c[m+16>>2]|0;j=c[k+108>>2]|0;do if(j){if(a[j+81>>0]|0){h=h+1|0;break}if(!u)g=g+((c[k+8>>2]|0)!=0&1)|0}while(0);j=c[k+100>>2]|0;do if(j){if(a[j+81>>0]|0){h=h+1|0;break}if(!u)g=g+((c[k+8>>2]|0)!=0&1)|0}while(0);j=c[k+104>>2]|0;do if(j){if(a[j+81>>0]|0){h=h+1|0;break}if(!u)g=g+((c[k+8>>2]|0)!=0&1)|0}while(0);j=c[k+96>>2]|0;do if(j){if(a[j+81>>0]|0){h=h+1|0;break}if(!u)g=g+((c[k+8>>2]|0)!=0&1)|0}while(0);m=Sm(e,m)|0}n=fo(e,n)|0;j=g}if(!(a[(c[o>>2]|0)+113>>0]&8))o=0;else o=Sx(e)|0;t=j+i|0;if(t|0){q=h+j+o+(nn(e)|0)|0;r=ww(q*40|0)|0;s=ww(t*40|0)|0;Jx(M,2147483647.0,2147483647.0);g=M+16|0;Jx(p,-2147483647.0,-2147483647.0);c[g>>2]=c[p>>2];c[g+4>>2]=c[p+4>>2];c[g+8>>2]=c[p+8>>2];c[g+12>>2]=c[p+12>>2];g=s;i=r;n=eo(e)|0;while(1){if(!n)break;c[L>>2]=c[M>>2];c[L+4>>2]=c[M+4>>2];c[L+8>>2]=c[M+8>>2];c[L+12>>2]=c[M+12>>2];c[L+16>>2]=c[M+16>>2];c[L+20>>2]=c[M+20>>2];c[L+24>>2]=c[M+24>>2];c[L+28>>2]=c[M+28>>2];Tx(C,n,i,L);c[M>>2]=c[C>>2];c[M+4>>2]=c[C+4>>2];c[M+8>>2]=c[C+8>>2];c[M+12>>2]=c[C+12>>2];c[M+16>>2]=c[C+16>>2];c[M+20>>2]=c[C+20>>2];c[M+24>>2]=c[C+24>>2];c[M+28>>2]=c[C+28>>2];h=c[(c[n+16>>2]|0)+108>>2]|0;do if(h)if(!(a[h+81>>0]|0)){c[L>>2]=c[B>>2];c[L+4>>2]=c[B+4>>2];c[L+8>>2]=c[B+8>>2];c[L+12>>2]=c[B+12>>2];Vx(h,i,g,0,L);g=g+40|0;break}else{i=i+40|0;c[L>>2]=c[M>>2];c[L+4>>2]=c[M+4>>2];c[L+8>>2]=c[M+8>>2];c[L+12>>2]=c[M+12>>2];c[L+16>>2]=c[M+16>>2];c[L+20>>2]=c[M+20>>2];c[L+24>>2]=c[M+24>>2];c[L+28>>2]=c[M+28>>2];Ux(D,h,i,L);c[M>>2]=c[D>>2];c[M+4>>2]=c[D+4>>2];c[M+8>>2]=c[D+8>>2];c[M+12>>2]=c[D+12>>2];c[M+16>>2]=c[D+16>>2];c[M+20>>2]=c[D+20>>2];c[M+24>>2]=c[D+24>>2];c[M+28>>2]=c[D+28>>2];break}while(0);m=Qm(e,n)|0;i=i+40|0;while(1){if(!m)break;k=m+16|0;h=c[k>>2]|0;j=c[h+96>>2]|0;a:do if(!j)v=52;else{do if(!(a[j+81>>0]|0)){if(!u?c[h+8>>2]|0:0){aA(F,e,m);c[L>>2]=c[F>>2];c[L+4>>2]=c[F+4>>2];c[L+8>>2]=c[F+8>>2];c[L+12>>2]=c[F+12>>2];Vx(j,i,g,1,L);g=g+40|0;break}c[H>>2]=c[j>>2];$l(0,88861,H)|0;break a}else{c[L>>2]=c[M>>2];c[L+4>>2]=c[M+4>>2];c[L+8>>2]=c[M+8>>2];c[L+12>>2]=c[M+12>>2];c[L+16>>2]=c[M+16>>2];c[L+20>>2]=c[M+20>>2];c[L+24>>2]=c[M+24>>2];c[L+28>>2]=c[M+28>>2];Ux(E,j,i,L);c[M>>2]=c[E>>2];c[M+4>>2]=c[E+4>>2];c[M+8>>2]=c[E+8>>2];c[M+12>>2]=c[E+12>>2];c[M+16>>2]=c[E+16>>2];c[M+20>>2]=c[E+20>>2];c[M+24>>2]=c[E+24>>2];c[M+28>>2]=c[E+28>>2]}while(0);i=i+40|0;h=c[k>>2]|0;v=52}while(0);b:do if((v|0)==52){v=0;j=c[h+104>>2]|0;if(j){do if(!(a[j+81>>0]|0)){if(!u?c[h+8>>2]|0:0){Wx(w,m);c[L>>2]=c[w>>2];c[L+4>>2]=c[w+4>>2];c[L+8>>2]=c[w+8>>2];c[L+12>>2]=c[w+12>>2];Vx(j,i,g,1,L);g=g+40|0;break}c[I>>2]=c[j>>2];$l(0,88896,I)|0;break b}else{c[L>>2]=c[M>>2];c[L+4>>2]=c[M+4>>2];c[L+8>>2]=c[M+8>>2];c[L+12>>2]=c[M+12>>2];c[L+16>>2]=c[M+16>>2];c[L+20>>2]=c[M+20>>2];c[L+24>>2]=c[M+24>>2];c[L+28>>2]=c[M+28>>2];Ux(G,j,i,L);c[M>>2]=c[G>>2];c[M+4>>2]=c[G+4>>2];c[M+8>>2]=c[G+8>>2];c[M+12>>2]=c[G+12>>2];c[M+16>>2]=c[G+16>>2];c[M+20>>2]=c[G+20>>2];c[M+24>>2]=c[G+24>>2];c[M+28>>2]=c[G+28>>2]}while(0);i=i+40|0;h=c[k>>2]|0}j=c[h+100>>2]|0;if(j){do if(!(a[j+81>>0]|0)){if(!u?c[h+8>>2]|0:0){Xx(y,m);c[L>>2]=c[y>>2];c[L+4>>2]=c[y+4>>2];c[L+8>>2]=c[y+8>>2];c[L+12>>2]=c[y+12>>2];Vx(j,i,g,1,L);g=g+40|0;break}c[J>>2]=c[j>>2];$l(0,88936,J)|0;break b}else{c[L>>2]=c[M>>2];c[L+4>>2]=c[M+4>>2];c[L+8>>2]=c[M+8>>2];c[L+12>>2]=c[M+12>>2];c[L+16>>2]=c[M+16>>2];c[L+20>>2]=c[M+20>>2];c[L+24>>2]=c[M+24>>2];c[L+28>>2]=c[M+28>>2];Ux(x,j,i,L);c[M>>2]=c[x>>2];c[M+4>>2]=c[x+4>>2];c[M+8>>2]=c[x+8>>2];c[M+12>>2]=c[x+12>>2];c[M+16>>2]=c[x+16>>2];c[M+20>>2]=c[x+20>>2];c[M+24>>2]=c[x+24>>2];c[M+28>>2]=c[x+28>>2]}while(0);i=i+40|0;h=c[k>>2]|0}j=c[h+108>>2]|0;if(j){do if(!(a[j+81>>0]|0)){if(!u?c[h+8>>2]|0:0){aA(A,e,m);c[L>>2]=c[A>>2];c[L+4>>2]=c[A+4>>2];c[L+8>>2]=c[A+8>>2];c[L+12>>2]=c[A+12>>2];Vx(j,i,g,1,L);g=g+40|0;break}c[K>>2]=c[j>>2];$l(0,88976,K)|0;break b}else{c[L>>2]=c[M>>2];c[L+4>>2]=c[M+4>>2];c[L+8>>2]=c[M+8>>2];c[L+12>>2]=c[M+12>>2];c[L+16>>2]=c[M+16>>2];c[L+20>>2]=c[M+20>>2];c[L+24>>2]=c[M+24>>2];c[L+28>>2]=c[M+28>>2];Ux(z,j,i,L);c[M>>2]=c[z>>2];c[M+4>>2]=c[z+4>>2];c[M+8>>2]=c[z+8>>2];c[M+12>>2]=c[z+12>>2];c[M+16>>2]=c[z+16>>2];c[M+20>>2]=c[z+20>>2];c[M+24>>2]=c[z+24>>2];c[M+28>>2]=c[z+28>>2]}while(0);i=i+40|0}}while(0);m=Sm(e,m)|0}n=fo(e,n)|0}if(o|0){c[f>>2]=c[M>>2];c[f+4>>2]=c[M+4>>2];c[f+8>>2]=c[M+8>>2];c[f+12>>2]=c[M+12>>2];c[f+16>>2]=c[M+16>>2];c[f+20>>2]=c[M+20>>2];c[f+24>>2]=c[M+24>>2];c[f+28>>2]=c[M+28>>2];c[f+32>>2]=i;h=L;g=h+40|0;do{c[h>>2]=c[f>>2];h=h+4|0;f=f+4|0}while((h|0)<(g|0));Yx(N,e,L);c[M>>2]=c[N>>2];c[M+4>>2]=c[N+4>>2];c[M+8>>2]=c[N+8>>2];c[M+12>>2]=c[N+12>>2];c[M+16>>2]=c[N+16>>2];c[M+20>>2]=c[N+20>>2];c[M+24>>2]=c[N+24>>2];c[M+28>>2]=c[N+28>>2]}a[O+32>>0]=IA(e,zm(e,0,89012,0)|0,1)|0;c[O>>2]=c[M>>2];c[O+4>>2]=c[M+4>>2];c[O+8>>2]=c[M+8>>2];c[O+12>>2]=c[M+12>>2];c[O+16>>2]=c[M+16>>2];c[O+20>>2]=c[M+20>>2];c[O+24>>2]=c[M+24>>2];c[O+28>>2]=c[M+28>>2];AE(r,q,s,t,O)|0;if(0)Zx(r,q,s,t,O);f=0;g=0;h=s;while(1){if((g|0)>=(t|0))break;if(a[h+36>>0]|0){O=c[h+32>>2]|0;a[O+81>>0]=1;N=O+56|0;_x(P,h);c[N>>2]=c[P>>2];c[N+4>>2]=c[P+4>>2];c[N+8>>2]=c[P+8>>2];c[N+12>>2]=c[P+12>>2];cB(e,O);f=f+1|0}g=g+1|0;h=h+40|0}if(!0){if((f|0)!=(t|0)){c[R>>2]=f;c[R+4>>2]=t;$l(0,89057,R)|0}}else{R=c[13918]|0;c[Q>>2]=f;c[Q+4>>2]=t;AL(R,89024,Q)|0}$I(r);$I(s)}}l=S;return}function Px(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0;i=l;l=l+48|0;e=i+32|0;f=i+16|0;g=i;if(+h[20897]!=0.0|+h[20898]!=0.0|(c[42310]|0)!=0){d=eo(a)|0;while(1){if(!d)break;if(c[42310]|0)LB(d,0);b=d+16|0;j=(c[b>>2]|0)+16|0;c[e>>2]=c[j>>2];c[e+4>>2]=c[j+4>>2];c[e+8>>2]=c[j+8>>2];c[e+12>>2]=c[j+12>>2];Kx(f,e);c[j>>2]=c[f>>2];c[j+4>>2]=c[f+4>>2];c[j+8>>2]=c[f+8>>2];c[j+12>>2]=c[f+12>>2];b=c[(c[b>>2]|0)+108>>2]|0;if(b|0){j=b+56|0;c[e>>2]=c[j>>2];c[e+4>>2]=c[j+4>>2];c[e+8>>2]=c[j+8>>2];c[e+12>>2]=c[j+12>>2];Kx(g,e);c[j>>2]=c[g>>2];c[j+4>>2]=c[g+4>>2];c[j+8>>2]=c[g+8>>2];c[j+12>>2]=c[g+12>>2]}a:do if((c[42182]|0)==1){b=Qm(a,d)|0;while(1){if(!b)break a;Rx(b);b=Sm(a,b)|0}}while(0);d=fo(a,d)|0}Ix(a,c[(c[a+16>>2]|0)+116>>2]&3)}l=i;return}function Qx(b,d){b=b|0;d=d|0;var e=0.0,f=0.0,g=0,i=0,j=0;i=b+16|0;j=c[i>>2]|0;g=a[j+275>>0]|0;b=g<<24>>24;do if(!(b&4)){e=+h[j+16>>3];if(!(b&2)){f=(+h[j+32>>3]+e)*.5;break}else{f=+h[d>>3]*.5+e;break}}else f=+h[j+32>>3]-+h[d>>3]*.5;while(0);if(!(g&1))e=+h[d+8>>3]*.5+ +h[j+24>>3];else e=+h[j+40>>3]-+h[d+8>>3]*.5;j=c[j+12>>2]|0;h[j+56>>3]=f;h[j+64>>3]=e;a[(c[(c[i>>2]|0)+12>>2]|0)+81>>0]=1;return}function Rx(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;s=l;l=l+144|0;q=s+120|0;e=s+16|0;i=s+104|0;j=s+88|0;k=s+72|0;m=s+56|0;n=s+40|0;o=s+24|0;r=s;p=b+16|0;d=c[p>>2]|0;f=c[d+8>>2]|0;if(!f){if((a[174080]|0)==0?(a[d+112>>0]|0)!=6:0){q=En(c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0;r=En(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0;c[e>>2]=q;c[e+4>>2]=r;$l(1,88844,e)|0}}else{h=0;b=f;while(1){if((h|0)>=(c[b+4>>2]|0))break;g=c[b>>2]|0;b=c[g+(h*48|0)>>2]|0;e=c[g+(h*48|0)+4>>2]|0;f=c[g+(h*48|0)+8>>2]|0;g=c[g+(h*48|0)+12>>2]|0;d=0;while(1){if((d|0)>=(e|0))break;t=b+(d<<4)|0;c[q>>2]=c[t>>2];c[q+4>>2]=c[t+4>>2];c[q+8>>2]=c[t+8>>2];c[q+12>>2]=c[t+12>>2];Kx(i,q);c[t>>2]=c[i>>2];c[t+4>>2]=c[i+4>>2];c[t+8>>2]=c[i+8>>2];c[t+12>>2]=c[i+12>>2];d=d+1|0}if(f|0){t=(c[c[(c[p>>2]|0)+8>>2]>>2]|0)+(h*48|0)+16|0;c[q>>2]=c[t>>2];c[q+4>>2]=c[t+4>>2];c[q+8>>2]=c[t+8>>2];c[q+12>>2]=c[t+12>>2];Kx(j,q);c[t>>2]=c[j>>2];c[t+4>>2]=c[j+4>>2];c[t+8>>2]=c[j+8>>2];c[t+12>>2]=c[j+12>>2]}if(g|0){t=(c[c[(c[p>>2]|0)+8>>2]>>2]|0)+(h*48|0)+32|0;c[q>>2]=c[t>>2];c[q+4>>2]=c[t+4>>2];c[q+8>>2]=c[t+8>>2];c[q+12>>2]=c[t+12>>2];Kx(k,q);c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[t+8>>2]=c[k+8>>2];c[t+12>>2]=c[k+12>>2]}d=c[p>>2]|0;h=h+1|0;b=c[d+8>>2]|0}b=c[d+96>>2]|0;if(b){d=b+56|0;c[q>>2]=c[d>>2];c[q+4>>2]=c[d+4>>2];c[q+8>>2]=c[d+8>>2];c[q+12>>2]=c[d+12>>2];Kx(m,q);c[d>>2]=c[m>>2];c[d+4>>2]=c[m+4>>2];c[d+8>>2]=c[m+8>>2];c[d+12>>2]=c[m+12>>2];d=c[p>>2]|0}b=c[d+108>>2]|0;if(b){d=b+56|0;c[q>>2]=c[d>>2];c[q+4>>2]=c[d+4>>2];c[q+8>>2]=c[d+8>>2];c[q+12>>2]=c[d+12>>2];Kx(n,q);c[d>>2]=c[n>>2];c[d+4>>2]=c[n+4>>2];c[d+8>>2]=c[n+8>>2];c[d+12>>2]=c[n+12>>2];d=c[p>>2]|0}b=c[d+100>>2]|0;if(b){d=b+56|0;c[q>>2]=c[d>>2];c[q+4>>2]=c[d+4>>2];c[q+8>>2]=c[d+8>>2];c[q+12>>2]=c[d+12>>2];Kx(o,q);c[d>>2]=c[o>>2];c[d+4>>2]=c[o+4>>2];c[d+8>>2]=c[o+8>>2];c[d+12>>2]=c[o+12>>2];d=c[p>>2]|0}d=c[d+104>>2]|0;if(d|0){t=d+56|0;c[q>>2]=c[t>>2];c[q+4>>2]=c[t+4>>2];c[q+8>>2]=c[t+8>>2];c[q+12>>2]=c[t+12>>2];Kx(r,q);c[t>>2]=c[r>>2];c[t+4>>2]=c[r+4>>2];c[t+8>>2]=c[r+8>>2];c[t+12>>2]=c[r+12>>2]}}l=s;return}function Sx(b){b=b|0;var d=0,e=0,f=0;f=b+16|0;if((to(b)|0)!=(b|0)?(d=c[(c[f>>2]|0)+12>>2]|0,(d|0)!=0):0){e=1;b=(a[d+81>>0]|0)!=0&1}else{e=1;b=0}while(1){d=c[f>>2]|0;if((e|0)>(c[d+180>>2]|0))break;d=(Sx(c[(c[d+184>>2]|0)+(e<<2)>>2]|0)|0)+b|0;e=e+1|0;b=d}return b|0}function Tx(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0.0,k=0.0,m=0,n=0;g=l;l=l+32|0;i=g;n=(a[174083]|0)==0;d=d+16|0;m=c[d>>2]|0;k=+h[(n?m+32|0:m+40|0)>>3];h[e+16>>3]=k*72.0;j=+h[(n?m+40|0:m+32|0)>>3];h[e+24>>3]=j*72.0;d=(c[d>>2]|0)+16|0;c[e>>2]=c[d>>2];c[e+4>>2]=c[d+4>>2];c[e+8>>2]=c[d+8>>2];c[e+12>>2]=c[d+12>>2];h[e>>3]=+h[e>>3]-k*36.0;d=e+8|0;h[d>>3]=+h[d>>3]-j*36.0;c[i>>2]=c[f>>2];c[i+4>>2]=c[f+4>>2];c[i+8>>2]=c[f+8>>2];c[i+12>>2]=c[f+12>>2];c[i+16>>2]=c[f+16>>2];c[i+20>>2]=c[f+20>>2];c[i+24>>2]=c[f+24>>2];c[i+28>>2]=c[f+28>>2];$x(b,e,i);l=g;return}function Ux(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0.0,k=0.0,m=0,n=0;g=l;l=l+32|0;i=g;n=(a[174083]|0)==0;m=d+24|0;k=+h[(n?m:d+32|0)>>3];h[e+16>>3]=k;j=+h[(n?d+32|0:m)>>3];h[e+24>>3]=j;d=d+56|0;c[e>>2]=c[d>>2];c[e+4>>2]=c[d+4>>2];c[e+8>>2]=c[d+8>>2];c[e+12>>2]=c[d+12>>2];h[e>>3]=+h[e>>3]-k*.5;d=e+8|0;h[d>>3]=+h[d>>3]-j*.5;c[i>>2]=c[f>>2];c[i+4>>2]=c[f+4>>2];c[i+8>>2]=c[f+8>>2];c[i+12>>2]=c[f+12>>2];c[i+16>>2]=c[f+16>>2];c[i+20>>2]=c[f+20>>2];c[i+24>>2]=c[f+24>>2];c[i+28>>2]=c[f+28>>2];$x(b,e,i);l=g;return}function Vx(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;if(f|0){f=d+16|0;c[f>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[d>>2]=c[g>>2];c[d+4>>2]=c[g+4>>2];c[d+8>>2]=c[g+8>>2];c[d+12>>2]=c[g+12>>2]}if(!(a[174083]|0)){g=b+24|0;c[e>>2]=c[g>>2];c[e+4>>2]=c[g+4>>2];c[e+8>>2]=c[g+8>>2];c[e+12>>2]=c[g+12>>2]}else{h[e>>3]=+h[b+32>>3];h[e+8>>3]=+h[b+24>>3]}c[e+32>>2]=b;a[e+36>>0]=0;c[d+32>>2]=e;return}function Wx(a,b){a=a|0;b=b|0;b=$z(b)|0;do if(b){b=c[b>>2]|0;if(!(c[b+8>>2]|0)){b=c[b>>2]|0;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];break}else{b=b+16|0;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];break}}else{c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0}while(0);return}function Xx(a,b){a=a|0;b=b|0;var d=0;b=$z(b)|0;do if(b){d=c[b>>2]|0;b=(c[b+4>>2]|0)+-1|0;if(!(c[d+(b*48|0)+12>>2]|0)){d=(c[d+(b*48|0)>>2]|0)+((c[d+(b*48|0)+4>>2]|0)+-1<<4)|0;c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];break}else{d=d+(b*48|0)+32|0;c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];break}}else{c[a>>2]=0;c[a+4>>2]=0;c[a+8>>2]=0;c[a+12>>2]=0}while(0);return}function Yx(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;q=l;l=l+112|0;k=q+72|0;n=q+32|0;o=q;p=d+16|0;j=1;while(1){f=c[p>>2]|0;if((j|0)>(c[f+180>>2]|0))break;f=c[(c[f+184>>2]|0)+(j<<2)>>2]|0;g=k;h=e;i=g+40|0;do{c[g>>2]=c[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));Yx(n,f,k);g=e;h=n;i=g+40|0;do{c[g>>2]=c[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));j=j+1|0}if(((to(d)|0)!=(d|0)?(m=c[(c[p>>2]|0)+12>>2]|0,m|0):0)?a[m+81>>0]|0:0){p=e+32|0;n=c[p>>2]|0;c[k>>2]=c[e>>2];c[k+4>>2]=c[e+4>>2];c[k+8>>2]=c[e+8>>2];c[k+12>>2]=c[e+12>>2];c[k+16>>2]=c[e+16>>2];c[k+20>>2]=c[e+20>>2];c[k+24>>2]=c[e+24>>2];c[k+28>>2]=c[e+28>>2];Ux(o,m,n,k);c[e>>2]=c[o>>2];c[e+4>>2]=c[o+4>>2];c[e+8>>2]=c[o+8>>2];c[e+12>>2]=c[o+12>>2];c[e+16>>2]=c[o+16>>2];c[e+20>>2]=c[o+20>>2];c[e+24>>2]=c[o+24>>2];c[e+28>>2]=c[o+28>>2];c[p>>2]=(c[p>>2]|0)+40}g=b;h=e;i=g+40|0;do{c[g>>2]=c[h>>2];g=g+4|0;h=h+4|0}while((g|0)<(i|0));l=q;return}function Zx(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var i=0.0,j=0.0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0;s=l;l=l+160|0;r=s+96|0;p=s+48|0;o=s;q=c[13918]|0;n=d[g+32>>0]|0;i=+h[g>>3];j=+h[g+8>>3];k=+h[g+16>>3];m=+h[g+24>>3];c[o>>2]=b;c[o+4>>2]=f;c[o+8>>2]=n;h[o+16>>3]=i;h[o+24>>3]=j;h[o+32>>3]=k;h[o+40>>3]=m;AL(q,89099,o)|0;a:do if(0>=2){YL(89159,8,1,q)|0;o=0;while(1){if((o|0)>=(b|0))break;g=c[a+32>>2]|0;i=+h[a>>3];j=+h[a+8>>3];k=+h[a+16>>3];m=+h[a+24>>3];if(!g)n=174185;else n=c[c[g+32>>2]>>2]|0;c[p>>2]=o;h[p+8>>3]=i;h[p+16>>3]=j;h[p+24>>3]=k;h[p+32>>3]=m;c[p+40>>2]=g;c[p+44>>2]=n;AL(q,89168,p)|0;o=o+1|0;a=a+40|0}YL(89211,8,1,q)|0;g=0;while(1){if((g|0)>=(f|0))break a;b=d[e+36>>0]|0;i=+h[e+16>>3];j=+h[e+24>>3];k=+h[e>>3];m=+h[e+8>>3];p=c[c[e+32>>2]>>2]|0;c[r>>2]=g;c[r+4>>2]=e;c[r+8>>2]=b;h[r+16>>3]=i;h[r+24>>3]=j;h[r+32>>3]=k;h[r+40>>3]=m;c[r+48>>2]=p;AL(q,89220,r)|0;e=e+40|0;g=g+1|0}}while(0);l=s;return}function _x(a,b){a=a|0;b=b|0;var c=0.0;c=+h[b+8>>3]*.5+ +h[b+24>>3];h[a>>3]=+h[b>>3]*.5+ +h[b+16>>3];h[a+8>>3]=c;return}function $x(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0.0,j=0.0;e=l;l=l+16|0;f=e;j=+h[b>>3];h[d>>3]=+h[(+h[d>>3]>3];g=d+8|0;i=+h[b+8>>3];h[g>>3]=+h[(+h[g>>3]>3];j=+h[b+16>>3]+j;h[f>>3]=j;i=+h[b+24>>3]+i;h[f+8>>3]=i;g=d+16|0;h[g>>3]=+h[(+h[g>>3]>j?g:f)>>3];b=d+24|0;h[b>>3]=+h[(+h[b>>3]>i?g:f)+8>>3];c[a>>2]=c[d>>2];c[a+4>>2]=c[d+4>>2];c[a+8>>2]=c[d+8>>2];c[a+12>>2]=c[d+12>>2];c[a+16>>2]=c[d+16>>2];c[a+20>>2]=c[d+20>>2];c[a+24>>2]=c[d+24>>2];c[a+28>>2]=c[d+28>>2];l=e;return}function ay(a){a=a|0;Lx(a,1);return}function by(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;e=l;l=l+16|0;d=e;b=SA(Jm(a,90560)|0)|0;if(b){b=cy(b)|0;if(b|0){f=c[b+40>>2]|0;d=c[b+44>>2]|0;g=a+16|0;a=c[g>>2]|0;h[a+32>>3]=+(f|0)*.013888888888888888;h[a+40>>3]=+(d|0)*.013888888888888888;a=ww(12)|0;c[(c[g>>2]|0)+12>>2]=a;c[a>>2]=c[b+12>>2];c[a+4>>2]=((f|0)/-2|0)-(c[b+32>>2]|0);c[a+8>>2]=((d|0)/-2|0)-(c[b+36>>2]|0)}}else{c[d>>2]=En(a)|0;$l(0,89268,d)|0}l=e;return}function cy(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;p=l;l=l+1152|0;i=p+24|0;h=p+8|0;e=p;f=p+120|0;j=p+44|0;k=p+40|0;m=p+36|0;n=p+32|0;o=p+28|0;d=c[42311]|0;if(!d){d=Rl(19832,c[4345]|0)|0;c[42311]=d}d=bb[c[d>>2]&31](d,b,512)|0;do if(!d){g=bM(b,123632)|0;if(!g){c[e>>2]=b;$l(0,89317,e)|0;d=0;break}else{d=0;e=0}while(1){if(!(hL(f,1024,g)|0)){f=11;break}c[h>>2]=k;c[h+4>>2]=m;c[h+8>>2]=n;c[h+12>>2]=o;q=(dM(f,89345,h)|0)==4;e=q?1:e;if((a[f>>0]|0)!=37){q=(iL(f,89374)|0)==0;d=q?d:1}if((e|0)!=0&(d|0)!=0){f=12;break}}if((f|0)==11)if(!e){c[i>>2]=b;$l(0,89379,i)|0;d=0}else f=12;if((f|0)==12){q=xw(64)|0;k=c[k>>2]|0;c[q+32>>2]=k;m=c[m>>2]|0;c[q+40>>2]=(c[n>>2]|0)-k;c[q+36>>2]=(c[o>>2]|0)-m;c[q+8>>2]=b;o=c[42312]|0;c[42312]=o+1;c[q+12>>2]=o;$L(AN(g)|0,j)|0;o=c[j+36>>2]|0;n=xw(o+1|0)|0;c[q+52>>2]=n;pM(g,0,0)|0;xN(n,o,1,g)|0;a[n+o>>0]=0;o=c[42311]|0;bb[c[o>>2]&31](o,q,1)|0;a[q+16>>0]=d;d=q}ML(g)|0}while(0);l=p;return d|0}function dy(a,b,d){a=a|0;b=b|0;d=d|0;$I(c[b+52>>2]|0);return}function ey(a){a=a|0;$I(c[(c[a+16>>2]|0)+12>>2]|0);return}function fy(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+16|0;m=n+8|0;k=n;j=(d|0)!=0;a:do if(j){h=0;f=0;b:while(1)while(1){if(h)break a;g=c[d+(f<<2)>>2]|0;if(!g){i=6;break a}f=f+1|0;if(!(a[g>>0]|0)){h=1;continue b}}}else i=6;while(0);c:do if((i|0)==6)while(1){f=c[e>>2]|0;if(!f)break c;nr(b,f)|0;nr(b,134901)|0;e=e+4|0;i=6}while(0);d:do if(j){h=0;while(1){f=c[d+(h<<2)>>2]|0;if(!f)break d;do if(a[f>>0]|0){e=SA(f)|0;if(!e){c[k>>2]=f;$l(0,89418,k)|0;break}g=bM(e,123632)|0;if(!g){c[m>>2]=e;$l(0,89446,m)|0;break}while(1){f=RA(g)|0;if(!f)break;nr(b,f)|0}nr(b,134901)|0;ML(g)|0}while(0);h=h+1|0}}while(0);l=n;return}function gy(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;d=c[d+52>>2]|0;a:while(1){e=a[d>>0]|0;b:do switch(e<<24>>24){case 0:break a;case 37:{if((a[d+1>>0]|0)==37){e=d+2|0;if((((qK(e,89474,3)|0)!=0?(qK(e,89478,5)|0)!=0:0)?(qK(e,89484,3)|0)!=0:0)?(qK(e,89488,7)|0)!=0:0){e=37;break b}else g=37;c:while(1){switch(g<<24>>24){case 13:{f=10;break c}case 10:case 0:{f=12;break c}default:{}}g=d+1|0;d=g;g=a[g>>0]|0}if((f|0)==10){e=d+1|0;if((a[e>>0]|0)==10){d=d+2|0;continue a}}else if((f|0)==12)e=d+1|0;d=g<<24>>24==0?d:e;continue a}else e=37;break}default:{}}while(0);d:while(1){switch(e<<24>>24){case 10:case 13:case 0:break d;default:{}}or(b,e<<24>>24)|0;g=d+1|0;d=g;e=a[g>>0]|0}f=d+1|0;if(e<<24>>24==13?(a[f>>0]|0)==10:0)d=d+2|0;else d=e<<24>>24==0?d:f;or(b,10)|0}return}function hy(b){b=b|0;var d=0,e=0,f=0,g=0;f=l;l=l+16|0;e=f;d=c[42311]|0;a:do if(d|0){d=bb[c[d>>2]&31](d,0,128)|0;while(1){if(!d)break a;if(!(a[d+16>>0]|0)){c[e>>2]=c[d+12>>2];tr(b,89496,e);nr(b,89514)|0;gy(b,d);nr(b,89532)|0;nr(b,89547)|0}g=c[42311]|0;d=bb[c[g>>2]&31](g,d,8)|0}}while(0);l=f;return}function iy(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;g=l;l=l+16|0;e=g;a:do switch(d|0){case 0:{f=b;break}case 1:{f=AB(b)|0;break}default:{switch(jy(b)|0){case 2:break;case 1:{f=AB(b)|0;break a}default:{f=b;break a}}if(!(c[42313]|0)){$l(0,89559,e)|0;c[42313]=1;f=b}else f=b}}while(0);if(!(c[42314]|0))dm(169256,0,0);d=c[42315]|0;if(d>>>0>=(c[42316]|0)>>>0){em(169256,1)|0;d=c[42315]|0}c[42315]=d+1;a[d>>0]=40;e=f;b:while(1){switch(a[e>>0]|0){case 0:break b;case 92:case 41:case 40:{d=c[42315]|0;if(d>>>0>=(c[42316]|0)>>>0){em(169256,1)|0;d=c[42315]|0}c[42315]=d+1;a[d>>0]=92;break}default:{}}d=c[42315]|0;if(d>>>0>=(c[42316]|0)>>>0){em(169256,1)|0;d=c[42315]|0}h=a[e>>0]|0;c[42315]=d+1;a[d>>0]=h;e=e+1|0}d=c[42315]|0;if(d>>>0>=(c[42316]|0)>>>0){em(169256,1)|0;d=c[42315]|0}c[42315]=d+1;a[d>>0]=41;if((f|0)!=(b|0))$I(f);d=c[42315]|0;if(d>>>0>=(c[42316]|0)>>>0){em(169256,1)|0;d=c[42315]|0}a[d>>0]=0;h=c[42314]|0;c[42315]=h;l=g;return h|0}function jy(b){b=b|0;var c=0,d=0;c=0;a:while(1){while(1){d=a[b>>0]|0;if(!(d<<24>>24))break a;if((d&255)<127)b=b+1|0;else break}if((d&-4)<<24>>24==-64){c=1;b=b+2|0}else{c=2;break}}return c|0}function ky(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;n=l;l=l+96|0;i=n+80|0;j=n+72|0;m=n+64|0;g=n+32|0;k=n;h[g>>3]=+h[a>>3];h[g+8>>3]=+h[a+8>>3];h[g+16>>3]=+h[b>>3];h[g+24>>3]=+h[b+8>>3];do if((EI(d,g,j)|0)>=0){if(!f){b=d+4|0;a=c[b>>2]|0;f=c[42319]|0;if((a|0)>(c[42318]|0)){if(!f)a=xw(a<<5)|0;else a=zw(f,a<<5)|0;c[42319]=a;g=c[b>>2]|0;c[42318]=g;f=a}else g=a;b=c[d>>2]|0;a=0;while(1){if((a|0)>=(g|0))break;o=f+(a<<5)|0;d=b+(a<<4)|0;c[o>>2]=c[d>>2];c[o+4>>2]=c[d+4>>2];c[o+8>>2]=c[d+8>>2];c[o+12>>2]=c[d+12>>2];o=f+(a<<5)+16|0;d=a+1|0;p=b+(((d|0)%(g|0)|0)<<4)|0;c[o>>2]=c[p>>2];c[o+4>>2]=c[p+4>>2];c[o+8>>2]=c[p+8>>2];c[o+12>>2]=c[p+12>>2];a=d}c[k>>2]=0;c[k+4>>2]=0;c[k+8>>2]=0;c[k+12>>2]=0;c[k+16>>2]=0;c[k+20>>2]=0;c[k+24>>2]=0;c[k+28>>2]=0;c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];if((iI(f,g,i,k,m)|0)<0){a=0;break}}else{c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];ZI(i,m)}a=m+4|0;if(!(ly(c[a>>2]|0)|0)){g=c[a>>2]|0;a=c[42320]|0;f=c[m>>2]|0;b=0;while(1){if((b|0)>=(g|0))break;p=a+(b<<4)|0;o=f+(b<<4)|0;c[p>>2]=c[o>>2];c[p+4>>2]=c[o+4>>2];c[p+8>>2]=c[o+8>>2];c[p+12>>2]=c[o+12>>2];b=b+1|0}c[e>>2]=g}else a=0}else a=0;while(0);l=n;return a|0}function ly(a){a=a|0;var b=0,d=0,e=0;e=l;l=l+16|0;d=e;b=c[42321]|0;do if((b|0)<(a|0)){a=a+300-((a|0)%300|0)+b|0;b=zw(c[42320]|0,a<<4)|0;c[42320]=b;if(!b){$l(1,89649,d)|0;a=1;break}else{c[42321]=a;a=0;break}}else a=0;while(0);l=e;return a|0}function my(){var a=0,b=0,d=0;b=l;l=l+16|0;a=b;d=c[42322]|0;c[42322]=d+1;do if((d|0)<=0){d=xw(4800)|0;c[42320]=d;if(!d){$l(1,89672,a)|0;a=1;break}c[42321]=300;c[42323]=0;c[42324]=0;if(0){yA();a=0}else a=0}else a=0;while(0);l=b;return a|0}function ny(){var a=0,b=0,d=0,e=0.0,f=0,g=0;b=l;l=l+16|0;a=b;d=c[42322]|0;c[42322]=d+-1;if((d|0)<=1?($I(c[42320]|0),0):0){d=c[13918]|0;g=c[42323]|0;f=c[42324]|0;e=+zA();c[a>>2]=g;c[a+4>>2]=f;h[a+8>>3]=e;AL(d,89710,a)|0}l=b;return}function oy(a,b){a=a|0;b=b|0;return py(a,b,0)|0}function py(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0;L=l;l=l+176|0;G=L+168|0;K=L+128|0;x=L+120|0;v=L+112|0;i=L+104|0;s=L+88|0;n=L+72|0;g=L+64|0;t=L+160|0;I=L+152|0;y=L+144|0;u=L+32|0;w=L;J=L+136|0;c[42323]=(c[42323]|0)+1;H=c[b+80>>2]|0;c[42324]=(c[42324]|0)+H;f=b+88|0;while(1){C=c[f>>2]|0;if(!C){D=4;break}f=c[C+16>>2]|0;if(!(a[f+112>>0]|0)){D=5;break}else f=f+116|0}do if((D|0)==4){$l(1,89753,g)|0;f=0}else if((D|0)==5){B=c[b+84>>2]|0;if(!(qy(H,B,b)|0)){g=H<<3;if((g|0)>(c[42325]|0)){f=c[42326]|0;if(!f)f=xw(H<<7)|0;else f=zw(f,H<<7)|0;c[42326]=f;c[42325]=g}a:do if((H|0)>1?+h[B+8>>3]>+h[B+40>>3]:0){f=0;while(1){if((f|0)==(H|0)){p=1;break a}z=B+(f<<5)+24|0;m=+h[z>>3];A=B+(f<<5)+8|0;h[z>>3]=-+h[A>>3];h[A>>3]=-m;f=f+1|0}}else p=0;while(0);r=c[C>>2]&3;z=C+48|0;f=c[((r|0)==3?C:z)+40>>2]|0;A=C+-48|0;if((f|0)==(c[((r|0)==2?C:A)+40>>2]|0)){c[i>>2]=En(f)|0;$l(1,89860,i)|0;f=0;break}o=H+-1|0;q=c[42326]|0;r=q;f=0;j=0;b:while(1){if((j|0)>=(H|0)){j=o;n=f;break}if((j|0)>0)g=+h[B+(j<<5)+8>>3]>+h[B+(j+-1<<5)+8>>3]?-1:1;else g=0;if((j|0)<(o|0))i=+h[B+(j+1<<5)+8>>3]>+h[B+(j<<5)+8>>3]?1:-1;else i=0;c:do if((g|0)!=(i|0))if((g|0)==1|(i|0)==-1){g=B+(j<<5)|0;h[q+(f<<4)>>3]=+h[g>>3];i=f+1|0;h[q+(f<<4)+8>>3]=+h[B+(j<<5)+24>>3];h[q+(i<<4)>>3]=+h[g>>3];g=B+(j<<5)+8|0;D=29;break}else{g=B+(j<<5)+16|0;h[q+(f<<4)>>3]=+h[g>>3];i=f+1|0;h[q+(f<<4)+8>>3]=+h[B+(j<<5)+8>>3];h[q+(i<<4)>>3]=+h[g>>3];g=B+(j<<5)+24|0;D=29;break}else{switch(g|0){case -1:break c;case 0:break;default:{D=28;break b}}g=B+(j<<5)|0;h[q+(f<<4)>>3]=+h[g>>3];i=f+1|0;h[q+(f<<4)+8>>3]=+h[B+(j<<5)+24>>3];h[q+(i<<4)>>3]=+h[g>>3];g=B+(j<<5)+8|0;D=29}while(0);if((D|0)==29){D=0;h[q+(i<<4)+8>>3]=+h[g>>3];f=f+2|0}j=j+1|0}if((D|0)==28){c[n>>2]=g;c[n+4>>2]=g;c[n+8>>2]=480;$l(1,89795,n)|0;f=0;break}d:while(1){if((j|0)<=-1)break;if((j|0)<(o|0))f=+h[B+(j<<5)+8>>3]>+h[B+(j+1<<5)+8>>3]?-1:1;else f=0;if((j|0)>0)g=+h[B+(j+-1<<5)+8>>3]>+h[B+(j<<5)+8>>3]?1:-1;else g=0;e:do if((f|0)!=(g|0))if((f|0)==1|(g|0)==-1){f=B+(j<<5)|0;h[q+(n<<4)>>3]=+h[f>>3];g=n+1|0;h[q+(n<<4)+8>>3]=+h[B+(j<<5)+24>>3];h[q+(g<<4)>>3]=+h[f>>3];f=B+(j<<5)+8|0;i=2;break}else{f=B+(j<<5)+16|0;h[q+(n<<4)>>3]=+h[f>>3];g=n+1|0;h[q+(n<<4)+8>>3]=+h[B+(j<<5)+8>>3];h[q+(g<<4)>>3]=+h[f>>3];f=B+(j<<5)+24|0;i=2;break}else switch(f|0){case 0:{f=B+(j<<5)+16|0;h[q+(n<<4)>>3]=+h[f>>3];g=n+1|0;h[q+(n<<4)+8>>3]=+h[B+(j<<5)+8>>3];h[q+(g<<4)>>3]=+h[f>>3];f=B+(j<<5)+24|0;i=2;break e}case -1:{N=B+(j<<5)+16|0;h[q+(n<<4)>>3]=+h[N>>3];f=B+(j<<5)+8|0;i=n+1|0;h[q+(n<<4)+8>>3]=+h[f>>3];h[q+(i<<4)>>3]=+h[N>>3];N=B+(j<<5)+24|0;M=n+2|0;h[q+(i<<4)+8>>3]=+h[N>>3];i=B+(j<<5)|0;h[q+(M<<4)>>3]=+h[i>>3];g=n+3|0;h[q+(M<<4)+8>>3]=+h[N>>3];h[q+(g<<4)>>3]=+h[i>>3];i=4;break e}default:{D=42;break d}}while(0);h[q+(g<<4)+8>>3]=+h[f>>3];j=j+-1|0;n=n+i|0}if((D|0)==42){c[s>>2]=f;c[s+4>>2]=f;c[s+8>>2]=513;$l(1,89795,s)|0;f=0;break}f:do if(!p)f=0;else{f=0;while(1){if((f|0)>=(H|0)){f=0;break}M=B+(f<<5)+24|0;m=+h[M>>3];N=B+(f<<5)+8|0;h[M>>3]=-+h[N>>3];h[N>>3]=-m;f=f+1|0}while(1){if((f|0)>=(n|0)){f=0;break f}N=q+(f<<4)+8|0;h[N>>3]=-+h[N>>3];f=f+1|0}}while(0);while(1){if((f|0)>=(H|0))break;h[B+(f<<5)>>3]=2147483647.0;h[B+(f<<5)+16>>3]=-2147483648.0;f=f+1|0}c[t>>2]=r;i=t+4|0;c[i>>2]=n;h[u>>3]=+h[b>>3];h[u+8>>3]=+h[b+8>>3];h[u+16>>3]=+h[b+40>>3];h[u+24>>3]=+h[b+48>>3];if((EI(t,u,I)|0)<0){$l(1,89899,v)|0;f=0;break}if(!e){g=c[i>>2]|0;f=c[42319]|0;if((g|0)>(c[42318]|0)){if(!f)f=xw(g<<5)|0;else f=zw(f,g<<5)|0;c[42319]=f;g=c[i>>2]|0;c[42318]=g}j=c[42326]|0;i=0;while(1){if((i|0)>=(g|0))break;M=f+(i<<5)|0;N=j+(i<<4)|0;c[M>>2]=c[N>>2];c[M+4>>2]=c[N+4>>2];c[M+8>>2]=c[N+8>>2];c[M+12>>2]=c[N+12>>2];M=f+(i<<5)+16|0;N=i+1|0;v=j+(((N|0)%(g|0)|0)<<4)|0;c[M>>2]=c[v>>2];c[M+4>>2]=c[v+4>>2];c[M+8>>2]=c[v+8>>2];c[M+12>>2]=c[v+12>>2];i=N}if(!(a[b+29>>0]|0)){k=0.0;m=0.0}else{m=+h[b+16>>3];k=+E(+m);m=+F(+m)}h[w+8>>3]=m;h[w>>3]=k;if(!(a[b+69>>0]|0)){k=0.0;m=0.0}else{m=+h[b+56>>3];k=-+E(+m);m=-+F(+m)}h[w+24>>3]=m;h[w+16>>3]=k;c[G>>2]=c[I>>2];c[G+4>>2]=c[I+4>>2];if((iI(f,g,G,w,y)|0)<0){$l(1,89938,x)|0;f=0;break}}else{c[G>>2]=c[I>>2];c[G+4>>2]=c[I+4>>2];ZI(G,y)}n=y+4|0;if(!(ly(c[n>>2]|0)|0)){f=0;while(1){if((f|0)>=(H|0))break;h[B+(f<<5)>>3]=2147483647.0;h[B+(f<<5)+16>>3]=-2147483648.0;f=f+1|0}i=c[n>>2]|0;j=c[42320]|0;g=c[y>>2]|0;f=0;while(1){if((f|0)>=(i|0)){i=1;f=10;g=0;break}N=j+(f<<4)|0;M=g+(f<<4)|0;c[N>>2]=c[M>>2];c[N+4>>2]=c[M+4>>2];c[N+8>>2]=c[M+8>>2];c[N+12>>2]=c[M+12>>2];f=f+1|0}while(1){if(!((g|0)<15&i<<24>>24!=0))break;ry(B,H,c[42320]|0,c[n>>2]|0,f);j=0;while(1){if((j|0)>=(H|0))break;if(+h[B+(j<<5)>>3]==2147483647.0){D=82;break}if(+h[B+(j<<5)+16>>3]==-2147483648.0){D=82;break}j=j+1|0}if((D|0)==82){D=0;N=f<<1;f=N;g=(N|0)>(2147483647/(H|0)|0|0)?15:g}i=(j|0)==(H|0)?0:i;g=g+1|0}if(i<<24>>24){M=En(c[((c[C>>2]&3|0)==3?C:z)+40>>2]|0)|0;N=En(c[((c[C>>2]&3|0)==2?C:A)+40>>2]|0)|0;c[K>>2]=M;c[K+4>>2]=N;$l(0,89976,K)|0;c[G>>2]=c[I>>2];c[G+4>>2]=c[I+4>>2];ZI(G,J);ry(B,H,c[J>>2]|0,c[J+4>>2]|0,10);$I(c[J>>2]|0)}c[d>>2]=c[n>>2];f=c[42320]|0}else f=0}else f=0}while(0);l=L;return f|0}function qy(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0.0,g=0.0,i=0,j=0,k=0,m=0.0,n=0.0,o=0,p=0.0,q=0.0,r=0.0,s=0.0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0.0,L=0,M=0,N=0,O=0.0,P=0,Q=0,R=0;R=l;l=l+32|0;I=R+16|0;H=R+8|0;k=R;e=0;j=0;while(1){if((j|0)>=(a|0))break;i=b+(j<<5)|0;s=+h[b+(j<<5)+8>>3]-+h[b+(j<<5)+24>>3];if(!((s>=0.0?s:-s)<.01)?(s=+h[i>>3]-+h[b+(j<<5)+16>>3],!((s>=0.0?s:-s)<.01)):0){if((e|0)!=(j|0)){P=b+(e<<5)|0;c[P>>2]=c[i>>2];c[P+4>>2]=c[i+4>>2];c[P+8>>2]=c[i+8>>2];c[P+12>>2]=c[i+12>>2];c[P+16>>2]=c[i+16>>2];c[P+20>>2]=c[i+20>>2];c[P+24>>2]=c[i+24>>2];c[P+28>>2]=c[i+28>>2]}e=e+1|0}j=j+1|0}J=b+16|0;do if(!(+h[b>>3]>+h[J>>3])?(L=b+8|0,N=b+24|0,!(+h[L>>3]>+h[N>>3])):0){P=e+-1|0;M=c[13918]|0;w=0;while(1){if((w|0)>=(P|0))break;D=w+1|0;E=b+(D<<5)|0;f=+h[E>>3];F=b+(D<<5)+16|0;g=+h[F>>3];if(f>g){Q=16;break}A=b+(D<<5)+8|0;m=+h[A>>3];B=b+(D<<5)+24|0;n=+h[B>>3];if(m>n){Q=16;break}G=b+(w<<5)+16|0;v=+h[G>>3]>3]>g;a=u&1;z=b+(w<<5)+24|0;t=+h[z>>3]>3]>n;i=k&1;x=a+e+j+i|0;o=(x|0)!=0;if(!(0==0|o^1)){c[I>>2]=w;c[I+4>>2]=D;AL(M,90176,I)|0;sy(d)}a:do if(o){if(!v)if(!u)if(!t){if(k){k=0;o=e;e=B;i=y;Q=24}}else{k=i;j=0;o=e;e=A;i=z;Q=24}else{k=i;a=0;o=e;e=F;i=C;Q=24}else{k=i;o=0;e=E;i=G;Q=24}if((Q|0)==24){Q=0;w=~~+h[i>>3];h[i>>3]=+h[e>>3];h[e>>3]=+(w|0);i=k;e=o}o=x+-1|0;k=0;while(1){if((k|0)>=(o|0))break a;do if((e|0)!=1){if((a|0)==1){s=+(~~((+h[F>>3]+ +h[C>>3])*.5+.5)|0);h[F>>3]=s;h[C>>3]=s;a=0;break}if((j|0)==1){s=+(~~((+h[A>>3]+ +h[z>>3])*.5+.5)|0);h[A>>3]=s;h[z>>3]=s;j=0;break}if((i|0)==1){s=+(~~((+h[B>>3]+ +h[y>>3])*.5+.5)|0);h[B>>3]=s;h[y>>3]=s;i=0}}else{s=+(~~((+h[E>>3]+ +h[G>>3])*.5+.5)|0);h[E>>3]=s;h[G>>3]=s;e=0}while(0);k=k+1|0}}while(0);p=+h[C>>3];q=+h[G>>3];r=+h[E>>3];s=+h[F>>3];i=ty(~~p,~~q,~~r,~~s)|0;n=+h[y>>3];m=+h[z>>3];g=+h[A>>3];f=+h[B>>3];e=ty(~~n,~~m,~~g,~~f)|0;if(!((i|0)!=0&(e|0)!=0)){w=D;continue}if((i|0)<(e|0)){B=q-p>s-r;w=q>3]=B?(w?r:s):w?q:p;w=D;continue}else{B=m-n>f-g;w=m>3]=B?(w?g:f):w?m:n;w=D;continue}}if((Q|0)==16){c[H>>2]=D;$l(1,90130,H)|0;sy(d);e=1;break}f=+h[d>>3];g=+h[b>>3];if(!(((!(f+h[J>>3]):0)?(K=+h[d+8>>3],!(K<+h[L>>3])):0)?!(K>+h[N>>3]):0)){if(0){YL(90219,42,1,M)|0;sy(d);g=+h[b>>3];f=+h[d>>3]}if(f>3]=g;else g=f;f=+h[J>>3];if(g>f)h[d>>3]=f;e=d+8|0;g=+h[e>>3];f=+h[L>>3];if(g>3]=f;g=f}f=+h[N>>3];if(g>f)h[e>>3]=f}i=d+40|0;f=+h[i>>3];e=b+(P<<5)|0;g=+h[e>>3];if(((!(f+h[b+(P<<5)+16>>3]):0)?(O=+h[d+48>>3],!(O<+h[b+(P<<5)+8>>3])):0)?!(O>+h[b+(P<<5)+24>>3]):0){e=0;break}if(0){YL(90262,39,1,M)|0;sy(d);g=+h[e>>3];f=+h[i>>3]}if(f>3]=g;f=g}g=+h[b+(P<<5)+16>>3];if(f>g)h[i>>3]=g;e=d+48|0;f=+h[e>>3];g=+h[b+(P<<5)+8>>3];if(f>3]=g;else g=f;f=+h[b+(P<<5)+24>>3];if(g>f){h[e>>3]=f;e=0}else e=0}else Q=12;while(0);if((Q|0)==12){$l(1,90085,k)|0;sy(d);e=1}l=R;return e|0}function ry(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0,p=0,q=0,r=0,s=0,t=0.0,u=0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0;s=O(e,b)|0;t=1.0/+(s|0);e=0;a:while(1){u=e+3|0;if((u|0)>=(d|0))break;o=c+(e<<4)|0;p=c+(e<<4)+8|0;r=e+1|0;q=c+(r<<4)|0;r=c+(r<<4)+8|0;j=e+2|0;i=c+(j<<4)|0;j=c+(j<<4)+8|0;k=c+(u<<4)|0;l=c+(u<<4)+8|0;g=0;while(1){if((g|0)>(s|0)){e=u;continue a}v=t*+(g|0);m=+h[o>>3];n=+h[p>>3];y=+h[q>>3];w=+h[r>>3];z=+h[i>>3];x=+h[j>>3];m=(y-m)*v+m;n=(w-n)*v+n;y=(z-y)*v+y;w=(x-w)*v+w;m=(y-m)*v+m;n=(w-n)*v+n;m=((z-y+(+h[k>>3]-z)*v)*v+y-m)*v+m;n=((x-w+(+h[l>>3]-x)*v)*v+w-n)*v+n;f=0;while(1){if((f|0)>=(b|0))break;if(n<=+h[a+(f<<5)+24>>3]+.0001?n>=+h[a+(f<<5)+8>>3]+-.0001:0){e=a+(f<<5)|0;if(+h[e>>3]>m)h[e>>3]=m;e=a+(f<<5)+16|0;if(+h[e>>3]>3]=m}f=f+1|0}g=g+1|0}}return}function sy(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0;m=l;l=l+112|0;j=m+80|0;k=m+48|0;i=m+8|0;g=m;e=c[13918]|0;f=b+80|0;c[g>>2]=c[f>>2];AL(e,90302,g)|0;g=b+84|0;d=0;while(1){if((d|0)>=(c[f>>2]|0))break;r=c[g>>2]|0;q=+h[r+(d<<5)>>3];p=+h[r+(d<<5)+8>>3];o=+h[r+(d<<5)+16>>3];n=+h[r+(d<<5)+24>>3];c[i>>2]=d;h[i+8>>3]=q;h[i+16>>3]=p;h[i+24>>3]=o;h[i+32>>3]=n;AL(e,90313,i)|0;d=d+1|0}q=+h[b+8>>3];p=+h[b+16>>3];r=a[b+29>>0]|0?90344:90356;h[k>>3]=+h[b>>3];h[k+8>>3]=q;h[k+16>>3]=p;c[k+24>>2]=r;AL(e,90372,k)|0;p=+h[b+48>>3];q=+h[b+56>>3];r=a[b+69>>0]|0?90344:90356;h[j>>3]=+h[b+40>>3];h[j+8>>3]=p;h[j+16>>3]=q;c[j+24>>2]=r;AL(e,90423,j)|0;l=m;return}function ty(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;do if((b|0)>(c|0)&(d|0)>(a|0)){if(!((c|0)>(a|0)|(d|0)<(a|0))){a=d-a|0;break}if((b|0)<(c|0)|(b|0)>(d|0)){b=b-a|0;a=d-c|0;a=(b|0)<(a|0)?b:a;break}else{a=b-c|0;break}}else a=0;while(0);return a|0}function uy(a,b){a=a|0;b=b|0;return py(a,b,1)|0}function vy(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0.0,M=0.0,N=0.0,P=0,Q=0;K=l;l=l+304|0;A=K+272|0;z=K+208|0;G=K+96|0;H=K+32|0;I=K+16|0;J=K;r=K+192|0;y=K+176|0;i=K+160|0;B=K+296|0;D=K+288|0;j=c[d>>2]|0;w=c[j>>2]&3;k=j+-48|0;E=c[((w|0)==2?j:k)+40>>2]|0;t=G+16|0;w=(c[(c[((w|0)==3?j:j+48|0)+40>>2]|0)+16>>2]|0)+16|0;x=j+16|0;F=(c[x>>2]|0)+16|0;c[z>>2]=c[w>>2];c[z+4>>2]=c[w+4>>2];c[z+8>>2]=c[w+8>>2];c[z+12>>2]=c[w+12>>2];c[A>>2]=c[F>>2];c[A+4>>2]=c[F+4>>2];c[A+8>>2]=c[F+8>>2];c[A+12>>2]=c[F+12>>2];wy(r,z,A);c[G>>2]=c[r>>2];c[G+4>>2]=c[r+4>>2];c[G+8>>2]=c[r+8>>2];c[G+12>>2]=c[r+12>>2];c[t>>2]=c[r>>2];c[t+4>>2]=c[r+4>>2];c[t+8>>2]=c[r+8>>2];c[t+12>>2]=c[r+12>>2];c[I>>2]=c[r>>2];c[I+4>>2]=c[r+4>>2];c[I+8>>2]=c[r+8>>2];c[I+12>>2]=c[r+12>>2];r=G+32|0;F=G+48|0;w=(c[E+16>>2]|0)+16|0;x=(c[x>>2]|0)+56|0;c[z>>2]=c[w>>2];c[z+4>>2]=c[w+4>>2];c[z+8>>2]=c[w+8>>2];c[z+12>>2]=c[w+12>>2];c[A>>2]=c[x>>2];c[A+4>>2]=c[x+4>>2];c[A+8>>2]=c[x+8>>2];c[A+12>>2]=c[x+12>>2];wy(y,z,A);c[F>>2]=c[y>>2];c[F+4>>2]=c[y+4>>2];c[F+8>>2]=c[y+8>>2];c[F+12>>2]=c[y+12>>2];c[r>>2]=c[y>>2];c[r+4>>2]=c[y+4>>2];c[r+8>>2]=c[y+8>>2];c[r+12>>2]=c[y+12>>2];c[J>>2]=c[y>>2];c[J+4>>2]=c[y+4>>2];c[J+8>>2]=c[y+8>>2];c[J+12>>2]=c[y+12>>2];a:do if((e|0)!=1&(a[174080]|0)==0){m=+h[G>>3];n=+h[F>>3];L=m-n;o=+h[G+8>>3];p=+h[G+56>>3];s=o-p;q=s*s;if(q+L*L<1.0e-06){c[t>>2]=c[G>>2];c[t+4>>2]=c[G+4>>2];c[t+8>>2]=c[G+8>>2];c[t+12>>2]=c[G+12>>2];c[r>>2]=c[F>>2];c[r+4>>2]=c[F+4>>2];c[r+8>>2]=c[F+8>>2];c[r+12>>2]=c[F+12>>2];y=G+24|0;x=G+40|0;n=0.0;m=0.0}else{M=n-m;L=+C(+(q+M*M));w=c[(c[(c[b+60>>2]|0)+16>>2]|0)+248>>2]|0;N=+((O(w,e+-1|0)|0)/2|0|0);q=s*N/L;h[t>>3]=q+m;m=M*N/L;y=G+24|0;h[y>>3]=m+o;h[r>>3]=q+n;x=G+40|0;h[x>>3]=p+m;m=+(0-w|0);n=M*m/L;m=s*m/L}f=(f|0)==6;u=D+4|0;v=B+4|0;j=0;while(1){if((j|0)>=(e|0))break a;w=c[d+(j<<2)>>2]|0;k=w+-48|0;b:do if((c[((c[w>>2]&3|0)==2?w:k)+40>>2]|0)==(E|0)){c[I>>2]=c[G>>2];c[I+4>>2]=c[G+4>>2];c[I+8>>2]=c[G+8>>2];c[I+12>>2]=c[G+12>>2];c[J>>2]=c[F>>2];c[J+4>>2]=c[F+4>>2];c[J+8>>2]=c[F+8>>2];c[J+12>>2]=c[F+12>>2];i=0;while(1){if((i|0)==4)break b;P=H+(i<<4)|0;Q=G+(i<<4)|0;c[P>>2]=c[Q>>2];c[P+4>>2]=c[Q+4>>2];c[P+8>>2]=c[Q+8>>2];c[P+12>>2]=c[Q+12>>2];i=i+1|0}}else{c[I>>2]=c[F>>2];c[I+4>>2]=c[F+4>>2];c[I+8>>2]=c[F+8>>2];c[I+12>>2]=c[F+12>>2];c[J>>2]=c[G>>2];c[J+4>>2]=c[G+4>>2];c[J+8>>2]=c[G+8>>2];c[J+12>>2]=c[G+12>>2];i=0;while(1){if((i|0)==4)break b;Q=H+(3-i<<4)|0;P=G+(i<<4)|0;c[Q>>2]=c[P>>2];c[Q+4>>2]=c[P+4>>2];c[Q+8>>2]=c[P+8>>2];c[Q+12>>2]=c[P+12>>2];i=i+1|0}}while(0);if(f){c[u>>2]=4;c[D>>2]=z;i=0;while(1){if((i|0)==4)break;Q=z+(i<<4)|0;P=H+(i<<4)|0;c[Q>>2]=c[P>>2];c[Q+4>>2]=c[P+4>>2];c[Q+8>>2]=c[P+8>>2];c[Q+12>>2]=c[P+12>>2];i=i+1|0}c[A>>2]=c[D>>2];c[A+4>>2]=c[D+4>>2];ZI(A,B);Kz(w,c[((c[w>>2]&3|0)==2?w:k)+40>>2]|0,c[B>>2]|0,c[v>>2]|0,g)}else Kz(w,c[((c[w>>2]&3|0)==2?w:k)+40>>2]|0,H,4,g);c[z>>2]=c[I>>2];c[z+4>>2]=c[I+4>>2];c[z+8>>2]=c[I+8>>2];c[z+12>>2]=c[I+12>>2];c[A>>2]=c[J>>2];c[A+4>>2]=c[J+4>>2];c[A+8>>2]=c[J+8>>2];c[A+12>>2]=c[J+12>>2];dA(b,w,z,A);h[t>>3]=+h[t>>3]+m;h[y>>3]=+h[y>>3]+n;h[r>>3]=+h[r>>3]+m;h[x>>3]=+h[x>>3]+n;j=j+1|0}}else{if((f|0)==4){xy(i,b);c[A>>2]=c[i>>2];c[A+4>>2]=c[i+4>>2];c[A+8>>2]=c[i+8>>2];c[A+12>>2]=c[i+12>>2];yy(G,A)}Kz(j,c[((c[j>>2]&3|0)==2?j:k)+40>>2]|0,G,4,g);c[z>>2]=c[I>>2];c[z+4>>2]=c[I+4>>2];c[z+8>>2]=c[I+8>>2];c[z+12>>2]=c[I+12>>2];c[A>>2]=c[J>>2];c[A+4>>2]=c[J+4>>2];c[A+8>>2]=c[J+8>>2];c[A+12>>2]=c[J+12>>2];dA(b,j,z,A)}while(0);l=K;return}function wy(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=+h[c+8>>3]+ +h[b+8>>3];h[a>>3]=+h[c>>3]+ +h[b>>3];h[a+8>>3]=d;return}function xy(a,b){a=a|0;b=b|0;b=c[b+16>>2]|0;h[20899]=(+h[b+32>>3]+ +h[b+16>>3])*.5;h[20900]=(+h[b+40>>3]+ +h[b+24>>3])*.5;c[a>>2]=c[41798];c[a+4>>2]=c[41799];c[a+8>>2]=c[41800];c[a+12>>2]=c[41801];return}function yy(a,b){a=a|0;b=b|0;var c=0.0,d=0.0,e=0.0,f=0.0,g=0.0,i=0.0;f=+h[a>>3];d=+h[a+48>>3];i=(d+f)*.5;g=+h[a+8>>3];c=+h[a+56>>3];e=(c+g)*.5;f=d-f;g=c-g;f=+C(+(g*g+f*f))*.2;g=+h[b>>3]-i;c=+h[b+8>>3]-e;d=+C(+(c*c+g*g));if(!(d==0.0)){g=i-g/d*f;i=e-c/d*f;h[a+32>>3]=g;h[a+16>>3]=g;h[a+40>>3]=i;h[a+24>>3]=i}return}function zy(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0.0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,D=0,E=0,F=0.0,G=0,H=0.0,I=0.0,J=0.0;E=l;l=l+208|0;t=E+192|0;s=E+176|0;B=E+32|0;w=E+16|0;x=E;y=E+160|0;z=E+144|0;u=E+128|0;v=E+112|0;g=e&2130706432;A=(e&8|0)==0?((g|0)==0?4:g):8;if((A|0)==436207616)Ay(a,b,d,f);else{D=ww((d<<6)+64|0)|0;p=d+-1|0;q=x+8|0;r=w+8|0;o=12.0;e=0;while(1){if((e|0)>=(d|0))break;n=b+(e<<4)|0;c[w>>2]=c[n>>2];c[w+4>>2]=c[n+4>>2];c[w+8>>2]=c[n+8>>2];c[w+12>>2]=c[n+12>>2];if((e|0)<(p|0)){e=e+1|0;n=b+(e<<4)|0;c[x>>2]=c[n>>2];c[x+4>>2]=c[n+4>>2];c[x+8>>2]=c[n+8>>2];c[x+12>>2]=c[n+12>>2]}else{c[x>>2]=c[b>>2];c[x+4>>2]=c[b+4>>2];c[x+8>>2]=c[b+8>>2];c[x+12>>2]=c[b+12>>2];e=e+1|0}m=+h[x>>3]-+h[w>>3];F=+h[q>>3]-+h[r>>3];m=+C(+(F*F+m*m))*.3333333333333333;o=o=(d|0))break;g=b+(i<<4)|0;c[w>>2]=c[g>>2];c[w+4>>2]=c[g+4>>2];c[w+8>>2]=c[g+8>>2];c[w+12>>2]=c[g+12>>2];if((i|0)<(p|0)){g=b+(i+1<<4)|0;c[x>>2]=c[g>>2];c[x+4>>2]=c[g+4>>2];c[x+8>>2]=c[g+8>>2];c[x+12>>2]=c[g+12>>2]}else{c[x>>2]=c[b>>2];c[x+4>>2]=c[b+4>>2];c[x+8>>2]=c[b+8>>2];c[x+12>>2]=c[b+12>>2]}m=+h[x>>3]-+h[w>>3];F=+h[q>>3]-+h[r>>3];m=o/+C(+(F*F+m*m));m=k?m*.3333333333333333:j?m*.5:m;g=D+(e<<4)|0;if(n){c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];c[t>>2]=c[x>>2];c[t+4>>2]=c[x+4>>2];c[t+8>>2]=c[x+8>>2];c[t+12>>2]=c[x+12>>2];By(y,m*.5,s,t);c[g>>2]=c[y>>2];c[g+4>>2]=c[y+4>>2];c[g+8>>2]=c[y+8>>2];c[g+12>>2]=c[y+12>>2]}else{c[g>>2]=c[w>>2];c[g+4>>2]=c[w+4>>2];c[g+8>>2]=c[w+8>>2];c[g+12>>2]=c[w+12>>2]}g=D+(e+1<<4)|0;c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];c[t>>2]=c[x>>2];c[t+4>>2]=c[x+4>>2];c[t+8>>2]=c[x+8>>2];c[t+12>>2]=c[x+12>>2];By(z,m,s,t);c[g>>2]=c[z>>2];c[g+4>>2]=c[z+4>>2];c[g+8>>2]=c[z+8>>2];c[g+12>>2]=c[z+12>>2];g=e+3|0;G=D+(e+2<<4)|0;c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];c[t>>2]=c[x>>2];c[t+4>>2]=c[x+4>>2];c[t+8>>2]=c[x+8>>2];c[t+12>>2]=c[x+12>>2];By(u,1.0-m,s,t);c[G>>2]=c[u>>2];c[G+4>>2]=c[u+4>>2];c[G+8>>2]=c[u+8>>2];c[G+12>>2]=c[u+12>>2];if(n){G=D+(g<<4)|0;c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];c[t>>2]=c[x>>2];c[t+4>>2]=c[x+4>>2];c[t+8>>2]=c[x+8>>2];c[t+12>>2]=c[x+12>>2];By(v,1.0-m*.5,s,t);c[G>>2]=c[v>>2];c[G+4>>2]=c[v+4>>2];c[G+8>>2]=c[v+8>>2];c[G+12>>2]=c[v+12>>2];e=e+4|0}else e=g;i=i+1|0}k=D+(e<<4)|0;c[k>>2]=c[D>>2];c[k+4>>2]=c[D+4>>2];c[k+8>>2]=c[D+8>>2];c[k+12>>2]=c[D+12>>2];k=D+(e+1<<4)|0;j=D+16|0;c[k>>2]=c[j>>2];c[k+4>>2]=c[j+4>>2];c[k+8>>2]=c[j+8>>2];c[k+12>>2]=c[j+12>>2];e=D+(e+2<<4)|0;k=D+32|0;c[e>>2]=c[k>>2];c[e+4>>2]=c[k+4>>2];c[e+8>>2]=c[k+8>>2];c[e+12>>2]=c[k+12>>2];e=A&2147483647;a:do if((e|0)<201326592){if((e|0)>=83886080){if((e|0)<134217728){if((e|0)<100663296){switch(e|0){case 83886080:break;default:break a}if((d|0)==4){G=ww(192)|0;c[G>>2]=c[b>>2];c[G+4>>2]=c[b+4>>2];c[G+8>>2]=c[b+8>>2];c[G+12>>2]=c[b+12>>2];p=G+16|0;t=b+16|0;c[p>>2]=c[t>>2];c[p+4>>2]=c[t+4>>2];c[p+8>>2]=c[t+8>>2];c[p+12>>2]=c[t+12>>2];p=D+48|0;t=D+64|0;o=+h[t>>3];n=G+32|0;h[n>>3]=o;q=D+56|0;r=D+72|0;H=+h[r>>3];z=G+40|0;h[z>>3]=H;F=+h[p>>3]+o-+h[k>>3];u=G+48|0;h[u>>3]=F;J=+h[q>>3]+H-+h[D+40>>3];x=G+56|0;h[x>>3]=J;I=+h[t>>3]+F-+h[p>>3];p=G+64|0;h[p>>3]=I;m=+h[r>>3]+J-+h[q>>3];q=G+72|0;h[q>>3]=m;r=G+80|0;h[r>>3]=o+I-F;h[G+88>>3]=H+m-J;t=D+96|0;v=D+80|0;J=+h[v>>3];d=G+144|0;h[d>>3]=J;w=D+104|0;s=D+88|0;m=+h[s>>3];h[G+152>>3]=m;H=+h[t>>3]+J-+h[D+112>>3];y=G+128|0;h[y>>3]=H;F=+h[w>>3]+m-+h[D+120>>3];A=G+136|0;h[A>>3]=F;I=+h[v>>3]+H-+h[t>>3];t=G+112|0;h[t>>3]=I;o=+h[s>>3]+F-+h[w>>3];w=G+120|0;h[w>>3]=o;s=G+96|0;h[s>>3]=J+I-H;v=G+104|0;h[v>>3]=m+o-F;k=G+160|0;j=b+32|0;c[k>>2]=c[j>>2];c[k+4>>2]=c[j+4>>2];c[k+8>>2]=c[j+8>>2];c[k+12>>2]=c[j+12>>2];k=G+176|0;b=b+48|0;c[k>>2]=c[b>>2];c[k+4>>2]=c[b+4>>2];c[k+8>>2]=c[b+8>>2];c[k+12>>2]=c[b+12>>2];ID(a,G,12,f);c[B>>2]=c[n>>2];c[B+4>>2]=c[n+4>>2];c[B+8>>2]=c[n+8>>2];c[B+12>>2]=c[n+12>>2];F=+h[n>>3];o=+h[u>>3];F=F+F-o;u=B+16|0;h[u>>3]=F;m=+h[z>>3];H=+h[x>>3];m=m+m-H;x=B+24|0;h[x>>3]=m;z=B+32|0;h[z>>3]=+h[p>>3]+F-o;b=B+40|0;h[b>>3]=+h[q>>3]+m-H;f=B+48|0;c[f>>2]=c[r>>2];c[f+4>>2]=c[r+4>>2];c[f+8>>2]=c[r+8>>2];c[f+12>>2]=c[r+12>>2];LD(a,B,4);c[B>>2]=c[s>>2];c[B+4>>2]=c[s+4>>2];c[B+8>>2]=c[s+8>>2];c[B+12>>2]=c[s+12>>2];H=+h[s>>3];m=+h[t>>3];H=H-(m-H);h[u>>3]=H;o=+h[v>>3];F=+h[w>>3];o=o-(F-o);h[x>>3]=o;h[z>>3]=+h[y>>3]+H-m;h[b>>3]=+h[A>>3]+o-F;c[f>>2]=c[d>>2];c[f+4>>2]=c[d+4>>2];c[f+8>>2]=c[d+8>>2];c[f+12>>2]=c[d+12>>2];LD(a,B,4);$I(G);break}else ma(90472,90483,737,90492)}if((e|0)<117440512){switch(e|0){case 100663296:break;default:break a}y=d+5|0;G=ww(y<<4)|0;z=b+16|0;H=+h[z>>3];H=(+h[b>>3]-H)*.625+H;h[G>>3]=H;A=b+40|0;J=+h[A>>3];d=b+24|0;v=D+48|0;w=D+56|0;x=D+72|0;J=(+h[d>>3]-J)*.5+J+(+h[w>>3]-+h[x>>3])*1.5;h[G+8>>3]=J;I=+h[z>>3];I=(+h[b>>3]-I)*.25+I;h[G+16>>3]=I;h[G+24>>3]=J;h[G+32>>3]=I;F=+h[A>>3];h[G+40>>3]=(+h[d>>3]-F)*.5+F;I=(+h[k>>3]-+h[v>>3])*.5+I;h[G+48>>3]=I;F=+h[A>>3];h[G+56>>3]=(+h[d>>3]-F)*.5+F;h[G+64>>3]=I;I=+h[A>>3];I=(+h[d>>3]-I)*.5+I+(+h[w>>3]-+h[x>>3]);h[G+72>>3]=I;h[G+80>>3]=H;h[G+88>>3]=I;h[G+96>>3]=H;I=I-(+h[w>>3]-+h[x>>3])*.25;h[G+104>>3]=I;h[G+112>>3]=+h[k>>3]+H-+h[v>>3];h[G+120>>3]=(+h[w>>3]-+h[x>>3])*.5+I;h[G+128>>3]=+h[G>>3];h[G+136>>3]=(+h[w>>3]-+h[x>>3])*.25+J;ID(a,G,y,f);h[B>>3]=+h[z>>3];J=+h[A>>3];h[B+8>>3]=(+h[d>>3]-J)*.5+J;h[B+16>>3]=+h[b>>3];h[B+24>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}else{switch(e|0){case 117440512:break;default:break a}d=d+1|0;G=ww(d<<4)|0;h[G>>3]=+h[j>>3];z=D+56|0;A=D+72|0;h[G+8>>3]=+h[D+24>>3]-(+h[z>>3]-+h[A>>3])*.5;h[G+16>>3]=+h[D+48>>3];J=+h[z>>3];h[G+24>>3]=J-(J-+h[A>>3])*.5;h[G+32>>3]=+h[b+32>>3];B=b+40|0;h[G+40>>3]=(+h[z>>3]-+h[A>>3])*.5+ +h[B>>3];h[G+48>>3]=+h[j>>3];h[G+56>>3]=(+h[z>>3]-+h[A>>3])*.5+ +h[B>>3];J=+h[b+8>>3];h[G+72>>3]=J-(J-+h[b+56>>3])*.5;h[G+64>>3]=+h[b>>3];ID(a,G,d,f);$I(G);break}}if((e|0)<167772160)if((e|0)<150994944){switch(e|0){case 134217728:break;default:break a}y=d+4|0;G=ww(y<<4)|0;z=b+16|0;F=+h[z>>3];x=D+48|0;F=(+h[b>>3]-F)*.5+F+(+h[k>>3]-+h[x>>3])*.25;h[G>>3]=F;A=b+40|0;J=+h[A>>3];d=b+24|0;J=(+h[d>>3]-J)*.5+J;h[G+8>>3]=J;h[G+16>>3]=F;v=D+56|0;w=D+72|0;H=(+h[v>>3]-+h[w>>3])*.5+J;h[G+24>>3]=H;F=(+h[k>>3]-+h[x>>3])*.5+F;h[G+32>>3]=F;h[G+40>>3]=H;h[G+48>>3]=F;F=(+h[v>>3]-+h[w>>3])*.5+H;h[G+56>>3]=F;I=+h[z>>3];I=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[x>>3])*-.75;h[G+64>>3]=I;h[G+72>>3]=F;h[G+80>>3]=I;h[G+88>>3]=H;I=+h[z>>3];I=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[x>>3])*-.25;h[G+96>>3]=I;h[G+104>>3]=H;h[G+112>>3]=I;h[G+120>>3]=J;ID(a,G,y,f);h[B>>3]=+h[z>>3];J=+h[A>>3];h[B+8>>3]=(+h[d>>3]-J)*.5+J;h[B+16>>3]=+h[b>>3];h[B+24>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}else{switch(e|0){case 150994944:break;default:break a}y=d+2|0;G=ww(y<<4)|0;z=b+16|0;H=+h[z>>3];x=D+48|0;H=(+h[b>>3]-H)*.5+H+(+h[k>>3]-+h[x>>3])*.75;h[G>>3]=H;A=b+40|0;J=+h[A>>3];d=b+24|0;J=(+h[d>>3]-J)*.5+J;h[G+8>>3]=J;h[G+16>>3]=H;v=D+56|0;w=D+72|0;H=(+h[v>>3]-+h[w>>3])*.25+J;h[G+24>>3]=H;I=+h[z>>3];h[G+32>>3]=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[x>>3])*.25;I=(+h[v>>3]-+h[w>>3])*.5+H;h[G+40>>3]=I;F=+h[z>>3];h[G+48>>3]=(+h[b>>3]-F)*.5+F+(+h[k>>3]-+h[x>>3])*-.25;h[G+56>>3]=I;I=+h[z>>3];I=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[x>>3])*-.75;h[G+64>>3]=I;h[G+72>>3]=H;h[G+80>>3]=I;h[G+88>>3]=J;ID(a,G,y,f);h[B>>3]=+h[z>>3];J=+h[A>>3];h[B+8>>3]=(+h[d>>3]-J)*.5+J;h[B+16>>3]=+h[b>>3];h[B+24>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}else if((e|0)<184549376){switch(e|0){case 167772160:break;default:break a}y=d+1|0;G=ww(y<<4)|0;z=b+16|0;H=+h[z>>3];v=D+48|0;H=+h[k>>3]+H+(+h[b>>3]-H)*.5-+h[v>>3];h[G>>3]=H;A=b+40|0;J=+h[A>>3];d=b+24|0;w=D+56|0;x=D+72|0;J=(+h[d>>3]-J)*.5+J+(+h[w>>3]-+h[x>>3])*.25;h[G+8>>3]=J;H=H-+h[k>>3]+ +h[v>>3];h[G+16>>3]=H;h[G+24>>3]=+h[w>>3]+J-+h[x>>3];h[G+32>>3]=H;H=(+h[w>>3]-+h[x>>3])*.5+J;h[G+40>>3]=H;I=+h[z>>3];I=(+h[b>>3]-I)*.25+I;h[G+48>>3]=I;h[G+56>>3]=H;h[G+64>>3]=I;h[G+72>>3]=J;ID(a,G,y,f);h[B>>3]=+h[z>>3];J=+h[A>>3];h[B+8>>3]=(+h[d>>3]-J)*.5+J;h[B+16>>3]=+h[b>>3];h[B+24>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}else{switch(e|0){case 184549376:break;default:break a}z=d+4|0;G=ww(z<<4)|0;y=b+16|0;H=+h[y>>3];I=+h[b>>3]-H;u=D+48|0;I=I*.125+H+(+h[k>>3]-+h[u>>3]+I)*.5;h[G>>3]=I;w=b+40|0;H=+h[w>>3];x=b+24|0;d=D+56|0;v=D+72|0;H=(+h[x>>3]-H)*.5+H+(+h[d>>3]-+h[v>>3])*.25;h[G+8>>3]=H;J=+h[y>>3];J=(+h[b>>3]-J)*.375+J;h[G+16>>3]=J;h[G+24>>3]=H;h[G+32>>3]=J;H=(+h[d>>3]-+h[v>>3])*.5+H;h[G+40>>3]=H;J=J-(+h[k>>3]-+h[u>>3])*.5;h[G+48>>3]=J;h[G+56>>3]=H;A=G+64|0;h[A>>3]=J;J=+h[w>>3];J=(+h[x>>3]-J)*.5+J+(+h[d>>3]-+h[v>>3])*-.25;h[G+72>>3]=J;H=I-(+h[k>>3]-+h[u>>3])*.5;h[G+80>>3]=H;h[G+88>>3]=J;h[G+96>>3]=H;J=J-(+h[d>>3]-+h[v>>3])*.5;h[G+104>>3]=J;v=G+112|0;h[v>>3]=I;h[G+120>>3]=J;ID(a,G,z,f);h[B>>3]=+h[y>>3];J=+h[w>>3];y=B+8|0;h[y>>3]=(+h[x>>3]-J)*.5+J;z=B+16|0;h[z>>3]=+h[A>>3];A=b+8|0;d=b+56|0;f=B+24|0;h[f>>3]=(+h[A>>3]-+h[d>>3])*.5+J;LD(a,B,2);h[B>>3]=+h[v>>3];J=+h[w>>3];h[y>>3]=(+h[x>>3]-J)*.5+J;h[z>>3]=+h[b>>3];h[f>>3]=(+h[A>>3]-+h[d>>3])*.5+J;LD(a,B,2);$I(G);break}}if((e|0)<33554432){if((e|0)<8){switch(e|0){case 4:break;default:break a}i=xw((d*96|0)+32|0)|0;e=0;g=0;while(1){j=g|1;k=i+(g<<4)|0;if((e|0)>=(d|0))break;b=e<<2;G=D+(b<<4)|0;c[k>>2]=c[G>>2];c[k+4>>2]=c[G+4>>2];c[k+8>>2]=c[G+8>>2];c[k+12>>2]=c[G+12>>2];G=i+(j<<4)|0;B=D+((b|1)<<4)|0;c[G>>2]=c[B>>2];c[G+4>>2]=c[B+4>>2];c[G+8>>2]=c[B+8>>2];c[G+12>>2]=c[B+12>>2];G=i+(g+2<<4)|0;c[G>>2]=c[B>>2];c[G+4>>2]=c[B+4>>2];c[G+8>>2]=c[B+8>>2];c[G+12>>2]=c[B+12>>2];G=i+(g+3<<4)|0;B=D+((b|2)<<4)|0;c[G>>2]=c[B>>2];c[G+4>>2]=c[B+4>>2];c[G+8>>2]=c[B+8>>2];c[G+12>>2]=c[B+12>>2];G=i+(g+4<<4)|0;c[G>>2]=c[B>>2];c[G+4>>2]=c[B+4>>2];c[G+8>>2]=c[B+8>>2];c[G+12>>2]=c[B+12>>2];G=i+(g+5<<4)|0;b=D+((b|3)<<4)|0;c[G>>2]=c[b>>2];c[G+4>>2]=c[b+4>>2];c[G+8>>2]=c[b+8>>2];c[G+12>>2]=c[b+12>>2];e=e+1|0;g=g+6|0}c[k>>2]=c[i>>2];c[k+4>>2]=c[i+4>>2];c[k+8>>2]=c[i+8>>2];c[k+12>>2]=c[i+12>>2];d=i+(j<<4)|0;G=i+16|0;c[d>>2]=c[G>>2];c[d+4>>2]=c[G+4>>2];c[d+8>>2]=c[G+8>>2];c[d+12>>2]=c[G+12>>2];KD(a,G,j,0,0,f&255);$I(i);break}if((e|0)<16777216){switch(e|0){case 8:break;default:break a}ID(a,b,d,f);g=B+16|0;e=0;while(1){if((e|0)>=(d|0))break a;G=e*3|0;f=D+(G+2<<4)|0;c[B>>2]=c[f>>2];c[B+4>>2]=c[f+4>>2];c[B+8>>2]=c[f+8>>2];c[B+12>>2]=c[f+12>>2];G=D+(G+4<<4)|0;c[g>>2]=c[G>>2];c[g+4>>2]=c[G+4>>2];c[g+8>>2]=c[G+8>>2];c[g+12>>2]=c[G+12>>2];LD(a,B,2);e=e+1|0}}switch(e|0){case 16777216:break;default:break a}g=d+1|0;i=ww(g<<4)|0;e=1;while(1){if((e|0)>=(d|0))break;G=i+(e<<4)|0;A=b+(e<<4)|0;c[G>>2]=c[A>>2];c[G+4>>2]=c[A+4>>2];c[G+8>>2]=c[A+8>>2];c[G+12>>2]=c[A+12>>2];e=e+1|0}b=d*3|0;A=D+(b+1<<4)|0;c[i>>2]=c[A>>2];c[i+4>>2]=c[A+4>>2];c[i+8>>2]=c[A+8>>2];c[i+12>>2]=c[A+12>>2];d=i+(d<<4)|0;G=D+(b+-1<<4)|0;c[d>>2]=c[G>>2];c[d+4>>2]=c[G+4>>2];c[d+8>>2]=c[G+8>>2];c[d+12>>2]=c[G+12>>2];ID(a,i,g,f);$I(i);c[B>>2]=c[G>>2];c[B+4>>2]=c[G+4>>2];c[B+8>>2]=c[G+8>>2];c[B+12>>2]=c[G+12>>2];G=B+16|0;c[G>>2]=c[A>>2];c[G+4>>2]=c[A+4>>2];c[G+8>>2]=c[A+8>>2];c[G+12>>2]=c[A+12>>2];f=B+32|0;h[f>>3]=+h[B>>3]+ +h[G>>3]-+h[D+(b<<4)>>3];h[B+40>>3]=+h[B+8>>3]+ +h[B+24>>3]-+h[D+(b<<4)+8>>3];LD(a,G,2);c[G>>2]=c[f>>2];c[G+4>>2]=c[f+4>>2];c[G+8>>2]=c[f+8>>2];c[G+12>>2]=c[f+12>>2];LD(a,B,2);break}else{if((e|0)<50331648){switch(e|0){case 33554432:break;default:break a}g=d+2|0;i=ww(g<<4)|0;c[i>>2]=c[b>>2];c[i+4>>2]=c[b+4>>2];c[i+8>>2]=c[b+8>>2];c[i+12>>2]=c[b+12>>2];j=i+16|0;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];c[j+8>>2]=c[k+8>>2];c[j+12>>2]=c[k+12>>2];j=D+48|0;d=D+64|0;h[i+32>>3]=(+h[j>>3]-+h[d>>3])*.3333333333333333+ +h[k>>3];G=D+56|0;e=D+72|0;h[i+40>>3]=(+h[G>>3]-+h[e>>3])*.3333333333333333+ +h[D+40>>3];J=+h[j>>3];h[i+48>>3]=(J-+h[d>>3])*.3333333333333333+J;J=+h[G>>3];h[i+56>>3]=(J-+h[e>>3])*.3333333333333333+J;e=4;while(1){if((e|0)>=(g|0))break;G=i+(e<<4)|0;d=b+(e+-2<<4)|0;c[G>>2]=c[d>>2];c[G+4>>2]=c[d+4>>2];c[G+8>>2]=c[d+8>>2];c[G+12>>2]=c[d+12>>2];e=e+1|0}ID(a,i,g,f);$I(i);c[B>>2]=c[j>>2];c[B+4>>2]=c[j+4>>2];c[B+8>>2]=c[j+8>>2];c[B+12>>2]=c[j+12>>2];G=B+16|0;c[G>>2]=c[k>>2];c[G+4>>2]=c[k+4>>2];c[G+8>>2]=c[k+8>>2];c[G+12>>2]=c[k+12>>2];LD(a,B,2);break}if((e|0)>=67108864){switch(e|0){case 67108864:break;default:break a}if((d|0)==4){G=ww(96)|0;c[G>>2]=c[b>>2];c[G+4>>2]=c[b+4>>2];c[G+8>>2]=c[b+8>>2];c[G+12>>2]=c[b+12>>2];d=G+16|0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[d+8>>2]=c[k+8>>2];c[d+12>>2]=c[k+12>>2];d=G+32|0;A=D+64|0;c[d>>2]=c[A>>2];c[d+4>>2]=c[A+4>>2];c[d+8>>2]=c[A+8>>2];c[d+12>>2]=c[A+12>>2];d=G+48|0;b=b+32|0;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];b=G+64|0;d=D+128|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];b=G+80|0;z=D+160|0;c[b>>2]=c[z>>2];c[b+4>>2]=c[z+4>>2];c[b+8>>2]=c[z+8>>2];c[b+12>>2]=c[z+12>>2];ID(a,G,6,f);$I(G);h[B>>3]=+h[D+176>>3]+ +h[j>>3]-+h[D>>3];h[B+8>>3]=+h[D+184>>3]+ +h[D+24>>3]-+h[D+8>>3];G=B+16|0;c[G>>2]=c[A>>2];c[G+4>>2]=c[A+4>>2];c[G+8>>2]=c[A+8>>2];c[G+12>>2]=c[A+12>>2];LD(a,B,2);c[G>>2]=c[d>>2];c[G+4>>2]=c[d+4>>2];c[G+8>>2]=c[d+8>>2];c[G+12>>2]=c[d+12>>2];LD(a,B,2);c[G>>2]=c[D>>2];c[G+4>>2]=c[D+4>>2];c[G+8>>2]=c[D+8>>2];c[G+12>>2]=c[D+12>>2];LD(a,B,2);break}else ma(90472,90483,714,90492)}switch(e|0){case 50331648:break;default:break a}g=d+3|0;i=ww(g<<4)|0;c[i>>2]=c[b>>2];c[i+4>>2]=c[b+4>>2];c[i+8>>2]=c[b+8>>2];c[i+12>>2]=c[b+12>>2];J=+h[b>>3];h[i+16>>3]=J-(J-+h[j>>3])*.25;e=D+56|0;J=(+h[e>>3]-+h[D+72>>3])*.3333333333333333+ +h[b+8>>3];h[i+24>>3]=J;I=+h[b>>3];h[i+32>>3]=I-(I-+h[j>>3])*2.0;h[i+40>>3]=J;J=+h[b>>3];h[i+48>>3]=J-(J-+h[j>>3])*2.25;h[i+56>>3]=+h[e>>3];h[i+64>>3]=+h[D+48>>3];h[i+72>>3]=+h[e>>3];e=4;while(1){if((e|0)>=(g|0))break;G=i+(e<<4)|0;d=b+(e+-3<<4)|0;c[G>>2]=c[d>>2];c[G+4>>2]=c[d+4>>2];c[G+8>>2]=c[d+8>>2];c[G+12>>2]=c[d+12>>2];e=e+1|0}ID(a,i,g,f);$I(i);break}}else if((e|0)<318767104){if((e|0)<251658240){if((e|0)<218103808){switch(e|0){case 201326592:break;default:break a}G=d<<4;u=ww(G)|0;v=b+16|0;J=+h[v>>3];h[u>>3]=J;z=b+40|0;I=+h[z>>3];A=b+24|0;y=D+48|0;w=D+56|0;x=D+72|0;I=(+h[A>>3]-I)*.5+I+(+h[w>>3]-+h[x>>3])*.125;h[u+8>>3]=I;H=(+h[k>>3]-+h[y>>3])*2.0+J;h[u+16>>3]=H;h[u+24>>3]=I;h[u+32>>3]=H;I=(+h[w>>3]-+h[x>>3])*.5+I;h[u+40>>3]=I;h[u+48>>3]=J;h[u+56>>3]=I;ID(a,u,d,f);$I(u);G=ww(G)|0;I=+h[k>>3]+ +h[v>>3]-+h[y>>3];h[G>>3]=I;J=+h[z>>3];J=(+h[A>>3]-J)*.5+J+(+h[w>>3]-+h[x>>3])*-.625;h[G+8>>3]=J;H=+h[k>>3]-+h[y>>3]+I;y=G+16|0;h[y>>3]=H;h[G+24>>3]=J;h[G+32>>3]=H;J=(+h[w>>3]-+h[x>>3])*.5+J;h[G+40>>3]=J;h[G+48>>3]=I;h[G+56>>3]=J;ID(a,G,d,f);h[B>>3]=+h[y>>3];J=+h[z>>3];h[B+8>>3]=(+h[A>>3]-J)*.5+J;h[B+16>>3]=+h[b>>3];h[B+24>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}if((e|0)<234881024){switch(e|0){case 218103808:break;default:break a}G=d<<4;w=ww(G)|0;J=+h[b>>3];h[w>>3]=J;y=b+40|0;I=+h[y>>3];z=b+24|0;x=D+56|0;A=D+72|0;I=(+h[z>>3]-I)*.5+I+(+h[x>>3]-+h[A>>3])*.125;h[w+8>>3]=I;h[w+16>>3]=J;H=(+h[x>>3]-+h[A>>3])*.5+I;h[w+24>>3]=H;J=J-(+h[x>>3]-+h[A>>3])*2.0;h[w+32>>3]=J;h[w+40>>3]=H;h[w+48>>3]=J;h[w+56>>3]=I;ID(a,w,d,f);$I(w);G=ww(G)|0;I=+h[b>>3]-+h[k>>3]+ +h[D+48>>3];h[G>>3]=I;J=+h[y>>3];J=(+h[z>>3]-J)*.5+J+(+h[x>>3]-+h[A>>3])*-.625;h[G+8>>3]=J;h[G+16>>3]=I;H=(+h[x>>3]-+h[A>>3])*.5+J;h[G+24>>3]=H;I=I-(+h[x>>3]-+h[A>>3]);h[G+32>>3]=I;h[G+40>>3]=H;A=G+48|0;h[A>>3]=I;h[G+56>>3]=J;ID(a,G,d,f);h[B>>3]=+h[b+16>>3];J=+h[y>>3];h[B+8>>3]=(+h[z>>3]-J)*.5+J;h[B+16>>3]=+h[A>>3];h[B+24>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}else{switch(e|0){case 234881024:break;default:break a}G=d<<4;y=ww(G)|0;u=b+16|0;I=+h[u>>3];v=D+48|0;I=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[v>>3])*-1.125;h[y>>3]=I;w=b+40|0;J=+h[w>>3];x=b+24|0;A=D+56|0;z=D+72|0;J=(+h[x>>3]-J)*.5+J+(+h[A>>3]-+h[z>>3])*.125;h[y+8>>3]=J;H=+h[k>>3]-+h[v>>3]+I;h[y+16>>3]=H;h[y+24>>3]=J;h[y+32>>3]=H;J=(+h[A>>3]-+h[z>>3])*.5+J;h[y+40>>3]=J;h[y+48>>3]=I;h[y+56>>3]=J;ID(a,y,d,f);$I(y);y=ww(G)|0;J=+h[u>>3];J=(+h[b>>3]-J)*.5+J+(+h[k>>3]-+h[v>>3])*-1.125;h[y>>3]=J;I=+h[w>>3];I=(+h[x>>3]-I)*.5+I+(+h[A>>3]-+h[z>>3])*-.625;h[y+8>>3]=I;H=+h[k>>3]-+h[v>>3]+J;h[y+16>>3]=H;h[y+24>>3]=I;h[y+32>>3]=H;I=(+h[A>>3]-+h[z>>3])*.5+I;h[y+40>>3]=I;h[y+48>>3]=J;h[y+56>>3]=I;ID(a,y,d,f);$I(y);y=ww(G)|0;I=+h[u>>3];I=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[v>>3])*.125;h[y>>3]=I;J=+h[w>>3];J=(+h[x>>3]-J)*.5+J+(+h[A>>3]-+h[z>>3])*-.625;h[y+8>>3]=J;H=+h[k>>3]-+h[v>>3]+I;h[y+16>>3]=H;h[y+24>>3]=J;h[y+32>>3]=H;J=(+h[A>>3]-+h[z>>3])*.5+J;h[y+40>>3]=J;h[y+48>>3]=I;h[y+56>>3]=J;ID(a,y,d,f);$I(y);G=ww(G)|0;J=+h[u>>3];J=(+h[b>>3]-J)*.5+J+(+h[k>>3]-+h[v>>3])*.125;h[G>>3]=J;I=+h[w>>3];I=(+h[x>>3]-I)*.5+I+(+h[A>>3]-+h[z>>3])*.125;h[G+8>>3]=I;H=+h[k>>3]-+h[v>>3]+J;y=G+16|0;h[y>>3]=H;h[G+24>>3]=I;h[G+32>>3]=H;I=(+h[A>>3]-+h[z>>3])*.5+I;h[G+40>>3]=I;h[G+48>>3]=J;h[G+56>>3]=I;ID(a,G,d,f);h[B>>3]=+h[y>>3];I=+h[w>>3];y=B+8|0;h[y>>3]=(+h[x>>3]-I)*.5+I;z=B+16|0;h[z>>3]=+h[b>>3];A=b+8|0;d=b+56|0;f=B+24|0;h[f>>3]=(+h[A>>3]-+h[d>>3])*.5+I;LD(a,B,2);I=+h[u>>3];h[B>>3]=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[v>>3])*-1.125;J=+h[w>>3];h[y>>3]=(+h[x>>3]-J)*.5+J;h[z>>3]=I;h[f>>3]=(+h[A>>3]-+h[d>>3])*.5+J;LD(a,B,2);$I(G);break}}if((e|0)<285212672)if((e|0)<268435456){switch(e|0){case 251658240:break;default:break a}G=d<<4;u=ww(G)|0;v=b+16|0;J=+h[v>>3];y=D+48|0;J=J-+h[k>>3]+(+h[b>>3]-J)*.5+ +h[y>>3];h[u>>3]=J;w=b+40|0;I=+h[w>>3];x=b+24|0;A=D+56|0;z=D+72|0;I=(+h[x>>3]-I)*.5+I+(+h[A>>3]-+h[z>>3])*.125;h[u+8>>3]=I;H=(+h[k>>3]-+h[y>>3])*2.0+J;h[u+16>>3]=H;h[u+24>>3]=I;h[u+32>>3]=H;I=(+h[A>>3]-+h[z>>3])*.5+I;h[u+40>>3]=I;h[u+48>>3]=J;h[u+56>>3]=I;ID(a,u,d,f);$I(u);G=ww(G)|0;I=+h[v>>3];I=I-+h[k>>3]+(+h[b>>3]-I)*.5+ +h[y>>3];h[G>>3]=I;J=+h[w>>3];J=(+h[x>>3]-J)*.5+J+(+h[A>>3]-+h[z>>3])*-.625;h[G+8>>3]=J;H=(+h[k>>3]-+h[y>>3])*2.0+I;y=G+16|0;h[y>>3]=H;h[G+24>>3]=J;h[G+32>>3]=H;J=(+h[A>>3]-+h[z>>3])*.5+J;h[G+40>>3]=J;h[G+48>>3]=I;h[G+56>>3]=J;ID(a,G,d,f);h[B>>3]=+h[y>>3];J=+h[w>>3];y=B+8|0;h[y>>3]=(+h[x>>3]-J)*.5+J;z=B+16|0;h[z>>3]=+h[b>>3];A=b+8|0;d=b+56|0;f=B+24|0;h[f>>3]=(+h[A>>3]-+h[d>>3])*.5+J;LD(a,B,2);h[B>>3]=+h[v>>3];J=+h[w>>3];h[y>>3]=(+h[x>>3]-J)*.5+J;h[z>>3]=+h[G>>3];h[f>>3]=(+h[A>>3]-+h[d>>3])*.5+J;LD(a,B,2);$I(G);break}else{switch(e|0){case 268435456:break;default:break a}G=ww(d<<4)|0;h[G>>3]=+h[b>>3];v=D+48|0;x=D+56|0;y=D+72|0;h[G+8>>3]=+h[D+24>>3]-(+h[x>>3]-+h[y>>3])*.5;h[G+16>>3]=+h[v>>3];J=+h[x>>3];h[G+24>>3]=J-(J-+h[y>>3])*.5;h[G+32>>3]=+h[b+32>>3];z=b+40|0;h[G+40>>3]=(+h[x>>3]-+h[y>>3])*.5+ +h[z>>3];h[G+48>>3]=+h[b>>3];h[G+56>>3]=(+h[x>>3]-+h[y>>3])*.5+ +h[z>>3];ID(a,G,d,f);w=b+16|0;J=(+h[k>>3]-+h[v>>3])*.25;I=J+ +h[w>>3];h[B>>3]=I;H=+h[z>>3];u=b+24|0;F=+h[x>>3]-+h[y>>3];H=(+h[u>>3]-H)*.5+H+F*.125;A=B+8|0;h[A>>3]=H;d=B+16|0;h[d>>3]=J+I;f=B+24|0;h[f>>3]=H-F*.25;LD(a,B,2);F=(+h[k>>3]-+h[v>>3])*.25;H=F+ +h[w>>3];h[B>>3]=H;I=+h[z>>3];J=+h[x>>3]-+h[y>>3];I=(+h[u>>3]-I)*.5+I+J*-.125;h[A>>3]=I;h[d>>3]=F+H;h[f>>3]=J*.25+I;LD(a,B,2);I=(+h[k>>3]-+h[v>>3])*.25;h[B>>3]=I+ +h[w>>3];J=(+h[x>>3]-+h[y>>3])*.75+ +h[z>>3];h[A>>3]=J;h[d>>3]=+h[b>>3]-I;h[f>>3]=J;LD(a,B,2);$I(G);break}else if((e|0)<301989888){switch(e|0){case 285212672:break;default:break a}y=ww(d<<4)|0;v=b+16|0;I=+h[v>>3];z=D+48|0;I=(+h[k>>3]-+h[z>>3]+(+h[b>>3]-I))*.5+I;h[y>>3]=I;w=b+40|0;F=+h[w>>3];x=b+24|0;F=(+h[k>>3]-+h[z>>3]+(+h[x>>3]-F))*.5+F;h[y+8>>3]=F;h[y+16>>3]=I;I=+h[w>>3];o=+h[k>>3]-+h[z>>3];I=(+h[x>>3]-I-o)*.5+I;h[y+24>>3]=I;J=+h[v>>3];J=(+h[b>>3]-J-o)*.5+J;h[y+32>>3]=J;h[y+40>>3]=I;h[y+48>>3]=J;h[y+56>>3]=F;ID(a,y,d,f);$I(y);F=+h[v>>3];F=(+h[b>>3]-F)*.5+F;J=+h[k>>3]-+h[z>>3];I=J*.75;o=F+I;h[B>>3]=o;H=+h[w>>3];H=(+h[x>>3]-H)*.5+H;I=H+I;y=B+8|0;h[y>>3]=I;A=B+16|0;h[A>>3]=o;J=J*-.75;H=H+J;G=B+24|0;h[G>>3]=H;J=F+J;h[B+32>>3]=J;h[B+40>>3]=H;h[B+48>>3]=J;h[B+56>>3]=I;d=B+64|0;c[d>>2]=c[B>>2];c[d+4>>2]=c[B+4>>2];c[d+8>>2]=c[B+8>>2];c[d+12>>2]=c[B+12>>2];LD(a,B,5);I=+h[v>>3];J=+h[b>>3];h[B>>3]=(J-I)*.5+I+(+h[k>>3]-+h[z>>3])*.75;I=+h[w>>3];h[y>>3]=(+h[x>>3]-I)*.5+I;h[A>>3]=J;d=b+8|0;f=b+56|0;h[G>>3]=(+h[d>>3]-+h[f>>3])*.5+I;LD(a,B,2);I=+h[v>>3];h[B>>3]=I;J=+h[w>>3];h[y>>3]=(+h[x>>3]-J)*.5+J;h[A>>3]=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[z>>3])*-.75;h[G>>3]=(+h[d>>3]-+h[f>>3])*.5+J;LD(a,B,2);break}else{switch(e|0){case 301989888:break;default:break a}A=d+12|0;G=ww(A<<4)|0;x=b+16|0;m=+h[x>>3];s=D+48|0;m=(+h[b>>3]-m)*.5+m+(+h[k>>3]-+h[s>>3])*.25;h[G>>3]=m;y=b+40|0;F=+h[y>>3];z=b+24|0;v=D+56|0;w=D+72|0;F=(+h[v>>3]-+h[w>>3]+(+h[z>>3]-F))*.5+F;u=G+8|0;h[u>>3]=F;h[G+16>>3]=m;F=(+h[v>>3]-+h[w>>3])*.125+F;t=G+24|0;h[t>>3]=F;H=m-(+h[k>>3]-+h[s>>3])*.125;d=G+32|0;h[d>>3]=H;o=(+h[v>>3]-+h[w>>3])*.125+F;h[G+40>>3]=o;h[G+48>>3]=m;I=(+h[v>>3]-+h[w>>3])*.125+o;h[G+56>>3]=I;h[G+64>>3]=m;m=(+h[v>>3]-+h[w>>3])*.125+I;h[G+72>>3]=m;h[G+80>>3]=H;h[G+88>>3]=m;H=+h[x>>3];H=(+h[b>>3]-H)*.5+H;h[G+96>>3]=H;h[G+104>>3]=I;J=H-(+h[k>>3]-+h[s>>3])*.125;h[G+112>>3]=J;h[G+120>>3]=m;J=J-(+h[k>>3]-+h[s>>3])*.125;h[G+128>>3]=J;h[G+136>>3]=m;h[G+144>>3]=J;h[G+152>>3]=I;I=(+h[k>>3]-+h[s>>3])*.125+J;h[G+160>>3]=I;h[G+168>>3]=o;h[G+176>>3]=J;h[G+184>>3]=F;h[G+192>>3]=J;J=+h[u>>3];h[G+200>>3]=J;h[G+208>>3]=I;h[G+216>>3]=J;u=G+224|0;h[u>>3]=H;h[G+232>>3]=+h[t>>3];h[G+240>>3]=+h[d>>3];h[G+248>>3]=J;ID(a,G,A,f);J=+h[u>>3];h[B>>3]=J;H=+h[y>>3];H=(+h[z>>3]-H)*.5+H;A=B+8|0;h[A>>3]=H;d=B+16|0;h[d>>3]=J;f=B+24|0;h[f>>3]=(+h[v>>3]-+h[w>>3])*.125+H;LD(a,B,2);H=+h[u>>3];h[B>>3]=H;J=+h[y>>3];I=+h[v>>3]-+h[w>>3];J=(+h[z>>3]-J)*.5+J+I*.25;h[A>>3]=J;h[d>>3]=H;h[f>>3]=I*.125+J;LD(a,B,2);h[B>>3]=+h[x>>3];J=+h[y>>3];h[A>>3]=(+h[z>>3]-J)*.5+J;h[d>>3]=+h[b>>3];h[f>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}}else{if((e|0)<369098752){if((e|0)<335544320){switch(e|0){case 318767104:break;default:break a}A=d+4|0;G=ww(A<<4)|0;x=b+16|0;H=+h[x>>3];d=D+48|0;H=(+h[b>>3]-H)*.5+H+(+h[k>>3]-+h[d>>3])*.125;h[G>>3]=H;y=b+40|0;J=+h[y>>3];z=b+24|0;v=D+56|0;w=D+72|0;J=(+h[v>>3]-+h[w>>3]+(+h[z>>3]-J))*.5+J;h[G+8>>3]=J;o=(+h[k>>3]-+h[d>>3])*.125+H;h[G+16>>3]=o;I=(+h[v>>3]-+h[w>>3])*.125+J;h[G+24>>3]=I;h[G+32>>3]=o;o=(+h[v>>3]-+h[w>>3])*.25+I;h[G+40>>3]=o;h[G+48>>3]=H;F=(+h[v>>3]-+h[w>>3])*.125+o;h[G+56>>3]=F;H=H-(+h[k>>3]-+h[d>>3])*.25;h[G+64>>3]=H;h[G+72>>3]=F;F=H-(+h[k>>3]-+h[d>>3])*.125;h[G+80>>3]=F;h[G+88>>3]=o;h[G+96>>3]=F;h[G+104>>3]=I;h[G+112>>3]=H;h[G+120>>3]=J;ID(a,G,A,f);J=+h[x>>3];J=(+h[b>>3]-J)*.5+J;h[B>>3]=J;H=+h[y>>3];H=(+h[z>>3]-H)*.5+H;A=B+8|0;h[A>>3]=H;d=B+16|0;h[d>>3]=J;f=B+24|0;h[f>>3]=(+h[v>>3]-+h[w>>3])*.125+H;LD(a,B,2);H=+h[x>>3];H=(+h[b>>3]-H)*.5+H;h[B>>3]=H;J=+h[y>>3];I=+h[v>>3]-+h[w>>3];J=(+h[z>>3]-J)*.5+J+I*.25;h[A>>3]=J;h[d>>3]=H;h[f>>3]=I*.125+J;LD(a,B,2);h[B>>3]=+h[x>>3];J=+h[y>>3];h[A>>3]=(+h[z>>3]-J)*.5+J;h[d>>3]=+h[b>>3];h[f>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}if((e|0)<352321536){switch(e|0){case 335544320:break;default:break a}x=d+12|0;G=ww(x<<4)|0;y=b+16|0;m=+h[y>>3];u=D+48|0;m=(+h[b>>3]-m)*.5+m+(+h[k>>3]-+h[u>>3])*.25;h[G>>3]=m;z=b+40|0;F=+h[z>>3];A=b+24|0;s=D+56|0;t=D+72|0;F=(+h[s>>3]-+h[t>>3]+(+h[A>>3]-F))*.5+F;d=G+8|0;h[d>>3]=F;h[G+16>>3]=m;F=(+h[s>>3]-+h[t>>3])*.125+F;v=G+24|0;h[v>>3]=F;I=m-(+h[k>>3]-+h[u>>3])*.125;w=G+32|0;h[w>>3]=I;o=(+h[s>>3]-+h[t>>3])*.125+F;h[G+40>>3]=o;h[G+48>>3]=m;H=(+h[s>>3]-+h[t>>3])*.125+o;h[G+56>>3]=H;h[G+64>>3]=m;m=(+h[s>>3]-+h[t>>3])*.125+H;h[G+72>>3]=m;h[G+80>>3]=I;h[G+88>>3]=m;I=+h[y>>3];I=(+h[b>>3]-I)*.5+I;h[G+96>>3]=I;h[G+104>>3]=H;J=I-(+h[k>>3]-+h[u>>3])*.125;h[G+112>>3]=J;h[G+120>>3]=m;J=J-(+h[k>>3]-+h[u>>3])*.125;h[G+128>>3]=J;h[G+136>>3]=m;h[G+144>>3]=J;h[G+152>>3]=H;H=(+h[k>>3]-+h[u>>3])*.125+J;h[G+160>>3]=H;h[G+168>>3]=o;h[G+176>>3]=J;h[G+184>>3]=F;h[G+192>>3]=J;J=+h[d>>3];h[G+200>>3]=J;h[G+208>>3]=H;h[G+216>>3]=J;d=G+224|0;h[d>>3]=I;h[G+232>>3]=+h[v>>3];h[G+240>>3]=+h[w>>3];h[G+248>>3]=J;ID(a,G,x,f);c[B>>2]=c[d>>2];c[B+4>>2]=c[d+4>>2];c[B+8>>2]=c[d+8>>2];c[B+12>>2]=c[d+12>>2];d=B+16|0;h[d>>3]=+h[B>>3];J=+h[z>>3];f=B+24|0;h[f>>3]=(+h[A>>3]-J)*.5+J;LD(a,B,2);h[B>>3]=+h[y>>3];J=+h[z>>3];h[B+8>>3]=(+h[A>>3]-J)*.5+J;h[d>>3]=+h[b>>3];h[f>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}else{switch(e|0){case 352321536:break;default:break a}A=d+4|0;G=ww(A<<4)|0;x=b+16|0;I=+h[x>>3];w=D+48|0;I=(+h[b>>3]-I)*.5+I+(+h[k>>3]-+h[w>>3])*.125;h[G>>3]=I;y=b+40|0;J=+h[y>>3];z=b+24|0;u=D+56|0;v=D+72|0;J=(+h[u>>3]-+h[v>>3]+(+h[z>>3]-J))*.5+J;d=G+8|0;h[d>>3]=J;o=(+h[k>>3]-+h[w>>3])*.125+I;h[G+16>>3]=o;H=(+h[u>>3]-+h[v>>3])*.125+J;h[G+24>>3]=H;h[G+32>>3]=o;o=(+h[u>>3]-+h[v>>3])*.25+H;h[G+40>>3]=o;h[G+48>>3]=I;F=(+h[u>>3]-+h[v>>3])*.125+o;h[G+56>>3]=F;I=I-(+h[k>>3]-+h[w>>3])*.25;h[G+64>>3]=I;h[G+72>>3]=F;F=I-(+h[k>>3]-+h[w>>3])*.125;h[G+80>>3]=F;h[G+88>>3]=o;h[G+96>>3]=F;h[G+104>>3]=H;h[G+112>>3]=I;h[G+120>>3]=J;ID(a,G,A,f);J=+h[x>>3];J=(+h[b>>3]-J)*.5+J;h[B>>3]=J;A=B+8|0;h[A>>3]=+h[d>>3];d=B+16|0;h[d>>3]=J;J=+h[y>>3];f=B+24|0;h[f>>3]=(+h[z>>3]-J)*.5+J;LD(a,B,2);h[B>>3]=+h[x>>3];J=+h[y>>3];h[A>>3]=(+h[z>>3]-J)*.5+J;h[d>>3]=+h[b>>3];h[f>>3]=(+h[b+8>>3]-+h[b+56>>3])*.5+J;LD(a,B,2);$I(G);break}}if((e|0)<402653184)if((e|0)<385875968){switch(e|0){case 369098752:break;default:break a}d=d+5|0;G=ww(d<<4)|0;B=D+48|0;h[G>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;y=D+56|0;A=D+72|0;h[G+8>>3]=+h[D+24>>3]-(+h[y>>3]-+h[A>>3])*.5;h[G+16>>3]=+h[B>>3];J=+h[y>>3];h[G+24>>3]=J-(J-+h[A>>3])*.5;h[G+32>>3]=+h[b+32>>3];z=b+40|0;h[G+40>>3]=+h[z>>3];J=+h[k>>3];h[G+48>>3]=(J-+h[B>>3])*.5+J;h[G+56>>3]=+h[z>>3];J=+h[k>>3];h[G+64>>3]=(J-+h[B>>3])*.5+J;h[G+72>>3]=(+h[y>>3]-+h[A>>3])*.5+ +h[z>>3];h[G+80>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;h[G+88>>3]=(+h[y>>3]-+h[A>>3])*.5+ +h[z>>3];h[G+96>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;z=b+56|0;h[G+104>>3]=+h[z>>3];A=b+8|0;J=+h[A>>3];h[G+120>>3]=J-(J-+h[z>>3])*.5;h[G+112>>3]=+h[b>>3];h[G+136>>3]=+h[A>>3];h[G+128>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;ID(a,G,d,f);$I(G);break}else{switch(e|0){case 385875968:break;default:break a}d=d+3|0;G=ww(d<<4)|0;B=D+48|0;h[G>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;y=D+56|0;A=D+72|0;h[G+8>>3]=+h[D+24>>3]-(+h[y>>3]-+h[A>>3])*.5;h[G+16>>3]=+h[B>>3];J=+h[y>>3];h[G+24>>3]=J-(J-+h[A>>3])*.5;h[G+32>>3]=+h[b+32>>3];z=b+40|0;h[G+40>>3]=(+h[y>>3]-+h[A>>3])*.5+ +h[z>>3];h[G+48>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;h[G+56>>3]=(+h[y>>3]-+h[A>>3])*.5+ +h[z>>3];h[G+64>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;z=b+56|0;h[G+72>>3]=+h[z>>3];A=b+8|0;J=+h[A>>3];h[G+88>>3]=J-(J-+h[z>>3])*.5;h[G+80>>3]=+h[b>>3];h[G+104>>3]=+h[A>>3];h[G+96>>3]=+h[j>>3]-(+h[k>>3]-+h[B>>3])*.5;ID(a,G,d,f);$I(G);break}else if((e|0)<419430400){switch(e|0){case 402653184:break;default:break a}d=d+3|0;G=ww(d<<4)|0;h[G>>3]=+h[b>>3];y=b+8|0;z=D+48|0;A=D+56|0;B=D+72|0;h[G+8>>3]=+h[y>>3]-(+h[A>>3]-+h[B>>3])*.5;J=+h[k>>3];h[G+16>>3]=(J-+h[z>>3])*.5+J;h[G+24>>3]=+h[y>>3]-(+h[A>>3]-+h[B>>3])*.5;J=+h[k>>3];h[G+32>>3]=(J-+h[z>>3])*.5+J;h[G+40>>3]=+h[D+40>>3];h[G+48>>3]=+h[b+16>>3];J=+h[b+24>>3];y=b+40|0;h[G+56>>3]=J-(J-+h[y>>3])*.5;J=+h[k>>3];h[G+64>>3]=(J-+h[z>>3])*.5+J;h[G+72>>3]=+h[y>>3];h[G+88>>3]=(+h[A>>3]-+h[B>>3])*.5+ +h[y>>3];J=+h[k>>3];h[G+80>>3]=(J-+h[z>>3])*.5+J;h[G+104>>3]=(+h[A>>3]-+h[B>>3])*.5+ +h[b+56>>3];h[G+96>>3]=+h[b>>3];ID(a,G,d,f);$I(G);break}else{switch(e|0){case 419430400:break;default:break a}d=d+5|0;G=ww(d<<4)|0;h[G>>3]=+h[b>>3];B=b+8|0;A=D+48|0;y=D+56|0;z=D+72|0;h[G+8>>3]=+h[B>>3]-(+h[y>>3]-+h[z>>3])*.5;J=+h[k>>3];h[G+16>>3]=(J-+h[A>>3])*.5+J;h[G+24>>3]=+h[B>>3]-(+h[y>>3]-+h[z>>3])*.5;J=+h[k>>3];h[G+32>>3]=(J-+h[A>>3])*.5+J;h[G+40>>3]=+h[D+40>>3];h[G+48>>3]=+h[b+16>>3];J=+h[b+24>>3];B=b+40|0;h[G+56>>3]=J-(J-+h[B>>3])*.5;J=+h[k>>3];h[G+64>>3]=(J-+h[A>>3])*.5+J;h[G+72>>3]=+h[B>>3];h[G+88>>3]=(+h[y>>3]-+h[z>>3])*.5+ +h[B>>3];J=+h[k>>3];h[G+80>>3]=(J-+h[A>>3])*.5+J;B=b+56|0;h[G+104>>3]=(+h[y>>3]-+h[z>>3])*.5+ +h[B>>3];h[G+96>>3]=+h[j>>3]-(+h[k>>3]-+h[A>>3])*.5;h[G+112>>3]=+h[j>>3]-(+h[k>>3]-+h[A>>3])*.5;h[G+120>>3]=+h[B>>3];h[G+128>>3]=+h[b+48>>3];h[G+136>>3]=+h[B>>3];ID(a,G,d,f);$I(G);break}}while(0);$I(D)}l=E;return}function Ay(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0;f=l;l=l+112|0;g=f;k=+h[b+8>>3]*2.0;c[g>>2]=c[b>>2];c[g+4>>2]=c[b+4>>2];c[g+8>>2]=c[b+8>>2];c[g+12>>2]=c[b+12>>2];h[g+16>>3]=+h[b+16>>3];h[g+24>>3]=k-+h[b+24>>3];h[g+32>>3]=+h[b+32>>3];h[g+40>>3]=k-+h[b+40>>3];h[g+48>>3]=+h[b+48>>3];h[g+56>>3]=k-+h[b+56>>3];h[g+64>>3]=+h[b+64>>3];h[g+72>>3]=k-+h[b+72>>3];h[g+80>>3]=+h[b+80>>3];h[g+88>>3]=k-+h[b+88>>3];i=g+96|0;j=b+96|0;c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];c[i+8>>2]=c[j+8>>2];c[i+12>>2]=c[j+12>>2];KD(a,b,d,0,0,e&255);KD(a,g,7,0,0,0);l=f;return}function By(a,b,c,d){a=a|0;b=+b;c=c|0;d=d|0;var e=0.0,f=0.0;f=+h[c>>3];e=+h[c+8>>3];e=(+h[d+8>>3]-e)*b+e;h[a>>3]=(+h[d>>3]-f)*b+f;h[a+8>>3]=e;return}function Cy(a){a=a|0;a=c[(c[a+16>>2]|0)+8>>2]|0;if(a){a=c[c[a+4>>2]>>2]|0;if((a|0)!=75)if((a|0)==78)a=2;else return ((a|0)==77?3:(a|0)==80?4:0)|0;else a=1}else a=0;return a|0}function Dy(b){b=b|0;var d=0,e=0,f=0.0,g=0,i=0,j=0,k=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0.0,w=0.0,x=0.0,y=0.0,z=0.0,A=0,D=0,G=0,H=0,I=0,J=0,L=0,M=0,N=0,P=0.0,Q=0.0,R=0,S=0,T=0.0,U=0.0,V=0.0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0.0;aa=l;l=l+144|0;J=aa+112|0;N=aa+104|0;G=aa+96|0;H=aa+88|0;i=aa+80|0;Y=aa+64|0;_=aa+48|0;R=aa+40|0;S=aa+32|0;j=aa+24|0;p=aa+16|0;D=aa+136|0;A=aa+128|0;L=aa;$=ww(48)|0;Z=b+16|0;W=c[(c[(c[Z>>2]|0)+8>>2]|0)+8>>2]|0;g=(W|0)==1552;X=c[W>>2]|0;d=c[W+4>>2]|0;e=c[W+8>>2]|0;m=+h[W+16>>3];n=+h[W+32>>3];o=+h[W+24>>3];X=X|(JA(Jm(b,90545)|0)|0)&255;do if(!g){if(!X){W=c[Z>>2]|0;k=+h[W+32>>3]*72.0;f=+h[W+40>>3]*72.0;f=+(~~(f+(f>=0.0?.5:-.5))|0);k=+(~~(k+(k>=0.0?.5:-.5))|0);break}k=+Ny(b);if(k>0.0)f=k;else{W=c[Z>>2]|0;f=+h[W+32>>3];k=+h[W+40>>3];k=(f=0.0?.5:-.5))|0);f=k}}else{f=0.0;k=0.0}while(0);W=EA(b,c[42205]|0,d,0)|0;V=+FA(b,c[42207]|0,0.0,-360.0)+m;if(!e){U=+FA(b,c[42208]|0,0.0,-100.0);I=EA(b,c[42204]|0,4,0)|0;T=+FA(b,c[42209]|0,0.0,-100.0)}else{I=e;U=n;T=o}d=c[(c[Z>>2]|0)+104>>2]|0;e=d+24|0;c[Y>>2]=c[e>>2];c[Y+4>>2]=c[e+4>>2];c[Y+8>>2]=c[e+8>>2];c[Y+12>>2]=c[e+12>>2];q=+h[Y>>3];if(q>0.0){if(!g)M=11}else if(!(g|!(+h[Y+8>>3]>0.0)))M=11;if((M|0)==11){d=Jm(b,90530)|0;do if(d){h[p>>3]=0.0;h[j>>3]=0.0;c[i>>2]=j;c[i+4>>2]=p;d=dM(d,90537,i)|0;m=+h[j>>3];if(m<0.0){h[j>>3]=0.0;m=0.0}n=+h[p>>3];if(n<0.0){h[p>>3]=0.0;o=0.0}else o=n;if((d|0)<=0){n=q+16.0;h[Y>>3]=n;m=8.0;break}m=m*72.0;m=+(~~(m+(m>=0.0?.5:-.5))<<1|0);n=q+m;h[Y>>3]=n;if((d|0)!=1){m=o*72.0;m=+(~~(m+(m>=0.0?.5:-.5))<<1|0)}}else{n=q+16.0;h[Y>>3]=n;m=8.0}while(0);d=Y+8|0;h[d>>3]=+h[d>>3]+m;d=c[(c[Z>>2]|0)+104>>2]|0;q=n}s=+h[d+24>>3];m=+h[c[(c[(so(b)|0)+16>>2]|0)+8>>2]>>3];if(m>0.0){P=m*72.0;P=+(~~(P+(P>=0.0?.5:-.5))|0);Q=+Oy(q,P);h[Y>>3]=Q;p=Y+8|0;h[p>>3]=+Oy(+h[p>>3],P)}else Q=q;d=c[(c[Z>>2]|0)+8>>2]|0;do if(!(a[d+12>>0]|0)){e=Jm(b,93847)|0;if((e|0)!=0?(a[e>>0]|0)!=0:0){Qr(A,so(b)|0,e);d=c[A>>2]|0;g=c[A+4>>2]|0;if((g&d|0)==-1){d=En(b)|0;c[G>>2]=e;c[G+4>>2]=d;$l(0,90621,G)|0;e=0;d=0;break}else{a[(c[(so(b)|0)+16>>2]|0)+114>>0]=1;e=d+2|0;d=g+2|0;break}}else{e=0;d=0}}else{d=c[d>>2]|0;if((a[d>>0]|0)==99?(yJ(d,90553)|0)==0:0){e=Jm(b,90560)|0;Qr(D,so(b)|0,e);d=c[D>>2]|0;g=c[D+4>>2]|0;if((g&d|0)==-1){d=En(b)|0;c[H>>2]=e|0?e:90570;c[H+4>>2]=d;$l(0,90576,H)|0;e=0;d=0;break}else{a[(c[(so(b)|0)+16>>2]|0)+114>>0]=1;e=d+2|0;d=g+2|0;break}}else{e=0;d=0}}while(0);P=+(e|0);h[_>>3]=Q>P?Q:P;P=+h[Y+8>>3];r=+(d|0);d=_+8|0;h[d>>3]=P>r?P:r;e=(I|0)<3&(T!=0.0|U!=0.0)?120:I;g=Jm(b,90662)|0;if(!g)i=99;else{i=a[g>>0]|0;i=i<<24>>24==116?116:i<<24>>24==98?98:99}g=c[Z>>2]|0;a[(c[g+104>>2]|0)+80>>0]=i;if((e|0)==4?(T==0.0?((~~(V+(V>=0.0?.5:-.5))|0)%90|0|0)==0:0)&U==0.0:0)p=1;else M=39;do if((M|0)==39){g=c[(c[(c[g+8>>2]|0)+8>>2]|0)+44>>2]|0;if(g|0){p=c[g>>2]|0;c[J>>2]=c[_>>2];c[J+4>>2]=c[_+4>>2];c[J+8>>2]=c[_+8>>2];c[J+12>>2]=c[_+12>>2];hb[p&31](L,J);c[_>>2]=c[L>>2];c[_+4>>2]=c[L+4>>2];c[_+8>>2]=c[L+8>>2];c[_+12>>2]=c[L+12>>2];p=0;break}m=+h[d>>3];n=m*1.4142135623730951;if(f>n&i<<24>>24==99){o=m/f;o=+C(+(1.0/(1.0-o*o)));o=+h[_>>3]*o;h[_>>3]=o}else{o=+h[_>>3]*1.4142135623730951;h[_>>3]=o;h[d>>3]=n;m=n}if((e|0)>2){z=+E(+(3.141592653589793/+(e|0)));h[_>>3]=o/z;h[d>>3]=m/z;p=0}else p=0}while(0);m=+h[d>>3];g=GA(b,c[42210]|0,122100)|0;if((a[g>>0]|0)==115?(yJ(g,90671)|0)==0:0){h[_>>3]=k;h[d>>3]=f;N=$+40|0;c[N>>2]=c[N>>2]|2048}else{if(!((JA(g)|0)<<24>>24)){z=+h[_>>3];k=k>z?k:z;h[_>>3]=k;z=+h[d>>3];f=f>z?f:z}else{M=c[(c[Z>>2]|0)+104>>2]|0;if(!(!(k<+h[M+24>>3])?!(f<+h[M+32>>3]):0)){L=En(b)|0;M=En(so(b)|0)|0;c[N>>2]=L;c[N+4>>2]=M;$l(0,90677,N)|0}h[_>>3]=k}h[d>>3]=f}if(!X){z=f;y=k}else{y=k>f?k:f;h[d>>3]=y;h[_>>3]=y;z=y}do if(!((JA(GA(b,c[42201]|0,122100)|0)|0)<<24>>24)){if(p){f=+h[(Q>+h[_>>3]?Y:_)>>3];break}f=+h[d>>3];if(P>3]*+C(+(1.0-P*P/(f*f)));f=Q>f?Q:f}else f=Q}else f=Q;while(0);g=c[(c[Z>>2]|0)+104>>2]|0;h[g+40>>3]=s-q+f;A=$+40|0;if(!(c[A>>2]&2048)){x=+h[d>>3]-m;h[g+48>>3]=(P1;g=j?W:1;a:do if((e|0)<3){g=ww(g<<5)|0;k=+h[_>>3]*.5;f=+h[d>>3]*.5;h[g>>3]=-k;h[g+8>>3]=-f;h[g+16>>3]=k;h[g+24>>3]=f;if(j){e=1;i=2;while(1){if((e|0)==(W|0))break;y=k+4.0;z=f+4.0;h[g+(i<<4)>>3]=-y;h[g+(i<<4)+8>>3]=-z;S=i|1;h[g+(S<<4)>>3]=y;h[g+(S<<4)+8>>3]=z;e=e+1|0;i=i+2|0;k=y;f=z}h[_>>3]=k*2.0;h[d>>3]=f*2.0;e=2}else e=2}else{g=ww(O(g<<4,e)|0)|0;i=c[(c[(c[(c[Z>>2]|0)+8>>2]|0)+8>>2]|0)+44>>2]|0;b:do if(!i){q=6.283185307179586/+(e|0);t=q*.5;r=+F(+t);s=+RJ(+B(+U)+ +B(+T),1.0);t=T*1.4142135623730951/+E(+t);u=U*.5;TJ((q+-3.141592653589793)*.5,R,S);v=V*.017453292519943295;k=0.0;f=0.0;m=0.0;i=0;n=+h[S>>3]*.5;o=+h[R>>3]*.5;while(1){if((i|0)>=(e|0))break b;m=m+q;TJ(m,R,S);n=+h[S>>3]*r+n;o=+h[R>>3]*r+o;x=(o*t+s)*n+u*o;TJ(+K(+o,+x)+v,R,S);x=+RJ(x,o);w=+h[S>>3]*x*+h[_>>3];x=+h[R>>3]*x*+h[d>>3];ba=+B(+w);f=ba>f?ba:f;ba=+B(+x);k=ba>k?ba:k;h[g+(i<<4)>>3]=w;h[g+(i<<4)+8>>3]=x;if(p)break;else i=i+1|0}ba=-w;h[g+16>>3]=ba;h[g+24>>3]=x;h[g+32>>3]=ba;ba=-x;h[g+40>>3]=ba;h[g+48>>3]=w;h[g+56>>3]=ba}else{hb[c[i+4>>2]&31](g,_);k=+h[d>>3]*.5;f=+h[_>>3]*.5}while(0);f=f*2.0;k=k*2.0;y=y>f?y:f;h[_>>3]=y;ba=z>k?z:k;h[d>>3]=ba;f=y/f;k=ba/k;i=0;while(1){if((i|0)>=(e|0))break;N=g+(i<<4)|0;b=g+(i<<4)+8|0;ba=+h[b>>3]*k;h[N>>3]=+h[N>>3]*f;h[b>>3]=ba;i=i+1|0}if(j){j=e+-1|0;k=+h[g>>3];m=+h[g+8>>3];f=+K(+(m-+h[g+(j<<4)+8>>3]),+(k-+h[g+(j<<4)>>3]));j=0;c:while(1){if((j|0)>=(e|0))break;p=j+1|0;i=(p|0)%(e|0)|0;n=+h[g+(i<<4)>>3];o=+h[g+(i<<4)+8>>3];q=+K(+(o-m),+(n-k));z=(f+3.141592653589793-q)*.5;ba=4.0/+F(+z);TJ(f-z,R,S);h[R>>3]=+h[R>>3]*ba;h[S>>3]=+h[S>>3]*ba;i=1;f=m;while(1){if((i|0)==(W|0)){f=q;j=p;k=n;m=o;continue c}z=+h[S>>3]+k;ba=+h[R>>3]+f;b=(O(i,e)|0)+j|0;h[g+(b<<4)>>3]=z;h[g+(b<<4)+8>>3]=ba;i=i+1|0;k=z;f=ba}}j=O(e,W+-1|0)|0;i=0;while(1){if((i|0)>=(e|0))break a;S=i+j|0;z=+h[g+(S<<4)+8>>3];y=+B(+(+h[g+(S<<4)>>3]))*2.0;ba=+h[_>>3];h[_>>3]=y>ba?y:ba;z=+B(+z)*2.0;ba=+h[d>>3];h[d>>3]=z>ba?z:ba;i=i+1|0}}}while(0);c[$>>2]=X;c[$+4>>2]=W;c[$+8>>2]=e;h[$+16>>3]=V;h[$+32>>3]=U;h[$+24>>3]=T;c[$+44>>2]=g;f=+h[_>>3];if(!(c[A>>2]&2048)){e=c[Z>>2]|0;h[e+32>>3]=f*.013888888888888888}else{e=c[Z>>2]|0;h[e+32>>3]=+h[(Q>f?Y:_)>>3]*.013888888888888888;d=(P>+h[d>>3]?Y:_)+8|0}h[e+40>>3]=+h[d>>3]*.013888888888888888;c[e+12>>2]=$;l=aa;return}function Ey(a){a=a|0;var b=0,d=0,e=0,f=0,g=0.0,i=0.0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+64|0;j=o+40|0;e=o+32|0;k=o+16|0;n=o;d=(c[(c[(so(a)|0)+16>>2]|0)+116>>2]|0)>>>2&1^1;m=a+16|0;f=c[c[(c[m>>2]|0)+104>>2]>>2]|0;c[42327]=f;f=sJ(f)|0;f=ww(((f|0)>1?f:1)+1|0)|0;b=Gy(a,d,1,f)|0;if(!b){c[e>>2]=c[c[(c[m>>2]|0)+104>>2]>>2];$l(1,90506,e)|0;c[42327]=90527;b=Gy(a,d,1,f)|0}$I(f);Hy(j,a,b);d=c[m>>2]|0;i=+h[d+32>>3]*72.0;i=+(~~(i+(i>=0.0?.5:-.5))|0);h[n>>3]=i;g=+h[d+40>>3]*72.0;g=+(~~(g+(g>=0.0?.5:-.5))|0);d=n+8|0;h[d>>3]=g;if(!((JA(GA(a,c[42210]|0,122100)|0)|0)<<24>>24)){i=+h[(+h[b>>3]>i?b:n)>>3];h[n>>3]=i;e=b+8|0;g=+h[(+h[e>>3]>g?b:n)+8>>3];h[d>>3]=g;d=e;e=b}else{d=b+8|0;e=b}a=(JA(GA(a,c[42201]|0,122100)|0)|0)&255;c[j>>2]=c[n>>2];c[j+4>>2]=c[n+4>>2];c[j+8>>2]=c[n+8>>2];c[j+12>>2]=c[n+12>>2];Iy(b,j,a);Jy(k,i*-.5,g*.5);c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];c[j+8>>2]=c[k+8>>2];c[j+12>>2]=c[k+12>>2];Ky(b,j,15);n=c[m>>2]|0;h[n+32>>3]=+h[e>>3]*.013888888888888888;h[n+40>>3]=(+h[d>>3]+1.0)*.013888888888888888;c[n+12>>2]=b;l=o;return}function Fy(a){a=a|0;var b=0.0,d=0,e=0.0,f=0.0,g=0,i=0,j=0,k=0,l=0.0,m=0;j=ww(48)|0;k=a+16|0;g=c[(c[(c[(c[k>>2]|0)+8>>2]|0)+8>>2]|0)+4>>2]|0;f=+FA(a,c[42191]|0,1797693134862315708145274.0e284,0.0);b=+FA(a,c[42190]|0,1797693134862315708145274.0e284,0.0);f=f0.0?(f>.0003?f:.0003):f;i=c[k>>2]|0;h[i+40>>3]=f;h[i+32>>3]=f;b=f*72.0;g=EA(a,c[42205]|0,g,0)|0;i=ww((g|0)<1?32:g<<5)|0;f=f*36.0;e=-f;h[i>>3]=e;h[i+8>>3]=e;h[i+16>>3]=f;h[i+24>>3]=f;if((g|0)>1){a=1;d=2;e=f;b=f;while(1){if((a|0)==(g|0))break;l=e+4.0;f=b+4.0;h[i+(d<<4)>>3]=-l;h[i+(d<<4)+8>>3]=-f;m=d|1;h[i+(m<<4)>>3]=l;h[i+(m<<4)+8>>3]=f;a=a+1|0;d=d+2|0;e=l;b=f}b=e*2.0}c[j>>2]=1;c[j+4>>2]=g;c[j+8>>2]=2;m=j+16|0;c[m>>2]=0;c[m+4>>2]=0;c[m+8>>2]=0;c[m+12>>2]=0;c[m+16>>2]=0;c[m+20>>2]=0;c[j+44>>2]=i;l=b*.013888888888888888;m=c[k>>2]|0;h[m+32>>3]=l;h[m+40>>3]=l;c[m+12>>2]=j;return}function Gy(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0;g=ww(72)|0;n=c[(c[b+16>>2]|0)+104>>2]|0;m=0;i=1;j=c[42327]|0;a:while(1){k=a[j>>0]|0;switch(k<<24>>24){case 0:break a;case 92:{j=j+1|0;k=a[j>>0]|0;switch(k<<24>>24){case 124:case 125:case 123:case 92:{l=m;break}default:E=4}break}default:E=4}if((E|0)==4){E=0;switch(k<<24>>24){case 123:{l=m+1|0;break}case 125:{l=m+-1|0;break}default:{l=m;i=i+((m|0)==0&k<<24>>24==124&1)|0}}if((l|0)<0)break}m=l;j=j+1|0}B=g+56|0;c[B>>2]=ww(i<<2)|0;a[g+64>>0]=d;y=(d|0)==0&1;z=n+82|0;A=f+1|0;v=(e|0)!=0;w=n+16|0;x=n+4|0;u=n+8|0;k=0;m=0;d=0;t=0;l=0;e=0;n=f;i=0;j=0;b:while(1){p=k;k=0;c:while(1){d:while(1){s=e;e:while(1){r=k;o=i;f:while(1){q=m;g:while(1){while(1){if(t){E=78;break b}m=c[42327]|0;i=a[m>>0]|0;if((i+-1&255)>=31)break;c[42327]=m+1}switch(i<<24>>24|0){case 92:{E=53;break d}case 0:case 124:case 125:break e;case 60:break f;case 62:break g;case 123:break;default:{k=d;i=m;break d}}i=m+1|0;c[42327]=i;if(l|0){E=34;break b}if(!(a[i>>0]|0)){E=34;break b}e=Gy(b,y,0,f)|0;c[(c[B>>2]|0)+(q<<2)>>2]=e;if(!e){E=36;break b}else{q=q+1|0;l=4}}if(a[z>>0]|0){k=d;i=m;break d}if(!(l&16)){E=27;break b}if(o>>>0>A>>>0?(C=o+-1|0,(C|0)!=(s|0)):0)i=(a[C>>0]|0)==32?C:o;else i=o;a[i>>0]=0;r=HL(f)|0;c[42327]=(c[42327]|0)+1;m=q;l=l&-17;o=i}if(l&6|0){E=22;break b}if(a[z>>0]|0){k=d;i=m;break d}c[42327]=m+1;m=q;l=l|18;k=r;s=f;i=f}if(!((l&16|0)==0&(v|i<<24>>24!=0))){E=38;break b}if(!(l&4)){k=ww(72)|0;c[(c[B>>2]|0)+(q<<2)>>2]=k;m=q+1|0}else{k=p;m=q}if(r|0)c[k+60>>2]=r;if(!(l&5)){a[f+j>>0]=32;l=l|1;j=j+1|0}i=f+j|0;if(l&1){if((j|0)>1?(D=i+-1|0,(D|0)!=(n|0)):0)i=(a[D>>0]|0)==32?D:i;a[i>>0]=0;n=HL(f)|0;c[k+52>>2]=mw(b,n,a[z>>0]|0?2:0,+h[w>>3],c[x>>2]|0,c[u>>2]|0)|0;a[k+64>>0]=1;n=f;j=0}i=c[42327]|0;switch(a[i>>0]|0){case 0:{t=1;e=s;i=o;continue b}case 125:{E=51;break b}default:{}}c[42327]=i+1;p=k;l=0;k=0;e=s;i=o}h:do if((E|0)==53){E=0;k=f+j|0;i=m+1|0;switch(a[i>>0]|0){case 0:{k=d;i=m;break h}case 62:case 60:case 124:case 125:case 123:{k=d;break}case 32:{if(!(a[z>>0]|0))k=1;else E=55;break}default:E=55}if((E|0)==55){E=0;a[k>>0]=92;k=d;l=l|9;j=j+1|0}c[42327]=i}while(0);d=f+j|0;if(l&4|0?(a[i>>0]|0)!=32:0){E=59;break b}if(!(l&24))l=(a[i>>0]|0)==32?l:l|9;if(!(l&8))if(!(l&16))e=s;else{m=a[i>>0]|0;d=(k|0)!=0;if(!(d|m<<24>>24!=32))if((o|0)!=(f|0))if((a[o+-1>>0]|0)==32)m=o;else E=73;else m=f;else E=73;if((E|0)==73){E=0;a[o>>0]=m;m=o+1|0;i=c[42327]|0}e=d?m+-1|0:s;o=m}else{m=a[i>>0]|0;e=(k|0)!=0;if(!((!(e|m<<24>>24!=32)?(a[d+-1>>0]|0)==32:0)?(a[z>>0]|0)==0:0)){a[d>>0]=m;j=j+1|0}if(e){e=s;n=f+j+-1|0}else e=s}i=i+1|0;c[42327]=i;while(1){if((a[i>>0]|0)>=0){m=q;d=k;k=r;i=o;continue c}s=i+1|0;c[42327]=s;a[f+j>>0]=a[i>>0]|0;j=j+1|0;i=s}}}if((E|0)==22){Ly(g,r);g=0}else if((E|0)==27){Ly(g,r);g=0}else if((E|0)==34){Ly(g,r);g=0}else if((E|0)==36){Ly(g,r);g=0}else if((E|0)==38){Ly(g,r);g=0}else if((E|0)==51){c[42327]=i+1;c[g+48>>2]=m}else if((E|0)==59){Ly(g,r);g=0}else if((E|0)==78)c[g+48>>2]=q;return g|0}function Hy(b,d,e){b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+64|0;k=u+48|0;m=u+40|0;n=u+32|0;t=u+16|0;s=u;j=c[e+52>>2]|0;a:do if(!j){n=t+8|0;o=e+48|0;p=e+56|0;q=e+64|0;r=s+8|0;c[t>>2]=0;c[t+4>>2]=0;c[t+8>>2]=0;c[t+12>>2]=0;j=0;while(1){if((j|0)>=(c[o>>2]|0))break a;Hy(s,d,c[(c[p>>2]|0)+(j<<2)>>2]|0);if(!(a[q>>0]|0)){h[n>>3]=+h[n>>3]+ +h[r>>3];k=t;m=+h[t>>3]>+h[s>>3]?t:s}else{h[t>>3]=+h[t>>3]+ +h[s>>3];k=n;m=(+h[n>>3]>+h[r>>3]?t:s)+8|0}h[k>>3]=+h[m>>3];j=j+1|0}}else{g=+h[j+24>>3];f=+h[j+32>>3];if(g>0.0|f>0.0){j=Jm(d,90530)|0;do if(j){c[k>>2]=m;c[k+4>>2]=n;j=dM(j,90537,k)|0;if((j|0)<=0){i=8.0;g=g+16.0;break}i=+h[m>>3]*72.0;i=+(~~(i+(i>=0.0?.5:-.5))<<1|0);g=g+i;if((j|0)!=1){i=+h[n>>3]*72.0;i=+(~~(i+(i>=0.0?.5:-.5))<<1|0)}}else{i=8.0;g=g+16.0}while(0);f=i+f}h[t>>3]=g;h[t+8>>3]=f}while(0);c[e>>2]=c[t>>2];c[e+4>>2]=c[t+4>>2];c[e+8>>2]=c[t+8>>2];c[e+12>>2]=c[t+12>>2];c[b>>2]=c[t>>2];c[b+4>>2]=c[t+4>>2];c[b+8>>2]=c[t+8>>2];c[b+12>>2]=c[t+12>>2];l=u;return}function Iy(b,d,e){b=b|0;d=d|0;e=e|0;var f=0.0,g=0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0;s=l;l=l+32|0;o=s+16|0;p=s;q=+h[d>>3];i=q-+h[b>>3];r=+h[d+8>>3];f=r-+h[b+8>>3];c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];d=c[b+52>>2]|0;if(!((e|0)!=0|(d|0)==0)){n=d+40|0;h[n>>3]=+h[n>>3]+i;n=d+48|0;h[n>>3]=+h[n>>3]+f}m=b+48|0;d=c[m>>2]|0;a:do if(d|0){n=b+64|0;f=((a[n>>0]|0)==0?f:i)/+(d|0);k=b+56|0;j=0;while(1){if((j|0)>=(d|0))break a;b=c[(c[k>>2]|0)+(j<<2)>>2]|0;g=j+1|0;d=~~(f*+(g|0))-~~(f*+(j|0))|0;if(!(a[n>>0]|0))Jy(p,q,+h[b+8>>3]+ +(d|0));else Jy(p,+h[b>>3]+ +(d|0),r);c[o>>2]=c[p>>2];c[o+4>>2]=c[p+4>>2];c[o+8>>2]=c[p+8>>2];c[o+12>>2]=c[p+12>>2];Iy(b,o,e);j=g;d=c[m>>2]|0}}while(0);l=s;return}function Jy(a,b,c){a=a|0;b=+b;c=+c;h[a>>3]=b;h[a+8>>3]=c;return}function Ky(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0;q=l;l=l+48|0;j=q+32|0;n=q+16|0;m=q;a[b+65>>0]=e;k=b+16|0;s=+h[d>>3];p=d+8|0;r=+h[p>>3];Jy(n,s,r-+h[b+8>>3]);c[k>>2]=c[n>>2];c[k+4>>2]=c[n+4>>2];c[k+8>>2]=c[n+8>>2];c[k+12>>2]=c[n+12>>2];k=b+32|0;Jy(m,+h[b>>3]+s,r);c[k>>2]=c[m>>2];c[k+4>>2]=c[m+4>>2];c[k+8>>2]=c[m+8>>2];c[k+12>>2]=c[m+12>>2];k=c[b+48>>2]|0;m=k+-1|0;n=(e|0)==0;o=b+56|0;i=b+64|0;g=0;while(1){if((g|0)>=(k|0))break;do if(!n){b=(g|0)==0;f=(g|0)==(m|0);if(!(a[i>>0]|0))if(b){b=f?15:14;break}else{b=f?11:10;break}else if(b){b=f?15:13;break}else{b=f?7:5;break}}else b=0;while(0);f=c[(c[o>>2]|0)+(g<<2)>>2]|0;c[j>>2]=c[d>>2];c[j+4>>2]=c[d+4>>2];c[j+8>>2]=c[d+8>>2];c[j+12>>2]=c[d+12>>2];Ky(f,j,b&e);if(!(a[i>>0]|0))h[p>>3]=+h[p>>3]-+h[(c[(c[o>>2]|0)+(g<<2)>>2]|0)+8>>3];else h[d>>3]=+h[c[(c[o>>2]|0)+(g<<2)>>2]>>3]+ +h[d>>3];g=g+1|0}l=q;return}function Ly(a,b){a=a|0;b=b|0;My(a);$I(b);return}function My(a){a=a|0;var b=0,d=0,e=0;d=a+48|0;e=a+56|0;b=0;while(1){if((b|0)>=(c[d>>2]|0))break;My(c[(c[e>>2]|0)+(b<<2)>>2]|0);b=b+1|0}$I(c[a+60>>2]|0);pw(c[a+52>>2]|0);$I(c[e>>2]|0);$I(a);return}function Ny(a){a=a|0;var b=0.0,d=0.0;d=+FA(a,c[42191]|0,0.0,.01);b=+FA(a,c[42190]|0,0.0,.02);b=(d>b?d:b)*72.0;return +(+(~~(b+(b>=0.0?.5:-.5))|0))}function Oy(a,b){a=+a;b=+b;var c=0;c=~~(a/b);return +(+((+(c|0)*b+1.0e-05>2]|0)+8>>2]|0;if(!a)a=0;else a=(c[c[a+4>>2]>>2]|0)==75&1;return a|0}function Qy(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;f=c[42328]|0;a:do if(!f)d=0;else{g=c[42329]|0;e=0;while(1){if((e|0)>=(g|0)){d=0;break a}d=c[f+(e<<2)>>2]|0;h=c[d>>2]|0;if((a[h>>0]|0)==(a[b>>0]|0)?(yJ(h,b)|0)==0:0)break a;e=e+1|0}}while(0);return d|0}function Ry(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;if(SA(Jm(d,90560)|0)|0)if((a[b>>0]|0)==101?(yJ(b,90725)|0)==0:0){d=101;g=6}else{b=90553;g=4}else g=4;if((g|0)==4){d=a[b>>0]|0;if(d<<24>>24==99)if(!(yJ(b,90553)|0))g=11;else{d=99;g=6}else g=6}a:do if((g|0)==6){e=19868;while(1){f=c[e>>2]|0;if(!f){g=11;break a}if((a[f>>0]|0)==d<<24>>24?(yJ(f,b)|0)==0:0){b=e;break a}e=e+16|0}}while(0);if((g|0)==11)b=Sy(b)|0;return b|0}function Sy(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;g=h;d=Qy(b)|0;if(!d){f=c[42329]|0;d=f+1|0;c[42329]=d;e=c[42328]|0;if(!e)d=xw(d<<2)|0;else d=zw(e,d<<2)|0;c[42328]=d;d=ww(16)|0;c[(c[42328]|0)+(f<<2)>>2]=d;c[d>>2]=c[4967];c[d+4>>2]=c[4968];c[d+8>>2]=c[4969];c[d+12>>2]=c[4970];e=HL(b)|0;c[d>>2]=e;do if(!0){if((a[b>>0]|0)==99?(yJ(b,90553)|0)==0:0){e=1;break}c[g>>2]=c[4967];c[g+4>>2]=e;$l(0,90730,g)|0;e=0}else e=1;while(0);a[d+12>>0]=e}l=h;return d|0}function Ty(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;d=+h[b>>3]*.5257311121191336;c=+h[b+8>>3]*.8944271909999159;c=d>c?d:c;h[a>>3]=c*4.97979656976556;h[a+8>>3]=c*4.73606797749979;return}function Uy(a,b){a=a|0;b=b|0;var c=0.0,d=0.0,e=0.0,f=0,g=0.0,i=0.0,j=0.0,k=0,l=0,m=0.0;d=+h[b>>3];k=b+8|0;e=+h[k>>3];c=e/d;if(!(c>.9510565162951536))if(c<.9510565162951536){j=d;e=d*.9510565162951536}else j=d;else j=e*1.0514622242382672;d=j*.5257311121191336;g=j*.20081141588622725;i=j*.05020285397155681;c=.3141592653589793;f=0;while(1){if((f|0)>=10)break;h[a+(f<<4)>>3]=+E(+c)*d;h[a+(f<<4)+8>>3]=+F(+c)*d-i;m=c+.6283185307179586;l=f|1;h[a+(l<<4)>>3]=+E(+m)*g;h[a+(l<<4)+8>>3]=+F(+m)*g-i;c=c+1.2566370614359172;f=f+2|0}h[b>>3]=j;h[k>>3]=e;return}function Vy(a){a=a|0;a=c[(c[a+16>>2]|0)+12>>2]|0;if(a|0){$I(c[a+44>>2]|0);$I(a)}return}function Wy(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+80|0;k=o+40|0;g=o;n=o+64|0;h=o+56|0;if(!(a[e>>0]|0)){g=4144;h=b+40|0;do{c[b>>2]=c[g>>2];b=b+4|0;g=g+4|0}while((b|0)<(h|0))}else{i=(f|0)==0?91400:f;c[n>>2]=15;j=d+16|0;f=c[j>>2]|0;do if(a[(c[f+104>>2]|0)+82>>0]|0){f=IF(d,e,n)|0;if(!f){f=c[j>>2]|0;m=8;break}if(iz(d,f,g,i,c[n>>2]|0,0)|0){c[k>>2]=En(d)|0;c[k+4>>2]=e;c[k+8>>2]=i;$l(0,91402,k)|0}}else m=8;while(0);if((m|0)==8){if((c[(c[f+8>>2]|0)+8>>2]|0)==1600)h=0;else{c[h>>2]=d;c[h+4>>2]=0}if(iz(d,0,g,e,c[n>>2]|0,h)|0)jz(d,e)}c[g+36>>2]=0;h=b+40|0;do{c[b>>2]=c[g>>2];b=b+4|0;g=g+4|0}while((b|0)<(h|0))}l=o;return}function Xy(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0,g=0,i=0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0;r=l;l=l+112|0;n=r+96|0;m=r+80|0;p=r+64|0;k=r+48|0;q=r+32|0;o=r;f=r+16|0;if(!a){c[42332]=0;a=0}else{g=c[a+4>>2]|0;a=c[a>>2]|0;i=(c[(c[(so(a)|0)+16>>2]|0)+116>>2]&3)*90|0;c[n>>2]=c[b>>2];c[n+4>>2]=c[b+4>>2];c[n+8>>2]=c[b+8>>2];c[n+12>>2]=c[b+12>>2];bw(f,n,i);c[q>>2]=c[f>>2];c[q+4>>2]=c[f+4>>2];c[q+8>>2]=c[f+8>>2];c[q+12>>2]=c[f+12>>2];a:do if(g){d=+h[g+8>>3];e=+h[g+24>>3];s=+h[q>>3];if((+h[g>>3]<=s?s<=+h[g+16>>3]:0)?(j=+h[q+8>>3],d<=j):0)a=j<=e&1;else a=0}else{if((a|0)==(c[42332]|0)){f=c[42333]|0;g=c[42335]|0;i=c[42334]|0}else{g=c[(c[a+16>>2]|0)+12>>2]|0;c[42336]=g;i=c[g+44>>2]|0;c[42334]=i;f=c[g+8>>2]|0;c[42333]=f;g=O((c[g+4>>2]|0)+-1|0,f)|0;g=(g|0)>0?g:0;c[42335]=g;c[42332]=a}a=0;b=0;while(1){if((a|0)>=(f|0)){a=1;break a}t=i+(g+a<<4)|0;c[o>>2]=c[t>>2];c[o+4>>2]=c[t+4>>2];c[o+8>>2]=c[t+8>>2];c[o+12>>2]=c[t+12>>2];t=i+(g+((a+4|0)%(f|0)|0)<<4)|0;c[k>>2]=c[q>>2];c[k+4>>2]=c[q+4>>2];c[k+8>>2]=c[q+8>>2];c[k+12>>2]=c[q+12>>2];c[p>>2]=c[41802];c[p+4>>2]=c[41803];c[p+8>>2]=c[41804];c[p+12>>2]=c[41805];c[m>>2]=c[o>>2];c[m+4>>2]=c[o+4>>2];c[m+8>>2]=c[o+8>>2];c[m+12>>2]=c[o+12>>2];c[n>>2]=c[t>>2];c[n+4>>2]=c[t+4>>2];c[n+8>>2]=c[t+8>>2];c[n+12>>2]=c[t+12>>2];b=b+((hz(k,p,m,n)|0)==0&1)|0;if((b|0)==2){a=0;break}else a=a+2|0}}while(0)}l=r;return a|0}function Yy(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;e=c[b+16>>2]|0;if((a[(c[e+104>>2]|0)+82>>0]|0)!=0?(a[e+145>>0]|0)!=0:0)b=LF(b,d,0,f,g)|0;else b=0;return b|0}function Zy(e,f){e=e|0;f=f|0;var i=0,j=0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,P=0,Q=0,R=0;P=l;l=l+48|0;H=P+24|0;G=P+16|0;A=P+8|0;z=P;L=P+32|0;n=P+28|0;M=c[e+16>>2]|0;N=M+208|0;i=c[N>>2]|0;if((i|0)==0?(b[M+260>>1]&1)==0:0)J=0;else E=4;if((E|0)==4)if(!(c[e+152>>2]&4)){xD(e,i,c[M+228>>2]|0,c[M+244>>2]|0,c[M+212>>2]|0);J=1}else J=1;I=f+16|0;i=c[I>>2]|0;r=c[i+12>>2]|0;F=c[r+44>>2]|0;K=c[r+8>>2]|0;r=c[r+4>>2]|0;if((c[42330]|0)<(K|0)){i=K+5|0;c[42330]=i;j=c[42331]|0;if(!j)i=xw(i<<4)|0;else i=zw(j,i<<4)|0;c[42331]=i;i=c[I>>2]|0}D=(c[i+104>>2]|0)+56|0;i=i+16|0;c[D>>2]=c[i>>2];c[D+4>>2]=c[i+4>>2];c[D+8>>2]=c[i+8>>2];c[D+12>>2]=c[i+12>>2];D=c[I>>2]|0;B=+h[D+32>>3]*72.0;B=(+h[D+96>>3]+ +h[D+88>>3])/+(~~(B+(B>=0.0?.5:-.5))|0);C=+h[D+40>>3]*72.0;C=+h[D+80>>3]/+(~~(C+(C>=0.0?.5:-.5))|0);D=_y(e,f)|0;c[L>>2]=0;i=d[(c[I>>2]|0)+117>>0]|0;do if(!(i&1)){if(i&2|0){s=HA(f,0,91300)|0;CD(e,s);ED(e,HA(f,0,91308)|0);j=0;i=1;break}if(i&8|0){s=HA(f,0,91316)|0;CD(e,s);ED(e,HA(f,0,91324)|0);j=0;i=1;break}if(i&4|0){s=HA(f,0,91332)|0;CD(e,s);ED(e,HA(f,0,91340)|0);j=0;i=1;break}if(!(D&1))if(!(D&576)){j=0;i=0}else{j=$y(f)|0;i=1}else{j=$y(f)|0;if(!((yv(j,L,n)|0)<<24>>24)){ED(e,j);i=1}else{ED(e,c[L>>2]|0);i=c[L+4>>2]|0;m=EA(f,c[42218]|0,0,0)|0;k=+g[n>>2];if(!i)FD(e,122106,m,k);else FD(e,i,m,k);i=(D&2)>>>1|2}}s=az(e,f)|0}else{s=HA(f,0,91284)|0;CD(e,s);ED(e,HA(f,0,91292)|0);j=0;i=1}while(0);m=c[(c[I>>2]|0)+8>>2]|0;if(a[m+12>>0]|0){m=c[m>>2]|0;if((a[m>>0]|0)==99){m=(yJ(m,90553)|0)==0;E=33}else u=1}else{m=1;E=33}if((E|0)==33){m=m^1;if((r|0)!=0|i<<24>>24==0|m)u=m;else{CD(e,122171);r=1;u=0}}v=(K|0)<3;w=(D&512|0)!=0;y=(D&8|0)==0;x=(D&64|0)==0;p=(D&1024|0)==0;q=(D&2130706444|0)==0;t=0;while(1){if((t|0)>=(r|0))break;n=O(t,K)|0;o=c[42331]|0;m=0;while(1){if((m|0)>=(K|0))break;R=m+n|0;k=+h[F+(R<<4)+8>>3];Q=c[I>>2]|0;h[o+(m<<4)>>3]=+h[Q+16>>3]+ +h[F+(R<<4)>>3]*B;h[o+(m<<4)+8>>3]=+h[Q+24>>3]+k*C;m=m+1|0}do if(v){if(w&(t|0)==0?(XJ(j,58)|0)!=0:0)if(($t(e,o,j)|0)>1){c[z>>2]=En(f)|0;$l(3,91348,z)|0;i=0}else i=0;HD(e,c[42331]|0,K,i&255);if(!y)bz(e,f)}else{if(!x){if((t|0)==0?(du(e,o,j,1)|0)>1:0){c[A>>2]=En(f)|0;$l(3,91348,A)|0}ID(e,c[42331]|0,K,0);break}if(!p){CD(e,122171);ID(e,c[42331]|0,K,i&255);CD(e,s);LD(e,(c[42331]|0)+32|0,2);break}i=i&255;if(q){ID(e,o,K,i);break}else{zy(e,o,K,D,i);break}}while(0);t=t+1|0;i=0}m=c[(c[I>>2]|0)+8>>2]|0;if(!(a[m+12>>0]|0)){m=Jm(f,93847)|0;if(m|0?a[m>>0]|0:0){o=m;E=65}}else{m=c[m>>2]|0;if((a[m>>0]|0)==99?(yJ(m,90553)|0)==0:0){m=Jm(f,90560)|0;if(m|0?a[m>>0]|0:0){o=m;E=65}}else{o=m;E=65}}if((E|0)==65){n=c[42331]|0;m=0;while(1){if((m|0)>=(K|0))break;k=+h[F+(m<<4)+8>>3];R=c[I>>2]|0;h[n+(m<<4)>>3]=+h[R+16>>3]+ +h[F+(m<<4)>>3]*B;h[n+(m<<4)+8>>3]=+h[R+24>>3]+k*C;m=m+1|0}m=i&255;do if(!(u|i<<24>>24==0)){if(v){if(w&(t|0)==0?(XJ(j,58)|0)!=0:0)if(($t(e,n,j)|0)>1){c[G>>2]=En(f)|0;$l(3,91348,G)|0;i=0}else i=0;HD(e,c[42331]|0,K,i&255);if(y)break;bz(e,f);break}if(x)if(!(D&12)){ID(e,n,K,m);break}else{zy(e,n,K,D,m);break}else{if((du(e,n,j,1)|0)>1){c[H>>2]=En(f)|0;$l(3,91348,H)|0}ID(e,c[42331]|0,K,0);break}}while(0);R=c[42331]|0;ND(e,o,R,K,i,GA(f,c[42211]|0,122100)|0)}$I(c[L>>2]|0);qw(e,10,c[(c[I>>2]|0)+104>>2]|0);if(J){if(c[e+152>>2]&4|0)xD(e,c[N>>2]|0,c[M+228>>2]|0,c[M+244>>2]|0,c[M+212>>2]|0);yD(e)}l=P;return}function _y(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;h=l;l=l+16|0;f=h;e=ez(d,f)|0;if(e|0)GD(b,e);e=c[42217]|0;if((e|0?(g=Km(d,e)|0,g|0):0)?a[g>>0]|0:0)PD(b,+FA(d,c[42217]|0,1.0,0.0));l=h;return c[f>>2]|0}function $y(a){a=a|0;return dz(a,119592)|0}function az(b,d){b=b|0;d=d|0;d=HA(d,c[42193]|0,174185)|0;d=a[d>>0]|0?d:122106;CD(b,d);return d|0}function bz(a,b){a=a|0;b=b|0;var d=0,e=0,f=0.0,g=0,i=0.0,j=0,k=0,m=0;d=l;l=l+96|0;j=d+80|0;k=d+64|0;e=d+32|0;m=d+16|0;g=d;b=c[b+16>>2]|0;f=+h[b+80>>3];h[m+8>>3]=f*.375;i=+h[b+96>>3];h[m>>3]=i*.6614;b=b+16|0;c[k>>2]=c[m>>2];c[k+4>>2]=c[m+4>>2];c[k+8>>2]=c[m+8>>2];c[k+12>>2]=c[m+12>>2];c[j>>2]=c[b>>2];c[j+4>>2]=c[b+4>>2];c[j+8>>2]=c[b+8>>2];c[j+12>>2]=c[b+12>>2];cz(g,k,j);c[e>>2]=c[g>>2];c[e+4>>2]=c[g+4>>2];c[e+8>>2]=c[g+8>>2];c[e+12>>2]=c[g+12>>2];g=e+8|0;b=e+24|0;h[b>>3]=+h[g>>3];h[e+16>>3]=+h[e>>3]-i*1.3228;LD(a,e,2);f=+h[g>>3]-f*.75;h[g>>3]=f;h[b>>3]=f;LD(a,e,2);l=d;return}function cz(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=+h[c+8>>3]+ +h[b+8>>3];h[a>>3]=+h[c>>3]+ +h[b>>3];h[a+8>>3]=d;return}function dz(b,d){b=b|0;d=d|0;var e=0;e=HA(b,c[42194]|0,174185)|0;if(!(a[e>>0]|0)){e=HA(b,c[42193]|0,174185)|0;return ((a[e>>0]|0)==0?d:e)|0}else return e|0;return 0}function ez(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;e=HA(b,c[42202]|0,174185)|0;a:do if(!(a[e>>0]|0)){g=0;e=0}else{g=Eu(e)|0;h=g;e=0;b:while(1){f=c[h>>2]|0;if(!f)break a;switch(a[f>>0]|0){case 102:{if(!(yJ(f,95923)|0)){h=h+4|0;e=e|1;continue b}break}case 114:{if(!(yJ(f,91360)|0)){f=h;do{j=f;f=f+4|0;i=c[f>>2]|0;c[j>>2]=i}while((i|0)!=0);j=h;e=e|4;h=j;continue b}if(!(yJ(f,91378)|0)){f=h;do{i=f;f=f+4|0;j=c[f>>2]|0;c[i>>2]=j}while((j|0)!=0);j=h;e=e|3;h=j;continue b}break}case 100:{if(!(yJ(f,91368)|0)){f=h;do{i=f;f=f+4|0;j=c[f>>2]|0;c[i>>2]=j}while((j|0)!=0);j=h;e=e|8;h=j;continue b}break}case 105:{if(!(yJ(f,119127)|0)){h=h+4|0;e=e|32;continue b}break}case 115:{if((yJ(f,91385)|0)==0?fz(b)|0:0){f=h;do{i=f;f=f+4|0;j=c[f>>2]|0;c[i>>2]=j}while((j|0)!=0);j=h;e=e|64;h=j;continue b}break}case 119:{if((yJ(f,91393)|0)==0?gz(b)|0:0){f=h;do{i=f;f=f+4|0;j=c[f>>2]|0;c[i>>2]=j}while((j|0)!=0);j=h;e=e|512;h=j;continue b}break}default:{}}h=h+4|0}}while(0);f=c[(c[(c[b+16>>2]|0)+8>>2]|0)+8>>2]|0;if(f)e=c[f+40>>2]|e;c[d>>2]=e;return g|0}function fz(a){a=a|0;var b=0.0;a=c[(c[(c[a+16>>2]|0)+8>>2]|0)+8>>2]|0;if((((a|0)!=0?(c[a+8>>2]|0)==4:0)?(b=+h[a+16>>3],((~~(b+(b>=0.0?.5:-.5))|0)%90|0|0)==0):0)?+h[a+24>>3]==0.0:0)a=+h[a+32>>3]==0.0&1;else a=0;return a|0}function gz(a){a=a|0;a=c[(c[(c[a+16>>2]|0)+8>>2]|0)+8>>2]|0;if(!a)a=0;else a=(c[a+8>>2]|0)<3&1;return a|0}function hz(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0.0,f=0.0,g=0.0,i=0.0;i=+h[c+8>>3];g=-(+h[d+8>>3]-i);f=+h[c>>3];e=+h[d>>3]-f;f=e*i+f*g;return (+h[a+8>>3]*e+ +h[a>>3]*g-f>=0.0^+h[b>>3]*g-f+ +h[b+8>>3]*e>=0.0^1)&1|0}function iz(b,d,e,f,g,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0.0,k=0.0,m=0,n=0,o=0,p=0,q=0.0,r=0.0,s=0.0,t=0.0,u=0.0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;G=l;l=l+192|0;B=G+176|0;E=G+160|0;m=G+144|0;z=G+128|0;A=G+112|0;n=G+96|0;o=G+80|0;p=G+64|0;v=G+48|0;w=G+32|0;x=G+16|0;D=G;if(!d){c[E>>2]=0;c[E+4>>2]=0;c[E+8>>2]=0;c[E+12>>2]=0;m=(c[(c[(so(b)|0)+16>>2]|0)+116>>2]&1|0)==0;C=c[b+16>>2]|0;q=+h[C+80>>3]*.5;j=+h[C+88>>3];t=m?q:j;q=m?j:q;m=0;C=E;j=0.0;k=-q;r=t;F=E+8|0;s=0.0;t=-t}else{k=+h[d>>3];t=+h[d+8>>3];q=+h[d+16>>3];r=+h[d+24>>3];Jy(m,(q+k)*.5,(r+t)*.5);c[E>>2]=c[m>>2];c[E+4>>2]=c[m+4>>2];c[E+8>>2]=c[m+8>>2];c[E+12>>2]=c[m+12>>2];H=E+8|0;m=1;C=E;j=+h[E>>3];F=H;s=+h[H>>3]}u=(q>r?q:r)*4.0;a:do if((f|0)!=0?(y=a[f>>0]|0,y<<24>>24!=0):0){f=f+1|0;switch(y<<24>>24|0){case 99:{p=1;g=0;f=0;n=0;j=0.0;o=0;break a}case 101:{if(a[f>>0]|0){p=1;g=0;f=0;n=0;j=0.0;o=1;break a}if(!i)h[C>>3]=q;else{kz(z,i,s,u);c[E>>2]=c[z>>2];c[E+4>>2]=c[z+4>>2];c[E+8>>2]=c[z+8>>2];c[E+12>>2]=c[z+12>>2]}p=0;g=g&2;f=0;n=1;j=0.0;o=0;m=1;break a}case 115:{h[F>>3]=t;switch(a[f>>0]|0){case 0:{if(!i)h[C>>3]=j;else{kz(A,i,-u,j);c[E>>2]=c[A>>2];c[E+4>>2]=c[A+4>>2];c[E+8>>2]=c[A+8>>2];c[E+12>>2]=c[A+12>>2]}p=0;g=g&1;f=0;n=1;j=-1.5707963267948966;o=0;m=1;break a}case 101:{if(!i)h[C>>3]=q;else{kz(n,i,-u,u);c[E>>2]=c[n>>2];c[E+4>>2]=c[n+4>>2];c[E+8>>2]=c[n+8>>2];c[E+12>>2]=c[n+12>>2]}p=0;g=g&3;f=0;n=1;j=-.7853981633974483;o=0;m=1;break a}case 119:{if(!i)h[C>>3]=k;else{u=-u;kz(o,i,u,u);c[E>>2]=c[o>>2];c[E+4>>2]=c[o+4>>2];c[E+8>>2]=c[o+8>>2];c[E+12>>2]=c[o+12>>2]}p=0;g=g&9;f=0;n=1;j=-2.356194490192345;o=0;m=1;break a}default:{h[F>>3]=s;p=1;g=0;f=0;n=0;j=0.0;o=1;break a}}}case 119:{if(a[f>>0]|0){p=1;g=0;f=0;n=0;j=0.0;o=1;break a}if(!i)h[C>>3]=k;else{kz(p,i,s,-u);c[E>>2]=c[p>>2];c[E+4>>2]=c[p+4>>2];c[E+8>>2]=c[p+8>>2];c[E+12>>2]=c[p+12>>2]}p=0;g=g&8;f=0;n=1;j=3.141592653589793;o=0;m=1;break a}case 110:{h[F>>3]=r;switch(a[f>>0]|0){case 0:{if(!i)h[C>>3]=j;else{kz(v,i,u,j);c[E>>2]=c[v>>2];c[E+4>>2]=c[v+4>>2];c[E+8>>2]=c[v+8>>2];c[E+12>>2]=c[v+12>>2]}p=0;g=g&4;f=0;n=1;j=1.5707963267948966;o=0;m=1;break a}case 101:{if(!i)h[C>>3]=q;else{kz(w,i,u,u);c[E>>2]=c[w>>2];c[E+4>>2]=c[w+4>>2];c[E+8>>2]=c[w+8>>2];c[E+12>>2]=c[w+12>>2]}p=0;g=g&6;f=0;n=1;j=.7853981633974483;o=0;m=1;break a}case 119:{if(!i)h[C>>3]=k;else{kz(x,i,u,-u);c[E>>2]=c[x>>2];c[E+4>>2]=c[x+4>>2];c[E+8>>2]=c[x+8>>2];c[E+12>>2]=c[x+12>>2]}p=0;g=g&12;f=0;n=1;j=2.356194490192345;o=0;m=1;break a}default:{h[F>>3]=s;p=1;g=0;f=0;n=0;j=0.0;o=1;break a}}}case 95:{p=1;f=1;n=0;j=0.0;o=0;break a}default:{p=1;g=0;f=0;n=0;j=0.0;o=1;break a}}}else{p=1;g=0;f=0;n=0;j=0.0;o=0}while(0);H=(c[(c[(so(b)|0)+16>>2]|0)+116>>2]&3)*90|0;c[B>>2]=c[E>>2];c[B+4>>2]=c[E+4>>2];c[B+8>>2]=c[E+8>>2];c[B+12>>2]=c[E+12>>2];aw(D,B,H);c[E>>2]=c[D>>2];c[E+4>>2]=c[D+4>>2];c[E+8>>2]=c[D+8>>2];c[E+12>>2]=c[D+12>>2];if(!(f<<24>>24))g=lz(g,c[(c[(so(b)|0)+16>>2]|0)+116>>2]&3)|0;a[e+33>>0]=g;c[e+24>>2]=d;k=+h[C>>3];h[e>>3]=+(~~(k+(k>=0.0?.5:-.5))|0);k=+h[F>>3];h[e+8>>3]=+(~~(k+(k>=0.0?.5:-.5))|0);h[e+16>>3]=+mz(j,c[(c[(so(b)|0)+16>>2]|0)+116>>2]&3);k=+h[C>>3];j=+h[F>>3];if(k==0.0&j==0.0)g=-128;else{u=+K(+j,+k);t=u+4.71238898038469;g=~~((!(t>=6.283185307179586)?t:u+-1.5707963267948966)*40.74366543152521)&255}a[e+32>>0]=g;a[e+29>>0]=n;a[e+28>>0]=m;a[e+30>>0]=p;a[e+31>>0]=f;l=G;return o|0}function jz(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=En(a)|0;c[e+4>>2]=b;$l(0,91463,e)|0;l=d;return}function kz(a,b,d,e){a=a|0;b=b|0;d=+d;e=+e;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;p=l;l=l+128|0;g=p+112|0;j=p+48|0;k=p+16|0;m=p+32|0;n=p;o=c[b>>2]|0;i=c[(c[(so(o)|0)+16>>2]|0)+116>>2]&3;h[k>>3]=e;h[k+8>>3]=d;f=(i|0)!=0;if(f){c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[g+8>>2]=c[k+8>>2];c[g+12>>2]=c[k+12>>2];aw(m,g,i*90|0);c[k>>2]=c[m>>2];c[k+4>>2]=c[m+4>>2];c[k+8>>2]=c[m+8>>2];c[k+12>>2]=c[m+12>>2]}m=j+48|0;q=j+32|0;c[j>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;c[j+16>>2]=0;c[j+20>>2]=0;c[j+24>>2]=0;c[j+28>>2]=0;c[q>>2]=c[k>>2];c[q+4>>2]=c[k+4>>2];c[q+8>>2]=c[k+8>>2];c[q+12>>2]=c[k+12>>2];c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];c[m+8>>2]=c[k+8>>2];c[m+12>>2]=c[k+12>>2];Gz(b,c[(c[(c[(c[o+16>>2]|0)+8>>2]|0)+4>>2]|0)+12>>2]|0,j,1);if(f){c[g>>2]=c[j>>2];c[g+4>>2]=c[j+4>>2];c[g+8>>2]=c[j+8>>2];c[g+12>>2]=c[j+12>>2];bw(n,g,i*90|0);c[j>>2]=c[n>>2];c[j+4>>2]=c[n+4>>2];c[j+8>>2]=c[n+8>>2];c[j+12>>2]=c[n+12>>2]};c[a>>2]=c[j>>2];c[a+4>>2]=c[j+4>>2];c[a+8>>2]=c[j+8>>2];c[a+12>>2]=c[j+12>>2];l=p;return}function lz(a,b){a=a|0;b=b|0;a:do switch(b|0){case 3:switch(a|0){case 4:{a=2;break a}case 1:{a=8;break a}case 8:{a=1;break a}case 2:{a=4;break a}default:break a}case 2:switch(a|0){case 4:{a=1;break a}case 1:{a=4;break a}default:break a}case 1:switch(a|0){case 4:{a=2;break a}case 1:{a=8;break a}case 8:{a=4;break a}case 2:{a=1;break a}default:break a}default:{}}while(0);return a|0}function mz(a,b){a=+a;b=b|0;switch(b|0){case 3:{if(!(a==3.141592653589793))if(!(a==2.356194490192345))if(!(a==1.5707963267948966))if(!(a==0.0))if(!(a==-.7853981633974483)){if(a==-1.5707963267948966)a=3.141592653589793}else a=2.356194490192345;else a=1.5707963267948966;else a=0.0;else a=-.7853981633974483;else a=-1.5707963267948966;break}case 2:{a=-a;break}case 1:{a=a+-1.5707963267948966;break}default:{}}return +a}function nz(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0.0,g=0.0,i=0,j=0,k=0;e=l;l=l+32|0;k=e+16|0;i=e;a=c[a>>2]|0;j=(c[(c[(so(a)|0)+16>>2]|0)+116>>2]&3)*90|0;c[k>>2]=c[b>>2];c[k+4>>2]=c[b+4>>2];c[k+8>>2]=c[b+8>>2];c[k+12>>2]=c[b+12>>2];bw(i,k,j);d=+h[i>>3];g=+h[i+8>>3];a=c[a+16>>2]|0;f=+h[a+80>>3]*.5;if(!(!(g>=-f)|!(g<=f))?d>=-+h[a+88>>3]:0)a=d<=+h[a+96>>3]&1;else a=0;l=e;return a|0}function oz(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0.0;n=l;l=l+32|0;m=n;i=c[a+16>>2]|0;j=i+208|0;g=c[j>>2]|0;if(!g)k=(b[i+260>>1]&1)!=0;else k=1;e=d+16|0;d=c[e>>2]|0;f=c[d+12>>2]|0;if(f|0){if(k?(c[a+152>>2]&4|0)==0:0){xD(a,g,c[i+228>>2]|0,c[i+244>>2]|0,c[i+212>>2]|0);d=c[e>>2]|0}g=c[a+36>>2]|0;p=+h[d+24>>3]+ +(c[f+8>>2]|0);o=c[f>>2]|0;h[m>>3]=+h[d+16>>3]+ +(c[f+4>>2]|0);h[m+8>>3]=p;c[m+16>>2]=o;AL(g,91494,m)|0;g=c[e>>2]|0;m=(c[g+104>>2]|0)+56|0;g=g+16|0;c[m>>2]=c[g>>2];c[m+4>>2]=c[g+4>>2];c[m+8>>2]=c[g+8>>2];c[m+12>>2]=c[g+12>>2];qw(a,10,c[(c[e>>2]|0)+104>>2]|0);if(k){if(c[a+152>>2]&4|0)xD(a,c[j>>2]|0,c[i+228>>2]|0,c[i+244>>2]|0,c[i+212>>2]|0);yD(a)}}l=n;return}function pz(a){a=a|0;My(c[(c[a+16>>2]|0)+12>>2]|0);return}function qz(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,m=0;m=l;l=l+64|0;k=m+40|0;h=m;if(!(a[f>>0]|0)){h=4144;g=b+40|0;do{c[b>>2]=c[h>>2];b=b+4|0;h=h+4|0}while((b|0)<(g|0))}else{g=(g|0)==0?91400:g;i=c[(c[e+16>>2]|0)+12>>2]|0;j=wz(i,f)|0;if(!j){if(iz(e,i+16|0,h,f,15,0)|0)jz(e,f)}else if(iz(e,j+16|0,h,g,d[j+65>>0]|0,0)|0){c[k>>2]=En(e)|0;c[k+4>>2]=f;c[k+8>>2]=g;$l(0,91402,k)|0}g=b+40|0;do{c[b>>2]=c[h>>2];b=b+4|0;h=h+4|0}while((b|0)<(g|0))}l=m;return}function rz(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0,g=0,i=0,j=0.0,k=0,m=0,n=0.0;k=l;l=l+32|0;m=k+16|0;i=k;f=c[a+4>>2]|0;a=c[a>>2]|0;g=(c[(c[(so(a)|0)+16>>2]|0)+116>>2]&3)*90|0;c[m>>2]=c[b>>2];c[m+4>>2]=c[b+4>>2];c[m+8>>2]=c[b+8>>2];c[m+12>>2]=c[b+12>>2];bw(i,m,g);c[b>>2]=c[i>>2];c[b+4>>2]=c[i+4>>2];c[b+8>>2]=c[i+8>>2];c[b+12>>2]=c[i+12>>2];if(!f){f=c[(c[a+16>>2]|0)+12>>2]|0;g=f+16|0;a=f+24|0;i=f+32|0;f=f+40|0}else{g=f;a=f+8|0;i=f+16|0;f=f+24|0}e=+h[a>>3];d=+h[f>>3];n=+h[b>>3];if((+h[g>>3]<=n?n<=+h[i>>3]:0)?(j=+h[b+8>>3],e<=j):0)a=j<=d&1;else a=0;l=k;return a|0}function sz(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0,t=0,u=0,v=0.0;u=l;l=l+80|0;r=u+64|0;q=u+32|0;t=u;a:do if(!(a[d+28>>0]|0))e=0;else{i=+h[d>>3];p=b+16|0;m=c[(c[p>>2]|0)+12>>2]|0;k=m+48|0;m=m+56|0;d=0;while(1){if((d|0)>=(c[k>>2]|0))break a;n=(c[(c[(so(b)|0)+16>>2]|0)+116>>2]&1|0)==0;o=c[(c[m>>2]|0)+(d<<2)>>2]|0;j=+(~~+h[(n?o+16|0:o+24|0)>>3]|0);if(i>=j?(s=+(~~+h[(n?o+32|0:o+40|0)>>3]|0),i<=s):0)break;d=d+1|0}if(!(c[(c[(so(b)|0)+16>>2]|0)+116>>2]&1)){t=c[p>>2]|0;v=+h[t+16>>3];h[f>>3]=v+j;j=+h[t+24>>3];i=+h[t+80>>3];h[f+8>>3]=j-i*.5;h[f+16>>3]=v+s}else{o=(c[(c[m>>2]|0)+(d<<2)>>2]|0)+16|0;b=(c[p>>2]|0)+16|0;c[q>>2]=c[o>>2];c[q+4>>2]=c[o+4>>2];c[q+8>>2]=c[o+8>>2];c[q+12>>2]=c[o+12>>2];c[q+16>>2]=c[o+16>>2];c[q+20>>2]=c[o+20>>2];c[q+24>>2]=c[o+24>>2];c[q+28>>2]=c[o+28>>2];c[r>>2]=c[b>>2];c[r+4>>2]=c[b+4>>2];c[r+8>>2]=c[b+8>>2];c[r+12>>2]=c[b+12>>2];cw(t,q,r);c[f>>2]=c[t>>2];c[f+4>>2]=c[t+4>>2];c[f+8>>2]=c[t+8>>2];c[f+12>>2]=c[t+12>>2];c[f+16>>2]=c[t+16>>2];c[f+20>>2]=c[t+20>>2];c[f+24>>2]=c[t+24>>2];c[f+28>>2]=c[t+28>>2];t=c[p>>2]|0;i=+h[t+80>>3];j=+h[t+24>>3]}h[f+24>>3]=i*.5+j;c[g>>2]=1}while(0);l=u;return e|0}function tz(d,e){d=d|0;e=e|0;var f=0,i=0,j=0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0.0;w=l;l=l+144|0;n=w+96|0;p=w+64|0;r=w;s=w+128|0;t=c[d+16>>2]|0;u=t+208|0;f=c[u>>2]|0;if(!f)v=(b[t+260>>1]&1)!=0;else v=1;m=e+16|0;q=c[m>>2]|0;o=c[q+12>>2]|0;j=o+16|0;c[p>>2]=c[j>>2];c[p+4>>2]=c[j+4>>2];c[p+8>>2]=c[j+8>>2];c[p+12>>2]=c[j+12>>2];c[p+16>>2]=c[j+16>>2];c[p+20>>2]=c[j+20>>2];c[p+24>>2]=c[j+24>>2];c[p+28>>2]=c[j+28>>2];x=+h[q+16>>3];h[p>>3]=+h[p>>3]+x;k=+h[q+24>>3];q=p+8|0;h[q>>3]=+h[q>>3]+k;q=p+16|0;h[q>>3]=+h[q>>3]+x;j=p+24|0;h[j>>3]=+h[j>>3]+k;if(v?(c[d+152>>2]&4|0)==0:0)xD(d,f,c[t+228>>2]|0,c[t+244>>2]|0,c[t+212>>2]|0);f=_y(d,e)|0;az(d,e)|0;c[s>>2]=0;if(!(f&1))i=0;else{i=$y(e)|0;if(!((yv(i,s,n)|0)<<24>>24)){ED(d,i);i=1}else{ED(d,c[s>>2]|0);i=c[s+4>>2]|0;j=EA(e,c[42218]|0,0,0)|0;k=+g[n>>2];if(!i)FD(d,122106,j,k);else FD(d,i,j,k);i=f>>>1&1|2}}j=c[c[(c[m>>2]|0)+8>>2]>>2]|0;if((a[j>>0]|0)==77){m=(yJ(j,91271)|0)==0;f=m?f|4:f}if(!(f&2130706444)){c[n>>2]=c[p>>2];c[n+4>>2]=c[p+4>>2];c[n+8>>2]=c[p+8>>2];c[n+12>>2]=c[p+12>>2];c[n+16>>2]=c[p+16>>2];c[n+20>>2]=c[p+20>>2];c[n+24>>2]=c[p+24>>2];c[n+28>>2]=c[p+28>>2];JD(d,n,i)}else{c[r>>2]=c[p>>2];c[r+4>>2]=c[p+4>>2];c[r+8>>2]=c[p+8>>2];c[r+12>>2]=c[p+12>>2];p=r+32|0;c[p>>2]=c[q>>2];c[p+4>>2]=c[q+4>>2];c[p+8>>2]=c[q+8>>2];c[p+12>>2]=c[q+12>>2];h[r+16>>3]=+h[p>>3];h[r+24>>3]=+h[r+8>>3];h[r+48>>3]=+h[r>>3];h[r+56>>3]=+h[r+40>>3];zy(d,r,4,f,i)}uz(d,e,o);$I(c[s>>2]|0);if(v){if(c[d+152>>2]&4|0)xD(d,c[u>>2]|0,c[t+228>>2]|0,c[t+244>>2]|0,c[t+212>>2]|0);yD(d)}l=w;return}function uz(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+144|0;p=u+128|0;o=u+112|0;q=u+16|0;r=u;g=u+96|0;i=u+80|0;s=u+64|0;t=u+48|0;j=e+52|0;f=c[j>>2]|0;if(!f)f=d+16|0;else{n=f+56|0;m=e+16|0;f=e+32|0;c[o>>2]=c[m>>2];c[o+4>>2]=c[m+4>>2];c[o+8>>2]=c[m+8>>2];c[o+12>>2]=c[m+12>>2];c[p>>2]=c[f>>2];c[p+4>>2]=c[f+4>>2];c[p+8>>2]=c[f+8>>2];c[p+12>>2]=c[f+12>>2];vz(g,o,p);f=d+16|0;m=(c[f>>2]|0)+16|0;c[o>>2]=c[g>>2];c[o+4>>2]=c[g+4>>2];c[o+8>>2]=c[g+8>>2];c[o+12>>2]=c[g+12>>2];c[p>>2]=c[m>>2];c[p+4>>2]=c[m+4>>2];c[p+8>>2]=c[m+8>>2];c[p+12>>2]=c[m+12>>2];cz(i,o,p);c[n>>2]=c[i>>2];c[n+4>>2]=c[i+4>>2];c[n+8>>2]=c[i+8>>2];c[n+12>>2]=c[i+12>>2];qw(b,10,c[j>>2]|0);az(b,d)|0}k=(c[f>>2]|0)+16|0;c[r>>2]=c[k>>2];c[r+4>>2]=c[k+4>>2];c[r+8>>2]=c[k+8>>2];c[r+12>>2]=c[k+12>>2];k=e+48|0;m=e+64|0;n=q+16|0;j=e+56|0;e=q+16|0;i=0;while(1){if((i|0)>=(c[k>>2]|0))break;if((i|0)>0){f=(c[j>>2]|0)+(i<<2)|0;g=c[f>>2]|0;if(!(a[m>>0]|0)){g=g+32|0;c[n>>2]=c[g>>2];c[n+4>>2]=c[g+4>>2];c[n+8>>2]=c[g+8>>2];c[n+12>>2]=c[g+12>>2];h[q>>3]=+h[(c[f>>2]|0)+16>>3];f=n;g=0}else{g=g+16|0;c[q>>2]=c[g>>2];c[q+4>>2]=c[g+4>>2];c[q+8>>2]=c[g+8>>2];c[q+12>>2]=c[g+12>>2];h[e>>3]=+h[q>>3];f=(c[f>>2]|0)+32|0;g=1}h[q+(g<<4)+8>>3]=+h[f+8>>3];c[o>>2]=c[q>>2];c[o+4>>2]=c[q+4>>2];c[o+8>>2]=c[q+8>>2];c[o+12>>2]=c[q+12>>2];c[p>>2]=c[r>>2];c[p+4>>2]=c[r+4>>2];c[p+8>>2]=c[r+8>>2];c[p+12>>2]=c[r+12>>2];cz(s,o,p);c[q>>2]=c[s>>2];c[q+4>>2]=c[s+4>>2];c[q+8>>2]=c[s+8>>2];c[q+12>>2]=c[s+12>>2];c[o>>2]=c[n>>2];c[o+4>>2]=c[n+4>>2];c[o+8>>2]=c[n+8>>2];c[o+12>>2]=c[n+12>>2];c[p>>2]=c[r>>2];c[p+4>>2]=c[r+4>>2];c[p+8>>2]=c[r+8>>2];c[p+12>>2]=c[r+12>>2];cz(t,o,p);c[n>>2]=c[t>>2];c[n+4>>2]=c[t+4>>2];c[n+8>>2]=c[t+8>>2];c[n+12>>2]=c[t+12>>2];LD(b,q,2)}uz(b,d,c[(c[j>>2]|0)+(i<<2)>>2]|0);i=i+1|0}l=u;return}function vz(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=(+h[c+8>>3]+ +h[b+8>>3])*.5;h[a>>3]=(+h[c>>3]+ +h[b>>3])*.5;h[a+8>>3]=d;return}function wz(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;e=c[b+60>>2]|0;if(!(((e|0)!=0?(a[e>>0]|0)==(a[d>>0]|0):0)?(yJ(e,d)|0)==0:0))f=4;a:do if((f|0)==4){g=b+56|0;f=c[b+48>>2]|0;e=0;while(1){if((e|0)>=(f|0)){b=0;break a}b=wz(c[(c[g>>2]|0)+(e<<2)>>2]|0,d)|0;if(!b)e=e+1|0;else break}}while(0);return b|0}function xz(a,b){a=a|0;b=b|0;var d=0;d=b+8|0;h[d>>3]=+h[d>>3]*1.375;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];return}function yz(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0.0,g=0.0,i=0.0,j=0.0,k=0.0,l=0.0,m=0.0;k=+h[b>>3];f=k*.5;m=+h[b+8>>3];i=m*.5;h[a>>3]=f;e=m*.40909090909090906;h[a+8>>3]=e;h[a+16>>3]=f;g=m*.4592530909090909;h[a+24>>3]=g;j=k*.275892;h[a+32>>3]=j;h[a+40>>3]=i;h[a+48>>3]=0.0;h[a+56>>3]=i;k=k*-.275892;h[a+64>>3]=k;h[a+72>>3]=i;l=-f;h[a+80>>3]=l;h[a+88>>3]=g;d=a+96|0;h[d>>3]=l;h[a+104>>3]=e;b=a+112|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];b=a+128|0;h[b>>3]=l;h[a+136>>3]=m*-.40909090909090906;d=a+144|0;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];h[a+160>>3]=l;g=-g;h[a+168>>3]=g;h[a+176>>3]=k;i=-i;h[a+184>>3]=i;h[a+192>>3]=0.0;h[a+200>>3]=i;h[a+208>>3]=j;h[a+216>>3]=i;h[a+224>>3]=f;h[a+232>>3]=g;d=a+240|0;h[d>>3]=f;h[a+248>>3]=-e;b=a+256|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];b=a+288|0;d=a+272|0;c[d>>2]=c[a>>2];c[d+4>>2]=c[a+4>>2];c[d+8>>2]=c[a+8>>2];c[d+12>>2]=c[a+12>>2];c[b>>2]=c[a>>2];c[b+4>>2]=c[a+4>>2];c[b+8>>2]=c[a+8>>2];c[b+12>>2]=c[a+12>>2];return}function zz(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0.0,g=0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;x=l;l=l+144|0;u=x+112|0;t=x+96|0;v=x+80|0;s=x+64|0;w=x+32|0;q=x+16|0;r=x;g=x+48|0;do if(a){j=c[a+4>>2]|0;k=c[a>>2]|0;o=(c[(c[(so(k)|0)+16>>2]|0)+116>>2]&3)*90|0;c[u>>2]=c[b>>2];c[u+4>>2]=c[b+4>>2];c[u+8>>2]=c[b+8>>2];c[u+12>>2]=c[b+12>>2];bw(g,u,o);c[w>>2]=c[g>>2];c[w+4>>2]=c[g+4>>2];c[w+8>>2]=c[g+8>>2];c[w+12>>2]=c[g+12>>2];if(j|0){d=+h[w>>3];if(!(+h[j>>3]<=d)){a=0;break}if(!(d<=+h[j+16>>3])){a=0;break}d=+h[w+8>>3];if(!(+h[j+8>>3]<=d)){a=0;break}a=d<=+h[j+24>>3];break}if((k|0)==(c[42337]|0)){d=+h[20903];e=+h[20904];i=+h[20905]}else{a=k+16|0;b=c[(c[a>>2]|0)+12>>2]|0;c[42338]=b;c[42339]=c[b+44>>2];c[42340]=c[b+8>>2];if(!(c[b+40>>2]&2048)){n=(c[(c[(so(k)|0)+16>>2]|0)+116>>2]&1|0)==0;o=c[a>>2]|0;h[(n?167248:167256)>>3]=+h[o+96>>3]+ +h[o+88>>3];h[(n?167256:167248)>>3]=+h[o+80>>3];i=+h[o+32>>3]*72.0;f=+h[o+40>>3]*72.0;f=+(~~(f+(f>=0.0?.5:-.5))|0);i=+(~~(i+(i>=0.0?.5:-.5))|0)}else{bB(u,b);i=+h[u+16>>3]-+h[u>>3];f=+h[u+24>>3]-+h[u+8>>3];o=(c[(c[(so(k)|0)+16>>2]|0)+116>>2]&1|0)==0;h[(o?167248:167256)>>3]=i;h[(o?167256:167248)>>3]=f}d=+h[20906];if(d==0.0){h[20906]=1.0;d=1.0}e=+h[20907];if(e==0.0){h[20907]=1.0;e=1.0}d=i/d;h[20903]=d;e=f/e;h[20904]=e;i=i*.5;h[20905]=i;h[20908]=f*.5;o=O((c[(c[42338]|0)+4>>2]|0)+-1|0,c[42340]|0)|0;c[42341]=(o|0)>0?o:0;c[42337]=k}f=+h[w>>3]*d;h[w>>3]=f;o=w+8|0;d=+h[o>>3]*e;h[o>>3]=d;if(!(+B(+f)>i)?(e=+B(+d),p=+h[20908],!(e>p)):0){o=c[42340]|0;if((o|0)<3){a=+RJ(f/i,d/p)<1.0;break}b=(c[42342]|0)%(o|0)|0;a=(b+1|0)%(o|0)|0;k=c[42339]|0;m=c[42341]|0;n=k+(m+b<<4)|0;c[q>>2]=c[n>>2];c[q+4>>2]=c[n+4>>2];c[q+8>>2]=c[n+8>>2];c[q+12>>2]=c[n+12>>2];n=k+(m+a<<4)|0;c[r>>2]=c[n>>2];c[r+4>>2]=c[n+4>>2];c[r+8>>2]=c[n+8>>2];c[r+12>>2]=c[n+12>>2];c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];c[v>>2]=c[41818];c[v+4>>2]=c[41819];c[v+8>>2]=c[41820];c[v+12>>2]=c[41821];c[t>>2]=c[q>>2];c[t+4>>2]=c[q+4>>2];c[t+8>>2]=c[q+8>>2];c[t+12>>2]=c[q+12>>2];c[u>>2]=c[n>>2];c[u+4>>2]=c[n+4>>2];c[u+8>>2]=c[n+8>>2];c[u+12>>2]=c[n+12>>2];if(hz(s,v,t,u)|0){c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];c[v>>2]=c[q>>2];c[v+4>>2]=c[q+4>>2];c[v+8>>2]=c[q+8>>2];c[v+12>>2]=c[q+12>>2];c[t>>2]=c[r>>2];c[t+4>>2]=c[r+4>>2];c[t+8>>2]=c[r+8>>2];c[t+12>>2]=c[r+12>>2];c[u>>2]=c[41818];c[u+4>>2]=c[41819];c[u+8>>2]=c[41820];c[u+12>>2]=c[41821];n=(hz(s,v,t,u)|0)!=0;if(n?(c[s>>2]=c[w>>2],c[s+4>>2]=c[w+4>>2],c[s+8>>2]=c[w+8>>2],c[s+12>>2]=c[w+12>>2],c[v>>2]=c[r>>2],c[v+4>>2]=c[r+4>>2],c[v+8>>2]=c[r+8>>2],c[v+12>>2]=c[r+12>>2],c[t>>2]=c[41818],c[t+4>>2]=c[41819],c[t+8>>2]=c[41820],c[t+12>>2]=c[41821],c[u>>2]=c[q>>2],c[u+4>>2]=c[q+4>>2],c[u+8>>2]=c[q+8>>2],c[u+12>>2]=c[q+12>>2],(hz(s,v,t,u)|0)!=0):0){a=1;break}else{j=b;b=1}while(1){if((b|0)>=(o|0)){b=31;break}if(n){g=a;a=(a+1|0)%(o|0)|0}else{g=(j+-1+o|0)%(o|0)|0;a=j}q=k+(m+g<<4)|0;r=k+(m+a<<4)|0;c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];c[v>>2]=c[41818];c[v+4>>2]=c[41819];c[v+8>>2]=c[41820];c[v+12>>2]=c[41821];c[t>>2]=c[q>>2];c[t+4>>2]=c[q+4>>2];c[t+8>>2]=c[q+8>>2];c[t+12>>2]=c[q+12>>2];c[u>>2]=c[r>>2];c[u+4>>2]=c[r+4>>2];c[u+8>>2]=c[r+8>>2];c[u+12>>2]=c[r+12>>2];if(!(hz(s,v,t,u)|0)){b=30;break}else{j=g;b=b+1|0}}if((b|0)==30){c[42342]=g;a=0;break}else if((b|0)==31){c[42342]=j;a=1;break}}else a=0}else a=0}else{c[42337]=0;a=0}while(0);l=x;return a&1|0}function Az(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0,g=0.0,i=0,j=0,k=0;j=l;l=l+32|0;f=j+16|0;i=j;if(a){a=c[a>>2]|0;k=(c[(c[(so(a)|0)+16>>2]|0)+116>>2]&3)*90|0;c[f>>2]=c[b>>2];c[f+4>>2]=c[b+4>>2];c[f+8>>2]=c[b+8>>2];c[f+12>>2]=c[b+12>>2];bw(i,f,k);g=+h[i>>3];e=+h[i+8>>3];if((a|0)==(c[42345]|0))d=+h[20911];else{i=c[(c[a+16>>2]|0)+12>>2]|0;k=(c[i+4>>2]<<1)+-2|0;d=+h[(c[i+44>>2]|0)+((((k|0)>0?k:0)|1)<<4)>>3];h[20911]=d;c[42345]=a}if(+B(+g)>d|+B(+e)>d)a=0;else a=+RJ(g,e)<=d&1}else{c[42345]=0;a=0}l=j;return a|0}function Bz(e,f){e=e|0;f=f|0;var g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0.0,v=0,w=0;t=l;l=l+16|0;j=t;r=c[e+16>>2]|0;s=r+208|0;g=c[s>>2]|0;if((g|0)==0?(b[r+260>>1]&1)==0:0)q=0;else if(!(c[e+152>>2]&4)){xD(e,g,c[r+228>>2]|0,c[r+244>>2]|0,c[r+212>>2]|0);q=1}else q=1;n=f+16|0;k=c[(c[n>>2]|0)+12>>2]|0;o=c[k+44>>2]|0;p=c[k+8>>2]|0;k=c[k+4>>2]|0;if((c[42343]|0)<(p|0)){g=p+2|0;c[42343]=g;i=c[42344]|0;if(!i)g=xw(g<<4)|0;else g=zw(i,g<<4)|0;c[42344]=g}ez(f,j)|0;if(!(c[j>>2]&32))GD(e,21040);else GD(e,21036);g=c[42217]|0;if(g|0)PD(e,+FA(f,g,1.0,0.0));g=d[(c[n>>2]|0)+117>>0]|0;do if(!(g&1)){if(g&2|0){CD(e,HA(f,0,91300)|0);g=HA(f,0,91308)|0;ED(e,g);break}if(g&8|0){CD(e,HA(f,0,91316)|0);g=HA(f,0,91324)|0;ED(e,g);break}if(!(g&4)){g=dz(f,122106)|0;ED(e,g);az(e,f)|0;break}else{CD(e,HA(f,0,91332)|0);g=HA(f,0,91340)|0;ED(e,g);break}}else{CD(e,HA(f,0,91284)|0);g=HA(f,0,91292)|0;ED(e,g)}while(0);if(!k)if(!(a[g>>0]|0))i=1;else{CD(e,g);i=1}else i=k;j=1;f=0;while(1){if((f|0)>=(i|0))break;k=O(f,p)|0;m=c[42344]|0;g=0;while(1){if((g|0)>=(p|0))break;w=g+k|0;u=+h[o+(w<<4)+8>>3];v=c[n>>2]|0;h[m+(g<<4)>>3]=+h[v+16>>3]+ +h[o+(w<<4)>>3];h[m+(g<<4)+8>>3]=+h[v+24>>3]+u;g=g+1|0}HD(e,m,p,j);j=0;f=f+1|0}if(q){if(c[e+152>>2]&4|0)xD(e,c[s>>2]|0,c[r+228>>2]|0,c[r+244>>2]|0,c[r+212>>2]|0);yD(e)}l=t;return}function Cz(a,b,e,f){a=a|0;b=b|0;e=e|0;f=f|0;var g=0,h=0;g=l;l=l+48|0;h=g;e=Dz(b,e,f)|0;c[h+36>>2]=c[f+36>>2];iz(b,c[f+24>>2]|0,h,e,d[f+33>>0]|0,0)|0;b=h;e=a+40|0;do{c[a>>2]=c[b>>2];a=a+4|0;b=b+4|0}while((a|0)<(e|0));l=g;return}function Dz(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0.0,j=0.0,k=0,m=0.0,n=0.0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0.0,C=0;z=l;l=l+32|0;y=z;g=z+24|0;k=z+16|0;x=c[(c[(c[(so(b)|0)+60>>2]|0)+16>>2]|0)+116>>2]&3;f=b+16|0;w=(c[f>>2]|0)+16|0;c[y>>2]=c[w>>2];c[y+4>>2]=c[w+4>>2];c[y+8>>2]=c[w+8>>2];c[y+12>>2]=c[w+12>>2];Ez(g,y,x);w=(c[d+16>>2]|0)+16|0;c[y>>2]=c[w>>2];c[y+4>>2]=c[w+4>>2];c[y+8>>2]=c[w+8>>2];c[y+12>>2]=c[w+12>>2];Ez(k,y,x);x=a[e+33>>0]|0;y=x&255;a:do switch(x<<24>>24){case 0:case 15:{d=0;break}default:{d=c[e+24>>2]|0;if(!d){x=(c[(c[(so(b)|0)+16>>2]|0)+116>>2]&1|0)==0;w=c[f>>2]|0;B=+h[w+80>>3]*.5;A=-B;m=+h[w+88>>3];j=-m;n=x?j:A;i=x?m:B;m=x?B:m;j=x?A:j}else{n=+h[d>>3];i=+h[d+16>>3];m=+h[d+24>>3];j=+h[d+8>>3]}x=c[g>>2]|0;v=c[g+4>>2]|0;w=c[k>>2]|0;s=c[k+4>>2]|0;t=~~j;u=~~((i+n)*.5);r=~~i;q=~~((m+j)*.5);p=~~m;o=~~n;g=0;k=0;d=0;e=0;b=0;while(1){if((k|0)==4)break a;if(1<>2]|0;else f=g}else f=g;g=f;k=k+1|0}}}while(0);l=z;return d|0}function Ez(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0.0;switch(d|0){case 0:{f=+h[b>>3];e=+h[b+8>>3];break}case 2:{f=+h[b>>3];e=-+h[b+8>>3];break}case 1:{f=-+h[b+8>>3];e=+h[b>>3];break}case 3:{f=+h[b+8>>3];e=+h[b>>3];break}default:{f=0.0;e=0.0}}c[a>>2]=~~(f+(f>=0.0?.5:-.5));c[a+4>>2]=~~(e+(e>=0.0?.5:-.5));return}function Fz(){var a=0,b=0,d=0;a=l;l=l+32|0;b=a+16|0;d=a;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];zz(0,b)|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];Az(0,b)|0;c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];Xy(0,b)|0;l=a;return}function Gz(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0.0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;z=l;l=l+192|0;s=z+176|0;x=z+112|0;y=z+48|0;t=z+32|0;u=z+24|0;v=z+16|0;w=z;if(!(e<<24>>24)){k=d+48|0;c[t>>2]=c[k>>2];c[t+4>>2]=c[k+4>>2];c[t+8>>2]=c[k+8>>2];c[t+12>>2]=c[k+12>>2];k=u;m=v;n=x;o=0}else{c[t>>2]=c[d>>2];c[t+4>>2]=c[d+4>>2];c[t+8>>2]=c[d+8>>2];c[t+12>>2]=c[d+12>>2];k=v;m=u;n=0;o=x}h[u>>3]=0.0;h[v>>3]=1.0;q=t+8|0;f=0.0;g=1.0;j=0;p=+h[t>>3];while(1){r=+h[q>>3];f=(f+g)*.5;QA(w,d,3,f,n,o);c[t>>2]=c[w>>2];c[t+4>>2]=c[w+4>>2];c[t+8>>2]=c[w+8>>2];c[t+12>>2]=c[w+12>>2];c[s>>2]=c[w>>2];c[s+4>>2]=c[w+4>>2];c[s+8>>2]=c[w+8>>2];c[s+12>>2]=c[w+12>>2];a:do if(!((ab[b&63](a,s)|0)<<24>>24)){e=0;while(1){if((e|0)==4){e=k;j=1;break a}j=y+(e<<4)|0;A=x+(e<<4)|0;c[j>>2]=c[A>>2];c[j+4>>2]=c[A+4>>2];c[j+8>>2]=c[A+8>>2];c[j+12>>2]=c[A+12>>2];e=e+1|0}}else e=m;while(0);h[e>>3]=f;i=+h[t>>3];p=p-i;if(!((p>=0.0?p:-p)>.5)?(r=r-+h[q>>3],!((r>=0.0?r:-r)>.5)):0)break;f=+h[u>>3];g=+h[v>>3];p=i}b:do if(!(j<<24>>24)){e=0;while(1){if((e|0)==4)break b;A=d+(e<<4)|0;y=x+(e<<4)|0;c[A>>2]=c[y>>2];c[A+4>>2]=c[y+4>>2];c[A+8>>2]=c[y+8>>2];c[A+12>>2]=c[y+12>>2];e=e+1|0}}else{e=0;while(1){if((e|0)==4)break b;A=d+(e<<4)|0;x=y+(e<<4)|0;c[A>>2]=c[x>>2];c[A+4>>2]=c[x+4>>2];c[A+8>>2]=c[x+8>>2];c[A+12>>2]=c[x+12>>2];e=e+1|0}}while(0);l=z;return}function Hz(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0.0;m=l;l=l+48|0;d=m+16|0;e=m;f=m+32|0;g=a+16|0;i=c[g>>2]|0;j=c[i+8>>2]|0;if(j|0?(k=j+4|0,c[(c[k>>2]|0)+12>>2]|0):0){c[f>>2]=a;c[f+4>>2]=0;n=+h[i+96>>3];h[e>>3]=+h[b>>3]-+h[i+16>>3];h[e+8>>3]=+h[b+8>>3]-+h[i+24>>3];k=c[(c[k>>2]|0)+12>>2]|0;c[d>>2]=c[e>>2];c[d+4>>2]=c[e+4>>2];c[d+8>>2]=c[e+8>>2];c[d+12>>2]=c[e+12>>2];k=ab[k&63](f,d)|0;h[(c[g>>2]|0)+96>>3]=n;Iz(f,a,b,k)}l=m;return}function Iz(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,i=0,j=0,k=0.0,m=0,n=0;n=l;l=l+64|0;m=n;j=b+16|0;g=c[j>>2]|0;k=+h[g+96>>3];i=g+16|0;f=g+24|0;b=0;while(1){if((b|0)==4)break;h[m+(b<<4)>>3]=+h[d+(b<<4)>>3]-+h[i>>3];h[m+(b<<4)+8>>3]=+h[d+(b<<4)+8>>3]-+h[f>>3];b=b+1|0}Gz(a,c[(c[(c[g+8>>2]|0)+4>>2]|0)+12>>2]|0,m,e);b=0;while(1){if((b|0)==4)break;e=c[j>>2]|0;h[d+(b<<4)>>3]=+h[e+16>>3]+ +h[m+(b<<4)>>3];h[d+(b<<4)+8>>3]=+h[e+24>>3]+ +h[m+(b<<4)+8>>3];b=b+1|0}h[(c[j>>2]|0)+96>>3]=k;l=n;return}function Jz(b,d){b=b|0;d=d|0;var e=0,f=0;while(1){f=b+16|0;b=c[f>>2]|0;if(!(a[b+112>>0]|0))break;b=c[b+116>>2]|0}b=c[b+8>>2]|0;if(!b){b=ww(40)|0;c[(c[f>>2]|0)+8>>2]=b}e=c[b>>2]|0;if(!e)b=xw(((c[b+4>>2]|0)*48|0)+48|0)|0;else b=zw(e,((c[b+4>>2]|0)*48|0)+48|0)|0;f=c[(c[f>>2]|0)+8>>2]|0;c[f>>2]=b;f=f+4|0;e=c[f>>2]|0;c[f>>2]=e+1;f=b+(e*48|0)|0;c[f>>2]=ww(d<<4)|0;c[b+(e*48|0)+4>>2]=d;b=b+(e*48|0)+8|0;e=b+40|0;do{c[b>>2]=0;b=b+4|0}while((b|0)<(e|0));return f|0}function Kz(b,e,f,g,i){b=b|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0.0,F=0.0;D=l;l=l+96|0;A=D+16|0;u=D;x=D+92|0;y=D+88|0;v=D+80|0;m=c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0;z=so(m)|0;B=Jz(b,g)|0;n=b;while(1){o=c[n+16>>2]|0;if(!(a[o+112>>0]|0))break;n=c[o+116>>2]|0}if((a[i+8>>0]|0)==0?(j=c[m+16>>2]|0,k=c[e+16>>2]|0,(c[j+232>>2]|0)==(c[k+232>>2]|0)):0){p=(c[j+236>>2]|0)>(c[k+236>>2]|0);w=p?m:e;m=p?e:m}else w=e;if((m|0)==(c[((c[n>>2]&3|0)==3?n:n+48|0)+40>>2]|0)){j=o+80|0;k=o+40|0;p=d[o+86>>0]|0;e=d[o+46>>0]|0}else{j=o+40|0;k=o+80|0;p=d[o+46>>0]|0;e=d[o+86>>0]|0}o=c[j>>2]|0;j=c[k>>2]|0;if(((e|0)!=0?(r=m+16|0,q=c[(c[r>>2]|0)+8>>2]|0,(q|0)!=0):0)?(c[(c[q+4>>2]|0)+12>>2]|0)!=0:0){c[v>>2]=m;c[v+4>>2]=j;j=g+-4|0;e=u+8|0;k=0;while(1){if((k|0)>=(j|0))break;n=k+3|0;q=c[r>>2]|0;h[u>>3]=+h[f+(n<<4)>>3]-+h[q+16>>3];h[e>>3]=+h[f+(n<<4)+8>>3]-+h[q+24>>3];q=c[(c[(c[q+8>>2]|0)+4>>2]|0)+12>>2]|0;c[A>>2]=c[u>>2];c[A+4>>2]=c[u+4>>2];c[A+8>>2]=c[u+8>>2];c[A+12>>2]=c[u+12>>2];if(!((ab[q&63](v,A)|0)<<24>>24))break;else k=n}c[x>>2]=k;Iz(v,m,f+(k<<4)|0,1)}else{c[x>>2]=0;k=0}if(((p|0)!=0?(t=w+16|0,s=c[(c[t>>2]|0)+8>>2]|0,(s|0)!=0):0)?(c[(c[s+4>>2]|0)+12>>2]|0)!=0:0){c[v>>2]=w;c[v+4>>2]=o;m=g+-4|0;e=u+8|0;j=m;while(1){if((j|0)<=0)break;g=c[t>>2]|0;h[u>>3]=+h[f+(j<<4)>>3]-+h[g+16>>3];h[e>>3]=+h[f+(j<<4)+8>>3]-+h[g+24>>3];g=c[(c[(c[g+8>>2]|0)+4>>2]|0)+12>>2]|0;c[A>>2]=c[u>>2];c[A+4>>2]=c[u+4>>2];c[A+8>>2]=c[u+8>>2];c[A+12>>2]=c[u+12>>2];if(!((ab[g&63](v,A)|0)<<24>>24))break;j=j+-3|0}c[y>>2]=j;Iz(v,w,f+(j<<4)|0,0)}else{m=g+-4|0;c[y>>2]=m;j=m}while(1){if((k|0)>=(m|0))break;e=k+3|0;E=+h[f+(k<<4)>>3]-+h[f+(e<<4)>>3];F=+h[f+(k<<4)+8>>3]-+h[f+(e<<4)+8>>3];if(F*F+E*E<1.0e-06)k=e;else break}c[x>>2]=k;while(1){if((j|0)<=0)break;v=j+3|0;F=+h[f+(j<<4)>>3]-+h[f+(v<<4)>>3];E=+h[f+(j<<4)+8>>3]-+h[f+(v<<4)+8>>3];if(!(E*E+F*F<1.0e-06))break;j=j+-3|0}c[y>>2]=j;Lz(b,w,f,x,y,B,i);r=c[x>>2]|0;n=c[y>>2]|0;m=n+4|0;n=n+3|0;o=A+16|0;p=A+32|0;q=A+48|0;k=z+16|0;j=r;while(1){if((j|0)>=(m|0))break;z=(c[B>>2]|0)+(j-r<<4)|0;e=f+(j<<4)|0;c[z>>2]=c[e>>2];c[z+4>>2]=c[e+4>>2];c[z+8>>2]=c[e+8>>2];c[z+12>>2]=c[e+12>>2];c[A>>2]=c[e>>2];c[A+4>>2]=c[e+4>>2];c[A+8>>2]=c[e+8>>2];c[A+12>>2]=c[e+12>>2];e=j+1|0;if((j|0)>=(n|0)){C=38;break}y=(c[B>>2]|0)+(e-r<<4)|0;z=f+(e<<4)|0;c[y>>2]=c[z>>2];c[y+4>>2]=c[z+4>>2];c[y+8>>2]=c[z+8>>2];c[y+12>>2]=c[z+12>>2];c[o>>2]=c[z>>2];c[o+4>>2]=c[z+4>>2];c[o+8>>2]=c[z+8>>2];c[o+12>>2]=c[z+12>>2];z=j+2|0;y=(c[B>>2]|0)+(z-r<<4)|0;z=f+(z<<4)|0;c[y>>2]=c[z>>2];c[y+4>>2]=c[z+4>>2];c[y+8>>2]=c[z+8>>2];c[y+12>>2]=c[z+12>>2];c[p>>2]=c[z>>2];c[p+4>>2]=c[z+4>>2];c[p+8>>2]=c[z+8>>2];c[p+12>>2]=c[z+12>>2];z=j+3|0;y=f+(z<<4)|0;c[q>>2]=c[y>>2];c[q+4>>2]=c[y+4>>2];c[q+8>>2]=c[y+8>>2];c[q+12>>2]=c[y+12>>2];fu((c[k>>2]|0)+16|0,A);j=z}c[B+4>>2]=m-r;l=D;return}function Lz(b,d,e,f,g,h,i){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0;p=l;l=l+16|0;m=p+4|0;n=p;o=b;while(1){j=c[(c[o+16>>2]|0)+116>>2]|0;if(!j)break;else o=j}if(!(a[i+8>>0]|0))j=($a[c[i>>2]&31](o)|0)&255;else j=0;Bt(o,m,n);k=i+4|0;if(($a[c[k>>2]&31](d)|0)<<24>>24)c[n>>2]=0;if(($a[c[k>>2]&31](c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0)<<24>>24)c[m>>2]=0;if(j|0){d=c[m>>2]|0;c[m>>2]=c[n>>2];c[n>>2]=d}if(!(a[i+9>>0]|0)){j=c[m>>2]|0;if(j|0)c[f>>2]=Qt(o,e,c[f>>2]|0,c[g>>2]|0,h,j)|0;j=c[n>>2]|0;if(j|0)c[g>>2]=Ot(o,e,c[f>>2]|0,c[g>>2]|0,h,j)|0}else{k=c[n>>2]|0;j=c[m>>2]|0;if(j|k|0)Rt(o,e,c[f>>2]|0,c[g>>2]|0,h,j,k)}l=p;return}function Mz(a,b){a=a|0;b=b|0;var d=0,e=0;if(+h[b>>3]<+h[b+16>>3]?+h[b+8>>3]<+h[b+24>>3]:0){d=c[a+84>>2]|0;e=a+80|0;a=c[e>>2]|0;c[e>>2]=a+1;a=d+(a<<5)|0;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];c[a+16>>2]=c[b+16>>2];c[a+20>>2]=c[b+20>>2];c[a+24>>2]=c[b+24>>2];c[a+28>>2]=c[b+28>>2]}return}function Nz(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0;x=l;l=l+112|0;u=x+72|0;o=x+56|0;n=x+16|0;q=x;j=c[d>>2]&3;p=d+48|0;w=c[((j|0)==3?d:p)+40>>2]|0;t=d+16|0;r=c[t>>2]|0;i=r+16|0;if(a[r+47>>0]|0){Cz(n,w,c[((j|0)==2?d:d+-48|0)+40>>2]|0,i);j=n;n=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(n|0))}r=w+16|0;j=c[r>>2]|0;i=c[j+8>>2]|0;if(!i)n=0;else n=c[(c[i+4>>2]|0)+16>>2]|0;i=j+16|0;j=(c[t>>2]|0)+16|0;c[o>>2]=c[i>>2];c[o+4>>2]=c[i+4>>2];c[o+8>>2]=c[i+8>>2];c[o+12>>2]=c[i+12>>2];c[u>>2]=c[j>>2];c[u+4>>2]=c[j+4>>2];c[u+8>>2]=c[j+8>>2];c[u+12>>2]=c[j+12>>2];Oz(q,o,u);c[b>>2]=c[q>>2];c[b+4>>2]=c[q+4>>2];c[b+8>>2]=c[q+8>>2];c[b+12>>2]=c[q+12>>2];if(!(g<<24>>24)){i=c[t>>2]|0;if(!(a[i+45>>0]|0))i=0;else{k=+h[i+32>>3];v=9}}else{k=+Pz(c[((c[d>>2]&3|0)==3?d:p)+40>>2]|0);v=9}if((v|0)==9){h[b+16>>3]=k;i=1}a[b+29>>0]=i;c[b+80>>2]=0;c[b+88>>2]=d;q=f+32|0;c[q>>2]=c[b>>2];c[q+4>>2]=c[b+4>>2];c[q+8>>2]=c[b+8>>2];c[q+12>>2]=c[b+12>>2];switch(e|0){case 1:{j=c[r>>2]|0;if((a[j+156>>0]|0)==0?(q=a[(c[t>>2]|0)+49>>0]|0,s=q&255,q<<24>>24!=0):0){c[u>>2]=c[f>>2];c[u+4>>2]=c[f+4>>2];c[u+8>>2]=c[f+8>>2];c[u+12>>2]=c[f+12>>2];c[u+16>>2]=c[f+16>>2];c[u+20>>2]=c[f+20>>2];c[u+24>>2]=c[f+24>>2];c[u+28>>2]=c[f+28>>2];do if(!(s&4)){if(s&1|0){c[f+48>>2]=1;i=u+24|0;h[i>>3]=+h[(+h[i>>3]>+h[b+8>>3]?u+16|0:b)+8>>3];i=f+56|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=1;break}i=f+48|0;if(!(s&8)){c[i>>2]=2;h[u>>3]=+h[b>>3];h[u+8>>3]=+h[j+24>>3]-+h[j+80>>3]*.5;h[u+24>>3]=+h[b+8>>3];i=f+56|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=1;break}else{c[i>>2]=8;h[u+16>>3]=+h[b>>3];h[u+8>>3]=+h[j+24>>3]-+h[j+80>>3]*.5;h[u+24>>3]=+h[b+8>>3];i=f+56|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=1;break}}else{c[f+48>>2]=4;k=+h[u>>3];if(+h[b>>3]<+h[j+16>>3]){z=k+-1.0;y=+h[b+8>>3];b=u+16|0;k=+h[b>>3];m=+h[j+80>>3]*.5+ +h[j+24>>3];m=m+ +((c[(c[(so(w)|0)+16>>2]|0)+252>>2]|0)/2|0|0);i=c[r>>2]|0;h[b>>3]=+h[i+16>>3]-+h[i+88>>3];h[u+24>>3]=y;h[u+8>>3]=+h[i+24>>3]-+h[i+80>>3]*.5;h[u>>3]=z;h[f+56>>3]=z;h[f+64>>3]=y;h[f+72>>3]=k;h[f+80>>3]=m;i=f+88|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=2;break}else{m=+h[b+8>>3];i=u+16|0;y=+h[i>>3]+1.0;z=+h[j+80>>3]*.5+ +h[j+24>>3];z=z+ +((c[(c[(so(w)|0)+16>>2]|0)+252>>2]|0)/2|0|0);b=c[r>>2]|0;h[u>>3]=+h[b+96>>3]+ +h[b+16>>3];h[u+24>>3]=m;h[u+8>>3]=+h[b+24>>3]-+h[b+80>>3]*.5;h[i>>3]=y;h[f+56>>3]=k;h[f+64>>3]=m;h[f+72>>3]=y;h[f+80>>3]=z;i=f+88|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=2;break}}while(0);c[f+52>>2]=i;while(1){i=c[d+16>>2]|0;if(!(a[i+112>>0]|0))break;d=c[i+116>>2]|0}a[((w|0)==(c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0)?i+16|0:i+56|0)+30>>0]=0}else{j=1;v=47}break}case 2:{s=a[(c[t>>2]|0)+49>>0]|0;j=s&255;if(!(s<<24>>24))v=46;else{c[u>>2]=c[f>>2];c[u+4>>2]=c[f+4>>2];c[u+8>>2]=c[f+8>>2];c[u+12>>2]=c[f+12>>2];c[u+16>>2]=c[f+16>>2];c[u+20>>2]=c[f+20>>2];c[u+24>>2]=c[f+24>>2];c[u+28>>2]=c[f+28>>2];do if(!(j&4)){if(j&1|0)if((c[f+48>>2]|0)==4){i=c[r>>2]|0;z=+h[i+24>>3]-+h[i+80>>3]*.5;i=u+16|0;y=+h[i>>3]+1.0;k=+h[b>>3];m=z-+((c[(c[(so(w)|0)+16>>2]|0)+252>>2]|0)/2|0|0);b=c[r>>2]|0;h[u>>3]=+h[b+96>>3]+ +h[b+16>>3];h[u+8>>3]=z;h[u+24>>3]=+h[b+80>>3]*.5+ +h[b+24>>3];h[i>>3]=y;h[f+56>>3]=k;h[f+64>>3]=m;h[f+72>>3]=y;h[f+80>>3]=z;i=f+88|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=2;break}else{i=u+24|0;h[i>>3]=+h[(+h[i>>3]>+h[b+8>>3]?u+16|0:b)+8>>3];i=f+56|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=1;break}k=+h[b>>3];if(!(j&8)){h[u>>3]=k;e=c[r>>2]|0;k=+h[e+24>>3];m=+h[e+80>>3]*.5;if((c[f+48>>2]|0)==4){h[u+24>>3]=m+k;k=+h[b+8>>3];i=u}else{h[u+8>>3]=k-m;k=+h[b+8>>3]+1.0;i=u+16|0}h[i+8>>3]=k;i=f+56|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=1;break}else{i=u+16|0;h[i>>3]=k+1.0;e=c[r>>2]|0;k=+h[e+24>>3];m=+h[e+80>>3]*.5;if((c[f+48>>2]|0)==4){h[u+24>>3]=m+k;k=+h[b+8>>3]+-1.0;i=u}else{h[u+8>>3]=k-m;k=+h[b+8>>3]+1.0}h[i+8>>3]=k;i=f+56|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=1;break}}else{i=u+8|0;h[i>>3]=+h[(+h[i>>3]<+h[b+8>>3]?u:b)+8>>3];i=f+56|0;c[i>>2]=c[u>>2];c[i+4>>2]=c[u+4>>2];c[i+8>>2]=c[u+8>>2];c[i+12>>2]=c[u+12>>2];c[i+16>>2]=c[u+16>>2];c[i+20>>2]=c[u+20>>2];c[i+24>>2]=c[u+24>>2];c[i+28>>2]=c[u+28>>2];i=1}while(0);c[f+52>>2]=i;while(1){i=c[d+16>>2]|0;if(!(a[i+112>>0]|0))break;d=c[i+116>>2]|0}a[((w|0)==(c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0)?i+16|0:i+56|0)+30>>0]=0;c[f+48>>2]=j}break}default:v=46}if((v|0)==46){j=c[f+48>>2]|0;v=47}a:do if((v|0)==47){if(n){d=f+56|0;i=f+52|0;j=db[n&3](w,(c[t>>2]|0)+16|0,j,d,i)|0;if(j){c[f+48>>2]=j;break}}else{i=f+52|0;d=f+56|0};c[d>>2]=c[f>>2];c[d+4>>2]=c[f+4>>2];c[d+8>>2]=c[f+8>>2];c[d+12>>2]=c[f+12>>2];c[d+16>>2]=c[f+16>>2];c[d+20>>2]=c[f+20>>2];c[d+24>>2]=c[f+24>>2];c[d+28>>2]=c[f+28>>2];c[i>>2]=1;switch(e|0){case 8:{ma(123205,91558,569,91568);break}case 2:{h[((c[f+48>>2]|0)==4?f+56|0:f+72|0)+8>>3]=+h[b+8>>3];break a}case 1:{h[f+80>>3]=+h[b+8>>3];c[f+48>>2]=1;break a}default:break a}}while(0);l=x;return}function Oz(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=+h[c+8>>3]+ +h[b+8>>3];h[a>>3]=+h[c>>3]+ +h[b>>3];h[a+8>>3]=d;return}function Pz(a){a=a|0;var b=0.0,d=0,e=0,f=0.0,g=0,i=0,j=0,k=0.0,l=0.0;i=c[a+16>>2]|0;j=c[i+172>>2]|0;f=0.0;g=0;while(1){a=c[j+(g<<2)>>2]|0;if(!a)break;f=+h[(c[(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+16>>3]+f;g=g+1|0}e=c[i+180>>2]|0;b=0.0;a=0;while(1){d=c[e+(a<<2)>>2]|0;if(!d)break;b=+h[(c[(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+16>>3]+b;a=a+1|0}k=+h[i+16>>3];l=+h[i+24>>3];j=c[j>>2]|0;f=+K(+(l-+h[(c[(c[((c[j>>2]&3|0)==3?j:j+48|0)+40>>2]|0)+16>>2]|0)+24>>3]),+(k-f/+(g|0)));j=c[e>>2]|0;return +((+K(+(+h[(c[(c[((c[j>>2]&3|0)==2?j:j+-48|0)+40>>2]|0)+16>>2]|0)+24>>3]-l),+(b/+(a|0)-k))+f)*.5)}function Qz(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0,j=0,k=0.0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0.0;z=l;l=l+112|0;w=z+72|0;p=z+56|0;n=z+16|0;t=z;j=c[d>>2]&3;r=d+-48|0;y=c[((j|0)==2?d:r)+40>>2]|0;u=d+16|0;s=c[u>>2]|0;i=s+56|0;if(a[s+87>>0]|0){Cz(n,y,c[((j|0)==3?d:d+48|0)+40>>2]|0,i);j=n;n=i+40|0;do{c[i>>2]=c[j>>2];i=i+4|0;j=j+4|0}while((i|0)<(n|0))}s=y+16|0;j=c[s>>2]|0;i=c[j+8>>2]|0;if(!i)o=0;else o=c[(c[i+4>>2]|0)+16>>2]|0;n=b+40|0;i=j+16|0;j=(c[u>>2]|0)+56|0;c[p>>2]=c[i>>2];c[p+4>>2]=c[i+4>>2];c[p+8>>2]=c[i+8>>2];c[p+12>>2]=c[i+12>>2];c[w>>2]=c[j>>2];c[w+4>>2]=c[j+4>>2];c[w+8>>2]=c[j+8>>2];c[w+12>>2]=c[j+12>>2];Oz(t,p,w);c[n>>2]=c[t>>2];c[n+4>>2]=c[t+4>>2];c[n+8>>2]=c[t+8>>2];c[n+12>>2]=c[t+12>>2];if(!(g<<24>>24)){i=c[u>>2]|0;if(!(a[i+85>>0]|0))q=0;else{h[b+56>>3]=+h[i+72>>3];q=1}}else{m=+Pz(c[((c[d>>2]&3|0)==2?d:r)+40>>2]|0)+3.141592653589793;h[b+56>>3]=m;if(m<6.283185307179586)q=1;else ma(91578,91558,606,91602)}a[b+69>>0]=q;t=f+32|0;c[t>>2]=c[n>>2];c[t+4>>2]=c[n+4>>2];c[t+8>>2]=c[n+8>>2];c[t+12>>2]=c[n+12>>2];switch(e|0){case 1:{j=c[s>>2]|0;if((a[j+156>>0]|0)==0?(t=a[(c[u>>2]|0)+89>>0]|0,v=t&255,t<<24>>24!=0):0){c[w>>2]=c[f>>2];c[w+4>>2]=c[f+4>>2];c[w+8>>2]=c[f+8>>2];c[w+12>>2]=c[f+12>>2];c[w+16>>2]=c[f+16>>2];c[w+20>>2]=c[f+20>>2];c[w+24>>2]=c[f+24>>2];c[w+28>>2]=c[f+28>>2];do if(!(v&4))if(!(v&1)){i=f+48|0;if(!(v&8)){c[i>>2]=2;h[w>>3]=+h[n>>3];h[w+24>>3]=+h[j+80>>3]*.5+ +h[j+24>>3];h[w+8>>3]=+h[b+48>>3];i=f+56|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=1;break}else{c[i>>2]=8;h[w+16>>3]=+h[n>>3];h[w+24>>3]=+h[j+80>>3]*.5+ +h[j+24>>3];h[w+8>>3]=+h[b+48>>3];i=f+56|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=1;break}}else{c[f+48>>2]=1;k=+h[w>>3];if(+h[n>>3]<+h[j+16>>3]){B=k+-1.0;m=+h[b+48>>3];b=w+16|0;k=+h[b>>3];A=+h[j+80>>3]*-.5+ +h[j+24>>3];A=A-+((c[(c[(so(y)|0)+16>>2]|0)+252>>2]|0)/2|0|0);i=c[s>>2]|0;h[b>>3]=+h[i+16>>3]-+h[i+88>>3];h[w+8>>3]=m;h[w+24>>3]=+h[i+80>>3]*.5+ +h[i+24>>3];h[w>>3]=B;h[f+56>>3]=B;h[f+64>>3]=A;h[f+72>>3]=k;h[f+80>>3]=m;i=f+88|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=2;break}else{B=+h[b+48>>3];i=w+16|0;A=+h[i>>3]+1.0;m=+h[j+80>>3]*-.5+ +h[j+24>>3];m=m-+((c[(c[(so(y)|0)+16>>2]|0)+252>>2]|0)/2|0|0);b=c[s>>2]|0;h[w>>3]=+h[b+96>>3]+ +h[b+16>>3];h[w+8>>3]=B;h[w+24>>3]=+h[b+80>>3]*.5+ +h[b+24>>3];h[i>>3]=A;h[f+56>>3]=k;h[f+64>>3]=m;h[f+72>>3]=A;h[f+80>>3]=B;i=f+88|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=2;break}}else{c[f+48>>2]=4;i=w+8|0;h[i>>3]=+h[(+h[i>>3]<+h[b+48>>3]?w:n)+8>>3];i=f+56|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=1}while(0);c[f+52>>2]=i;while(1){i=c[d+16>>2]|0;if(!(a[i+112>>0]|0))break;d=c[i+116>>2]|0}a[((y|0)==(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)?i+56|0:i+16|0)+30>>0]=0;c[f+48>>2]=v}else{j=4;x=47}break}case 2:{v=a[(c[u>>2]|0)+89>>0]|0;j=v&255;if(!(v<<24>>24))x=46;else{c[w>>2]=c[f>>2];c[w+4>>2]=c[f+4>>2];c[w+8>>2]=c[f+8>>2];c[w+12>>2]=c[f+12>>2];c[w+16>>2]=c[f+16>>2];c[w+20>>2]=c[f+20>>2];c[w+24>>2]=c[f+24>>2];c[w+28>>2]=c[f+28>>2];do if(!(j&4)){if(j&1|0)if((c[f+48>>2]|0)==4){k=+h[w>>3]+-1.0;i=c[s>>2]|0;B=+h[i+24>>3]-+h[i+80>>3]*.5;A=+h[n>>3];m=B-+((c[(c[(so(y)|0)+16>>2]|0)+252>>2]|0)/2|0|0);i=c[s>>2]|0;h[w+16>>3]=+h[i+16>>3]+-2.0-+h[i+88>>3];h[w+8>>3]=B;h[w+24>>3]=+h[i+80>>3]*.5+ +h[i+24>>3];h[w>>3]=k;h[f+56>>3]=k;h[f+64>>3]=m;h[f+72>>3]=A;h[f+80>>3]=B;i=f+88|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=2;break}else{i=w+24|0;h[i>>3]=+h[(+h[i>>3]>+h[b+8>>3]?w+16|0:b)+8>>3];i=f+56|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=1;break}k=+h[n>>3];if(!(j&8)){h[w>>3]=k+-1.0;e=c[s>>2]|0;k=+h[e+24>>3];m=+h[e+80>>3]*.5;if((c[f+48>>2]|0)==4){h[w+24>>3]=m+k;k=+h[b+48>>3]+-1.0;i=w}else{h[w+8>>3]=k-m;k=+h[b+48>>3];i=w+16|0}h[i+8>>3]=k;i=f+56|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=1;break}else{i=w+16|0;h[i>>3]=k+1.0;e=c[s>>2]|0;k=+h[e+24>>3];m=+h[e+80>>3]*.5;if((c[f+48>>2]|0)==4){h[w+24>>3]=m+k;k=+h[b+48>>3]+-1.0;i=w}else{h[w+8>>3]=k-m;k=+h[b+48>>3]+1.0}h[i+8>>3]=k;i=f+56|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=1;break}}else{i=w+8|0;h[i>>3]=+h[(+h[i>>3]<+h[b+48>>3]?w:n)+8>>3];i=f+56|0;c[i>>2]=c[w>>2];c[i+4>>2]=c[w+4>>2];c[i+8>>2]=c[w+8>>2];c[i+12>>2]=c[w+12>>2];c[i+16>>2]=c[w+16>>2];c[i+20>>2]=c[w+20>>2];c[i+24>>2]=c[w+24>>2];c[i+28>>2]=c[w+28>>2];i=1}while(0);c[f+52>>2]=i;while(1){i=c[d+16>>2]|0;if(!(a[i+112>>0]|0))break;d=c[i+116>>2]|0}a[((y|0)==(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)?i+56|0:i+16|0)+30>>0]=0;c[f+48>>2]=j}break}default:x=46}if((x|0)==46){j=c[f+48>>2]|0;x=47}a:do if((x|0)==47){if(o){d=f+56|0;i=f+52|0;j=db[o&3](y,(c[u>>2]|0)+56|0,j,d,i)|0;if(j){c[f+48>>2]=j;break}}else{i=f+52|0;d=f+56|0};c[d>>2]=c[f>>2];c[d+4>>2]=c[f+4>>2];c[d+8>>2]=c[f+8>>2];c[d+12>>2]=c[f+12>>2];c[d+16>>2]=c[f+16>>2];c[d+20>>2]=c[f+20>>2];c[d+24>>2]=c[f+24>>2];c[d+28>>2]=c[f+28>>2];c[i>>2]=1;switch(e|0){case 8:{ma(123205,91558,765,91602);break}case 2:{h[((c[f+48>>2]|0)==4?f+56|0:f+72|0)+8>>3]=+h[b+48>>3];break a}case 1:{h[f+64>>3]=+h[b+48>>3];c[f+48>>2]=4;break a}default:break a}}while(0);l=z;return}function Rz(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0;g=c[b+16>>2]|0;i=c[g+96>>2]|0;if((a[g+44>>0]|0)==0?(a[g+84>>0]|0)==0:0)j=6;else{d=a[g+49>>0]|0;e=d&255;if(((e&8|0)==0?(f=a[g+89>>0]|0,(f&8)==0):0)?((e&5|0)==0?1:d<<24>>24!=f<<24>>24):0)j=6;else b=0}if((j|0)==6)if(!i)b=18;else{b=(c[(c[(so(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0)+16>>2]|0)+116>>2]&1|0)!=0;b=~~(+h[(b?i+32|0:i+24|0)>>3]+18.0)}return b|0}function Sz(b,d,e,f,g,h,i){b=b|0;d=d|0;e=e|0;f=f|0;g=+g;h=+h;i=i|0;var j=0,k=0,l=0,m=0;b=c[(c[d+(e<<2)>>2]|0)+16>>2]|0;if((a[b+44>>0]|0)==0?(a[b+84>>0]|0)==0:0)l=6;else l=3;do if((l|0)==3){j=a[b+49>>0]|0;k=j&255;if(!(k&8)){m=a[b+89>>0]|0;if((m&8)==0?((k&5|0)==0?1:j<<24>>24!=m<<24>>24):0){l=6;break}if(!(a[b+89>>0]&8)){if(k&4|0){Uz(d,e,f,g,h,i);break}if(!(k&1))ma(123205,91558,1231,91610);else{Wz(d,e,f,g,h,i);break}}}if((j&2)==0?(a[b+89>>0]&2)==0:0){Vz(d,e,f,g,h,i);break}Uz(d,e,f,g,h,i)}while(0);if((l|0)==6)Tz(d,e,f,g,h,i);return}function Tz(b,e,f,g,i,j){b=b|0;e=e|0;f=f|0;g=+g;i=+i;j=j|0;var k=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0.0,D=0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0.0,R=0.0,S=0;P=l;l=l+16080|0;L=P+80|0;M=P+64|0;N=P+48|0;O=P+32|0;J=P+16|0;K=P;B=c[b+(e<<2)>>2]|0;n=i*.5/+(f|0);n=n>2.0?n:2.0;D=(c[((c[B>>2]&3|0)==3?B:B+48|0)+40>>2]|0)+16|0;A=c[D>>2]|0;C=+h[A+16>>3];H=+h[A+24>>3];B=c[B+16>>2]|0;m=+h[B+16>>3];E=m+C;F=+h[B+24>>3]+H;i=+h[B+56>>3];G=i+C;H=+h[B+64>>3]+H;k=!(F>=H)?-1:1;p=+h[A+96>>3];switch(Xz(d[B+49>>0]|0,d[B+89>>0]|0)|0){case 65:case 32:{if(F==H)k=0-k|0;break}default:{}}Q=(p-m)*3.0;m=(p-i)*3.0;v=n*+(k|0);u=L+8|0;w=L+16|0;x=L+32|0;y=L+48|0;z=(H+F)*.5;A=L+64|0;B=L+80|0;s=L+96|0;t=L+104|0;r=0;o=0.0;i=p;n=p=(f|0))break;q=e+1|0;e=c[b+(e<<2)>>2]|0;p=i+g;n=n+g;m=m+g;o=o+v;h[L>>3]=E;h[u>>3]=F;Q=o+F;Yz(M,n*.3333333333333333+E,Q);c[w>>2]=c[M>>2];c[w+4>>2]=c[M+4>>2];c[w+8>>2]=c[M+8>>2];c[w+12>>2]=c[M+12>>2];R=p+C;Yz(N,R,Q);c[x>>2]=c[N>>2];c[x+4>>2]=c[N+4>>2];c[x+8>>2]=c[N+8>>2];c[x+12>>2]=c[N+12>>2];Yz(O,R,z);c[y>>2]=c[O>>2];c[y+4>>2]=c[O+4>>2];c[y+8>>2]=c[O+8>>2];c[y+12>>2]=c[O+12>>2];Q=H-o;Yz(J,R,Q);c[A>>2]=c[J>>2];c[A+4>>2]=c[J+4>>2];c[A+8>>2]=c[J+8>>2];c[A+12>>2]=c[J+12>>2];Yz(K,m*.3333333333333333+G,Q);c[B>>2]=c[K>>2];c[B+4>>2]=c[K+4>>2];c[B+8>>2]=c[K+8>>2];c[B+12>>2]=c[K+12>>2];h[s>>3]=G;h[t>>3]=H;k=e+16|0;if((c[(c[k>>2]|0)+96>>2]|0)!=0?(S=(c[(c[(so(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0)|0)+16>>2]|0)+116>>2]&1|0)==0,k=c[(c[k>>2]|0)+96>>2]|0,I=+h[(S?k+24|0:k+32|0)>>3],S=c[D>>2]|0,h[k+56>>3]=I*.5+p+ +h[S+16>>3],h[k+64>>3]=+h[S+24>>3],a[k+81>>0]=1,I>g):0)i=I+i;else i=p;Kz(e,c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,L,7,j);e=q;r=r+1|0}l=P;return}function Uz(b,e,f,g,i,j){b=b|0;e=e|0;f=f|0;g=+g;i=+i;j=j|0;var k=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0,C=0,D=0.0,E=0,F=0.0,G=0.0,H=0.0,I=0.0,J=0.0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0.0,S=0;Q=l;l=l+16080|0;M=Q+80|0;N=Q+64|0;O=Q+48|0;P=Q+32|0;K=Q+16|0;L=Q;C=c[b+(e<<2)>>2]|0;q=g*.5/+(f|0);q=q>2.0?q:2.0;E=(c[((c[C>>2]&3|0)==3?C:C+48|0)+40>>2]|0)+16|0;m=c[E>>2]|0;H=+h[m+16>>3];D=+h[m+24>>3];C=c[C+16>>2]|0;k=+h[C+16>>3];p=+h[C+24>>3];F=k+H;G=p+D;g=+h[C+56>>3];o=+h[C+64>>3];H=g+H;I=o+D;n=!(F>=H)?-1.0:1.0;s=+h[m+80>>3]*.5;switch(Xz(d[C+49>>0]|0,d[C+89>>0]|0)|0){case 15:{k=(q-g+ +h[m+96>>3])*n;break}case 38:{k=(g+q+ +h[m+88>>3])*n;break}case 41:{k=(q-k+ +h[m+96>>3])*n;break}case 48:{k=(q-k+ +h[m+96>>3])*n;break}case 58:case 57:case 51:case 47:case 37:case 14:{k=n*.3333333333333333*(k-g+ +h[m+88>>3]+ +h[m+96>>3]);break}case 73:{k=(k+q+ +h[m+88>>3])*n;break}case 83:{k=(+h[m+88>>3]+k)*n;break}case 84:{k=((k-g+ +h[m+88>>3]+ +h[m+96>>3])*.5+q)*n;break}case 85:case 75:case 74:{k=((k-g+ +h[m+88>>3]+ +h[m+96>>3])*.5+q*2.0)*n;break}default:k=0.0}p=(s-p)*3.0;o=(s-o)*3.0;q=n*q;w=M+8|0;x=M+16|0;y=M+32|0;z=M+48|0;A=(H+F)*.5;B=M+64|0;C=M+80|0;u=M+96|0;v=M+104|0;t=0;g=s;p=s=(f|0))break;r=e+1|0;e=c[b+(e<<2)>>2]|0;o=g+i;p=p+i;n=n+i;k=k+q;h[M>>3]=F;h[w>>3]=G;s=k+F;Yz(N,s,p*.3333333333333333+G);c[x>>2]=c[N>>2];c[x+4>>2]=c[N+4>>2];c[x+8>>2]=c[N+8>>2];c[x+12>>2]=c[N+12>>2];R=o+D;Yz(O,s,R);c[y>>2]=c[O>>2];c[y+4>>2]=c[O+4>>2];c[y+8>>2]=c[O+8>>2];c[y+12>>2]=c[O+12>>2];Yz(P,A,R);c[z>>2]=c[P>>2];c[z+4>>2]=c[P+4>>2];c[z+8>>2]=c[P+8>>2];c[z+12>>2]=c[P+12>>2];s=H-k;Yz(K,s,R);c[B>>2]=c[K>>2];c[B+4>>2]=c[K+4>>2];c[B+8>>2]=c[K+8>>2];c[B+12>>2]=c[K+12>>2];Yz(L,s,n*.3333333333333333+I);c[C>>2]=c[L>>2];c[C+4>>2]=c[L+4>>2];c[C+8>>2]=c[L+8>>2];c[C+12>>2]=c[L+12>>2];h[u>>3]=H;h[v>>3]=I;m=e+16|0;if((c[(c[m>>2]|0)+96>>2]|0)!=0?(S=(c[(c[(so(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0)|0)+16>>2]|0)+116>>2]&1|0)==0,m=c[(c[m>>2]|0)+96>>2]|0,J=+h[(S?m+32|0:m+24|0)>>3],S=c[E>>2]|0,h[m+64>>3]=J*.5+o+ +h[S+24>>3],h[m+56>>3]=+h[S+16>>3],a[m+81>>0]=1,J>i):0)g=J+g;else g=o;Kz(e,c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,M,7,j);e=r;t=t+1|0}l=Q;return}function Vz(b,e,f,g,i,j){b=b|0;e=e|0;f=f|0;g=+g;i=+i;j=j|0;var k=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0,x=0,y=0,z=0.0,A=0,B=0,C=0.0,D=0,E=0.0,F=0.0,G=0.0,H=0.0,I=0.0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0.0,R=0.0,S=0;P=l;l=l+16080|0;L=P+80|0;M=P+64|0;N=P+48|0;O=P+32|0;J=P+16|0;K=P;B=c[b+(e<<2)>>2]|0;n=i*.5/+(f|0);n=n>2.0?n:2.0;D=(c[((c[B>>2]&3|0)==3?B:B+48|0)+40>>2]|0)+16|0;A=c[D>>2]|0;C=+h[A+16>>3];H=+h[A+24>>3];B=c[B+16>>2]|0;m=+h[B+16>>3];E=m+C;F=+h[B+24>>3]+H;i=+h[B+56>>3];G=i+C;H=+h[B+64>>3]+H;k=!(F>=H)?-1:1;p=+h[A+88>>3];switch(Xz(d[B+49>>0]|0,d[B+89>>0]|0)|0){case 67:case 12:{if(F==H)k=0-k|0;break}default:{}}Q=(m+p)*3.0;m=(i+p)*3.0;v=n*+(k|0);u=L+8|0;w=L+16|0;x=L+32|0;y=L+48|0;z=(H+F)*.5;A=L+64|0;B=L+80|0;s=L+96|0;t=L+104|0;r=0;o=0.0;i=p;n=p=(f|0))break;q=e+1|0;e=c[b+(e<<2)>>2]|0;p=i+g;n=n+g;m=m+g;o=o+v;h[L>>3]=E;h[u>>3]=F;Q=o+F;Yz(M,E-n*.3333333333333333,Q);c[w>>2]=c[M>>2];c[w+4>>2]=c[M+4>>2];c[w+8>>2]=c[M+8>>2];c[w+12>>2]=c[M+12>>2];R=C-p;Yz(N,R,Q);c[x>>2]=c[N>>2];c[x+4>>2]=c[N+4>>2];c[x+8>>2]=c[N+8>>2];c[x+12>>2]=c[N+12>>2];Yz(O,R,z);c[y>>2]=c[O>>2];c[y+4>>2]=c[O+4>>2];c[y+8>>2]=c[O+8>>2];c[y+12>>2]=c[O+12>>2];Q=H-o;Yz(J,R,Q);c[A>>2]=c[J>>2];c[A+4>>2]=c[J+4>>2];c[A+8>>2]=c[J+8>>2];c[A+12>>2]=c[J+12>>2];Yz(K,G-m*.3333333333333333,Q);c[B>>2]=c[K>>2];c[B+4>>2]=c[K+4>>2];c[B+8>>2]=c[K+8>>2];c[B+12>>2]=c[K+12>>2];h[s>>3]=G;h[t>>3]=H;k=e+16|0;if((c[(c[k>>2]|0)+96>>2]|0)!=0?(S=(c[(c[(so(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0)|0)+16>>2]|0)+116>>2]&1|0)==0,k=c[(c[k>>2]|0)+96>>2]|0,I=+h[(S?k+24|0:k+32|0)>>3],S=c[D>>2]|0,h[k+56>>3]=I*-.5-p+ +h[S+16>>3],h[k+64>>3]=+h[S+24>>3],a[k+81>>0]=1,I>g):0)i=I+i;else i=p;Kz(e,c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,L,7,j);e=q;r=r+1|0}l=P;return}function Wz(b,e,f,g,i,j){b=b|0;e=e|0;f=f|0;g=+g;i=+i;j=j|0;var k=0.0,m=0.0,n=0.0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0.0,w=0,x=0.0,y=0.0,z=0.0,A=0.0,B=0.0,C=0,D=0,E=0,F=0.0,G=0,H=0,I=0.0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0.0,R=0.0,S=0;P=l;l=l+16080|0;L=P+80|0;M=P+64|0;N=P+48|0;O=P+32|0;J=P+16|0;K=P;C=c[b+(e<<2)>>2]|0;B=g*.5/+(f|0);w=(c[((c[C>>2]&3|0)==3?C:C+48|0)+40>>2]|0)+16|0;D=c[w>>2]|0;z=+h[D+16>>3];v=+h[D+24>>3];C=c[C+16>>2]|0;m=+h[C+24>>3];x=+h[C+16>>3]+z;y=m+v;n=+h[C+64>>3];z=+h[C+56>>3]+z;A=n+v;u=!(x>=z)?-1:1;o=+h[D+80>>3]*.5;C=(Xz(d[C+49>>0]|0,d[C+89>>0]|0)|0)==67;m=(m+o)*3.0;n=(n+o)*3.0;B=(B>2.0?B:2.0)*+((C?0-u|0:u)|0);u=L+8|0;C=L+16|0;D=L+32|0;E=L+48|0;F=(z+x)*.5;G=L+64|0;H=L+80|0;s=L+96|0;t=L+104|0;g=o;k=0.0;m=o=(f|0))break;r=e+1|0;p=c[b+(e<<2)>>2]|0;o=g+i;m=m+i;n=n+i;k=k+B;h[L>>3]=x;h[u>>3]=y;Q=k+x;Yz(M,Q,y-m*.3333333333333333);c[C>>2]=c[M>>2];c[C+4>>2]=c[M+4>>2];c[C+8>>2]=c[M+8>>2];c[C+12>>2]=c[M+12>>2];R=v-o;Yz(N,Q,R);c[D>>2]=c[N>>2];c[D+4>>2]=c[N+4>>2];c[D+8>>2]=c[N+8>>2];c[D+12>>2]=c[N+12>>2];Yz(O,F,R);c[E>>2]=c[O>>2];c[E+4>>2]=c[O+4>>2];c[E+8>>2]=c[O+8>>2];c[E+12>>2]=c[O+12>>2];Q=z-k;Yz(J,Q,R);c[G>>2]=c[J>>2];c[G+4>>2]=c[J+4>>2];c[G+8>>2]=c[J+8>>2];c[G+12>>2]=c[J+12>>2];Yz(K,Q,A-n*.3333333333333333);c[H>>2]=c[K>>2];c[H+4>>2]=c[K+4>>2];c[H+8>>2]=c[K+8>>2];c[H+12>>2]=c[K+12>>2];h[s>>3]=z;h[t>>3]=A;e=p+16|0;if((c[(c[e>>2]|0)+96>>2]|0)!=0?(S=(c[(c[(so(c[((c[p>>2]&3|0)==3?p:p+48|0)+40>>2]|0)|0)+16>>2]|0)+116>>2]&1|0)==0,e=c[(c[e>>2]|0)+96>>2]|0,I=+h[(S?e+32|0:e+24|0)>>3],S=c[w>>2]|0,h[e+64>>3]=I*-.5-o+ +h[S+24>>3],h[e+56>>3]=+h[S+16>>3],a[e+81>>0]=1,I>i):0)g=I+g;else g=o;Kz(p,c[((c[p>>2]&3|0)==2?p:p+-48|0)+40>>2]|0,L,7,j);e=r;q=q+1|0}l=P;return}function Xz(a,b){a=a|0;b=b|0;var d=0;d=0;while(1){if((d|0)>=8){b=-1;break}if((c[21064+(d<<2)>>2]|0)==(b|0)){b=d;break}d=d+1|0}d=0;while(1){if((d|0)>=8){d=-1;break}if((c[21064+(d<<2)>>2]|0)==(a|0))break;d=d+1|0}if((d|b|0)<0)d=0;else d=c[21096+(d<<5)+(b<<2)>>2]|0;return d|0}function Yz(a,b,c){a=a|0;b=+b;c=+c;h[a>>3]=b;h[a+8>>3]=c;return}function Zz(b){b=b|0;var d=0,e=0;if((c[42248]|0)!=0|(c[42247]|0)!=0){d=b+16|0;e=c[(c[d>>2]|0)+100>>2]|0;if((e|0?(a[e+81>>0]|0)==0:0)?_z(b,1)|0:0){e=so(c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0;cB(e,c[(c[d>>2]|0)+100>>2]|0)}e=c[(c[d>>2]|0)+104>>2]|0;if((e|0?(a[e+81>>0]|0)==0:0)?_z(b,0)|0:0){e=so(c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0;cB(e,c[(c[d>>2]|0)+104>>2]|0)}}return}function _z(b,d){b=b|0;d=d|0;var e=0,f=0.0,g=0.0,i=0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0;q=l;l=l+96|0;o=q+32|0;m=q+16|0;n=q;i=b+16|0;do if((a[(c[i>>2]|0)+112>>0]|0)!=6){e=c[42248]|0;if(!((e|0)!=0?(a[(Km(b,e)|0)>>0]|0)!=0:0)){e=c[42247]|0;if(!e){e=0;break}if(!(a[(Km(b,e)|0)>>0]|0)){e=0;break}}d=d<<24>>24==0;p=c[i>>2]|0;p=c[(d?p+104|0:p+100|0)>>2]|0;e=$z(b)|0;if(e){k=c[e>>2]|0;do if(d){if(c[k+8>>2]|0){e=c[k>>2]|0;j=+h[e>>3];g=+h[k+16>>3];e=e+8|0;f=+h[k+24>>3];break}e=c[k>>2]|0;g=+h[e>>3];f=+h[e+8>>3];e=0;while(1){if((e|0)==4)break;n=o+(e<<4)|0;i=(c[k>>2]|0)+(e<<4)|0;c[n>>2]=c[i>>2];c[n+4>>2]=c[i+4>>2];c[n+8>>2]=c[i+8>>2];c[n+12>>2]=c[i+12>>2];e=e+1|0}QA(m,o,3,.1,0,0);j=+h[m>>3];e=m+8|0}else{d=(c[e+4>>2]|0)+-1|0;i=k+(d*48|0)|0;if(c[k+(d*48|0)+12>>2]|0){o=c[i>>2]|0;e=(c[k+(d*48|0)+4>>2]|0)+-1|0;j=+h[o+(e<<4)>>3];g=+h[k+(d*48|0)+32>>3];e=o+(e<<4)+8|0;f=+h[k+(d*48|0)+40>>3];break}m=c[i>>2]|0;d=k+(d*48|0)+4|0;e=(c[d>>2]|0)+-1|0;g=+h[m+(e<<4)>>3];f=+h[m+(e<<4)+8>>3];e=0;while(1){if((e|0)==4)break;m=o+(e<<4)|0;k=(c[i>>2]|0)+(e+-4+(c[d>>2]|0)<<4)|0;c[m>>2]=c[k>>2];c[m+4>>2]=c[k+4>>2];c[m+8>>2]=c[k+8>>2];c[m+12>>2]=c[k+12>>2];e=e+1|0}QA(n,o,3,.9,0,0);j=+h[n>>3];e=n+8|0}while(0);r=+K(+(+h[e>>3]-f),+(j-g));r=+FA(b,c[42248]|0,-25.0,-180.0)*.017453292519943295+r;j=+FA(b,c[42247]|0,1.0,0.0)*10.0;h[p+56>>3]=j*+E(+r)+g;h[p+64>>3]=+F(+r)*j+f;a[p+81>>0]=1;e=1}else e=0}else e=0;while(0);l=q;return e|0}function $z(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;f=h;d=b;while(1){e=c[d+16>>2]|0;d=c[e+8>>2]|0;if(d|0)break;if(!(a[e+112>>0]|0)){g=5;break}d=c[e+116>>2]|0}if((g|0)==5){g=En(c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0;d=En(c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0;c[f>>2]=g;c[f+4>>2]=d;$l(1,91623,f)|0;d=0}l=h;return d|0}function aA(a,d,e){a=a|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0.0,u=0.0;s=l;l=l+96|0;m=s+80|0;n=s+64|0;o=s+48|0;p=s+32|0;q=s+16|0;r=s;k=b[(c[d+16>>2]|0)+136>>1]|0;d=e+16|0;bA(c[(c[d>>2]|0)+8>>2]|0,p,q);f=+h[p>>3];g=+h[q>>3];t=f-g;i=+h[p+8>>3];j=+h[q+8>>3];u=i-j;a:do if(u*u+t*t<1.0e-06){c[o>>2]=c[p>>2];c[o+4>>2]=c[p+4>>2];c[o+8>>2]=c[p+8>>2];c[o+12>>2]=c[p+12>>2]}else switch(k&14){case 4:case 10:{h[n>>3]=(g+f)*.5;h[n+8>>3]=(j+i)*.5;q=c[(c[d>>2]|0)+8>>2]|0;c[m>>2]=c[n>>2];c[m+4>>2]=c[n+4>>2];c[m+8>>2]=c[n+8>>2];c[m+12>>2]=c[n+12>>2];WA(r,q,m);c[o>>2]=c[r>>2];c[o+4>>2]=c[r+4>>2];c[o+8>>2]=c[r+8>>2];c[o+12>>2]=c[r+12>>2];break a}default:{cA(o,c[(c[d>>2]|0)+8>>2]|0,p,q);break a}}while(0);c[a>>2]=c[o>>2];c[a+4>>2]=c[o+4>>2];c[a+8>>2]=c[o+8>>2];c[a+12>>2]=c[o+12>>2];l=s;return}function bA(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;h=l;l=l+32|0;g=h+16|0;f=h;j=c[a>>2]|0;e=c[j>>2]|0;i=c[j+8>>2]|0;k=j+16|0;c[g>>2]=c[k>>2];c[g+4>>2]=c[k+4>>2];c[g+8>>2]=c[k+8>>2];c[g+12>>2]=c[k+12>>2];j=j+32|0;c[f>>2]=c[j>>2];c[f+4>>2]=c[j+4>>2];c[f+8>>2]=c[j+8>>2];c[f+12>>2]=c[j+12>>2];if(!i){c[b>>2]=c[e>>2];c[b+4>>2]=c[e+4>>2];c[b+8>>2]=c[e+8>>2];c[b+12>>2]=c[e+12>>2]}else{c[b>>2]=c[g>>2];c[b+4>>2]=c[g+4>>2];c[b+8>>2]=c[g+8>>2];c[b+12>>2]=c[g+12>>2]}i=c[a>>2]|0;j=(c[a+4>>2]|0)+-1|0;e=c[i+(j*48|0)>>2]|0;a=c[i+(j*48|0)+4>>2]|0;k=c[i+(j*48|0)+12>>2]|0;b=i+(j*48|0)+16|0;c[g>>2]=c[b>>2];c[g+4>>2]=c[b+4>>2];c[g+8>>2]=c[b+8>>2];c[g+12>>2]=c[b+12>>2];j=i+(j*48|0)+32|0;c[f>>2]=c[j>>2];c[f+4>>2]=c[j+4>>2];c[f+8>>2]=c[j+8>>2];c[f+12>>2]=c[j+12>>2];if(!k){k=e+(a+-1<<4)|0;c[d>>2]=c[k>>2];c[d+4>>2]=c[k+4>>2];c[d+8>>2]=c[k+8>>2];c[d+12>>2]=c[k+12>>2]}else{c[d>>2]=c[f>>2];c[d+4>>2]=c[f+4>>2];c[d+8>>2]=c[f+8>>2];c[d+12>>2]=c[f+12>>2]}l=h;return}function cA(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0.0,i=0,j=0,k=0,l=0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0.0;r=c[b+4>>2]|0;g=0.0;f=0;while(1){if((f|0)>=(r|0))break;l=c[b>>2]|0;k=c[l+(f*48|0)>>2]|0;l=c[l+(f*48|0)+4>>2]|0;i=3;j=0;while(1){if((i|0)>=(l|0))break;q=+h[k+(j<<4)>>3]-+h[k+(i<<4)>>3];p=+h[k+(j<<4)+8>>3]-+h[k+(i<<4)+8>>3];i=i+3|0;j=j+3|0;g=+C(+(p*p+q*q))+g}f=f+1|0}l=0;g=g*.5;a:while(1){if((l|0)>=(r|0)){f=15;break}k=c[b>>2]|0;j=c[k+(l*48|0)>>2]|0;k=c[k+(l*48|0)+4>>2]|0;f=3;i=0;while(1){if((f|0)>=(k|0))break;m=+h[j+(i<<4)>>3];p=+h[j+(i<<4)+8>>3];n=+h[j+(f<<4)>>3];o=+h[j+(f<<4)+8>>3];q=m-n;s=p-o;q=+C(+(s*s+q*q));if(q>=g){f=12;break a}f=f+3|0;i=i+3|0;g=g-q}l=l+1|0}if((f|0)==12){h[d>>3]=m;h[d+8>>3]=p;h[e>>3]=n;h[e+8>>3]=o;s=q-g;h[a>>3]=(s*m+n*g)/q;h[a+8>>3]=(s*p+o*g)/q;return}else if((f|0)==15)ma(123523,91558,1316,91685)}function dA(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Zz(b);return}function eA(b,d,e,f,g){b=b|0;d=d|0;e=+e;f=f|0;g=g|0;var i=0.0,j=0.0,k=0.0,l=0.0,m=0.0,n=0,o=0,p=0.0,q=0.0,r=0.0,s=0,t=0.0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0.0,C=0.0,D=0,G=0,H=0,I=0,J=0,K=0,L=0;J=fA(b)|0;I=c[J+4>>2]|0;K=c[J>>2]|0;H=I+-1|0;B=+h[K+(H<<6)+16>>3];C=+(I|0);D=(g|0)==2;G=(f|0)!=0;n=0;j=0.0;i=0.0;l=0.0;m=0.0;while(1){if((n|0)>=(I|0))break;b=~~+gA(+(n+-1|0),C);A=n+1|0;L=~~+gA(+(A|0),C);o=K+(n<<6)|0;m=+h[o>>3];z=K+(n<<6)+8|0;l=+h[z>>3];s=K+(n<<6)+16|0;t=+h[s>>3];u=K+(n<<6)+24|0;v=K+(n<<6)+32|0;w=K+(n<<6)+40|0;x=K+(n<<6)+48|0;y=K+(n<<6)+56|0;k=+hA(+h[K+(L<<6)+8>>3]-l,+h[K+(L<<6)>>3]-m);q=+hA(+h[K+(b<<6)+8>>3]-l,+h[K+(b<<6)>>3]-m);r=+Za[d&7](t,B,e);b=(n|0)==0;do if(b|(n|0)==(H|0))if(b){i=k+1.5707963267948966;if(!D){b=0;p=i;j=r;break}b=0;p=i;j=r;l=l-+F(+k)*r;m=m-+E(+k)*r;break}else{i=q+-1.5707963267948966;if(!D){b=0;p=i;j=r;break}b=0;p=i;j=r;l=l-+F(+q)*r;m=m-+E(+q)*r;break}else{p=k-q;p=1.5707963267948966-(p<0.0?p+6.283185307179586:p)*.5;j=+E(+p);j=j==0.0?0.0:r/j;i=k+1.5707963267948966;k=p+i;if(G|j>r*10.0){q=+gA(q+-1.5707963267948966,6.283185307179586);b=1;p=+gA(i,6.283185307179586);j=r;i=q}else{b=0;p=k;i=k}}while(0);h[o>>3]=m;h[z>>3]=l;h[s>>3]=t;a[u>>0]=108;h[v>>3]=i;h[w>>3]=j;c[x>>2]=b;h[y>>3]=p;n=A}o=ww(12)|0;b=0;while(1){if((b|0)>=(I|0))break;m=+h[K+(b<<6)>>3];l=+h[K+(b<<6)+8>>3];i=+h[K+(b<<6)+32>>3];j=+h[K+(b<<6)+40>>3];L=c[K+(b<<6)+48>>2]|0;k=+h[K+(b<<6)+56>>3];iA(o,+E(+i)*j+m,+F(+i)*j+l);if(L|0)jA(m,l,j,1,i,k,f,o);b=b+1|0}n=(g|0)==1;k=i+3.141592653589793;if(n)kA(o,m,l,j,i,k);else{iA(o,+E(+k)*j+m,+F(+k)*j+l);i=k}b=I+-2|0;k=m;while(1){if((b|0)<=-1)break;m=+h[K+(b<<6)>>3];l=+h[K+(b<<6)+8>>3];j=+h[K+(b<<6)+40>>3];L=c[K+(b<<6)+48>>2]|0;i=+h[K+(b<<6)+32>>3]+3.141592653589793;k=+h[K+(b<<6)+56>>3]+3.141592653589793;iA(o,+E(+k)*j+m,+F(+k)*j+l);if(L|0)jA(m,l,j,0,i,k,f,o);b=b+-1|0;k=m}if(n)kA(o,k,l,j,i,i+3.141592653589793);lA(J);return o|0}function fA(a){a=a|0;var b=0.0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0.0;q=l;l=l+144|0;i=q+128|0;h=q+112|0;j=q+96|0;k=q+64|0;m=q;n=q+80|0;o=mA()|0;p=c[a+4>>2]|0;f=c[a>>2]|0;c[i>>2]=c[f>>2];c[i+4>>2]=c[f+4>>2];c[i+8>>2]=c[f+8>>2];c[i+12>>2]=c[f+12>>2];nA(o,i,0.0);g=m+48|0;c[g>>2]=c[f>>2];c[g+4>>2]=c[f+4>>2];c[g+8>>2]=c[f+8>>2];c[g+12>>2]=c[f+12>>2];d=0;b=0.0;a:while(1){e=d+3|0;if((e|0)>=(p|0))break;c[m>>2]=c[g>>2];c[m+4>>2]=c[g+4>>2];c[m+8>>2]=c[g+8>>2];c[m+12>>2]=c[g+12>>2];a=1;while(1){if((a|0)==4)break;r=m+(a<<4)|0;s=f+(a+d<<4)|0;c[r>>2]=c[s>>2];c[r+4>>2]=c[s+4>>2];c[r+8>>2]=c[s+8>>2];c[r+12>>2]=c[s+12>>2];a=a+1|0}c[j>>2]=c[m>>2];c[j+4>>2]=c[m+4>>2];c[j+8>>2]=c[m+8>>2];c[j+12>>2]=c[m+12>>2];a=1;while(1){if((a|0)==21){d=e;continue a}QA(n,m,3,+(a|0)*.05,0,0);c[k>>2]=c[n>>2];c[k+4>>2]=c[n+4>>2];c[k+8>>2]=c[n+8>>2];c[k+12>>2]=c[n+12>>2];c[h>>2]=c[j>>2];c[h+4>>2]=c[j+4>>2];c[h+8>>2]=c[j+8>>2];c[h+12>>2]=c[j+12>>2];c[i>>2]=c[n>>2];c[i+4>>2]=c[n+4>>2];c[i+8>>2]=c[n+8>>2];c[i+12>>2]=c[n+12>>2];t=+oA(h,i)+b;c[i>>2]=c[k>>2];c[i+4>>2]=c[k+4>>2];c[i+8>>2]=c[k+8>>2];c[i+12>>2]=c[k+12>>2];nA(o,i,t);c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];c[j+8>>2]=c[k+8>>2];c[j+12>>2]=c[k+12>>2];a=a+1|0;b=t}}pA(o);l=q;return o|0}function gA(a,b){a=+a;b=+b;var c=0.0;c=a-+A(+(a/b))*b;return +(!(a<0.0)&!(a>=b)?a:c)}function hA(a,b){a=+a;b=+b;if(!(a==0.0&b==0.0)){a=+K(+a,+b);if(!(a>=0.0))a=a+6.283185307179586}else a=0.0;return +a}function iA(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0;e=c[a>>2]|0;f=a+4|0;if((e|0)<(c[f>>2]|0))f=c[a+8>>2]|0;else{c[f>>2]=2e3;e=a+8|0;f=zw(c[e>>2]|0,32e3)|0;c[e>>2]=f;e=c[a>>2]|0}c[a>>2]=e+1;h[f+(e<<4)>>3]=b;h[f+(e<<4)+8>>3]=d;return}function jA(a,b,c,d,e,f,g,h){a=+a;b=+b;c=+c;d=d|0;e=+e;f=+f;g=g|0;h=h|0;var i=0.0;d=(d|0)==0;i=d?e:f;do if((g|0)==1){e=(d?f:e)-i;e=!(e<=1.7453292519943296e-03)?e:e+6.283185307179586;if(e<3.141592653589793){kA(h,a,b,c,e+i,i);break}else{iA(h,+E(+i)*c+a,+F(+i)*c+a);break}}else iA(h,+E(+i)*c+a,+F(+i)*c+a);while(0);return}function kA(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=+d;e=+e;f=+f;var g=0,h=0.0;iA(a,+E(+e)*d+b,+F(+e)*d+c);a:do if(!(d==0.0)){while(1){if(!(f>e))break;f=f+-6.283185307179586}f=e-f;while(1){if(!(f>6.283185307179586))break;f=f+-6.283185307179586}f=f*.05263157894736842;g=1;while(1){if((g|0)==20)break a;h=e-f*+(g|0);iA(a,+E(+h)*d+b,+F(+h)*d+c);g=g+1|0}}while(0);return}function lA(a){a=a|0;$I(c[a>>2]|0);$I(a);return}function mA(){var a=0;a=ww(12)|0;c[a+4>>2]=0;c[a+8>>2]=2e3;c[a>>2]=ww(128e3)|0;return a|0}function nA(a,b,d){a=a|0;b=b|0;d=+d;var e=0,f=0,g=0,i=0;i=a+4|0;e=c[i>>2]|0;f=a+8|0;g=c[f>>2]|0;if((e|0)<(g|0))a=c[a>>2]|0;else{c[f>>2]=g<<1;e=zw(c[a>>2]|0,g<<7)|0;c[a>>2]=e;a=e;e=c[i>>2]|0}h[a+(e<<6)>>3]=+h[b>>3];h[a+(e<<6)+8>>3]=+h[b+8>>3];c[i>>2]=e+1;h[a+(e<<6)+16>>3]=d;return}function oA(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;c=+h[a>>3]-+h[b>>3];d=+h[a+8>>3]-+h[b+8>>3];return +(+C(+(d*d+c*c)))}function pA(a){a=a|0;var b=0;b=c[a+4>>2]|0;if((c[a+8>>2]|0)>(b|0))c[a>>2]=zw(c[a>>2]|0,b<<6)|0;return}function qA(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;j=k+8|0;i=k;g=k+12|0;c[g>>2]=0;h=c[d+4>>2]|0;if(!h)ma(91702,91713,203,91724);e=c[h>>2]|0;if(!e)ma(91738,91713,206,91724);f=h+8|0;if(!(c[f>>2]|0))c[f>>2]=rA(e)|0;if(!0)e=0;else{e=(Ev(c[h>>2]|0)|0)==0;e=e?0:g}if(!((wE(b,d,e)|0)<<24>>24))sA(d,e);do if(e|0){f=c[g>>2]|0;b=c[13918]|0;e=c[h>>2]|0;if(!f){c[j>>2]=e;AL(b,91781,j)|0;break}else{c[i>>2]=e;c[i+4>>2]=f;AL(b,91749,i)|0;break}}while(0);j=d+32|0;c[a>>2]=c[j>>2];c[a+4>>2]=c[j+4>>2];c[a+8>>2]=c[j+8>>2];c[a+12>>2]=c[j+12>>2];l=k;return}function rA(a){a=a|0;var b=0;b=c[42346]|0;if((b|0)!=0?(jK(b,a)|0)==0:0)a=c[42355]|0;else{$I(b);c[42346]=HL(a)|0;a=wM(169384,21352,35,36,29)|0;c[42355]=a}return a|0}function sA(b,d){b=b|0;d=d|0;var e=0,f=0.0,g=0,i=0.0,j=0,k=0.0;j=c[b+4>>2]|0;e=c[j>>2]|0;i=+h[j+16>>3];j=b+32|0;h[j>>3]=0.0;h[b+40>>3]=i*1.2;h[b+16>>3]=0.0;h[b+24>>3]=i*.1;c[b+8>>2]=0;c[b+12>>2]=0;if(qK(e,91815,4)|0)if((qK(e,91820,5)|0)!=0?(qK(e,91826,9)|0)!=0:0){g=4184;e=91836}else{g=8280;e=91872}else{g=6232;e=91853}if(d|0)c[d>>2]=e;e=c[b>>2]|0;if(e|0){f=0.0;while(1){b=a[e>>0]|0;if(!(b<<24>>24))break;k=f+ +h[g+((b&255)<<3)>>3];h[j>>3]=k;e=e+1|0;f=k}h[j>>3]=f*i}return}function tA(a,b){a=a|0;b=b|0;return jK(c[a>>2]|0,c[b>>2]|0)|0}function uA(a){a=a|0;var b=0;b=a+108|0;c[b>>2]=0;c[a+112>>2]=32;c[a+116>>2]=-1;c[a+120>>2]=14;c[a+124>>2]=58;c[a+128>>2]=20;c[a+132>>2]=0;c[a+136>>2]=0;c[a+140>>2]=0;b=Rl(b,c[4345]|0)|0;c[a+144>>2]=b;return b|0}function vA(a,b,d){a=a|0;b=b|0;d=d|0;d=aJ(1,32)|0;a=c[b>>2]|0;if(a|0)c[d>>2]=HL(a)|0;a=c[b+4>>2]|0;if(a|0)c[d+4>>2]=HL(a)|0;c[d+24>>2]=c[b+24>>2]&127;h[d+16>>3]=+h[b+16>>3];c[d+8>>2]=c[b+8>>2];return d|0}function wA(a,b,d){a=a|0;b=b|0;d=d|0;$I(c[b>>2]|0);$I(c[b+4>>2]|0);$I(b);return}function xA(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0,j=0;a=c[b>>2]|0;e=c[d>>2]|0;i=(e|0)==0;if(!a)if(i)j=5;else a=-1;else if(!i){a=yJ(a,e)|0;if(!a)j=5}else a=1;do if((j|0)==5){a=c[b+4>>2]|0;e=c[d+4>>2]|0;i=(e|0)==0;if(!a){if(!i){a=-1;break}}else{if(i){a=1;break}a=yJ(a,e)|0;if(a|0)break}a=(c[b+24>>2]&127)-(c[d+24>>2]&127)|0;if(!a){g=+h[b+16>>3];f=+h[d+16>>3];if(gf&1}}while(0);return a|0}function yA(){Wa(169424)|0;return}function zA(){var a=0,b=0;b=l;l=l+16|0;a=b;Wa(a|0)|0;l=b;return +(+((c[a+4>>2]|0)+(c[a>>2]|0)-(c[42356]|0)-(c[42357]|0)|0)*.016666666666666666)}function AA(a){a=a|0;var b=0,d=0;b=ww(16)|0;a=(a|0)>2?a:2;d=ww(a<<2)|0;c[b>>2]=d;c[b+12>>2]=d;c[b+8>>2]=d;c[b+4>>2]=d+(a<<2);return b|0}function BA(a){a=a|0;$I(c[a>>2]|0);$I(a);return}function CA(a,b){a=a|0;b=b|0;var d=0,e=0;d=a+12|0;e=c[d>>2]|0;c[d>>2]=e+4;c[e>>2]=b;if((c[d>>2]|0)>>>0>=(c[a+4>>2]|0)>>>0)c[d>>2]=c[a>>2];return}function DA(a){a=a|0;var b=0,d=0,e=0;d=a+8|0;b=c[d>>2]|0;if((b|0)!=(c[a+12>>2]|0)){e=b+4|0;c[d>>2]=e;b=c[b>>2]|0;if(e>>>0>=(c[a+4>>2]|0)>>>0)c[d>>2]=c[a>>2]}else b=0;return b|0}function EA(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0;i=l;l=l+16|0;g=i;if(((d|0)!=0?(h=Km(b,d)|0,(h|0)!=0):0)?(a[h>>0]|0)!=0:0){d=CL(h,g,10)|0;e=(h|0)==(c[g>>2]|0)?e:(d|0)<(f|0)?f:d}l=i;return e|0}function FA(b,d,e,f){b=b|0;d=d|0;e=+e;f=+f;var g=0,h=0,i=0,j=0.0;i=l;l=l+16|0;g=i;if(((b|0)!=0&(d|0)!=0?(h=Km(b,d)|0,(h|0)!=0):0)?(a[h>>0]|0)!=0:0){j=+uM(h,g);e=(h|0)==(c[g>>2]|0)?e:j>0]|0)!=0:0)d=b;return d|0}function IA(a,b,c){a=a|0;b=b|0;c=c|0;if(!b)a=c&255;else a=JA(Km(a,b)|0)|0;return a|0}function JA(a){a=a|0;return KA(a,0)|0}function KA(b,c){b=b|0;c=c|0;var d=0;if((b|0)!=0?(d=a[b>>0]|0,d<<24>>24!=0):0)if((jK(b,122100)|0)!=0?(jK(b,92682)|0)!=0:0)if((jK(b,92685)|0)!=0?(jK(b,92690)|0)!=0:0){if(((d<<24>>24)+-48|0)>>>0<10)c=(sM(b)|0)&255}else c=1;else c=0;return c|0}function LA(a){a=a|0;var b=0,d=0;while(1){b=(c[a+16>>2]|0)+220|0;d=c[b>>2]|0;if(!((d|0)!=(a|0)&(d|0)!=0))break;a=c[(c[d+16>>2]|0)+220>>2]|0;if(!a){a=d;continue}c[b>>2]=a}return a|0}function MA(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;if((a|0)!=(b|0)){d=c[a+16>>2]|0;e=d+220|0;if(!(c[e>>2]|0)){c[e>>2]=a;c[d+216>>2]=1}else a=LA(a)|0;d=c[b+16>>2]|0;e=d+220|0;if(!(c[e>>2]|0)){c[e>>2]=b;c[d+216>>2]=1}else{d=LA(b)|0;b=d;d=c[d+16>>2]|0}g=a+16|0;e=c[g>>2]|0;f=b+16|0;h=(c[e+120>>2]|0)>(c[d+120>>2]|0);a=h?b:a;c[(h?e:d)+220>>2]=a;e=(c[(h?f:g)>>2]|0)+216|0;c[e>>2]=(c[e>>2]|0)+(c[(c[(h?g:f)>>2]|0)+216>>2]|0)}return a|0}function NA(b){b=b|0;b=c[b+16>>2]|0;c[b+216>>2]=1;c[b+220>>2]=0;a[b+159>>0]=0;return}function OA(a,b){a=a|0;b=b|0;if((LA(a)|0)==(a|0)){a=c[a+16>>2]|0;c[a+220>>2]=b;b=(c[b+16>>2]|0)+216|0;c[b>>2]=(c[b>>2]|0)+(c[a+216>>2]|0);return}else ma(92702,92694,194,92718)}function PA(a,b){a=a|0;b=b|0;var d=0.0;b=c[(c[b+16>>2]|0)+132>>2]|0;d=+h[b+8>>3]*72.0;h[a>>3]=+h[b>>3]*72.0;h[a+8>>3]=d;return}function QA(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=+e;f=f|0;g=g|0;var i=0,j=0,k=0,m=0.0,n=0,o=0,p=0;o=l;l=l+576|0;n=o;i=0;while(1){if((i|0)>(d|0))break;k=n+(i<<4)|0;j=b+(i<<4)|0;c[k>>2]=c[j>>2];c[k+4>>2]=c[j+4>>2];c[k+8>>2]=c[j+8>>2];c[k+12>>2]=c[j+12>>2];i=i+1|0}m=1.0-e;i=1;while(1){if((i|0)>(d|0))break;j=d-i|0;k=i+-1|0;b=0;while(1){if((b|0)>(j|0))break;p=b+1|0;h[n+(i*96|0)+(b<<4)>>3]=+h[n+(k*96|0)+(p<<4)>>3]*e+ +h[n+(k*96|0)+(b<<4)>>3]*m;h[n+(i*96|0)+(b<<4)+8>>3]=+h[n+(k*96|0)+(p<<4)+8>>3]*e+ +h[n+(k*96|0)+(b<<4)+8>>3]*m;b=p}i=i+1|0}a:do if(f|0){i=0;while(1){if((i|0)>(d|0))break a;p=f+(i<<4)|0;k=n+(i*96|0)|0;c[p>>2]=c[k>>2];c[p+4>>2]=c[k+4>>2];c[p+8>>2]=c[k+8>>2];c[p+12>>2]=c[k+12>>2];i=i+1|0}}while(0);b:do if(g|0){i=0;while(1){if((i|0)>(d|0))break b;p=g+(i<<4)|0;f=n+((d-i|0)*96|0)+(i<<4)|0;c[p>>2]=c[f>>2];c[p+4>>2]=c[f+4>>2];c[p+8>>2]=c[f+8>>2];c[p+12>>2]=c[f+12>>2];i=i+1|0}}while(0);p=n+(d*96|0)|0;c[a>>2]=c[p>>2];c[a+4>>2]=c[p+4>>2];c[a+8>>2]=c[p+8>>2];c[a+12>>2]=c[p+12>>2];l=o;return}function RA(b){b=b|0;var d=0,e=0,f=0,g=0;e=0;do{d=c[42360]|0;f=d+1024|0;if((d-e|0)<1024){c[42360]=f;f=zw(c[42361]|0,f)|0;c[42361]=f;d=c[42360]|0}else f=c[42361]|0;d=hL(f+e|0,d-e|0,b)|0;if(!d){g=6;break}e=(sJ(d)|0)+e|0;d=c[42361]|0}while((a[d+(e+-1)>>0]|0)!=10);if((g|0)==6)d=c[42361]|0;return ((e|0)>0?d:0)|0}function SA(b){b=b|0;var d=0,e=0,f=0;f=l;l=l+16|0;do if((b|0)!=0?(a[b>>0]|0)!=0:0)if(!0){d=c[42178]|0;e=c[42363]|0;if((c[42362]|0)==(d|0))d=e;else{if(e){$I(c[e>>2]|0);$I(c[42363]|0);c[42363]=0;d=c[42178]|0}c[42362]=d;if(!d)break;if(!(a[d>>0]|0))break;d=TA(d)|0;c[42363]=d}if(!((a[b>>0]|0)!=47&(d|0)!=0))break;b=UA(d,c[42364]|0,b)|0;break}else S();else b=0;while(0);l=f;return b|0}function TA(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;e=0;f=0;g=0;b=HL(a)|0;d=0;while(1){b=EL(b,93017)|0;if(!b)break;a=(g<<2)+8|0;if(!f)a=xw(a)|0;else a=zw(d,a)|0;c[a+(g<<2)>>2]=b;f=sJ(b)|0;e=e>>>0>f>>>0?e:f;f=a;g=g+1|0;b=0;d=a}c[f+(g<<2)>>2]=0;c[42364]=e;return f|0}function UA(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;g=l;l=l+16|0;e=g;h=c[42365]|0;c[42365]=bJ(h,b+2+(sJ(d)|0)|0)|0;while(1){b=c[a>>2]|0;if(!b){a=0;break}h=c[42365]|0;c[e>>2]=b;c[e+4>>2]=93015;c[e+8>>2]=d;qL(h,93008,e)|0;if(!(aM(c[42365]|0,4)|0)){f=4;break}else a=a+4|0}if((f|0)==4)a=c[42365]|0;l=g;return a|0}function VA(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;g=(b|0)==0;f=0;while(1){h=c[d+(f<<2)>>2]|0;if(!h)break;if((!g?(a[b>>0]|0)==(a[h>>0]|0):0)?(yJ(b,h)|0)==0:0)break;f=f+1|0}return c[e+(f<<2)>>2]|0}function WA(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0,i=0.0,j=0.0,k=0.0,m=0.0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,C=0;z=l;l=l+80|0;x=z+16|0;y=z;u=c[b+4>>2]|0;v=c[b>>2]|0;w=d+8|0;f=0;e=-1;g=1.e+38;b=-1;while(1){if((f|0)>=(u|0))break;s=c[v+(f*48|0)>>2]|0;t=c[v+(f*48|0)+4>>2]|0;r=0;while(1){if((r|0)>=(t|0))break;q=+h[s+(r<<4)>>3]-+h[d>>3];p=+h[s+(r<<4)+8>>3]-+h[w>>3];q=p*p+q*q;A=(e|0)==-1|q>2]|0;e=e+(((e|0)==((c[v+(b*48|0)+4>>2]|0)+-1|0))<<31>>31)|0;e=e-((e|0)%3|0)|0;b=0;while(1){if((b|0)==4)break;C=b+e|0;h[x+(b<<4)>>3]=+h[f+(C<<4)>>3];h[x+(b<<4)+8>>3]=+h[f+(C<<4)+8>>3];b=b+1|0}q=+h[d>>3];k=+h[x>>3]-q;o=+h[w>>3];p=+h[x+8>>3]-o;j=+h[x+48>>3]-q;n=+h[x+56>>3]-o;b=y+8|0;g=1.0;i=0.0;j=n*n+j*j;k=p*p+k*k;while(1){p=(g+i)*.5;QA(y,x,3,p,0,0);m=+h[y>>3];n=+h[b>>3];if(+B(+(k-j))<1.0)break;if(+B(+(g-i))<1.0e-05)break;C=k>3]=m;h[a+8>>3]=n;l=z;return}function XA(b){b=b|0;var d=0.0,e=0,f=0,g=0,i=0,j=0,k=0,l=0;d=+FA(b,c[42191]|0,.75,.01);g=b+16|0;h[(c[g>>2]|0)+32>>3]=d;d=+FA(b,c[42190]|0,.5,.02);h[(c[g>>2]|0)+40>>3]=d;l=Ry(HA(b,c[42192]|0,93019)|0,b)|0;c[(c[g>>2]|0)+8>>2]=l;l=Km(b,c[42199]|0)|0;d=+FA(b,c[42195]|0,14.0,1.0);e=HA(b,c[42196]|0,93027)|0;f=HA(b,c[42197]|0,122106)|0;i=(dp(l)|0)!=0;k=(Cy(b)|0)==2;i=mw(b,l,(k?4:0)|(i?2:0),d,e,f)|0;c[(c[g>>2]|0)+104>>2]=i;i=c[42200]|0;if((i|0?(j=Km(b,i)|0,j|0):0)?a[j>>0]|0:0){l=(dp(j)|0)!=0;l=mw(b,j,l?2:0,d,e,f)|0;c[(c[g>>2]|0)+108>>2]=l;l=(c[(so(b)|0)+16>>2]|0)+113|0;a[l>>0]=a[l>>0]|16}k=(EA(b,c[42203]|0,0,0)|0)&255;l=c[g>>2]|0;a[l+144>>0]=k;gb[c[c[(c[l+8>>2]|0)+4>>2]>>2]&127](b);return}function YA(b){b=b|0;var d=0,e=0,f=0,g=0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;v=l;l=l+112|0;m=v+96|0;n=v+80|0;s=v+40|0;u=v;r=b+48|0;p=so(c[((c[b>>2]&3|0)==3?b:r)+40>>2]|0)|0;g=m+8|0;c[g>>2]=0;o=n+8|0;c[o>>2]=0;d=c[42227]|0;if(((d|0)!=0?(e=Km(b,d)|0,(e|0)!=0):0)?(a[e>>0]|0)!=0:0){ZA(b,m);t=(dp(e)|0)!=0;i=+h[m>>3];f=c[g>>2]|0;d=c[m+12>>2]|0;e=mw(b,e,t?2:0,i,f,d)|0;t=b+16|0;c[(c[t>>2]|0)+96>>2]=e;e=(c[p+16>>2]|0)+113|0;a[e>>0]=a[e>>0]|1;e=JA(GA(b,c[42237]|0,122100)|0)|0;a[(c[t>>2]|0)+114>>0]=e;t=1;e=f}else{t=0;d=0;i=0.0;e=0}f=c[42228]|0;if((f|0?(j=Km(b,f)|0,j|0):0)?a[j>>0]|0:0){if(!e){ZA(b,m);i=+h[m>>3];e=c[g>>2]|0;d=c[m+12>>2]|0}g=(dp(j)|0)!=0;j=mw(b,j,g?2:0,i,e,d)|0;c[(c[b+16>>2]|0)+108>>2]=j;j=(c[p+16>>2]|0)+113|0;a[j>>0]=a[j>>0]|32}d=c[42242]|0;if(((d|0)!=0?(k=Km(b,d)|0,(k|0)!=0):0)?(a[k>>0]|0)!=0:0){_A(b,m,n);j=(dp(k)|0)!=0;i=+h[n>>3];d=c[o>>2]|0;e=c[n+12>>2]|0;k=mw(b,k,j?2:0,i,d,e)|0;c[(c[b+16>>2]|0)+100>>2]=k;k=(c[p+16>>2]|0)+113|0;a[k>>0]=a[k>>0]|2}else{e=0;i=0.0;d=0}f=c[42243]|0;if((f|0?(q=Km(b,f)|0,q|0):0)?a[q>>0]|0:0){if(!d){_A(b,m,n);e=c[n+12>>2]|0;i=+h[n>>3];d=c[o>>2]|0}o=(dp(q)|0)!=0;q=mw(b,q,o?2:0,i,d,e)|0;c[(c[b+16>>2]|0)+104>>2]=q;q=(c[p+16>>2]|0)+113|0;a[q>>0]=a[q>>0]|4}d=Jm(b,96242)|0;d=d|0?d:174185;if(a[d>>0]|0)a[(c[(c[((c[b>>2]&3|0)==3?b:r)+40>>2]|0)+16>>2]|0)+145>>0]=1;g=b+16|0;f=(c[g>>2]|0)+16|0;e=c[((c[b>>2]&3|0)==3?b:r)+40>>2]|0;$A(s,c[(c[(c[(c[e+16>>2]|0)+8>>2]|0)+4>>2]|0)+8>>2]|0,e,d);d=s;e=f+40|0;do{c[f>>2]=c[d>>2];f=f+4|0;d=d+4|0}while((f|0)<(e|0));if((aB(b,c[42249]|0)|0)<<24>>24)a[(c[g>>2]|0)+46>>0]=0;d=Jm(b,96251)|0;d=d|0?d:174185;if(!(a[d>>0]|0))e=b+-48|0;else{e=b+-48|0;a[(c[(c[((c[b>>2]&3|0)==2?b:e)+40>>2]|0)+16>>2]|0)+145>>0]=1}f=(c[g>>2]|0)+56|0;e=c[((c[b>>2]&3|0)==2?b:e)+40>>2]|0;$A(u,c[(c[(c[(c[e+16>>2]|0)+8>>2]|0)+4>>2]|0)+8>>2]|0,e,d);d=u;e=f+40|0;do{c[f>>2]=c[d>>2];f=f+4|0;d=d+4|0}while((f|0)<(e|0));if((aB(b,c[42250]|0)|0)<<24>>24)a[(c[g>>2]|0)+86>>0]=0;l=v;return t|0}function ZA(a,b){a=a|0;b=b|0;h[b>>3]=+FA(a,c[42224]|0,14.0,1.0);c[b+8>>2]=HA(a,c[42225]|0,93027)|0;c[b+12>>2]=HA(a,c[42226]|0,122106)|0;return}function _A(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=b+8|0;if(!(c[e>>2]|0))ZA(a,b);h[d>>3]=+FA(a,c[42244]|0,+h[b>>3],1.0);c[d+8>>2]=HA(a,c[42245]|0,c[e>>2]|0)|0;c[d+12>>2]=HA(a,c[42246]|0,c[b+12>>2]|0)|0;return}function $A(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+128|0;k=m+80|0;h=m+40|0;g=m;if((f|0)!=0?(j=XJ(f,58)|0,(j|0)!=0):0){a[j>>0]=0;i=j+1|0;kb[d&31](h,e,f,i);e=k;g=h;d=e+36|0;do{c[e>>2]=c[g>>2];e=e+4|0;g=g+4|0}while((e|0)<(d|0));a[j>>0]=58;f=i}else{kb[d&31](g,e,f,0);e=k;d=e+36|0;do{c[e>>2]=c[g>>2];e=e+4|0;g=g+4|0}while((e|0)<(d|0))}e=b;g=k;d=e+36|0;do{c[e>>2]=c[g>>2];e=e+4|0;g=g+4|0}while((e|0)<(d|0));c[b+36>>2]=f;l=m;return}function aB(b,c){b=b|0;c=c|0;var d=0;if(((c|0)!=0?(d=Km(b,c)|0,(d|0)!=0):0)?(a[d>>0]|0)!=0:0)b=(JA(d)|0)<<24>>24==0&1;else b=0;return b|0}function bB(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0.0,o=0.0;k=l;l=l+32|0;i=k;j=c[b+8>>2]|0;d=c[b+4>>2]|0;d=(c[b+44>>2]|0)+((O((d|0)>1?d+-1|0:0,j)|0)<<4)|0;e=i+16|0;c[e>>2]=c[d>>2];c[e+4>>2]=c[d+4>>2];c[e+8>>2]=c[d+8>>2];c[e+12>>2]=c[d+12>>2];c[i>>2]=c[d>>2];c[i+4>>2]=c[d+4>>2];c[i+8>>2]=c[d+8>>2];c[i+12>>2]=c[d+12>>2];f=i+8|0;g=i+24|0;b=1;while(1){if((b|0)>=(j|0))break;m=d+(b<<4)|0;o=+h[m>>3];h[i>>3]=+h[(+h[i>>3]>3];n=+h[m+8>>3];h[f>>3]=+h[(+h[f>>3]>3];h[e>>3]=+h[(+h[e>>3]>o?e:m)>>3];h[g>>3]=+h[(+h[g>>3]>n?e:m)+8>>3];b=b+1|0}c[a>>2]=c[i>>2];c[a+4>>2]=c[i+4>>2];c[a+8>>2]=c[i+8>>2];c[a+12>>2]=c[i+12>>2];c[a+16>>2]=c[i+16>>2];c[a+20>>2]=c[i+20>>2];c[a+24>>2]=c[i+24>>2];c[a+28>>2]=c[i+28>>2];l=k;return}function cB(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=l;l=l+64|0;g=d+32|0;e=d;f=c[a+16>>2]|0;a=f+16|0;f=c[f+116>>2]&1;c[g>>2]=c[a>>2];c[g+4>>2]=c[a+4>>2];c[g+8>>2]=c[a+8>>2];c[g+12>>2]=c[a+12>>2];c[g+16>>2]=c[a+16>>2];c[g+20>>2]=c[a+20>>2];c[g+24>>2]=c[a+24>>2];c[g+28>>2]=c[a+28>>2];dB(e,g,b,f);c[a>>2]=c[e>>2];c[a+4>>2]=c[e+4>>2];c[a+8>>2]=c[e+8>>2];c[a+12>>2]=c[e+12>>2];c[a+16>>2]=c[e+16>>2];c[a+20>>2]=c[e+20>>2];c[a+24>>2]=c[e+24>>2];c[a+28>>2]=c[e+28>>2];l=d;return}function dB(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0.0,j=0,k=0.0,l=0.0,m=0.0;g=+h[d+56>>3];l=+h[d+64>>3];j=e<<24>>24==0;k=+h[d+24>>3];i=+h[d+32>>3];m=(j?k:i)*.5;f=g-m;g=m+g;if(f<+h[b>>3])h[b>>3]=f;e=b+16|0;if(g>+h[e>>3])h[e>>3]=g;g=(j?i:k)*.5;f=l-g;g=g+l;e=b+8|0;if(f<+h[e>>3])h[e>>3]=f;e=b+24|0;if(g>+h[e>>3])h[e>>3]=g;c[a>>2]=c[b>>2];c[a+4>>2]=c[b+4>>2];c[a+8>>2]=c[b+8>>2];c[a+12>>2]=c[b+12>>2];c[a+16>>2]=c[b+16>>2];c[a+20>>2]=c[b+20>>2];c[a+24>>2]=c[b+24>>2];c[a+28>>2]=c[b+28>>2];return}function eB(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0.0,N=0.0,O=0.0,P=0.0;L=l;l=l+448|0;H=L+416|0;t=L+384|0;u=L+304|0;K=L+256|0;G=L+192|0;B=L+144|0;C=L+96|0;d=L+400|0;e=L+368|0;f=L+352|0;g=L+336|0;v=L+288|0;w=L+224|0;x=L+160|0;y=L+112|0;z=L+64|0;A=L+32|0;I=L;J=b+16|0;if((nn(b)|0)==0?(c[(c[J>>2]|0)+180>>2]|0)==0:0){fB(d,0.0,0.0);c[K>>2]=c[d>>2];c[K+4>>2]=c[d+4>>2];c[K+8>>2]=c[d+8>>2];c[K+12>>2]=c[d+12>>2];K=K+16|0;fB(e,0.0,0.0);c[K>>2]=c[e>>2];c[K+4>>2]=c[e+4>>2];c[K+8>>2]=c[e+8>>2];c[K+12>>2]=c[e+12>>2]}else{fB(f,2147483647.0,2147483647.0);c[K>>2]=c[f>>2];c[K+4>>2]=c[f+4>>2];c[K+8>>2]=c[f+8>>2];c[K+12>>2]=c[f+12>>2];F=K+16|0;fB(g,-2147483647.0,-2147483647.0);c[F>>2]=c[g>>2];c[F+4>>2]=c[g+4>>2];c[F+8>>2]=c[g+8>>2];c[F+12>>2]=c[g+12>>2];o=C+8|0;p=u+16|0;D=K+8|0;q=u+8|0;E=K+24|0;r=u+24|0;s=B+8|0;n=eo(b)|0;while(1){if(!n)break;PA(B,n);d=n+16|0;m=c[d>>2]|0;h[C>>3]=(+h[m+96>>3]+ +h[m+88>>3])*.5;h[o>>3]=+h[m+80>>3]*.5;c[t>>2]=c[B>>2];c[t+4>>2]=c[B+4>>2];c[t+8>>2]=c[B+8>>2];c[t+12>>2]=c[B+12>>2];c[H>>2]=c[C>>2];c[H+4>>2]=c[C+4>>2];c[H+8>>2]=c[C+8>>2];c[H+12>>2]=c[C+12>>2];gB(u,t,H);c[t>>2]=c[B>>2];c[t+4>>2]=c[B+4>>2];c[t+8>>2]=c[B+8>>2];c[t+12>>2]=c[B+12>>2];c[H>>2]=c[C>>2];c[H+4>>2]=c[C+4>>2];c[H+8>>2]=c[C+8>>2];c[H+12>>2]=c[C+12>>2];hB(v,t,H);c[p>>2]=c[v>>2];c[p+4>>2]=c[v+4>>2];c[p+8>>2]=c[v+8>>2];c[p+12>>2]=c[v+12>>2];h[K>>3]=+h[(+h[K>>3]<+h[u>>3]?K:u)>>3];h[D>>3]=+h[(+h[D>>3]<+h[q>>3]?K:u)+8>>3];h[F>>3]=+h[(+h[F>>3]>+h[p>>3]?K:u)+16>>3];h[E>>3]=+h[(+h[E>>3]>+h[r>>3]?K:u)+24>>3];d=c[(c[d>>2]|0)+108>>2]|0;if(d|0?a[d+81>>0]|0:0){m=c[(c[J>>2]|0)+116>>2]&1;c[H>>2]=c[K>>2];c[H+4>>2]=c[K+4>>2];c[H+8>>2]=c[K+8>>2];c[H+12>>2]=c[K+12>>2];c[H+16>>2]=c[K+16>>2];c[H+20>>2]=c[K+20>>2];c[H+24>>2]=c[K+24>>2];c[H+28>>2]=c[K+28>>2];dB(w,H,d,m);c[K>>2]=c[w>>2];c[K+4>>2]=c[w+4>>2];c[K+8>>2]=c[w+8>>2];c[K+12>>2]=c[w+12>>2];c[K+16>>2]=c[w+16>>2];c[K+20>>2]=c[w+20>>2];c[K+24>>2]=c[w+24>>2];c[K+28>>2]=c[w+28>>2]}m=Qm(b,n)|0;while(1){if(!m)break;k=m+16|0;d=c[k>>2]|0;j=d+8|0;e=c[j>>2]|0;if(e|0){i=0;while(1){if((i|0)<(c[e+4>>2]|0))g=0;else break;while(1){f=c[e>>2]|0;if((g|0)>=(c[f+(i*48|0)+4>>2]|0))break;e=(c[f+(i*48|0)>>2]|0)+(g<<4)|0;c[B>>2]=c[e>>2];c[B+4>>2]=c[e+4>>2];c[B+8>>2]=c[e+8>>2];c[B+12>>2]=c[e+12>>2];N=+h[B>>3];h[K>>3]=+h[(+h[K>>3]>3];M=+h[s>>3];h[D>>3]=+h[(+h[D>>3]>3];h[F>>3]=+h[(+h[F>>3]>N?F:B)>>3];h[E>>3]=+h[(+h[E>>3]>M?F:B)+8>>3];g=g+1|0;e=c[j>>2]|0}i=i+1|0}e=c[d+96>>2]|0;if((e|0)!=0?(a[e+81>>0]|0)!=0:0){d=c[(c[J>>2]|0)+116>>2]&1;c[H>>2]=c[K>>2];c[H+4>>2]=c[K+4>>2];c[H+8>>2]=c[K+8>>2];c[H+12>>2]=c[K+12>>2];c[H+16>>2]=c[K+16>>2];c[H+20>>2]=c[K+20>>2];c[H+24>>2]=c[K+24>>2];c[H+28>>2]=c[K+28>>2];dB(x,H,e,d);c[K>>2]=c[x>>2];c[K+4>>2]=c[x+4>>2];c[K+8>>2]=c[x+8>>2];c[K+12>>2]=c[x+12>>2];c[K+16>>2]=c[x+16>>2];c[K+20>>2]=c[x+20>>2];c[K+24>>2]=c[x+24>>2];c[K+28>>2]=c[x+28>>2];d=c[k>>2]|0}e=c[d+100>>2]|0;if((e|0)!=0?(a[e+81>>0]|0)!=0:0){d=c[(c[J>>2]|0)+116>>2]&1;c[H>>2]=c[K>>2];c[H+4>>2]=c[K+4>>2];c[H+8>>2]=c[K+8>>2];c[H+12>>2]=c[K+12>>2];c[H+16>>2]=c[K+16>>2];c[H+20>>2]=c[K+20>>2];c[H+24>>2]=c[K+24>>2];c[H+28>>2]=c[K+28>>2];dB(y,H,e,d);c[K>>2]=c[y>>2];c[K+4>>2]=c[y+4>>2];c[K+8>>2]=c[y+8>>2];c[K+12>>2]=c[y+12>>2];c[K+16>>2]=c[y+16>>2];c[K+20>>2]=c[y+20>>2];c[K+24>>2]=c[y+24>>2];c[K+28>>2]=c[y+28>>2];d=c[k>>2]|0}e=c[d+104>>2]|0;if((e|0)!=0?(a[e+81>>0]|0)!=0:0){d=c[(c[J>>2]|0)+116>>2]&1;c[H>>2]=c[K>>2];c[H+4>>2]=c[K+4>>2];c[H+8>>2]=c[K+8>>2];c[H+12>>2]=c[K+12>>2];c[H+16>>2]=c[K+16>>2];c[H+20>>2]=c[K+20>>2];c[H+24>>2]=c[K+24>>2];c[H+28>>2]=c[K+28>>2];dB(z,H,e,d);c[K>>2]=c[z>>2];c[K+4>>2]=c[z+4>>2];c[K+8>>2]=c[z+8>>2];c[K+12>>2]=c[z+12>>2];c[K+16>>2]=c[z+16>>2];c[K+20>>2]=c[z+20>>2];c[K+24>>2]=c[z+24>>2];c[K+28>>2]=c[z+28>>2];d=c[k>>2]|0}d=c[d+108>>2]|0;if(d|0?a[d+81>>0]|0:0){k=c[(c[J>>2]|0)+116>>2]&1;c[H>>2]=c[K>>2];c[H+4>>2]=c[K+4>>2];c[H+8>>2]=c[K+8>>2];c[H+12>>2]=c[K+12>>2];c[H+16>>2]=c[K+16>>2];c[H+20>>2]=c[K+20>>2];c[H+24>>2]=c[K+24>>2];c[H+28>>2]=c[K+28>>2];dB(A,H,d,k);c[K>>2]=c[A>>2];c[K+4>>2]=c[A+4>>2];c[K+8>>2]=c[A+8>>2];c[K+12>>2]=c[A+12>>2];c[K+16>>2]=c[A+16>>2];c[K+20>>2]=c[A+20>>2];c[K+24>>2]=c[A+24>>2];c[K+28>>2]=c[A+28>>2]}}m=Sm(b,m)|0}n=fo(b,n)|0}d=c[J>>2]|0;f=c[d+180>>2]|0;g=d+184|0;i=G+8|0;j=G+16|0;k=G+24|0;e=1;while(1){if((e|0)>(f|0))break;P=+h[(c[(c[(c[g>>2]|0)+(e<<2)>>2]|0)+16>>2]|0)+16>>3];h[G>>3]=P;C=c[(c[(c[g>>2]|0)+(e<<2)>>2]|0)+16>>2]|0;O=+h[C+24>>3];h[i>>3]=O;M=+h[C+32>>3];h[j>>3]=M;N=+h[C+40>>3];h[k>>3]=N;h[K>>3]=+h[(+h[K>>3]>3];h[D>>3]=+h[(+h[D>>3]>3];h[F>>3]=+h[(+h[F>>3]>M?K:G)+16>>3];h[E>>3]=+h[(+h[E>>3]>N?K:G)+24>>3];e=e+1|0}e=c[d+12>>2]|0;if((e|0)!=0?(a[e+81>>0]|0)!=0:0){d=c[d+116>>2]&1;c[H>>2]=c[K>>2];c[H+4>>2]=c[K+4>>2];c[H+8>>2]=c[K+8>>2];c[H+12>>2]=c[K+12>>2];c[H+16>>2]=c[K+16>>2];c[H+20>>2]=c[K+20>>2];c[H+24>>2]=c[K+24>>2];c[H+28>>2]=c[K+28>>2];dB(I,H,e,d);c[K>>2]=c[I>>2];c[K+4>>2]=c[I+4>>2];c[K+8>>2]=c[I+8>>2];c[K+12>>2]=c[I+12>>2];c[K+16>>2]=c[I+16>>2];c[K+20>>2]=c[I+20>>2];c[K+24>>2]=c[I+24>>2];c[K+28>>2]=c[I+28>>2];d=c[J>>2]|0}J=d+16|0;c[J>>2]=c[K>>2];c[J+4>>2]=c[K+4>>2];c[J+8>>2]=c[K+8>>2];c[J+12>>2]=c[K+12>>2];c[J+16>>2]=c[K+16>>2];c[J+20>>2]=c[K+20>>2];c[J+24>>2]=c[K+24>>2];c[J+28>>2]=c[K+28>>2]}l=L;return}function fB(a,b,c){a=a|0;b=+b;c=+c;h[a>>3]=b;h[a+8>>3]=c;return}function gB(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=+h[b+8>>3]-+h[c+8>>3];h[a>>3]=+h[b>>3]-+h[c>>3];h[a+8>>3]=d;return}function hB(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=+h[c+8>>3]+ +h[b+8>>3];h[a>>3]=+h[c>>3]+ +h[b>>3];h[a+8>>3]=d;return}function iB(a){a=a|0;if((c[a+60>>2]|0)==(a|0))a=1;else a=(qK(En(a)|0,93039,7)|0)==0&1;return a|0}function jB(a){a=a|0;var b=0;b=Rl(22612,c[4345]|0)|0;mB(a,b);return b|0}function kB(a,b){a=a|0;b=b|0;a=bb[c[a>>2]&31](a,b,512)|0;if(!a)a=0;else a=c[a+12>>2]|0;return a|0}function lB(a,b,c){a=a|0;b=b|0;c=c|0;c=bn(so(b)|0,b,c,0,1)|0;Oo(c,122254,176,1)|0;Nm(a,c)|0;return c|0}function mB(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=l;l=l+16|0;g=h;f=a+16|0;e=1;while(1){a=c[f>>2]|0;if((e|0)>(c[a+180>>2]|0))break;a=c[(c[a+184>>2]|0)+(e<<2)>>2]|0;d=En(a)|0;if(!(bb[c[b>>2]&31](b,d,512)|0)){i=ww(16)|0;c[i+8>>2]=d;c[i+12>>2]=a;bb[c[b>>2]&31](b,i,1)|0}else{c[g>>2]=d;$l(0,93062,g)|0}mB(a,b);e=e+1|0}l=h;return}function nB(a,b,c){a=a|0;b=b|0;c=c|0;$I(b);return}function oB(a){a=a|0;var b=0,c=0,d=0;d=Jp(a,93047,1)|0;Oo(d,122277,280,1)|0;b=eo(a)|0;while(1){if(!b)break;c=Qm(a,b)|0;while(1){if(!c)break;pB(c,d);c=Sm(a,c)|0}b=fo(a,b)|0}b=eo(d)|0;while(1){if(!b)break;c=fo(d,b)|0;qB(b);ro(a,b)|0;b=c}mn(d)|0;return}function pB(b,d){b=b|0;d=d|0;var e=0,f=0;e=c[b>>2]&3;f=c[((e|0)==3?b:b+48|0)+40>>2]|0;e=c[((e|0)==2?b:b+-48|0)+40>>2]|0;if(!((a[(c[f+16>>2]|0)+118>>0]|0)==0?!(a[(c[e+16>>2]|0)+118>>0]|0):0)){f=rB(f,d)|0;e=lB(b,f,rB(e,d)|0)|0;f=c[b+16>>2]|0;d=f+8|0;e=c[e+16>>2]|0;c[e+8>>2]=c[d>>2];c[d>>2]=0;d=f+96|0;c[e+96>>2]=c[d>>2];c[d>>2]=0;d=f+108|0;c[e+108>>2]=c[d>>2];c[d>>2]=0;d=f+100|0;c[e+100>>2]=c[d>>2];c[d>>2]=0;f=f+104|0;c[e+104>>2]=c[f>>2];c[f>>2]=0;sB(b)}return}function qB(a){a=a|0;var b=0,d=0,e=0;e=a+16|0;b=c[e>>2]|0;d=c[b+132>>2]|0;if(d){$I(d);b=c[e>>2]|0}d=c[b+8>>2]|0;if(d){gb[c[(c[d+4>>2]|0)+4>>2]&127](a);b=c[e>>2]|0}pw(c[b+104>>2]|0);pw(c[(c[e>>2]|0)+108>>2]|0);Qo(a,122241)|0;return}function rB(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;f=so(b)|0;a:do if(a[(c[b+16>>2]|0)+118>>0]|0){jo(d,b,1)|0;b=XJ(En(b)|0,58)|0;if(!b)ma(96030,92694,1225,93114);d=b+1|0;b=oo(f,d,0)|0;if(!b){b=oo(f,d,1)|0;Oo(b,122241,304,1)|0;d=Em(f,1,0)|0;while(1){if(!d)break a;g=Km(b,d)|0;e=c[d+12>>2]|0;if((g|0)!=(e|0))Dm(b,d,e)|0;d=Em(f,1,d)|0}}}while(0);return b|0}function sB(a){a=a|0;var b=0;b=a+16|0;$I(c[(c[b>>2]|0)+144>>2]|0);tB(a);pw(c[(c[b>>2]|0)+96>>2]|0);pw(c[(c[b>>2]|0)+108>>2]|0);pw(c[(c[b>>2]|0)+100>>2]|0);pw(c[(c[b>>2]|0)+104>>2]|0);Qo(a,122254)|0;return}function tB(a){a=a|0;var b=0,d=0,e=0;e=a+16|0;a=c[e>>2]|0;b=c[a+8>>2]|0;if(b){d=0;while(1){a=c[b>>2]|0;if((d|0)>=(c[b+4>>2]|0))break;$I(c[a+(d*48|0)>>2]|0);d=d+1|0;b=c[(c[e>>2]|0)+8>>2]|0}$I(a);$I(c[(c[e>>2]|0)+8>>2]|0);a=c[e>>2]|0}c[a+8>>2]=0;return}function uB(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;e=zm(a,b,c,0)|0;if(!e)e=zm(a,b,c,d)|0;return e|0}function vB(a,b){a=a|0;b=b|0;return yJ(c[a>>2]|0,c[b>>2]|0)|0}function wB(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;q=l;l=l+1072|0;k=q+8|0;j=q;i=q+16|0;o=q+24|0;c[i>>2]=b;if((c[42366]|0)!=(d|0)){c[42366]=d;a[174084]=0}dm(o,1024,q+40|0);p=o+4|0;n=o+8|0;while(1){f=b+1|0;c[i>>2]=f;e=a[b>>0]|0;if(!(e<<24>>24))break;do if((e&255)<192)if(e<<24>>24==38){f=yB(i)|0;if(!f)e=38;else{if(f>>>0<127){e=f&255;break}b=c[p>>2]|0;e=b>>>0>=(c[n>>2]|0)>>>0;if(f>>>0<2047){if(e){em(o,1)|0;b=c[p>>2]|0}c[p>>2]=b+1;a[b>>0]=f>>>6|192;e=(f&63|128)&255;break}if(e){em(o,1)|0;b=c[p>>2]|0}c[p>>2]=b+1;a[b>>0]=f>>>12|224;b=c[p>>2]|0;if(b>>>0>=(c[n>>2]|0)>>>0){em(o,1)|0;b=c[p>>2]|0}c[p>>2]=b+1;a[b>>0]=f>>>6&63|128;e=(f&63|128)&255}}else{h=0;m=9}else if((e&255)>=224)if((e&255)>=240)if((e&255)<248){h=3;m=9}else{if(!(a[174084]|0)){c[j>>2]=En(d)|0;$l(0,94529,j)|0;a[174084]=1}h=-1;e=xB(e,o)|0;m=9}else{h=2;m=9}else{h=1;m=9}while(0);do if((m|0)==9){m=0;g=0;while(1){if((g|0)>=(h|0)){m=34;break}if((a[f>>0]&-64)<<24>>24!=-128)break;b=c[p>>2]|0;if(b>>>0>=(c[n>>2]|0)>>>0){em(o,1)|0;b=c[p>>2]|0}c[p>>2]=b+1;a[b>>0]=e;g=g+1|0;e=a[f>>0]|0;f=f+1|0}if((m|0)==34){m=0;c[i>>2]=f;break}c[i>>2]=f;if(!(a[174084]|0)){g=En(d)|0;c[k>>2]=h+1;c[k+4>>2]=g;$l(0,94650,k)|0;a[174084]=1}e=xB(e,o)|0}while(0);b=c[p>>2]|0;if(b>>>0>=(c[n>>2]|0)>>>0){em(o,1)|0;b=c[p>>2]|0}c[p>>2]=b+1;a[b>>0]=e;b=c[i>>2]|0}b=c[p>>2]|0;if(b>>>0>=(c[n>>2]|0)>>>0){em(o,1)|0;b=c[p>>2]|0}a[b>>0]=0;n=c[o>>2]|0;c[p>>2]=n;p=HL(n)|0;hm(o);l=q;return p|0}function xB(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;j=l;l=l+16|0;g=j;a[g>>0]=b;a[g+1>>0]=0;g=zB(g)|0;h=d+4|0;i=d+8|0;e=sJ(g)|0;f=g;while(1){if((e|0)<=1)break;b=c[h>>2]|0;if(b>>>0>=(c[i>>2]|0)>>>0){em(d,1)|0;b=c[h>>2]|0}k=a[f>>0]|0;c[h>>2]=b+1;a[b>>0]=k;e=e+-1|0;f=f+1|0}k=a[f>>0]|0;$I(g);l=j;return k|0}function yB(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+32|0;h=i;d=i+8|0;e=c[b>>2]|0;a:do if((a[e>>0]|0)!=35){c[h>>2]=d;g=0;b:while(1){if((g|0)>=8){d=0;break a}f=a[e+g>>0]|0;switch(f<<24>>24){case 0:{d=0;break a}case 59:break b;default:{}}a[d>>0]=f;d=d+1|0;g=g+1|0}a[d>>0]=0;d=wM(h,22648,252,8,30)|0;if(!d)d=0;else{e=e+(g+1)|0;d=c[d+4>>2]|0}}else{h=a[e+1>>0]|0;d=h&255;c:do if((h|32)<<24>>24==120){h=0;g=2;while(1){if((g|0)>=8){f=h;break c}f=a[e+g>>0]|0;d=f&255;if((f+-65&255)>=6)if((f+-97&255)>=6)if((f+-48&255)<10)f=-48;else{f=h;break c}else f=-87;else f=-55;d=f+d|0;h=d+(h<<4)|0;g=g+1|0}}else{f=0;g=1;while(1){if((g|0)>=8)break c;h=a[e+g>>0]|0;d=h&255;if((h+-48&255)>=10)break c;f=(f*10|0)+-48+d|0;g=g+1|0}}while(0);d=(d|0)==59;e=d?e+(g+1)|0:e;d=d?f:0}while(0);c[b>>2]=e;l=i;return d|0}function zB(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+1056|0;g=k;i=k+8|0;c[g>>2]=b;dm(i,1024,k+24|0);j=i+4|0;h=i+8|0;while(1){c[g>>2]=b+1;d=a[b>>0]|0;if(!(d<<24>>24))break;b=d&255;if(d<<24>>24==38){b=yB(g)|0;if(!b){b=38;f=6}else f=5}else f=5;do if((f|0)==5){f=0;if(b>>>0<127)f=6;else{d=c[j>>2]|0;e=d>>>0>=(c[h>>2]|0)>>>0;if(b>>>0<2047){if(e){em(i,1)|0;d=c[j>>2]|0}c[j>>2]=d+1;a[d>>0]=b>>>6|192;d=c[j>>2]|0;if(d>>>0>=(c[h>>2]|0)>>>0){em(i,1)|0;d=c[j>>2]|0}b=b&63|128;break}if(e){em(i,1)|0;d=c[j>>2]|0}c[j>>2]=d+1;a[d>>0]=b>>>12|224;d=c[j>>2]|0;if(d>>>0>=(c[h>>2]|0)>>>0){em(i,1)|0;d=c[j>>2]|0}c[j>>2]=d+1;a[d>>0]=b>>>6&63|128;d=c[j>>2]|0;if(d>>>0>=(c[h>>2]|0)>>>0){em(i,1)|0;d=c[j>>2]|0}b=b&63|128}}while(0);if((f|0)==6){d=c[j>>2]|0;if(d>>>0>=(c[h>>2]|0)>>>0){em(i,1)|0;d=c[j>>2]|0}}c[j>>2]=d+1;a[d>>0]=b;b=c[g>>2]|0}b=c[j>>2]|0;if(b>>>0>=(c[h>>2]|0)>>>0){em(i,1)|0;b=c[j>>2]|0}a[b>>0]=0;h=c[i>>2]|0;c[j>>2]=h;j=HL(h)|0;hm(i);l=k;return j|0}function AB(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+1040|0;g=i;dm(g,1024,i+16|0);h=g+4|0;f=g+8|0;while(1){d=b+1|0;e=a[b>>0]|0;if(!(e<<24>>24))break;if((e&255)<127){b=c[h>>2]|0;if(b>>>0>=(c[f>>2]|0)>>>0){em(g,1)|0;b=c[h>>2]|0}c[h>>2]=b+1;a[b>>0]=e;b=d;continue}else{e=a[d>>0]&63|e<<6&255;d=c[h>>2]|0;if(d>>>0>=(c[f>>2]|0)>>>0){em(g,1)|0;d=c[h>>2]|0}c[h>>2]=d+1;a[d>>0]=e;b=b+2|0;continue}}b=c[h>>2]|0;if(b>>>0>=(c[f>>2]|0)>>>0){em(g,1)|0;b=c[h>>2]|0}a[b>>0]=0;f=c[g>>2]|0;c[h>>2]=f;h=HL(f)|0;hm(g);l=i;return h|0}function BB(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+80|0;e=n+48|0;d=n+32|0;f=n+64|0;g=n+16|0;i=n;j=b+16|0;k=a+16|0;m=c[k>>2]|0;if(((+h[j>>3]>=+h[m+48>>3]?+h[m+64>>3]>=+h[b>>3]:0)?+h[b+24>>3]>=+h[m+56>>3]:0)?+h[m+72>>3]>=+h[b+8>>3]:0){m=m+16|0;c[d>>2]=c[j>>2];c[d+4>>2]=c[j+4>>2];c[d+8>>2]=c[j+8>>2];c[d+12>>2]=c[j+12>>2];c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];c[e+8>>2]=c[b+8>>2];c[e+12>>2]=c[b+12>>2];CB(g,d,e);c[d>>2]=c[m>>2];c[d+4>>2]=c[m+4>>2];c[d+8>>2]=c[m+8>>2];c[d+12>>2]=c[m+12>>2];c[e>>2]=c[g>>2];c[e+4>>2]=c[g+4>>2];c[e+8>>2]=c[g+8>>2];c[e+12>>2]=c[g+12>>2];gB(i,d,e);c[f>>2]=a;c[f+4>>2]=0;d=c[(c[(c[(c[k>>2]|0)+8>>2]|0)+4>>2]|0)+12>>2]|0;c[e>>2]=c[i>>2];c[e+4>>2]=c[i+4>>2];c[e+8>>2]=c[i+8>>2];c[e+12>>2]=c[i+12>>2];d=ab[d&63](f,e)|0}else d=0;l=n;return d|0}function CB(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=(+h[c+8>>3]+ +h[b+8>>3])*.5;h[a>>3]=(+h[c>>3]+ +h[b>>3])*.5;h[a+8>>3]=d;return}function DB(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0.0,g=0,i=0.0,j=0,k=0,m=0,n=0;e=l;l=l+80|0;j=e+64|0;k=e+48|0;m=e;n=e+32|0;g=e+16|0;h[m>>3]=+h[a+24>>3]*.5;h[m+8>>3]=+h[a+32>>3]*.5;a=a+56|0;c[k>>2]=c[a>>2];c[k+4>>2]=c[a+4>>2];c[k+8>>2]=c[a+8>>2];c[k+12>>2]=c[a+12>>2];c[j>>2]=c[m>>2];c[j+4>>2]=c[m+4>>2];c[j+8>>2]=c[m+8>>2];c[j+12>>2]=c[m+12>>2];gB(n,k,j);i=+h[n>>3];f=+h[n+8>>3];c[k>>2]=c[a>>2];c[k+4>>2]=c[a+4>>2];c[k+8>>2]=c[a+8>>2];c[k+12>>2]=c[a+12>>2];c[j>>2]=c[m>>2];c[j+4>>2]=c[m+4>>2];c[j+8>>2]=c[m+8>>2];c[j+12>>2]=c[m+12>>2];hB(g,k,j);d=+h[g+8>>3];if((+h[b+16>>3]>=i?+h[g>>3]>=+h[b>>3]:0)?+h[b+24>>3]>=f:0)a=d>=+h[b+8>>3]&1;else a=0;l=e;return a|0}function EB(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+80|0;k=n+48|0;j=n;h=a+16|0;a=c[h>>2]|0;i=c[a+8>>2]|0;a:do if((i|0)!=0?(g=i+8|0,c[j>>2]=c[g>>2],c[j+4>>2]=c[g+4>>2],c[j+8>>2]=c[g+8>>2],c[j+12>>2]=c[g+12>>2],c[j+16>>2]=c[g+16>>2],c[j+20>>2]=c[g+20>>2],c[j+24>>2]=c[g+24>>2],c[j+28>>2]=c[g+28>>2],c[k>>2]=c[b>>2],c[k+4>>2]=c[b+4>>2],c[k+8>>2]=c[b+8>>2],c[k+12>>2]=c[b+12>>2],c[k+16>>2]=c[b+16>>2],c[k+20>>2]=c[b+20>>2],c[k+24>>2]=c[b+24>>2],c[k+28>>2]=c[b+28>>2],(FB(j,k)|0)!=0):0){d=i+4|0;a=0;while(1){if((a|0)>=(c[d>>2]|0))break;e=j;f=(c[i>>2]|0)+(a*48|0)|0;g=e+48|0;do{c[e>>2]=c[f>>2];e=e+4|0;f=f+4|0}while((e|0)<(g|0));c[k>>2]=c[b>>2];c[k+4>>2]=c[b+4>>2];c[k+8>>2]=c[b+8>>2];c[k+12>>2]=c[b+12>>2];c[k+16>>2]=c[b+16>>2];c[k+20>>2]=c[b+20>>2];c[k+24>>2]=c[b+24>>2];c[k+28>>2]=c[b+28>>2];if(!((GB(j,k)|0)<<24>>24))a=a+1|0;else{a=1;break a}}a=c[h>>2]|0;m=7}else m=7;while(0);do if((m|0)==7){a=c[a+96>>2]|0;if(a|0?(c[k>>2]=c[b>>2],c[k+4>>2]=c[b+4>>2],c[k+8>>2]=c[b+8>>2],c[k+12>>2]=c[b+12>>2],c[k+16>>2]=c[b+16>>2],c[k+20>>2]=c[b+20>>2],c[k+24>>2]=c[b+24>>2],c[k+28>>2]=c[b+28>>2],(DB(a,k)|0)<<24>>24):0){a=1;break}a=0}while(0);l=n;return a|0} +function ti(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;h=a+16|0;i=ww((b[(c[h>>2]|0)+238>>1]<<2)+8|0)|0;g=eo(a)|0;while(1){if(!g)break;f=i+(c[(c[g+16>>2]|0)+232>>2]<<2)|0;c[f>>2]=(c[f>>2]|0)+1;f=Qm(a,g)|0;while(1){if(!f)break;j=c[f>>2]&3;d=c[(c[(c[((j|0)==3?f:f+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0;j=c[(c[(c[((j|0)==2?f:f+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0;k=(d|0)>(j|0);e=k?d:j;d=k?j:d;while(1){d=d+1|0;if((d|0)>=(e|0))break;k=i+(d<<2)|0;c[k>>2]=(c[k>>2]|0)+1}f=Sm(a,f)|0}g=fo(a,g)|0}f=ww((b[(c[h>>2]|0)+238>>1]<<6)+128|0)|0;e=c[h>>2]|0;c[e+196>>2]=f;d=b[e+236>>1]|0;while(1){if((d|0)>(b[e+238>>1]|0))break;j=i+(d<<2)|0;e=c[j>>2]|0;c[f+(d<<6)>>2]=e;c[f+(d<<6)+8>>2]=e;j=ww((c[j>>2]<<2)+4|0)|0;e=c[h>>2]|0;k=c[e+196>>2]|0;c[k+(d<<6)+4>>2]=j;c[k+(d<<6)+12>>2]=j;d=d+1|0;f=k}$I(i);return}function ui(a,d,e,f){a=a|0;d=d|0;e=e|0;f=f|0;var g=0,i=0,j=0,k=0,l=0,m=0;m=a+16|0;i=1;while(1){g=c[m>>2]|0;if((i|0)>(c[g+180>>2]|0))break;l=ui(c[(c[g+184>>2]|0)+(i<<2)>>2]|0,d,e,f)|0;i=i+1|0;f=l}a:do if((Wf(a)|0)!=(a|0)){WN(d|0,0,e<<2|0)|0;g=eo(a)|0;while(1){if(!g)break;k=g+16|0;c[d+(c[(c[k>>2]|0)+232>>2]<<2)>>2]=1;i=Qm(a,g)|0;while(1){if(!i)break;l=i+-48|0;j=c[(c[k>>2]|0)+232>>2]|0;while(1){e=j+1|0;if((j|0)>=(c[(c[(c[((c[i>>2]&3|0)==2?i:l)+40>>2]|0)+16>>2]|0)+232>>2]|0))break;c[d+(e<<2)>>2]=1;j=e}i=Sm(a,i)|0}g=fo(a,g)|0}g=c[m>>2]|0;i=b[g+236>>1]|0;while(1){if((i|0)>(b[g+238>>1]|0))break a;if(!(c[d+(i<<2)>>2]|0)){if(!f)f=Jp(Wf(a)|0,79522,1)|0;g=oo(f,0,1)|0;Oo(g,122241,304,1)|0;l=g+16|0;j=c[l>>2]|0;c[j+232>>2]=i;h[j+96>>3]=.5;h[j+88>>3]=.5;h[j+80>>3]=1.0;c[j+216>>2]=1;c[j+176>>2]=0;j=ww(20)|0;k=c[l>>2]|0;c[k+172>>2]=j;c[k+184>>2]=0;k=ww(20)|0;c[(c[l>>2]|0)+180>>2]=k;jo(a,g,1)|0;g=c[m>>2]|0}i=i+1|0}}while(0);return f|0}function vi(a){a=a|0;var b=0,d=0;Lh(a);b=a+16|0;a=1;while(1){d=c[b>>2]|0;if((a|0)>(c[d+180>>2]|0))break;vi(c[(c[d+184>>2]|0)+(a<<2)>>2]|0);a=a+1|0}return}function wi(a){a=a|0;var b=0,d=0;b=c[a>>2]&3;d=xi(c[((b|0)==3?a:a+48|0)+40>>2]|0)|0;b=c[17236+(d*12|0)+((xi(c[((b|0)==2?a:a+-48|0)+40>>2]|0)|0)<<2)>>2]|0;a=(c[a+16>>2]|0)+156|0;c[a>>2]=O(c[a>>2]|0,b)|0;return}function xi(b){b=b|0;b=c[b+16>>2]|0;if((a[b+156>>0]|0)==1)b=2;else b=(a[b+160>>0]|0)<2&1;return b|0}function yi(b,d){b=b|0;d=d|0;if(c[(c[b+16>>2]|0)+192>>2]|0){Zk(b);zi(b);if(a[174080]|0)ll(b);Ai(b);if(Dl(b)|0)zi(b);Bi(b);if(hx(b,2,Ci(b)|0)|0?(Di(b),hx(b,2,Ci(b)|0)|0):0)ma(79540,79568,134,79579);Ei(b);Fi(b,d);Gi(b)}return}function zi(d){d=d|0;var e=0,f=0,g=0,i=0,j=0.0,k=0.0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0,z=0.0;v=d+16|0;e=c[v>>2]|0;w=c[e+196>>2]|0;t=b[e+236>>1]|0;while(1){if((t|0)>(b[e+238>>1]|0))break;n=w+(t<<6)|0;o=w+(t<<6)+4|0;p=w+(t<<6)+40|0;q=w+(t<<6)+24|0;r=w+(t<<6)+32|0;s=w+(t<<6)+16|0;m=0;while(1){if((m|0)>=(c[n>>2]|0))break;l=(c[(c[o>>2]|0)+(m<<2)>>2]|0)+16|0;e=c[l>>2]|0;j=+h[e+80>>3]*.5;i=c[e+204>>2]|0;a:do if(i){g=0;while(1){f=c[i+(g<<2)>>2]|0;if(!f)break a;x=c[f>>2]&3;if((c[((x|0)==3?f:f+48|0)+40>>2]|0)==(c[((x|0)==2?f:f+-48|0)+40>>2]|0)?(u=c[(c[f+16>>2]|0)+96>>2]|0,(u|0)!=0):0){k=+h[u+32>>3]*.5;j=j>k?j:k}g=g+1|0}}while(0);if(+h[p>>3]>3]=j;h[p>>3]=j}if(+h[r>>3]>3]=j;h[r>>3]=j}f=c[e+212>>2]|0;if(f|0){if((f|0)==(d|0))g=0;else{g=EA(f,c[42189]|0,8,0)|0;e=c[l>>2]|0}i=c[e+232>>2]|0;f=c[f+16>>2]|0;e=f+128|0;j=j+ +(g|0);if((i|0)==(b[f+236>>1]|0)){k=+h[e>>3];h[e>>3]=k>j?k:j}e=f+120|0;if((i|0)==(b[f+238>>1]|0)){k=+h[e>>3];h[e>>3]=k>j?k:j}}m=m+1|0}t=t+1|0;e=c[v>>2]|0}m=fj(d)|0;g=c[v>>2]|0;e=b[g+238>>1]|0;h[(c[(c[c[w+(e<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]=+h[w+(e<<6)+16>>3];f=b[g+236>>1]|0;i=g+252|0;k=0.0;while(1){l=e+-1|0;if((e|0)<=(f|0))break;y=+h[w+(l<<6)+32>>3]+ +h[w+(e<<6)+40>>3]+ +(c[i>>2]|0);j=+h[w+(e<<6)+24>>3]+8.0+ +h[w+(l<<6)+16>>3];j=y>j?y:j;if((c[w+(l<<6)>>2]|0)>0)h[(c[(c[c[w+(l<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]=+h[(c[(c[c[w+(e<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]+j;k=k>j?k:j;e=l}b:do if((m|0)!=0?(c[g+116>>2]&1|0)!=0:0){gj(d,0);g=c[v>>2]|0;if(a[g+276>>0]|0){e=b[g+238>>1]|0;f=b[g+236>>1]|0;j=+h[(c[(c[c[w+(e<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3];k=0.0;while(1){i=e+-1|0;if((e|0)<=(f|0))break b;z=+h[(c[(c[c[w+(i<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3];y=z-j;j=z;k=k>y?k:y;e=i}}}while(0);c:do if(a[g+276>>0]|0){i=b[g+236>>1]|0;f=b[g+238>>1]|0;while(1){e=f+-1|0;if((f|0)<=(i|0))break c;if((c[w+(e<<6)>>2]|0)<=0){f=e;continue}h[(c[(c[c[w+(e<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]=+h[(c[(c[c[w+(f<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]+k;f=e}}while(0);e=g+192|0;while(1){e=c[e>>2]|0;if(!e)break;e=c[e+16>>2]|0;h[e+24>>3]=+h[(c[(c[c[w+(c[e+232>>2]<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3];e=e+164|0}return}function Ai(a){a=a|0;var b=0,d=0,e=0;bj(a);b=(c[a+16>>2]|0)+192|0;while(1){b=c[b>>2]|0;if(!b)break;e=b+16|0;b=c[e>>2]|0;d=c[b+224>>2]|0;if(d){cj(a,d);b=c[e>>2]|0}d=c[b+228>>2]|0;if(!d)d=b;else{cj(a,d);d=c[e>>2]|0}e=c[d+204>>2]|0;if(e|0){b=0;while(1)if(!(c[e+(b<<2)>>2]|0))break;else b=b+1|0}b=d+164|0}return}function Bi(a){a=a|0;Pi(a);Qi(a);Ri(a);Si(a);Ti(a);return}function Ci(a){a=a|0;var b=0,c=0.0;b=Jm(a,79768)|0;if(!b)a=2147483647;else{c=+tM(b);a=~~(c*+(nn(a)|0))}return a|0}function Di(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;r=d+16|0;e=c[r>>2]|0;q=b[e+236>>1]|0;while(1){p=b[e+238>>1]|0;if((q|0)>(p|0)){s=19;break}n=c[e+196>>2]|0;o=n+(q<<6)|0;m=c[o>>2]|0;n=n+(q<<6)+4|0;l=0;f=0;a:while(1){if((l|0)>=(m|0)){s=14;break}f=c[(c[n>>2]|0)+(l<<2)>>2]|0;h=c[f+16>>2]|0;i=c[h+256>>2]|0;b:do if(i|0){g=0;while(1){j=c[i+(g<<2)>>2]|0;if(!j)break b;k=c[j>>2]&3;if((c[(c[(c[((k|0)==2?j:j+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)>(q|0))break a;if((c[(c[(c[((k|0)==3?j:j+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)>(q|0))break a;else g=g+1|0}}while(0);h=c[h+248>>2]|0;c:do if(h|0){g=0;while(1){i=c[h+(g<<2)>>2]|0;if(!i)break c;j=c[i>>2]&3;if((c[(c[(c[((j|0)==3?i:i+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)>(q|0))break a;if((c[(c[(c[((j|0)==2?i:i+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)>(q|0))break a;else g=g+1|0}}while(0);l=l+1|0}if((s|0)==14){s=0;if(f){f=c[c[n>>2]>>2]|0;e=c[c[o+(((q|0)<(p|0)?1:-1)<<6)+4>>2]>>2]|0;if(!e){s=16;break}o=gh(d)|0;p=o+16|0;a[(c[p>>2]|0)+156>>0]=2;Ni(o,f,0.0,0)|0;Ni(o,e,0.0,0)|0;c[(c[p>>2]|0)+232>>2]=c[(c[((c[(c[f+16>>2]|0)+232>>2]|0)<(c[(c[e+16>>2]|0)+232>>2]|0)?f:e)+16>>2]|0)+232>>2];e=c[r>>2]|0}}q=q+1|0}if((s|0)==16)ma(79676,79568,111,79679);else if((s|0)==19)return}function Ei(a){a=a|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0;a=c[a+16>>2]|0;i=c[a+196>>2]|0;e=b[a+238>>1]|0;a=b[a+236>>1]|0;while(1){if((a|0)>(e|0))break;f=c[i+(a<<6)>>2]|0;g=i+(a<<6)+4|0;d=0;while(1){if((d|0)>=(f|0))break;k=c[(c[(c[g>>2]|0)+(d<<2)>>2]|0)+16>>2]|0;j=k+232|0;h[k+16>>3]=+(c[j>>2]|0);c[j>>2]=a;d=d+1|0}a=a+1|0}return}function Fi(a,d){a=a|0;d=d|0;var e=0,f=0.0,g=0,i=0.0,j=0,k=0,l=0.0,m=0,n=0,o=0,p=0;Hi(a,a);g=a+16|0;k=c[g>>2]|0;a:do if((b[k+238>>1]|0)>0?(j=c[k+8>>2]|0,e=c[j+84>>2]|0,e|0):0){o=~~(+h[k+32>>3]-+h[k+16>>3]);m=~~(+h[k+40>>3]-+h[k+24>>3]);p=(c[k+116>>2]&1|0)==0;n=p?m:o;m=p?o:m;if((e|0)==4){e=Ii(a)|0;k=c[g>>2]|0;j=c[k+8>>2]|0}else e=(e|0)==2&1;b:do if(!(e<<24>>24)){switch(c[j+84>>2]|0){case 5:{f=+h[j+64>>3];if(f<=0.0)break a;i=f/+h[k+32>>3];l=+h[j+72>>3]/+h[k+40>>3];f=i1.0&l>1.0){l=f;break b}else break a}case 1:break;default:break a}i=+h[j+16>>3];f=+(n|0)/+(m|0);if(f>3];if(f<=0.0)break a;i=f/+(m|0);f=+h[j+72>>3]/+(n|0);if(i<1.0|f<1.0)if(i>2]&1|0)==0;i=e?f:l;f=e?l:f;e=k+192|0;while(1){e=c[e>>2]|0;if(!e)break;e=c[e+16>>2]|0;p=e+16|0;l=+h[p>>3]*f;h[p>>3]=+(~~(l+(l>=0.0?.5:-.5))|0);p=e+24|0;l=+h[p>>3]*i;h[p>>3]=+(~~(l+(l>=0.0?.5:-.5))|0);e=e+164|0}Ji(a,f,i)}while(0);if(d|0)Ki(a,d);return}function Gi(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;h=b+16|0;b=(c[h>>2]|0)+192|0;while(1){b=c[b>>2]|0;if(!b)break;g=b+16|0;d=0;while(1){b=c[g>>2]|0;f=c[b+180>>2]|0;e=c[f+(d<<2)>>2]|0;if(!e)break;$I(c[e+16>>2]|0);$I(e);d=d+1|0}if(f){$I(f);b=c[g>>2]|0}d=c[b+172>>2]|0;if(d){$I(d);b=c[g>>2]|0}f=b+256|0;e=c[f+4>>2]|0;b=b+180|0;c[b>>2]=c[f>>2];c[b+4>>2]=e;b=c[g>>2]|0;e=b+248|0;f=c[e+4>>2]|0;b=b+172|0;c[b>>2]=c[e>>2];c[b+4>>2]=f;b=(c[g>>2]|0)+164|0}b=0;d=c[(c[h>>2]|0)+192>>2]|0;a:while(1){g=(b|0)==0;f=b+16|0;b=d;while(1){if(!b)break a;e=c[b+16>>2]|0;d=c[e+164>>2]|0;if((a[e+156>>0]|0)!=2)continue a;if(g)c[(c[h>>2]|0)+192>>2]=d;else c[(c[f>>2]|0)+164>>2]=d;$I(e);$I(b);b=d}}c[(c[(c[(c[h>>2]|0)+192>>2]|0)+16>>2]|0)+168>>2]=0;return}function Hi(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;e=a+16|0;d=1;while(1){f=c[e>>2]|0;if((d|0)>(c[f+180>>2]|0))break;Hi(c[(c[f+184>>2]|0)+(d<<2)>>2]|0,b);d=d+1|0}Mi(a,b);return}function Ii(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0.0,k=0.0,m=0,n=0.0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0;s=l;l=l+80|0;e=s+64|0;d=s+48|0;f=s+16|0;m=s;r=s+32|0;a=a+16|0;b=c[(c[a>>2]|0)+8>>2]|0;t=b+48|0;c[f>>2]=c[t>>2];c[f+4>>2]=c[t+4>>2];c[f+8>>2]=c[t+8>>2];c[f+12>>2]=c[t+12>>2];if((!(+h[f>>3]<.001)?(g=f+8|0,!(+h[g>>3]<.001)):0)?(i=b+32|0,c[m>>2]=c[i>>2],c[m+4>>2]=c[i+4>>2],c[m+8>>2]=c[i+8>>2],c[m+12>>2]=c[i+12>>2],c[d>>2]=c[f>>2],c[d+4>>2]=c[f+4>>2],c[d+8>>2]=c[f+8>>2],c[d+12>>2]=c[f+12>>2],c[e>>2]=c[i>>2],c[e+4>>2]=c[i+4>>2],c[e+8>>2]=c[i+8>>2],c[e+12>>2]=c[i+12>>2],Li(r,d,e),c[f>>2]=c[r>>2],c[f+4>>2]=c[r+4>>2],c[f+8>>2]=c[r+8>>2],c[f+12>>2]=c[r+12>>2],c[d>>2]=c[r>>2],c[d+4>>2]=c[r+4>>2],c[d+8>>2]=c[r+8>>2],c[d+12>>2]=c[r+12>>2],c[e>>2]=c[m>>2],c[e+4>>2]=c[m+4>>2],c[e+8>>2]=c[m+8>>2],c[e+12>>2]=c[m+12>>2],Li(f,d,e),i=c[a>>2]|0,j=+h[i+32>>3],k=+h[i+40>>3],n=+h[f>>3],o=n/j,p=+h[g>>3],q=p/k,!(o>=1.0&q>=1.0)):0){o=o.5?o:.5;q=+N(+(o*k/p))*p/k;p=+N(+(o*j/n))*n/j*j;a=c[i+8>>2]|0;h[a+64>>3]=p;h[a+72>>3]=q*k;a=1}else a=0;l=s;return a|0}function Ji(a,b,d){a=a|0;b=+b;d=+d;var e=0,f=0;e=a+16|0;a=1;while(1){f=c[e>>2]|0;if((a|0)>(c[f+180>>2]|0))break;Ji(c[(c[f+184>>2]|0)+(a<<2)>>2]|0,b,d);a=a+1|0}e=f+16|0;h[e>>3]=+h[e>>3]*b;e=f+24|0;h[e>>3]=+h[e>>3]*d;e=f+32|0;h[e>>3]=+h[e>>3]*b;f=f+40|0;h[f>>3]=+h[f>>3]*d;return}function Ki(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0,g=0,i=0.0,j=0,k=0,m=0,n=0;m=l;l=l+32|0;j=m+24|0;g=m+16|0;f=m;n=c[a+16>>2]|0;e=+h[n+32>>3]-+h[n+16>>3];d=+h[n+40>>3]-+h[n+24>>3];i=e/d;if(0){n=c[13918]|0;h[f>>3]=i;h[f+8>>3]=e*.0001*d;AL(n,79592,f)|0;c[g>>2]=lk(a)|0;AL(n,79617,g)|0}d=+h[b>>3];do if(!(i>d*1.1)){a=b+24|0;if(!(i<=d*.8)){c[a>>2]=0;k=9;break}c[a>>2]=-1;if(0){YL(79627,34,1,c[13918]|0)|0;k=9}}else{c[b+24>>2]=~~(d*+((c[b+20>>2]|0)-(c[b+16>>2]|0)|0)/i);k=9}while(0);if((k|0)==9?0:0){n=c[13918]|0;c[j>>2]=c[b+24>>2];AL(n,79662,j)|0}l=m;return}function Li(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=+h[b+8>>3]-+h[c+8>>3];h[a>>3]=+h[b>>3]-+h[c>>3];h[a+8>>3]=d;return}function Mi(d,e){d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0.0;s=(Wf(d)|0)==(d|0);v=d+16|0;w=c[v>>2]|0;a:do if(s){f=b[w+236>>1]|0;d=b[w+238>>1]|0;q=d<<16>>16;r=w+196|0;s=w+196|0;p=f<<16>>16;i=-2147483647.0;g=2147483647.0;while(1){if((p|0)>(q|0))break;j=c[r>>2]|0;o=c[j+(p<<6)>>2]|0;if((o|0)!=0?(t=c[j+(p<<6)+4>>2]|0,u=c[t>>2]|0,(u|0)!=0):0){l=1;j=u;while(1){j=c[j+16>>2]|0;k=a[j+156>>0]|0;if(!((l|0)<(o|0)&k<<24>>24!=0))break;j=c[t+(l<<2)>>2]|0;l=l+1|0}if(!(k<<24>>24)){m=+h[j+16>>3]-+h[j+88>>3];n=g>2]|0)+(p<<6)+4>>2]|0;k=o+-2|0;j=o+-1|0;while(1){j=c[(c[l+(j<<2)>>2]|0)+16>>2]|0;if(!(a[j+156>>0]|0))break;else{j=k;k=k+-1|0}}x=+h[j+96>>3]+ +h[j+16>>3];i=i>x?i:x;g=n?g:m}}p=p+1|0}k=c[w+180>>2]|0;l=w+184|0;j=1;while(1){if((j|0)>(k|0))break a;u=c[(c[(c[l>>2]|0)+(j<<2)>>2]|0)+16>>2]|0;x=+h[u+16>>3]+-8.0;m=+h[u+32>>3]+8.0;j=j+1|0;i=i>m?i:m;g=g>2]|0)+16>>2]|0)+232>>2]|0);g=+(c[(c[(c[w+256>>2]|0)+16>>2]|0)+232>>2]|0);f=b[w+236>>1]|0;d=b[w+238>>1]|0}while(0);e=c[(c[e+16>>2]|0)+196>>2]|0;m=+h[(c[(c[c[e+(d<<16>>16<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]-+h[w+120>>3];x=+h[w+128>>3]+ +h[(c[(c[c[e+(f<<16>>16<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3];h[w+16>>3]=g;h[w+24>>3]=m;e=c[v>>2]|0;h[e+32>>3]=i;h[e+40>>3]=x;return}function Ni(a,d,e,f){a=a|0;d=d|0;e=+e;f=f|0;var g=0,h=0,i=0,j=0;i=ww(96)|0;j=i+48|0;c[j>>2]=c[j>>2]|3;c[i>>2]=c[i>>2]&-4|2;g=ww(176)|0;h=i+16|0;c[h>>2]=g;c[((c[i>>2]&3|0)==3?i:j)+40>>2]=a;c[((c[i>>2]&3|0)==2?i:i+-48|0)+40>>2]=d;if(e>65535.0){Oi(e);e=65535.0;g=c[h>>2]|0}b[g+170>>1]=~~(e+(e>=0.0?.5:-.5));c[g+156>>2]=f;Wg(i)|0;return i|0}function Oi(a){a=+a;var b=0,d=0;b=l;l=l+16|0;d=b;h[d>>3]=a;c[d+8>>2]=65535;$l(1,79692,d)|0;l=b;return}function Pi(a){a=a|0;var b=0,d=0,e=0,f=0;a=(c[a+16>>2]|0)+192|0;while(1){a=c[a>>2]|0;if(!a)break;f=a+16|0;e=c[f>>2]|0;a=e+172|0;d=c[a+4>>2]|0;e=e+248|0;c[e>>2]=c[a>>2];c[e+4>>2]=d;e=c[f>>2]|0;d=e+180|0;a=c[d+4>>2]|0;e=e+256|0;c[e>>2]=c[d>>2];c[e+4>>2]=a;e=c[f>>2]|0;a=c[e+180>>2]|0;d=0;while(1)if(!(c[a+(d<<2)>>2]|0))break;else d=d+1|0;b=c[e+172>>2]|0;a=0;while(1)if(!(c[b+(a<<2)>>2]|0))break;else a=a+1|0;c[e+176>>2]=0;a=ww((a+d<<2)+16|0)|0;e=c[f>>2]|0;c[e+172>>2]=a;c[e+184>>2]=0;e=ww(16)|0;a=c[f>>2]|0;c[a+180>>2]=e;a=a+164|0}return}function Qi(d){d=d|0;var f=0,g=0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0.0,q=0,r=0,s=0,t=0.0,u=0,v=0,w=0,x=0,y=0,z=0,A=0.0,B=0.0;z=l;l=l+16|0;w=z;x=d+16|0;u=c[x>>2]|0;y=c[u+196>>2]|0;d=(a[(c[(c[d+60>>2]|0)+16>>2]|0)+113>>0]&1)!=0;v=c[u+248>>2]|0;c[w>>2]=v;c[w+4>>2]=d?5:v;v=b[u+236>>1]|0;d=u;while(1){if((v|0)>(b[d+238>>1]|0))break;r=y+(v<<6)+4|0;c[(c[(c[c[r>>2]>>2]|0)+16>>2]|0)+232>>2]=0;s=y+(v<<6)|0;t=+(c[w+((v&1)<<2)>>2]|0);p=0.0;k=0;a:while(1){if((k|0)>=(c[s>>2]|0))break;f=c[r>>2]|0;m=c[f+(k<<2)>>2]|0;u=m+16|0;d=c[u>>2]|0;i=+h[d+96>>3];h[d+240>>3]=i;if((c[d+208>>2]|0)>0){j=0;f=0;while(1){g=c[(c[d+204>>2]|0)+(j<<2)>>2]|0;if(!g)break;q=c[g>>2]&3;if((c[((q|0)==3?g:g+48|0)+40>>2]|0)==(c[((q|0)==2?g:g+-48|0)+40>>2]|0)){f=(Rz(g)|0)+f|0;d=c[u>>2]|0}j=j+1|0}q=d+96|0;i=+h[q>>3]+ +(f|0);h[q>>3]=i;f=c[r>>2]|0}q=k+1|0;f=c[f+(q<<2)>>2]|0;if(f){o=f+16|0;i=i+t+ +h[(c[o>>2]|0)+88>>3];Ni(m,f,i,0)|0;d=~~(i+p);c[(c[o>>2]|0)+232>>2]=d;p=+(d|0);d=c[u>>2]|0}f=c[d+112>>2]|0;if(f){j=c[d+256>>2]|0;k=c[j>>2]|0;j=c[j+4>>2]|0;d=(c[(c[(c[((c[k>>2]&3|0)==2?k:k+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0)>(c[(c[(c[((c[j>>2]&3|0)==2?j:j+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0);g=d?j:k;j=d?k:j;k=f+16|0;d=c[k>>2]|0;i=+((O(c[(c[x>>2]|0)+248>>2]|0,e[d+170>>1]|0)|0)/2|0|0);o=c[g>>2]&3;f=c[((o|0)==2?g:g+-48|0)+40>>2]|0;g=c[((o|0)==3?g:g+48|0)+40>>2]|0;if(!($i(g,f)|0))Ni(f,g,+(~~(+h[(c[f+16>>2]|0)+96>>3]+i+ +h[(c[g+16>>2]|0)+88>>3])|0),c[d+156>>2]|0)|0;d=c[j>>2]&3;f=c[((d|0)==3?j:j+48|0)+40>>2]|0;d=c[((d|0)==2?j:j+-48|0)+40>>2]|0;if(!($i(d,f)|0)){Ni(f,d,+(~~(+h[(c[f+16>>2]|0)+96>>3]+i+ +h[(c[d+16>>2]|0)+88>>3])|0),c[(c[k>>2]|0)+156>>2]|0)|0;o=0}else o=0}else o=0;while(1){d=c[u>>2]|0;if((o|0)>=(c[d+192>>2]|0)){k=q;continue a}m=c[(c[d+188>>2]|0)+(o<<2)>>2]|0;k=c[m>>2]&3;g=c[((k|0)==3?m:m+48|0)+40>>2]|0;k=c[((k|0)==2?m:m+-48|0)+40>>2]|0;j=(c[(c[g+16>>2]|0)+236>>2]|0)<(c[(c[k+16>>2]|0)+236>>2]|0);f=j?g:k;g=j?k:g;i=+h[(c[g+16>>2]|0)+88>>3]+ +h[(c[f+16>>2]|0)+96>>3];k=m+16|0;j=~~(i+ +(O(c[(c[x>>2]|0)+248>>2]|0,e[(c[k>>2]|0)+170>>1]|0)|0));n=Tg(f,g)|0;if(!n){d=c[k>>2]|0;if(!(c[d+96>>2]|0))Ni(f,g,+(j|0),c[d+156>>2]|0)|0}else{A=+(j|0);d=c[k>>2]|0;B=+h[d+136>>3];i=i+ +(c[(c[x>>2]|0)+248>>2]|0)+ +(~~(B+(B>=0.0?.5:-.5))|0);f=~~(i65535){Oi(+(f|0));f=65535;d=c[k>>2]|0}k=c[n+16>>2]|0;j=k+170|0;g=e[j>>1]|0;b[j>>1]=(f|0)<(g|0)?g:f;k=k+156|0;c[k>>2]=c[(c[((c[k>>2]|0)>(c[d+156>>2]|0)?n:m)+16>>2]|0)+156>>2]}o=o+1|0}}v=v+1|0;d=c[x>>2]|0}l=z;return}function Ri(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0;d=(c[b+16>>2]|0)+192|0;while(1){d=c[d>>2]|0;if(!d)break;g=d+16|0;d=c[g>>2]|0;e=c[d+256>>2]|0;a:do if(e){f=0;while(1){e=c[e+(f<<2)>>2]|0;if(!e)break a;n=gh(b)|0;d=n+16|0;a[(c[d>>2]|0)+156>>0]=2;l=e+16|0;k=c[l>>2]|0;i=~~(+h[k+56>>3]-+h[k+16>>3]);m=(i|0)>0;j=m?0:0-i|0;i=m?i:0;m=e+48|0;Ni(n,c[((c[e>>2]&3|0)==3?e:m)+40>>2]|0,+(i+1|0),c[k+156>>2]|0)|0;k=e+-48|0;Ni(n,c[((c[e>>2]&3|0)==2?e:k)+40>>2]|0,+(j+1|0),c[(c[l>>2]|0)+156>>2]|0)|0;l=c[e>>2]&3;i=(c[(c[(c[((l|0)==3?e:m)+40>>2]|0)+16>>2]|0)+232>>2]|0)-i|0;e=(c[(c[(c[((l|0)==2?e:k)+40>>2]|0)+16>>2]|0)+232>>2]|0)-j|0;c[(c[d>>2]|0)+232>>2]=((i|0)<(e|0)?i:e)+-1;d=c[g>>2]|0;f=f+1|0;e=c[d+256>>2]|0}}while(0);d=d+164|0}return}function Si(a){a=a|0;if((c[(c[a+16>>2]|0)+180>>2]|0)>0){Wi(a);Xi(a);Yi(a);Zi(a)}return}function Ti(a){a=a|0;var b=0.0,d=0.0,e=0,f=0;e=a+16|0;f=c[(c[e>>2]|0)+8>>2]|0;if((c[f+84>>2]|0)==3?(b=+h[f+64>>3],d=+h[f+72>>3],!(d*b<=1.0)):0){Ui(a);f=c[e>>2]|0;d=(c[f+116>>2]&1|0)==0?b:d;Ni(c[f+256>>2]|0,c[f+260>>2]|0,d<65535.0?d:65535.0,1e3)|0}return}function Ui(a){a=a|0;var d=0,e=0,f=0.0,g=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+16|0;m=n;e=EA(a,c[42189]|0,8,0)|0;Vi(a);i=a+16|0;g=c[i>>2]|0;j=c[g+256>>2]|0;k=c[g+260>>2]|0;f=+(e|0);e=b[g+236>>1]|0;while(1){if((e|0)>(b[g+238>>1]|0))break;d=c[g+196>>2]|0;do if(c[d+(e<<6)>>2]|0){d=c[c[d+(e<<6)+4>>2]>>2]|0;if(!d){c[m>>2]=En(a)|0;c[m+4>>2]=e;$l(1,79776,m)|0;break}else{Ni(j,d,+h[(c[d+16>>2]|0)+88>>3]+f+ +h[g+96>>3],0)|0;g=c[i>>2]|0;d=c[g+196>>2]|0;d=c[(c[d+(e<<6)+4>>2]|0)+((c[d+(e<<6)>>2]|0)+-1<<2)>>2]|0;Ni(d,k,+h[(c[d+16>>2]|0)+96>>3]+f+ +h[g+64>>3],0)|0;break}}while(0);e=e+1|0;g=c[i>>2]|0}l=n;return}function Vi(b){b=b|0;var d=0,e=0,f=0;d=b+16|0;if(!(c[(c[d>>2]|0)+256>>2]|0)){f=gh(Wf(b)|0)|0;a[(c[f+16>>2]|0)+156>>0]=2;e=gh(Wf(b)|0)|0;a[(c[e+16>>2]|0)+156>>0]=2;if((c[(c[d>>2]|0)+12>>2]|0?(Wf(b)|0)!=(b|0):0)?(c[(c[(to(b)|0)+16>>2]|0)+116>>2]&1|0)==0:0){b=c[d>>2]|0;Ni(f,e,+(~~+h[b+48+((+h[b+48>>3]>+h[b+80>>3]?0:2)<<4)>>3]|0),0)|0}d=c[d>>2]|0;c[d+256>>2]=f;c[d+260>>2]=e}return}function Wi(a){a=a|0;var b=0,d=0;do if((Wf(a)|0)!=(a|0)){Ui(a);a=a+16|0;b=c[a>>2]|0;b=Tg(c[b+256>>2]|0,c[b+260>>2]|0)|0;if(!b){d=c[a>>2]|0;Ni(c[d+256>>2]|0,c[d+260>>2]|0,1.0,128)|0;break}else{d=(c[b+16>>2]|0)+156|0;c[d>>2]=(c[d>>2]|0)+128;break}}else a=a+16|0;while(0);b=1;while(1){d=c[a>>2]|0;if((b|0)>(c[d+180>>2]|0))break;Wi(c[(c[d+184>>2]|0)+(b<<2)>>2]|0);b=b+1|0}return}function Xi(d){d=d|0;var e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0.0,n=0,o=0;k=EA(d,c[42189]|0,8,0)|0;o=d+16|0;e=c[o>>2]|0;m=+(k|0);k=b[e+236>>1]|0;while(1){if((k|0)>(b[e+238>>1]|0)){f=1;break}e=c[e+196>>2]|0;a:do if(c[e+(k<<6)>>2]|0?(l=c[c[e+(k<<6)+4>>2]>>2]|0,l|0):0){i=l+16|0;f=c[(c[i>>2]|0)+236>>2]|0;while(1){if((f|0)<=0)break;f=f+-1|0;j=c[(c[(c[(c[(Wf(d)|0)+16>>2]|0)+196>>2]|0)+(k<<6)+4>>2]|0)+(f<<2)>>2]|0;g=j+16|0;e=c[g>>2]|0;if(!(a[e+156>>0]|0)){n=10;break}if(_i(d,j)|0){n=9;break}}if((n|0)==9){e=c[g>>2]|0;n=10}if((n|0)==10){n=0;Ni(j,c[(c[o>>2]|0)+256>>2]|0,+h[e+96>>3]+m,0)|0}f=(c[(c[(c[o>>2]|0)+196>>2]|0)+(k<<6)>>2]|0)+(c[(c[i>>2]|0)+236>>2]|0)|0;while(1){if((f|0)>=(c[(c[(c[(Wf(d)|0)+16>>2]|0)+196>>2]|0)+(k<<6)>>2]|0))break a;i=c[(c[(c[(c[(Wf(d)|0)+16>>2]|0)+196>>2]|0)+(k<<6)+4>>2]|0)+(f<<2)>>2]|0;g=i+16|0;e=c[g>>2]|0;if(!(a[e+156>>0]|0))break;if(!(_i(d,i)|0))f=f+1|0;else{n=15;break}}if((n|0)==15){n=0;e=c[g>>2]|0}Ni(c[(c[o>>2]|0)+260>>2]|0,i,+h[e+88>>3]+m,0)|0}while(0);k=k+1|0;e=c[o>>2]|0}while(1){if((f|0)>(c[e+180>>2]|0))break;Xi(c[(c[e+184>>2]|0)+(f<<2)>>2]|0);f=f+1|0;e=c[o>>2]|0}return}function Yi(a){a=a|0;var b=0,d=0.0,e=0,f=0,g=0;e=EA(a,c[42189]|0,8,0)|0;Vi(a);b=a+16|0;d=+(e|0);a=1;while(1){e=c[b>>2]|0;if((a|0)>(c[e+180>>2]|0))break;e=c[(c[e+184>>2]|0)+(a<<2)>>2]|0;Vi(e);f=c[b>>2]|0;g=e+16|0;Ni(c[f+256>>2]|0,c[(c[g>>2]|0)+256>>2]|0,+h[f+96>>3]+d,0)|0;f=c[b>>2]|0;Ni(c[(c[g>>2]|0)+260>>2]|0,c[f+260>>2]|0,+h[f+64>>3]+d,0)|0;Yi(e);a=a+1|0}return}function Zi(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0.0,n=0,o=0;d=EA(a,c[42189]|0,8,0)|0;n=a+16|0;a=1;while(1){f=c[n>>2]|0;e=c[f+180>>2]|0;if((a|0)>(e|0))break;Vi(c[(c[f+184>>2]|0)+(a<<2)>>2]|0);a=a+1|0}m=+(d|0);l=1;a=e;d=f;while(1){if((l|0)>(a|0))break;k=l+1|0;j=k;while(1){e=c[d+184>>2]|0;f=c[e+(l<<2)>>2]|0;if((j|0)>(a|0))break;e=c[e+(j<<2)>>2]|0;g=(b[(c[f+16>>2]|0)+236>>1]|0)>(b[(c[e+16>>2]|0)+236>>1]|0);i=g?e:f;e=g?f:e;f=c[i+16>>2]|0;g=c[e+16>>2]|0;o=b[g+236>>1]|0;h=o<<16>>16;if((b[f+238>>1]|0)>=o<<16>>16){a=(c[(c[(c[c[(c[f+196>>2]|0)+(h<<6)+4>>2]>>2]|0)+16>>2]|0)+236>>2]|0)<(c[(c[(c[c[(c[g+196>>2]|0)+(h<<6)+4>>2]>>2]|0)+16>>2]|0)+236>>2]|0);Ni(c[(c[(a?i:e)+16>>2]|0)+260>>2]|0,c[(c[(a?e:i)+16>>2]|0)+256>>2]|0,m,0)|0;a=c[n>>2]|0;d=a;a=c[a+180>>2]|0}j=j+1|0}Zi(f);d=c[n>>2]|0;l=k;a=c[d+180>>2]|0}return}function _i(b,d){b=b|0;d=d|0;var e=0;d=c[d+16>>2]|0;if((a[d+156>>0]|0)==1){d=c[c[d+256>>2]>>2]|0;while(1){e=c[(c[d+16>>2]|0)+116>>2]|0;if(!e)break;else d=e}if(!(Co(b,c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0)|0))d=(Co(b,c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)|0)==0&1;else d=0}else d=0;return d|0}function $i(a,b){a=a|0;b=b|0;return aj(a,b)|0}function aj(a,b){a=a|0;b=b|0;var d=0,e=0;a:do if((a|0)==(b|0))a=1;else{d=c[(c[a+16>>2]|0)+180>>2]|0;a=0;while(1){e=c[d+(a<<2)>>2]|0;if(!e){a=0;break a}if(!(aj(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,b)|0))a=a+1|0;else{a=1;break}}}while(0);return a|0}function bj(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=d+16|0;d=c[k>>2]|0;j=b[d+236>>1]|0;while(1){if((j|0)>(b[d+238>>1]|0))break;h=c[d+196>>2]|0;g=c[h+(j<<6)>>2]|0;h=h+(j<<6)+4|0;i=0;f=0;while(1){if((f|0)>=(g|0))break;e=c[(c[(c[h>>2]|0)+(f<<2)>>2]|0)+16>>2]|0;c[e+236>>2]=i;if((a[e+159>>0]|0)==6)e=c[e+216>>2]|0;else e=1;i=e+i|0;f=f+1|0}if((i|0)>(g|0)){d=c[h>>2]|0;if(!d)d=xw((i<<2)+4|0)|0;else d=zw(d,(i<<2)+4|0)|0;f=c[(c[k>>2]|0)+196>>2]|0;c[f+(j<<6)+4>>2]=d;e=c[f+(j<<6)>>2]|0;while(1){d=e+-1|0;if((e|0)<=0)break;h=c[f+(j<<6)+4>>2]|0;e=c[h+(d<<2)>>2]|0;c[h+(c[(c[e+16>>2]|0)+236>>2]<<2)>>2]=e;e=d;f=c[(c[k>>2]|0)+196>>2]|0}c[f+(j<<6)>>2]=i;c[(c[f+(j<<6)+4>>2]|0)+(i<<2)>>2]=0;d=c[k>>2]|0}j=j+1|0}return}function cj(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;o=l;l=l+48|0;n=o+32|0;m=o+8|0;d=o+24|0;k=o+16|0;j=o;e=b+16|0;f=c[e>>2]|0;a:do if((c[f+216>>2]|0)>=2){c[m>>2]=~~(+h[f+16>>3]-+h[f+88>>3]);c[m+4>>2]=~~+h[f+24>>3];c[n>>2]=c[m>>2];c[n+4>>2]=c[m+4>>2];dj(d,b,n);g=d;i=c[g+4>>2]|0;d=m;c[d>>2]=c[g>>2];c[d+4>>2]=i;d=c[e>>2]|0;if((c[d+184>>2]|0)>0){j=c[c[d+180>>2]>>2]|0;d=(c[d+236>>2]|0)+1|0;j=Tm(a,c[((c[j>>2]&3|0)==2?j:j+-48|0)+40>>2]|0)|0;while(1){if(!j)break a;i=(c[j>>2]&3|0)==2?j:j+-48|0;e=i+48|0;f=c[((c[i>>2]&3|0)==3?i:e)+40>>2]|0;if((f|0)!=(b|0)?(LA(f)|0)==(b|0):0){f=c[((c[i>>2]&3|0)==3?i:e)+40>>2]|0;c[n>>2]=c[m>>2];c[n+4>>2]=c[m+4>>2];ej(k,a,f,n,d);f=k;e=c[f+4>>2]|0;g=m;c[g>>2]=c[f>>2];c[g+4>>2]=e;lh(i);g=i+-48|0;e=c[(c[((c[i>>2]&3|0)==2?i:g)+40>>2]|0)+16>>2]|0;f=c[e+172>>2]|0;if(!f)e=xw((c[e+176>>2]<<2)+8|0)|0;else e=zw(f,(c[e+176>>2]<<2)+8|0)|0;c[(c[(c[((c[i>>2]&3|0)==2?i:g)+40>>2]|0)+16>>2]|0)+172>>2]=e;p=c[(c[((c[i>>2]&3|0)==2?i:g)+40>>2]|0)+16>>2]|0;e=c[p+172>>2]|0;p=p+176|0;f=c[p>>2]|0;c[p>>2]=f+1;c[e+(f<<2)>>2]=i;i=c[(c[((c[i>>2]&3|0)==2?i:g)+40>>2]|0)+16>>2]|0;c[(c[i+172>>2]|0)+(c[i+176>>2]<<2)>>2]=0;d=d+1|0}j=Um(a,j)|0}}else{i=c[c[d+172>>2]>>2]|0;d=(c[d+236>>2]|0)+1|0;i=Qm(a,c[((c[i>>2]&3|0)==3?i:i+48|0)+40>>2]|0)|0;while(1){if(!i)break a;e=i+-48|0;f=c[((c[i>>2]&3|0)==2?i:e)+40>>2]|0;if((f|0)!=(b|0)?(LA(f)|0)==(b|0):0){f=c[((c[i>>2]&3|0)==2?i:e)+40>>2]|0;c[n>>2]=c[m>>2];c[n+4>>2]=c[m+4>>2];ej(j,a,f,n,d);f=j;e=c[f+4>>2]|0;g=m;c[g>>2]=c[f>>2];c[g+4>>2]=e;lh(i);g=i+48|0;e=c[(c[((c[i>>2]&3|0)==3?i:g)+40>>2]|0)+16>>2]|0;f=c[e+180>>2]|0;if(!f)e=xw((c[e+184>>2]<<2)+8|0)|0;else e=zw(f,(c[e+184>>2]<<2)+8|0)|0;c[(c[(c[((c[i>>2]&3|0)==3?i:g)+40>>2]|0)+16>>2]|0)+180>>2]=e;f=c[(c[((c[i>>2]&3|0)==3?i:g)+40>>2]|0)+16>>2]|0;k=c[f+180>>2]|0;f=f+184|0;p=c[f>>2]|0;c[f>>2]=p+1;c[k+(p<<2)>>2]=i;p=c[(c[((c[i>>2]&3|0)==3?i:g)+40>>2]|0)+16>>2]|0;c[(c[p+180>>2]|0)+(c[p+184>>2]<<2)>>2]=0;d=d+1|0}i=Sm(a,i)|0}}}while(0);l=o;return}function dj(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0.0;LB(b,c[(c[(so(b)|0)+16>>2]|0)+116>>2]&1);e=c[b+16>>2]|0;h[e+24>>3]=+(c[d+4>>2]|0);f=+h[e+88>>3]+ +(c[d>>2]|0);h[e+16>>3]=f;f=f+ +h[e+96>>3];c[d>>2]=~~(f+ +(c[(c[(so(b)|0)+16>>2]|0)+248>>2]|0));e=d;b=c[e+4>>2]|0;d=a;c[d>>2]=c[e>>2];c[d+4>>2]=b;return}function ej(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;i=l;l=l+16|0;h=i;b=Wf(b)|0;g=LA(d)|0;if((g|0)!=(d|0))dh(g,d);j=c[d+16>>2]|0;c[j+236>>2]=f;g=c[(c[g+16>>2]|0)+232>>2]|0;c[j+232>>2]=g;c[(c[(c[(c[b+16>>2]|0)+196>>2]|0)+(g<<6)+4>>2]|0)+(f<<2)>>2]=d;c[h>>2]=c[e>>2];c[h+4>>2]=c[e+4>>2];dj(a,d,h);l=i;return}function fj(a){a=a|0;var d=0.0,e=0.0,f=0,g=0,i=0,j=0.0,k=0,l=0,m=0,n=0.0;m=c[(c[(Wf(a)|0)+16>>2]|0)+196>>2]|0;if((Wf(a)|0)==(a|0))j=8.0;else j=+(EA(a,c[42189]|0,8,0)|0);l=a+16|0;g=c[l>>2]|0;f=0;k=1;e=+h[g+120>>3];d=+h[g+128>>3];while(1){if((k|0)>(c[g+180>>2]|0))break;i=c[(c[g+184>>2]|0)+(k<<2)>>2]|0;f=fj(i)|0|f;i=c[i+16>>2]|0;g=c[l>>2]|0;if((b[i+238>>1]|0)==(b[g+238>>1]|0)){n=+h[i+120>>3]+j;e=e>n?e:n}if((b[i+236>>1]|0)==(b[g+236>>1]|0)){n=+h[i+128>>3]+j;d=d>n?d:n}k=k+1|0}if((Wf(a)|0)!=(a|0)?(c[(c[l>>2]|0)+12>>2]|0)!=0:0)if(!(c[(c[(to(a)|0)+16>>2]|0)+116>>2]&1)){k=c[l>>2]|0;f=1;e=+h[k+56>>3]+e;d=+h[k+88>>3]+d}else f=1;k=c[l>>2]|0;h[k+120>>3]=e;h[k+128>>3]=d;if((Wf(a)|0)!=(a|0)){l=c[l>>2]|0;a=m+(b[l+236>>1]<<6)+24|0;n=+h[a>>3];h[a>>3]=n>d?n:d;m=m+(b[l+238>>1]<<6)+16|0;n=+h[m>>3];h[m>>3]=n>e?n:e}return f|0}function gj(a,d){a=a|0;d=d|0;var e=0,f=0.0,g=0.0,i=0,j=0,k=0.0,l=0,m=0,n=0,o=0,p=0.0,q=0.0;o=c[(c[(Wf(a)|0)+16>>2]|0)+196>>2]|0;if((Wf(a)|0)==(a|0))e=0;else e=EA(a,c[42189]|0,8,0)|0;l=a+16|0;i=c[l>>2]|0;m=e+d|0;k=+(e|0);j=1;f=+h[i+128>>3];g=+h[i+120>>3];e=i;while(1){if((j|0)>(c[e+180>>2]|0))break;i=c[(c[e+184>>2]|0)+(j<<2)>>2]|0;gj(i,m);i=c[i+16>>2]|0;e=c[l>>2]|0;if((b[i+238>>1]|0)==(b[e+238>>1]|0)){q=+h[i+120>>3]+k;g=g>q?g:q}if((b[i+236>>1]|0)==(b[e+236>>1]|0)){q=+h[i+128>>3]+k;f=f>q?f:q}j=j+1|0}h[e+120>>3]=g;h[e+128>>3]=f;if(((Wf(a)|0)!=(a|0)?(n=c[l>>2]|0,c[n+12>>2]|0):0)?(p=-g-f+ +h[n+48+((+h[n+104>>3]>+h[n+72>>3]?3:1)<<4)+8>>3]-+h[(c[(c[c[o+(b[n+236>>1]<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]+ +h[(c[(c[c[o+(b[n+238>>1]<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3],p>0.0):0)hj(a,~~p,d);if((Wf(a)|0)!=(a|0)){n=c[l>>2]|0;m=o+(b[n+236>>1]<<6)+24|0;q=+h[m>>3];p=+h[n+128>>3];h[m>>3]=q>p?q:p;o=o+(b[n+238>>1]<<6)+16|0;p=+h[o>>3];q=+h[n+120>>3];h[o>>3]=p>q?p:q}return}function hj(a,d,e){a=a|0;d=d|0;e=e|0;var f=0,g=0.0,i=0.0,j=0.0,k=0,l=0,m=0,n=0.0,o=0.0,p=0,q=0,r=0;k=c[(Wf(a)|0)+16>>2]|0;q=c[k+196>>2]|0;p=c[a+16>>2]|0;a=b[p+238>>1]|0;f=b[p+236>>1]|0;l=(d+1|0)/2|0;m=p+120|0;n=+h[m>>3];o=+(l|0);i=+(e|0);e=~~(o+i+n-+h[q+(a<<6)+16>>3]);if((e|0)>0){g=+(e|0);while(1){if((a|0)<(f|0))break;if((c[q+(a<<6)>>2]|0)>0){r=(c[(c[c[q+(a<<6)+4>>2]>>2]|0)+16>>2]|0)+24|0;h[r>>3]=+h[r>>3]+g}a=a+-1|0}j=+h[p+128>>3];a=e;g=j+ +(d-l|0)}else{j=+h[p+128>>3];a=d-l|0;g=j}a=~~(+(a|0)+i+g-+h[q+(f<<6)+24>>3]);a:do if((a|0)>0){e=b[k+236>>1]|0;g=+(a|0);while(1){a=f+-1|0;if((f|0)<=(e|0))break a;if((c[q+(a<<6)>>2]|0)<=0){f=a;continue}f=(c[(c[c[q+(a<<6)+4>>2]>>2]|0)+16>>2]|0)+24|0;h[f>>3]=+h[f>>3]+g;f=a}}while(0);h[p+128>>3]=j+ +(d-l|0);h[m>>3]=n+o;return}function ij(b,d){b=b|0;d=d|0;var e=0,f=0;e=c[b+16>>2]|0;f=a[e+84>>0]|0;b=c[d+16>>2]|0;do if(f<<24>>24==(a[b+84>>0]|0)){if(+h[e+56>>3]==+h[b+56>>3]){if(!(f<<24>>24==0?1:+h[e+64>>3]==+h[b+64>>3])){b=0;break}}else if(f<<24>>24){b=0;break}if(+h[e+16>>3]==+h[b+16>>3]?+h[e+24>>3]==+h[b+24>>3]:0){b=1;break}b=(a[e+44>>0]|0)==0&1}else b=0;while(0);return b|0}function jj(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=a+16|0;d=c[i>>2]|0;b[d+236>>1]=32767;b[d+238>>1]=-1;d=0;h=eo(a)|0;while(1){e=c[i>>2]|0;if(!h)break;f=e+238|0;g=c[(c[h+16>>2]|0)+232>>2]|0;if((g|0)>(b[f>>1]|0))b[f>>1]=g;e=e+236|0;if((g|0)<(b[e>>1]|0))b[e>>1]=g;if(!d)d=h;else d=(g|0)<(c[(c[d+16>>2]|0)+232>>2]|0)?h:d;h=fo(a,h)|0}c[e+264>>2]=d;return}function kj(a){a=a|0;var b=0,d=0,e=0,f=0,g=0.0;b=Jm(a,79821)|0;if(!b)b=2147483647;else{g=+tM(b);b=~~(g*+(nn(a)|0))}e=a+16|0;d=0;while(1){f=c[e>>2]|0;if((d|0)>=(c[f+220>>2]|0))break;c[f+192>>2]=c[(c[f+216>>2]|0)+(d<<2)>>2];hx(a,(c[f+180>>2]|0)==0&1,b)|0;d=d+1|0}return}function lj(a,d){a=a|0;d=d|0;var e=0,f=0,g=0;f=l;l=l+16|0;e=f;if(!(Jm(a,79830)|0))nj(a,d);else{g=(c[a+16>>2]|0)+136|0;b[g>>1]=b[g>>1]|16;mj(a,d)}if(0){g=c[13918]|0;a=c[a+16>>2]|0;d=b[a+236>>1]|0;c[e>>2]=b[a+238>>1];c[e+4>>2]=d;AL(g,79838,e)|0}l=f;return}function mj(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0.0;i=l;l=l+16|0;h=i;c[41933]=0;a[h>>0]=a[17644]|0;a[h+1>>0]=a[17645]|0;a[h+2>>0]=a[17646]|0;a[h+3>>0]=a[17647]|0;h=hn(80048,h,0)|0;Oo(h,80077,280,1)|0;Ao(h,17332,17272);oj(b);e=Jm(b,79821)|0;if(!e)f=2147483647;else{j=+tM(e);f=~~(j*+(nn(b)|0))}Ej(b,0);Fj(b,h);Gj(b,h);Hj(b,h,0,0);Ij(h);g=Jj(h)|0;Kj(h);if(d|0){yk(h);mk(h)}e=Jm(b,87620)|0;if(!e)e=-1;else e=sM(e)|0;Aw(h,1,f,e)|0;Lj(b,h,g);mn(h)|0;l=i;return}function nj(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;g=l;l=l+32|0;f=g+16|0;e=g+8|0;d=g;oj(a);do if(!b){pj(a,a);Bk(a);qj(d,a);h=d;d=c[h+4>>2]|0;b=e;c[b>>2]=c[h>>2];c[b+4>>2]=d;ul(a,0);b=0}else{yk(a);mk(a);pj(a,a);Bk(a);qj(d,a);i=d;d=c[i+4>>2]|0;h=e;c[h>>2]=c[i>>2];c[h+4>>2]=d;ul(a,0);h=c[a+16>>2]|0;if((c[h+220>>2]|0)<=1?(c[h+180>>2]|0)<=0:0)break;c[b+32>>2]=1;b=0}while(0);jk(a);c[f>>2]=c[e>>2];c[f+4>>2]=c[e+4>>2];if(rj(a,f)|0)ul(a,0);if(!b)kj(a);else nk(a,b);sj(a,b);tj(a);l=g;return}function oj(d){d=d|0;var f=0,g=0,h=0;if(a[(c[(c[d+60>>2]|0)+16>>2]|0)+113>>0]&1){g=eo(d)|0;while(1){if(!g)break;f=Qm(d,g)|0;while(1){if(!f)break;h=(c[f+16>>2]|0)+170|0;b[h>>1]=(e[h>>1]|0)<<1;f=Sm(d,f)|0}g=fo(d,g)|0}h=(c[d+16>>2]|0)+252|0;c[h>>2]=((c[h>>2]|0)+1|0)/2|0}return}function pj(a,b){a=a|0;b=b|0;var d=0;b=Kp(b)|0;while(1){if(!b)break;d=Bj(b)|0;do if(d)if((d|0)==7&(c[42180]|0)==100){xj(a,b);break}else{Cj(a,b,d);break}else pj(a,b);while(0);b=Lp(b)|0}return}function qj(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;i=d+16|0;e=c[i>>2]|0;d=c[e+228>>2]|0;e=c[e+224>>2]|0;f=(e|0)==0;if(!d)if(f){j=0;k=0}else g=4;else if(f)g=5;else g=4;if((g|0)==4){d=LA(e)|0;e=c[i>>2]|0;c[e+224>>2]=d;d=c[e+228>>2]|0;if(!d){h=0;d=e;g=12}else g=5}do if((g|0)==5){d=LA(d)|0;e=c[i>>2]|0;c[e+228>>2]=d;if(d){e=d+16|0;d=c[e>>2]|0;f=(a[d+159>>0]|0)==5&1;while(1){d=c[c[d+180>>2]>>2]|0;if(!d){g=11;break}h=c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0;if((h|0)!=(LA(h)|0)){g=9;break}ik(d);d=c[e>>2]|0}if((g|0)==9)ma(79941,79881,346,79973);else if((g|0)==11){h=f;d=c[i>>2]|0;g=12;break}}else{h=0;d=e;g=12}}while(0);a:do if((g|0)==12){d=c[d+224>>2]|0;if(!d){j=0;k=h}else{e=d+16|0;d=c[e>>2]|0;f=(a[d+159>>0]|0)==3&1;while(1){d=c[c[d+172>>2]>>2]|0;if(!d){j=f;k=h;break a}i=c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0;if((i|0)!=(LA(i)|0))break;ik(d);d=c[e>>2]|0}ma(79986,79881,353,79973)}}while(0);c[b>>2]=j;c[b+4>>2]=k;return}function rj(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;j=a+16|0;i=c[j>>2]|0;if((c[i+228>>2]|0)==0?(c[i+224>>2]|0)==0:0)d=0;else e=3;a:do if((e|0)==3){g=eo(a)|0;i=d+4|0;h=c[d>>2]&65535;d=0;while(1){if(!g)break a;if((g|0)==(LA(g)|0)){f=g+16|0;e=c[f>>2]|0;if((c[e+184>>2]|0)==0?(k=c[(c[j>>2]|0)+228>>2]|0,!((k|0)==0|(g|0)==(k|0))):0){d=bh(g,k,0)|0;e=c[d+16>>2]|0;b[e+170>>1]=c[i>>2];c[e+156>>2]=0;e=c[f>>2]|0}if((c[e+176>>2]|0)==0?(l=c[(c[j>>2]|0)+224>>2]|0,!((l|0)==0|(g|0)==(l|0))):0){d=bh(l,g,0)|0;f=c[d+16>>2]|0;b[f+170>>1]=h;c[f+156>>2]=0}}g=fo(a,g)|0}}while(0);return (d|0)!=0|0}function sj(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;g=eo(d)|0;k=d+16|0;f=c[k>>2]|0;a:do if(g){b[f+236>>1]=32767;b[f+238>>1]=-1;j=(e|0)==0;while(1){if(!g)break;f=LA(g)|0;i=c[g+16>>2]|0;e=c[i+232>>2]|0;do if((f|0)!=(g|0)){if(!j)if(!e)e=0;else break;e=e+(c[(c[f+16>>2]|0)+232>>2]|0)|0;c[i+232>>2]=e}while(0);f=c[k>>2]|0;h=f+238|0;if((e|0)>(b[h>>1]|0))b[h>>1]=e;f=f+236|0;if((e|0)<(b[f>>1]|0))b[f>>1]=e;switch(a[i+159>>0]|0){case 6:case 0:break;default:NA(g)}g=fo(d,g)|0}if((Wf(d)|0)==(d|0)){if((c[42180]|0)==100)e=1;else{wj(d);break}while(1){f=c[k>>2]|0;if((e|0)>(c[f+180>>2]|0))break a;vj(c[(c[f+184>>2]|0)+(e<<2)>>2]|0);e=e+1|0}}}else{b[f+238>>1]=0;b[f+236>>1]=0}while(0);return}function tj(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;j=b+16|0;e=0;while(1){d=c[j>>2]|0;if((e|0)>=(c[d+220>>2]|0))break;i=c[(c[d+216>>2]|0)+(e<<2)>>2]|0;c[d+192>>2]=i;d=i;while(1){if(!d)break;i=d+16|0;uj((c[i>>2]|0)+172|0);uj((c[i>>2]|0)+180|0);i=c[i>>2]|0;a[i+157>>0]=0;d=c[i+164>>2]|0}e=e+1|0}i=eo(b)|0;while(1){if(!i)break;h=Qm(b,i)|0;while(1){if(!h)break;f=h+16|0;d=c[f>>2]|0;g=c[d+172>>2]|0;if((g|0)!=0?(k=g+16|0,(h|0)==(c[(c[k>>2]|0)+116>>2]|0)):0){d=eo(b)|0;while(1){if(!d)break;e=Qm(b,d)|0;while(1){if(!e)break;if((h|0)!=(e|0)?(l=(c[e+16>>2]|0)+172|0,m=c[l>>2]|0,(m|0)!=0&(g|0)==(m|0)):0)c[l>>2]=0;e=Sm(b,e)|0}d=fo(b,d)|0}$I(c[k>>2]|0);$I(g);d=c[f>>2]|0}c[d+172>>2]=0;h=Sm(b,h)|0}i=fo(b,i)|0}$I(c[(c[j>>2]|0)+216>>2]|0);m=c[j>>2]|0;c[m+216>>2]=0;c[m+220>>2]=0;return}function uj(a){a=a|0;var b=0,d=0;d=a+4|0;b=c[d>>2]|0;while(1){if((b|0)<=-1)break;c[(c[a>>2]|0)+(b<<2)>>2]=0;b=b+-1|0}c[d>>2]=0;return}function vj(a){a=a|0;var d=0,f=0,g=0;d=a+16|0;f=c[d>>2]|0;g=c[(c[(c[f+264>>2]|0)+16>>2]|0)+232>>2]|0;a=f+236|0;b[a>>1]=g+(e[a>>1]|0);a=f+238|0;b[a>>1]=g+(e[a>>1]|0);a=1;while(1){if((a|0)>(c[f+180>>2]|0))break;vj(c[(c[f+184>>2]|0)+(a<<2)>>2]|0);a=a+1|0;f=c[d>>2]|0}return}function wj(b){b=b|0;var d=0;d=Kp(Wf(b)|0)|0;while(1){if(!d)break;if((a[(c[d+16>>2]|0)+274>>0]|0)==7)xj(b,d);d=Lp(d)|0}return}function xj(a,b){a=a|0;b=b|0;var d=0;d=(c[b+16>>2]|0)+200|0;do if((c[d>>2]|0)==0?(c[d>>2]=a,yj(a,b),eo(b)|0):0){zj(a,b);if((c[42180]|0)==100){nj(b,0);Aj(b);break}else{jj(b);break}}while(0);return}function yj(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;h=b+16|0;g=eo(d)|0;while(1){if(!g)break;i=fo(d,g)|0;j=g+16|0;if(!(a[(c[j>>2]|0)+159>>0]|0))f=1;else{ro(d,g)|0;g=i;continue}while(1){e=c[h>>2]|0;b=c[e+180>>2]|0;if((f|0)>=(b|0))break;if(Co(c[(c[e+184>>2]|0)+(f<<2)>>2]|0,g)|0){k=7;break}f=f+1|0}if((k|0)==7){k=0;b=c[(c[h>>2]|0)+180>>2]|0}if((f|0)<(b|0))ro(d,g)|0;c[(c[j>>2]|0)+212>>2]=0;g=i}e=eo(d)|0;while(1){if(!e)break;b=Qm(Wf(d)|0,e)|0;while(1){if(!b)break;if(Co(d,c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0)fn(d,b,1)|0;b=Sm(Wf(d)|0,b)|0}e=fo(d,e)|0}return}function zj(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;e=a+16|0;d=c[e>>2]|0;g=d+180|0;a=c[g>>2]|0;f=a+1|0;c[g>>2]=f;d=c[d+184>>2]|0;if(!d)a=ww((a<<2)+8|0)|0;else a=yw(d,a+2|0,4,f)|0;c[(c[e>>2]|0)+184>>2]=a;c[a+(f<<2)>>2]=b;iw(b);return}function Aj(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;g=c[b+16>>2]|0;d=g+192|0;h=0;while(1){d=c[d>>2]|0;if(!d)break;f=c[d+16>>2]|0;if(!(c[f+232>>2]|0))e=(a[f+156>>0]|0)==0?d:h;else e=h;d=f+164|0;h=e}if(!h)ma(79866,79881,238,79888);c[g+264>>2]=h;d=eo(b)|0;while(1){if(!d){d=13;break}e=d+16|0;if(!((d|0)==(h|0)?1:(c[(c[e>>2]|0)+216>>2]|0)<2)){d=11;break}MA(d,h)|0;a[(c[e>>2]|0)+159>>0]=7;d=fo(b,d)|0}if((d|0)==11)ma(79903,79881,242,79888);else if((d|0)==13)return}function Bj(b){b=b|0;var d=0;if(!(Dj(b)|0)){d=VA(Jm(b,80018)|0,17284,17308)|0;a[(c[b+16>>2]|0)+274>>0]=d;b=d}else b=7;return b|0}function Cj(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;g=eo(d)|0;a:do if(g|0){j=e&255;i=g+16|0;f=g;h=j;while(1){a[(c[f+16>>2]|0)+159>>0]=h;f=fo(d,f)|0;if(!f)break;MA(g,f)|0;h=a[(c[i>>2]|0)+159>>0]|0}switch(e|0){case 3:case 2:{b=b+16|0;f=c[b>>2]|0;h=c[f+224>>2]|0;if(h){g=MA(h,g)|0;f=c[b>>2]|0}c[f+224>>2]=g;break}case 5:case 4:{b=b+16|0;f=c[b>>2]|0;h=c[f+228>>2]|0;if(h){g=MA(h,g)|0;f=c[b>>2]|0}c[f+228>>2]=g;break}default:break a}switch(e|0){case 3:{f=f+224|0;break}case 5:{f=f+228|0;break}default:break a}a[(c[(c[f>>2]|0)+16>>2]|0)+159>>0]=j}while(0);return}function Dj(a){a=a|0;return (WJ(En(a)|0,93039,7)|0)==0|0}function Ej(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+16|0;g=m;if(!(Zj(b)|0)){do if(iB(b)|0)if(!d){c[(c[b+16>>2]|0)+204>>2]=0;d=b;break}else{c[(c[b+16>>2]|0)+204>>2]=(c[(c[d+16>>2]|0)+204>>2]|0)+1;_j(b,d);d=b;break}while(0);e=Kp(b)|0;while(1){if(!e)break;Ej(e,d);e=Lp(e)|0}a:do if(iB(b)|0){e=eo(b)|0;while(1){if(!e)break a;f=(c[e+16>>2]|0)+212|0;if(!(c[f>>2]|0))c[f>>2]=b;e=fo(b,e)|0}}while(0);switch($j(b)|0){case 3:{d=d+16|0;a[(c[d>>2]|0)+241>>0]=1;k=19;break}case 2:{d=d+16|0;k=19;break}case 5:{d=d+16|0;a[(c[d>>2]|0)+242>>0]=1;k=21;break}case 4:{d=d+16|0;k=21;break}case 1:{ak(b)|0;break}case 6:break;default:{e=En(b)|0;f=Jm(b,80018)|0;c[g>>2]=e;c[g+4>>2]=f;$l(0,80201,g)|0}}if((k|0)==19){k=ak(b)|0;k=bk(k,c[(c[d>>2]|0)+208>>2]|0)|0;c[(c[d>>2]|0)+208>>2]=k}else if((k|0)==21){k=ak(b)|0;k=bk(k,c[(c[d>>2]|0)+212>>2]|0)|0;c[(c[d>>2]|0)+212>>2]=k}if((iB(b)|0?(h=b+16|0,i=c[h>>2]|0,j=c[i+208>>2]|0,j|0):0)?(j|0)==(c[i+212>>2]|0):0){j=ak(b)|0;k=c[h>>2]|0;c[k+208>>2]=j;c[k+212>>2]=j}}l=m;return}function Fj(a,b){a=a|0;b=b|0;var d=0,e=0;c[41933]=0;d=eo(a)|0;while(1){if(!d)break;if((Mj(d)|0)==(d|0)){e=Pj(b,En(d)|0)|0;c[(c[d+16>>2]|0)+148>>2]=e}d=fo(a,d)|0}d=eo(a)|0;while(1){if(!d)break;b=d+16|0;if(!(c[(c[b>>2]|0)+148>>2]|0)){e=c[(c[(Mj(d)|0)+16>>2]|0)+148>>2]|0;c[(c[b>>2]|0)+148>>2]=e}d=fo(a,d)|0}return}function Gj(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;h=eo(a)|0;while(1){if(!h)break;d=c[(c[h+16>>2]|0)+148>>2]|0;i=Qm(a,h)|0;while(1){if(!i)break;do if((Uj(i)|0)==0?(j=i+-48|0,k=c[(c[(Mj(c[((c[i>>2]&3|0)==2?i:j)+40>>2]|0)|0)+16>>2]|0)+148>>2]|0,(d|0)!=(k|0)):0){f=c[i>>2]&3;g=i+48|0;e=((f|0)==3?i:g)+40|0;f=c[(c[(c[((f|0)==2?i:j)+40>>2]|0)+16>>2]|0)+212>>2]|0;if(!(Vj(i)|0)){if((Tj(c[(c[(c[e>>2]|0)+16>>2]|0)+212>>2]|0)|0)==0?(Tj(f)|0)==0:0){Wj(b,d,k,i);break}Xj(b,d,k,i);break}else{f=Mj(c[e>>2]|0)|0;e=c[i>>2]&3;if((f|0)!=(c[(c[(c[(c[(c[((e|0)==3?i:g)+40>>2]|0)+16>>2]|0)+212>>2]|0)+16>>2]|0)+212>>2]|0)?(g=Mj(c[((e|0)==2?i:j)+40>>2]|0)|0,(g|0)!=(c[(c[(c[(c[(c[((c[i>>2]&3|0)==2?i:j)+40>>2]|0)+16>>2]|0)+212>>2]|0)+16>>2]|0)+208>>2]|0)):0)e=k;else{e=d;d=k}Wj(b,d,e,i);break}}while(0);i=Sm(a,i)|0}h=fo(a,h)|0}return}function Hj(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;if((iB(a)|0)!=0?(Tj(a)|0)!=0:0){g=eo(a)|0;while(1){if(!g)break;if(!(Tm(a,g)|0)){f=c[(c[(Mj(g)|0)+16>>2]|0)+148>>2]|0;if(!d)d=Pj(b,80099)|0;bn(b,d,f,0,1)|0}if(!(Qm(a,g)|0)){f=c[(c[(Mj(g)|0)+16>>2]|0)+148>>2]|0;if(!e)e=Pj(b,80104)|0;bn(b,f,e,0,1)|0}g=fo(a,g)|0}if((e|0)!=0&(d|0)!=0){Sj(bn(b,d,e,0,1)|0,0,1e3);f=d}else f=d}else f=d;d=Kp(a)|0;while(1){if(!d)break;Hj(d,b,f,e);d=Lp(d)|0}return}function Ij(b){b=b|0;var d=0,e=0;d=eo(b)|0;while(1){if(!d)break;e=c[d+16>>2]|0;a[e+158>>0]=0;a[e+157>>0]=0;d=fo(b,d)|0}d=eo(b)|0;while(1){if(!d)break;Qj(b,d);d=fo(b,d)|0}return}function Jj(a){a=a|0;var b=0,d=0,e=0,f=0;b=eo(a)|0;while(1){if(!b)break;c[(c[b+16>>2]|0)+128>>2]=0;b=fo(a,b)|0}b=0;e=eo(a)|0;while(1){if(!e)break;d=b+1|0;if(!(c[(c[e+16>>2]|0)+128>>2]|0)){Oj(a,e,d);b=d}e=fo(a,e)|0}a:do if((b|0)>1){f=Pj(a,80093)|0;d=1;e=eo(a)|0;while(1){if(!e)break a;if((c[(c[e+16>>2]|0)+128>>2]|0)==(d|0)){bn(a,f,e,0,1)|0;d=d+1|0}e=fo(a,e)|0}}while(0);return b|0}function Kj(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0;g=eo(a)|0;while(1){if(!g)break;h=g+16|0;f=Qm(a,g)|0;while(1){if(!f)break;b=c[h>>2]|0;d=c[b+180>>2]|0;if(!d)b=xw((c[b+184>>2]<<2)+8|0)|0;else b=zw(d,(c[b+184>>2]<<2)+8|0)|0;d=c[h>>2]|0;c[d+180>>2]=b;d=d+184|0;e=c[d>>2]|0;c[d>>2]=e+1;c[b+(e<<2)>>2]=f;e=c[h>>2]|0;c[(c[e+180>>2]|0)+(c[e+184>>2]<<2)>>2]=0;e=f+-48|0;b=c[(c[((c[f>>2]&3|0)==2?f:e)+40>>2]|0)+16>>2]|0;d=c[b+172>>2]|0;if(!d)b=xw((c[b+176>>2]<<2)+8|0)|0;else b=zw(d,(c[b+176>>2]<<2)+8|0)|0;c[(c[(c[((c[f>>2]&3|0)==2?f:e)+40>>2]|0)+16>>2]|0)+172>>2]=b;i=c[(c[((c[f>>2]&3|0)==2?f:e)+40>>2]|0)+16>>2]|0;b=c[i+172>>2]|0;i=i+176|0;d=c[i>>2]|0;c[i>>2]=d+1;c[b+(d<<2)>>2]=f;e=c[(c[((c[f>>2]&3|0)==2?f:e)+40>>2]|0)+16>>2]|0;c[(c[e+172>>2]|0)+(c[e+176>>2]<<2)>>2]=0;f=Sm(a,f)|0}g=fo(a,g)|0}return}function Lj(a,d,f){a=a|0;d=d|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;n=a+16|0;o=c[n>>2]|0;b[o+236>>1]=32767;b[o+238>>1]=-1;a:do if((f|0)>1){h=ww((f<<2)+4|0)|0;g=f+1|0;f=1;while(1){if((f|0)==(g|0)){m=h;o=h;break a}c[h+(f<<2)>>2]=32767;f=f+1|0}}else{m=0;o=0}while(0);i=(m|0)==0;h=eo(a)|0;while(1){if(!h)break;j=c[(c[(c[(Mj(h)|0)+16>>2]|0)+148>>2]|0)+16>>2]|0;k=c[j+232>>2]|0;l=c[h+16>>2]|0;c[l+232>>2]=k;f=c[n>>2]|0;g=f+238|0;if((k|0)>(b[g>>1]|0))b[g>>1]=k;f=f+236|0;if((k|0)<(b[f>>1]|0))b[f>>1]=k;if(!i){j=c[j+128>>2]|0;c[l+128>>2]=j;l=m+(j<<2)|0;j=c[l>>2]|0;c[l>>2]=(j|0)<(k|0)?j:k}h=fo(a,h)|0}j=(m|0)!=0;b:do if(!j){m=b[(c[n>>2]|0)+236>>1]|0;g=m<<16>>16;if(m<<16>>16>0){f=eo(a)|0;while(1){if(!f)break;m=(c[f+16>>2]|0)+232|0;c[m>>2]=(c[m>>2]|0)-g;f=fo(a,f)|0}f=c[n>>2]|0;n=f+236|0;b[n>>1]=(e[n>>1]|0)-g;f=f+238|0;b[f>>1]=(e[f>>1]|0)-g;f=0}else f=0}else{f=eo(a)|0;while(1){if(!f){f=1;break b}l=c[f+16>>2]|0;n=l+232|0;c[n>>2]=(c[n>>2]|0)-(c[m+(c[l+128>>2]<<2)>>2]|0);f=fo(a,f)|0}}while(0);Nj(a,f);i=eo(d)|0;while(1){if(!i)break;g=i+16|0;f=c[g>>2]|0;h=c[f+172>>2]|0;if(h){$I(h);f=c[g>>2]|0}f=c[f+180>>2]|0;if(f|0)$I(f);i=fo(d,i)|0}$I(c[(c[(eo(a)|0)+16>>2]|0)+112>>2]|0);f=eo(a)|0;while(1){if(!f)break;c[(c[f+16>>2]|0)+112>>2]=0;f=fo(a,f)|0}if(j)$I(o);return}function Mj(a){a=a|0;var b=0,d=0,e=0;b=a+16|0;d=(c[b>>2]|0)+152|0;e=c[d>>2]|0;if(e){if((e|0)!=(a|0)){e=Mj(e)|0;c[(c[b>>2]|0)+152>>2]=e;return e|0}}else c[d>>2]=a;return a|0}function Nj(a,d){a=a|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=a+16|0;e=1;while(1){f=c[i>>2]|0;if((e|0)>(c[f+180>>2]|0))break;Nj(c[(c[f+184>>2]|0)+(e<<2)>>2]|0,0);e=e+1|0}if((d|0)!=0|(c[f+200>>2]|0)!=0){b[f+236>>1]=32767;b[f+238>>1]=-1;e=0;h=eo(a)|0;while(1){if(!h)break;g=c[(c[h+16>>2]|0)+232>>2]|0;d=c[i>>2]|0;f=d+238|0;if((g|0)>(b[f>>1]|0))b[f>>1]=g;d=d+236|0;if((g|0)<(b[d>>1]|0)){b[d>>1]=g;e=h}h=fo(a,h)|0}c[(c[i>>2]|0)+264>>2]=e}return}function Oj(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=(c[b+16>>2]|0)+128|0;a:do if(!(c[e>>2]|0)){c[e>>2]=d;e=Qm(a,b)|0;while(1){if(!e)break;Oj(a,c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0,d);e=Sm(a,e)|0}e=Tm(a,b)|0;while(1){if(!e)break a;Oj(a,c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0,d);e=Um(a,e)|0}}while(0);return}function Pj(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=oo(a,b,1)|0;b=f+16|0;c[(c[b>>2]|0)+176>>2]=0;e=ww(20)|0;d=c[b>>2]|0;c[d+172>>2]=e;c[d+184>>2]=0;d=ww(20)|0;b=c[b>>2]|0;c[b+180>>2]=d;d=c[41933]|0;e=b+168|0;if(!d){c[e>>2]=0;c[(c[a+16>>2]|0)+192>>2]=f}else{c[e>>2]=d;c[(c[d+16>>2]|0)+164>>2]=f}c[41933]=f;c[b+164>>2]=0;return f|0}function Qj(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;h=d+16|0;e=c[h>>2]|0;f=e+157|0;if(!(a[f>>0]|0)){a[f>>0]=1;a[e+158>>0]=1;d=Qm(b,d)|0;while(1){if(!d)break;e=Sm(b,d)|0;f=c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0;g=c[f+16>>2]|0;if(a[g+158>>0]|0){Rj(b,d);d=e;continue}if(a[g+157>>0]|0){d=e;continue}Qj(b,f);d=e}a[(c[h>>2]|0)+158>>0]=0}return}function Rj(a,b){a=a|0;b=b|0;var d=0,f=0,g=0;d=c[b>>2]&3;g=b+-48|0;f=b+48|0;d=bn(a,c[((d|0)==2?b:g)+40>>2]|0,c[((d|0)==3?b:f)+40>>2]|0,0,0)|0;if(!d){d=c[b>>2]&3;d=bn(a,c[((d|0)==2?b:g)+40>>2]|0,c[((d|0)==3?b:f)+40>>2]|0,0,1)|0}g=c[b+16>>2]|0;Sj(d,e[g+170>>1]|0,c[g+156>>2]|0);ro(a,b)|0;return}function Sj(a,d,f){a=a|0;d=d|0;f=f|0;var g=0,h=0;a=c[a+16>>2]|0;g=a+170|0;h=e[g>>1]|0;b[g>>1]=(h|0)>(d|0)?h:d;d=a+156|0;c[d>>2]=(c[d>>2]|0)+f;return}function Tj(a){a=a|0;return (KA(Jm(a,80109)|0,0)|0)&255|0}function Uj(b){b=b|0;var d=0,e=0;d=c[42234]|0;if((((d|0)!=0?(e=Km(b,d)|0,(e|0)!=0):0)?(a[e>>0]|0)!=0:0)?(JA(e)|0)<<24>>24==0:0)b=1;else b=0;return b|0}function Vj(a){a=a|0;var b=0,d=0;d=c[a>>2]&3;b=c[(c[(c[((d|0)==3?a:a+48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0;a=c[(c[(c[((d|0)==2?a:a+-48|0)+40>>2]|0)+16>>2]|0)+212>>2]|0;if((b|0)==(a|0))return 1;else{d=Yj(b,a)|0;return ((d|0)==(b|0)|(d|0)==(a|0))&1|0}return 0}function Wj(a,b,d,f){a=a|0;b=b|0;d=d|0;f=f|0;var g=0,h=0,i=0,j=0;j=l;l=l+16|0;h=j;g=bn(a,b,d,0,0)|0;if(!g){g=bn(a,d,b,0,0)|0;if(!g){g=bn(a,b,d,0,1)|0;if(!g){b=En(b)|0;f=En(d)|0;c[h>>2]=b;c[h+4>>2]=f;$l(1,80126,h)|0}else i=4}else i=4}else i=4;if((i|0)==4){i=c[f+16>>2]|0;Sj(g,e[i+170>>1]|0,c[i+156>>2]|0)}l=j;return}function Xj(a,d,f,g){a=a|0;d=d|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,m=0,n=0;m=l;l=l+112|0;j=m;i=m+4|0;h=Tm(a,d)|0;while(1){if(!h){k=6;break}n=Qm(a,c[((c[h>>2]&3|0)==3?h:h+48|0)+40>>2]|0)|0;if(n|0?(c[((c[n>>2]&3|0)==2?n:n+-48|0)+40>>2]|0)==(f|0):0)break;h=Um(a,h)|0}if((k|0)==6){n=c[41934]|0;c[41934]=n+1;c[j>>2]=n;qL(i,80117,j)|0;i=Pj(a,i)|0;n=bn(a,i,d,0,1)|0;i=bn(a,i,f,0,1)|0;f=c[g+16>>2]|0;k=f+156|0;n=(c[n+16>>2]|0)+156|0;c[n>>2]=(c[n>>2]|0)+((c[k>>2]|0)*1e3|0);n=c[i+16>>2]|0;j=n+170|0;b[j>>1]=b[(c[((e[j>>1]|0)>(e[f+170>>1]|0)?i:g)+16>>2]|0)+170>>1]|0;n=n+156|0;c[n>>2]=(c[n>>2]|0)+(c[k>>2]|0)}l=m;return}function Yj(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;a:while(1){e=a+16|0;while(1){if((a|0)==(b|0))break a;f=c[e>>2]|0;d=c[b+16>>2]|0;if((c[f+204>>2]|0)>=(c[d+204>>2]|0))break;b=c[d+200>>2]|0}a=c[f+200>>2]|0}return a|0}function Zj(a){a=a|0;return (eo(a)|0)==0|0}function _j(a,b){a=a|0;b=b|0;c[(c[a+16>>2]|0)+200>>2]=b;zj(b,a);yj(b,a);return}function $j(b){b=b|0;var c=0;b=Jm(b,80018)|0;if((b|0)!=0?(a[b>>0]|0)!=0:0)if(yJ(b,80028)|0)if(yJ(b,80032)|0)if(yJ(b,80039)|0)if(yJ(b,80043)|0)if(!(yJ(b,80023)|0))b=1;else c=8;else b=5;else b=4;else b=3;else b=2;else c=8;if((c|0)==8)b=6;return b|0}function ak(a){a=a|0;var b=0,c=0;c=eo(a)|0;a:do if(!c)b=0;else{b=Mj(c)|0;while(1){c=fo(a,c)|0;if(!c)break a;bk(b,c)|0}}while(0);return b|0}function bk(a,b){a=a|0;b=b|0;if(b){a=Mj(a)|0;c[(c[(Mj(b)|0)+16>>2]|0)+152>>2]=a}return a|0}function ck(a,b,d){a=a|0;b=b|0;d=d|0;Oo(b,80077,c[d>>2]|0,1)|0;return}function dk(a,b,d){a=a|0;b=b|0;d=d|0;Oo(b,80244,c[d+4>>2]|0,1)|0;return}function ek(a,b,d){a=a|0;b=b|0;d=d|0;Oo(b,80229,c[d+8>>2]|0,1)|0;return}function fk(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;p=l;l=l+240|0;m=p+120|0;n=p;c[42238]=zm(b,2,80259,0)|0;k=zm(b,2,80268,0)|0;c[42239]=k;a:do if((k|0)!=0|(c[42238]|0)!=0){k=eo(b)|0;while(1){if(!k)break a;j=0;d=0;i=Vm(b,k)|0;while(1){if(!i){f=0;break}e=c[i>>2]|0;g=e&3;f=c[((g|0)==2?i:i+-48|0)+40>>2]|0;h=i+48|0;b:do if((f|0)!=(c[((g|0)==3?i:h)+40>>2]|0)){g=c[42238]|0;do if((f|0)==(k|0)&(g|0)!=0){f=Km(i,g)|0;if(!(a[f>>0]|0)){e=c[i>>2]|0;break}else{e=j;d=gk(m,d,k,i,f)|0;break b}}while(0);f=c[42239]|0;if((f|0?(c[((e&3|0)==3?i:h)+40>>2]|0)==(k|0):0)?(o=Km(i,f)|0,(a[o>>0]|0)!=0):0)e=gk(n,j,k,i,o)|0;else e=j}else e=j;while(0);j=e;i=Wm(b,i,k)|0}while(1){if((f|0)>=(d|0)){e=0;break}e=m+(f*24|0)+4|0;if((c[m+(f*24|0)+8>>2]|0)>1)hk(k,e);e=c[e>>2]|0;if(e|0)$I(e);f=f+1|0}while(1){if((e|0)>=(j|0))break;d=n+(e*24|0)+4|0;if((c[n+(e*24|0)+8>>2]|0)>1)hk(k,d);d=c[d>>2]|0;if(d|0)$I(d);e=e+1|0}k=fo(b,k)|0}}while(0);l=p;return}function gk(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;p=l;l=l+16|0;k=p;m=p+12|0;n=p+8|0;o=0;while(1){if((o|0)>=(d|0)){j=10;break}j=c[b+(o*24|0)>>2]|0;if((a[j>>0]|0)==(a[g>>0]|0)?(yJ(j,g)|0)==0:0){j=5;break}o=o+1|0}do if((j|0)==5){k=b+(o*24|0)+4|0;j=c[k>>2]|0;if(!j){j=b+(o*24|0)+8|0;g=j;j=xw((c[j>>2]<<2)+8|0)|0}else{q=b+(o*24|0)+8|0;g=q;j=zw(j,(c[q>>2]<<2)+8|0)|0}c[k>>2]=j;r=c[g>>2]|0;q=r+1|0;c[g>>2]=q;c[j+(r<<2)>>2]=f;c[(c[k>>2]|0)+(q<<2)>>2]=0;j=13}else if((j|0)==10)if((d|0)>4){r=En(e)|0;c[k>>2]=5;c[k+4>>2]=r;$l(1,80277,k)|0;break}else{s=b+(o*24|0)+8|0;c[s>>2]=0;k=ww(8)|0;r=b+(o*24|0)+4|0;c[r>>2]=k;q=c[s>>2]|0;j=q+1|0;c[s>>2]=j;c[k+(q<<2)>>2]=f;c[(c[r>>2]|0)+(j<<2)>>2]=0;c[b+(o*24|0)>>2]=g;c[b+(o*24|0)+12>>2]=0;h[b+(o*24|0)+16>>3]=0.0;d=d+1|0;j=13;break}while(0);if((j|0)==13){Bt(f,m,n);j=(c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0)==(e|0)?c[n>>2]|0:c[m>>2]|0;if(j){r=b+(o*24|0)+12|0;s=c[r>>2]|0;c[r>>2]=s+1;if(!s)i=+Ft(f,j);else i=0.0;h[b+(o*24|0)+16>>3]=i}}l=p;return d|0}function hk(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,i=0,j=0.0,k=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0.0;x=l;l=l+80|0;t=x+68|0;u=x+64|0;r=x;v=d+4|0;n=c[v>>2]|0;w=b+16|0;i=0;p=0.0;q=0.0;while(1){if((i|0)>=(n|0))break;f=c[(c[d>>2]|0)+(i<<2)>>2]|0;g=c[f>>2]&3;e=c[((g|0)==2?f:f+-48|0)+40>>2]|0;if((e|0)==(b|0))e=c[((g|0)==3?f:f+48|0)+40>>2]|0;g=c[e+16>>2]|0;s=c[w>>2]|0;k=+h[g+16>>3]-+h[s+16>>3];m=+h[g+24>>3]-+h[s+24>>3];o=+RJ(k,m);i=i+1|0;p=k/o+p;q=m/o+q}j=+RJ(p,q);s=c[w>>2]|0;k=+h[s+16>>3];m=+h[s+24>>3];y=+h[s+96>>3]+ +h[s+88>>3];o=+h[s+80>>3];s=y>o+ +(c[(c[(so(b)|0)+16>>2]|0)+252>>2]|0);e=c[w>>2]|0;if(s)o=+h[e+96>>3]+ +h[e+88>>3];else{o=+h[e+80>>3];o=o+ +(c[(c[(so(b)|0)+16>>2]|0)+252>>2]|0);e=c[w>>2]|0}y=+h[e+16>>3]+o*(p/j);j=+h[e+24>>3]+o*(q/j);h[r>>3]=k;n=r+8|0;h[n>>3]=m;h[r+16>>3]=(y+k*2.0)*.3333333333333333;h[r+24>>3]=(j+m*2.0)*.3333333333333333;h[r+32>>3]=(y*2.0+k)*.3333333333333333;h[r+40>>3]=(j*2.0+m)*.3333333333333333;h[r+48>>3]=y;h[r+56>>3]=j;Hz(b,r);s=c[w>>2]|0;j=+h[r>>3]-+h[s+16>>3];k=+h[n>>3]-+h[s+24>>3];j=+(~~(j+(j>=0.0?.5:-.5))|0);k=+(~~(k+(k>=0.0?.5:-.5))|0);y=+h[s+88>>3];s=~~((y+j)*256.0/(+h[s+96>>3]+y))&255;r=0;while(1){if((r|0)>=(c[v>>2]|0))break;n=c[(c[d>>2]|0)+(r<<2)>>2]|0;Bt(n,t,u);while(1){if(!n)break;else g=n;while(1){if(!g){i=n;break}e=c[g>>2]|0;i=g+-48|0;if((c[((e&3|0)==2?g:i)+40>>2]|0)==(b|0)){e=c[g+16>>2]|0;h[e+56>>3]=j;h[e+64>>3]=k;h[e+72>>3]=0.0;c[e+80>>2]=0;a[e+84>>0]=1;a[e+85>>0]=0;a[e+86>>0]=0;a[e+87>>0]=0;a[e+88>>0]=s;a[e+89>>0]=0;c[e+92>>2]=0;e=c[g>>2]|0}f=g+16|0;if((c[((e&3|0)==3?g:g+48|0)+40>>2]|0)==(b|0)){e=c[f>>2]|0;h[e+16>>3]=j;h[e+24>>3]=k;h[e+32>>3]=0.0;c[e+40>>2]=0;a[e+44>>0]=1;a[e+45>>0]=0;a[e+46>>0]=0;a[e+47>>0]=0;a[e+48>>0]=s;a[e+49>>0]=0;c[e+52>>2]=0}if((a[(c[f>>2]|0)+112>>0]|0)!=1){g=0;continue}e=c[(c[((c[g>>2]&3|0)==2?g:i)+40>>2]|0)+16>>2]|0;if((a[e+156>>0]|0)!=1){g=0;continue}if((c[e+184>>2]|0)!=1){g=0;continue}g=c[c[e+180>>2]>>2]|0}while(1){if(!i)break;e=c[i>>2]|0;if((c[((e&3|0)==2?i:i+-48|0)+40>>2]|0)==(b|0)){e=c[i+16>>2]|0;h[e+56>>3]=j;h[e+64>>3]=k;h[e+72>>3]=0.0;c[e+80>>2]=0;a[e+84>>0]=1;a[e+85>>0]=0;a[e+86>>0]=0;a[e+87>>0]=0;a[e+88>>0]=s;a[e+89>>0]=0;c[e+92>>2]=0;e=c[i>>2]|0}f=i+48|0;g=i+16|0;if((c[((e&3|0)==3?i:f)+40>>2]|0)==(b|0)){e=c[g>>2]|0;h[e+16>>3]=j;h[e+24>>3]=k;h[e+32>>3]=0.0;c[e+40>>2]=0;a[e+44>>0]=1;a[e+45>>0]=0;a[e+46>>0]=0;a[e+47>>0]=0;a[e+48>>0]=s;a[e+49>>0]=0;c[e+52>>2]=0}if((a[(c[g>>2]|0)+112>>0]|0)!=1){i=0;continue}e=c[(c[((c[i>>2]&3|0)==3?i:f)+40>>2]|0)+16>>2]|0;if((a[e+156>>0]|0)!=1){i=0;continue}if((c[e+176>>2]|0)!=1){i=0;continue}i=c[c[e+172>>2]>>2]|0}n=c[(c[n+16>>2]|0)+172>>2]|0}r=r+1|0}a[(c[w>>2]|0)+145>>0]=1;l=x;return}function ik(a){a=a|0;var b=0,d=0,e=0;Yg(a);b=c[a>>2]&3;d=a+-48|0;e=a+48|0;b=Tg(c[((b|0)==2?a:d)+40>>2]|0,c[((b|0)==3?a:e)+40>>2]|0)|0;if(!b){b=c[a>>2]&3;bh(c[((b|0)==2?a:d)+40>>2]|0,c[((b|0)==3?a:e)+40>>2]|0,a)|0}else jh(a,b);return}function jk(b){b=b|0;var d=0,e=0,f=0,g=0;f=b+16|0;e=0;while(1){b=c[f>>2]|0;if((e|0)>=(c[b+220>>2]|0))break;d=c[(c[b+216>>2]|0)+(e<<2)>>2]|0;c[b+192>>2]=d;b=d;d=b;while(1){if(!d)break;g=c[d+16>>2]|0;a[g+157>>0]=0;d=c[g+164>>2]|0}while(1){if(!b)break;kk(b);b=c[(c[b+16>>2]|0)+164>>2]|0}e=e+1|0}return}function kk(b){b=b|0;var d=0,e=0,f=0,g=0;g=b+16|0;d=c[g>>2]|0;b=d+157|0;if(!(a[b>>0]|0)){a[b>>0]=1;a[d+158>>0]=1;b=0;while(1){f=c[(c[d+180>>2]|0)+(b<<2)>>2]|0;if(!f)break;d=c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0;e=c[d+16>>2]|0;if(!(a[e+158>>0]|0)){if(!(a[e+157>>0]|0))kk(d)}else{ik(f);b=b+-1|0}b=b+1|0;d=c[g>>2]|0}a[d+158>>0]=0}return}function lk(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;e=eo(a)|0;b=0;while(1){if(!e)break;d=Qm(a,e)|0;while(1){if(!d)break;g=c[d>>2]&3;h=c[(c[(c[((g|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0;g=c[(c[(c[((g|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0;f=h-g|0;d=Sm(a,d)|0;b=((h|0)==(g|0)?0:((f|0)>-1?f:0-f|0)+-1|0)+b|0}e=fo(a,e)|0}return b|0}function mk(b){b=b|0;var d=0,e=0,f=0,g=0;e=eo(b)|0;while(1){if(!e)break;g=c[e+16>>2]|0;f=c[g+176>>2]|0;g=g+172|0;d=0;while(1){if((d|0)>=(f|0))break;a[(c[(c[(c[g>>2]|0)+(d<<2)>>2]|0)+16>>2]|0)+112>>0]=0;d=d+1|0}e=fo(b,e)|0}return}function nk(a,b){a=a|0;b=b|0;var d=0,e=0.0,f=0.0,g=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;q=l;l=l+16|0;o=q;j=c[b+24>>2]|0;ok(a);k=(j|0)==-1;m=b+8|0;i=k^1;n=c[13918]|0;f=1797693134862315708145274.0e284;g=0;while(1){if(!(k|(g|0)<(j|0)))break;d=eo(a)|0;while(1){if(!d)break;c[(c[d+16>>2]|0)+232>>2]=0;d=fo(a,d)|0}kj(a);e=+pk(a);h[m>>3]=e;if(0){h[o>>3]=e;AL(n,80329,o)|0;e=+h[m>>3]}if(!(!(e<=+h[b>>3])&(!(f<=e)|i))){p=9;break}qk(a);f=e;g=g+1|0}if((p|0)==9){p=b+20|0;c[b+16>>2]=c[p>>2];c[p>>2]=g}kj(a);rk(a);sk();h[m>>3]=+pk(a);l=q;return}function ok(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0,k=0,l=0.0,m=0.0,n=0;c[41938]=xw((nn(a)|0)*24|0)|0;c[41937]=0;b=eo(a)|0;while(1){if(!b)break;c[(c[b+16>>2]|0)+120>>2]=-1;b=fo(a,b)|0}i=eo(a)|0;while(1){if(!i)break;j=i+16|0;do if(!(c[(c[j>>2]|0)+216>>2]|0)){f=ww(4)|0;g=c[41938]|0;k=c[41937]|0;c[g+(k*24|0)>>2]=f;c[f>>2]=i;c[g+(k*24|0)+4>>2]=1;j=c[j>>2]|0;h[g+(k*24|0)+8>>3]=+h[j+32>>3];h[g+(k*24|0)+16>>3]=+h[j+40>>3];c[j+120>>2]=k;c[41937]=k+1}else{g=LA(i)|0;k=g+16|0;b=c[k>>2]|0;d=c[b+120>>2]|0;if((d|0)>-1){g=c[41938]|0;f=c[g+(d*24|0)>>2]|0;e=g+(d*24|0)+4|0;k=c[e>>2]|0;c[e>>2]=k+1;c[f+(k<<2)>>2]=i;k=c[j>>2]|0;j=g+(d*24|0)+8|0;h[j>>3]=+h[j>>3]+ +h[k+32>>3];j=g+(d*24|0)+16|0;l=+h[j>>3];m=+h[k+40>>3];h[j>>3]=l>2]=d;break}d=ww(c[b+216>>2]<<2)|0;e=c[41938]|0;f=c[41937]|0;b=e+(f*24|0)|0;c[b>>2]=d;c[d>>2]=g;if((g|0)==(i|0)){h[e+(f*24|0)+8>>3]=+h[(c[k>>2]|0)+32>>3];d=1;b=i}else{c[(c[b>>2]|0)+4>>2]=i;n=c[k>>2]|0;b=c[j>>2]|0;h[e+(f*24|0)+8>>3]=+h[b+32>>3]+ +h[n+32>>3];d=2;b=+h[n+40>>3]<+h[b+40>>3]?i:g}c[e+(f*24|0)+4>>2]=d;h[e+(f*24|0)+16>>3]=+h[(c[b+16>>2]|0)+40>>3];c[(c[k>>2]|0)+120>>2]=f;c[(c[j>>2]|0)+120>>2]=f;c[41937]=f+1}while(0);i=fo(a,i)|0}return}function pk(a){a=a|0;var b=0.0,d=0.0,e=0,f=0,g=0,i=0.0,j=0.0;rk(a);g=c[41935]|0;e=c[a+16>>2]|0;b=+(O(c[e+252>>2]|0,g+-1|0)|0);f=c[41936]|0;e=e+248|0;a=0;d=0.0;while(1){if((a|0)>=(g|0))break;i=+h[f+(a*40|0)+24>>3]+ +(O(c[e>>2]|0,c[f+(a*40|0)+16>>2]|0)|0);j=+h[f+(a*40|0)+32>>3]+b;a=a+1|0;b=j;d=d=(nn(a)|0))break;c[(c[41939]|0)+(b<<2)>>2]=b;b=b+1|0}rk(a);tk(a);uk(a);return}function rk(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,i=0,j=0.0,k=0,l=0;c[41935]=0;b=c[41936]|0;if(b|0){e=0;while(1){if((e|0)>=(c[41937]|0))break;d=c[b+(e*40|0)+4>>2]|0;if(d){$I(d);b=c[41936]|0}d=c[b+(e*40|0)+8>>2]|0;if(d){$I(d);b=c[41936]|0}e=e+1|0}$I(b)}c[41936]=ww((c[41937]|0)*40|0)|0;b=0;while(1){d=c[41937]|0;if((b|0)>=(d|0))break;k=ww(d<<2)|0;c[(c[41936]|0)+(b*40|0)+4>>2]=k;k=ww(c[41937]<<2)|0;l=c[41936]|0;c[l+(b*40|0)+8>>2]=k;c[l+(b*40|0)>>2]=b;c[l+(b*40|0)+12>>2]=0;c[l+(b*40|0)+16>>2]=0;l=l+(b*40|0)+24|0;c[l>>2]=0;c[l+4>>2]=0;c[l+8>>2]=0;c[l+12>>2]=0;b=b+1|0}e=eo(a)|0;while(1){if(!e)break;d=Qm(a,e)|0;while(1){if(!d)break;i=c[d>>2]|0;f=d+-48|0;g=c[41936]|0;b=c[(c[(c[((i&3|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0;while(1){b=b+1|0;if((b|0)>=(c[(c[(c[((i&3|0)==2?d:f)+40>>2]|0)+16>>2]|0)+232>>2]|0))break;i=g+(b*40|0)+16|0;c[i>>2]=(c[i>>2]|0)+1;i=c[d>>2]|0}d=Sm(a,d)|0}e=fo(a,e)|0}i=c[41937]|0;k=c[41938]|0;l=c[41936]|0;d=a+16|0;b=0;while(1){if((b|0)>=(i|0))break;e=(c[c[k+(b*24|0)>>2]>>2]|0)+16|0;f=c[(c[e>>2]|0)+232>>2]|0;if((f|0)>=(c[41935]|0))c[41935]=f+1;g=l+(f*40|0)+24|0;j=+h[g>>3];h[g>>3]=j+ +h[k+(b*24|0)+8>>3]*72.0+(j>0.0?+(c[(c[d>>2]|0)+248>>2]|0):0.0);g=l+(f*40|0)+32|0;j=+h[k+(b*24|0)+16>>3]*72.0;if(+h[g>>3]>3]=j;c[(c[l+(f*40|0)+4>>2]|0)+(c[l+(f*40|0)+12>>2]<<2)>>2]=k+(b*24|0);a=l+((c[(c[e>>2]|0)+232>>2]|0)*40|0)+12|0;c[a>>2]=(c[a>>2]|0)+1;b=b+1|0}return}function sk(){var a=0,b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;k=c[41935]|0;l=c[41936]|0;j=0;b=0;a=0;while(1){if((j|0)>=(k|0))break;d=l+(j*40|0)|0;i=c[l+(j*40|0)+12>>2]|0;e=(b|0)==0;a:do if(i)if(!e){if((c[d>>2]|0)>(a|0)){f=l+(j*40|0)+4|0;d=0;while(1){if((d|0)>=(i|0))break a;g=c[(c[f>>2]|0)+(d<<2)>>2]|0;h=c[g+4>>2]|0;e=0;while(1){if((e|0)>=(h|0))break;m=(c[(c[(c[g>>2]|0)+(e<<2)>>2]|0)+16>>2]|0)+232|0;c[m>>2]=(c[m>>2]|0)-b;e=e+1|0}d=d+1|0}}}else b=0;else{if(e)a=c[d>>2]|0;b=b+1|0}while(0);j=j+1|0}return}function tk(a){a=a|0;var b=0;b=c[41939]|0;sL(b,nn(a)|0,4,15);return}function uk(b){b=b|0;var d=0.0,e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0.0,n=0,o=0,p=0,q=0,r=0.0,s=0;j=c[41935]|0;k=c[41936]|0;g=c[41939]|0;i=0;while(1){if((i|0)>=(j|0)){e=0;d=0.0;break}e=c[g+(i<<2)>>2]|0;f=i+1|0;if((c[k+(e*40|0)+12>>2]|0)<2)i=f;else{l=4;break}}if((l|0)==4)if((j|0)>(f|0))d=+h[k+((c[g+(f<<2)>>2]|0)*40|0)+24>>3];else d=0.0;a:do if((i|0)!=(j|0)){sL(c[k+(e*40|0)+4>>2]|0,c[k+(e*40|0)+12>>2]|0,4,16);g=c[41936]|0;r=+h[g+(e*40|0)+24>>3];r=!(d<=r*.25)&!(d>=r*.75)?d:r*.5;s=c[g+(e*40|0)+12>>2]|0;q=b+16|0;n=0;o=0;d=0.0;f=0;p=0;while(1){if((p|0)>=(f+s|0))break a;do if(!(c[(c[g+(e*40|0)+8>>2]|0)+(p<<2)>>2]|0)){l=c[(c[g+(e*40|0)+4>>2]|0)+(p<<2)>>2]|0;b=l+8|0;m=+h[b>>3]*72.0+d+(d>0.0?+(c[(c[q>>2]|0)+248>>2]|0):0.0);i=(o|0)!=0;if(!(i&!(m<=r))){j=i?n:l;i=i?o:1;d=m;break}j=n+4|0;k=l+4|0;i=0;while(1){if((i|0)<(c[j>>2]|0))g=0;else break;while(1){if((g|0)>=(c[k>>2]|0))break;a[(c[(bh(c[(c[n>>2]|0)+(i<<2)>>2]|0,c[(c[l>>2]|0)+(g<<2)>>2]|0,0)|0)+16>>2]|0)+112>>0]=1;g=g+1|0}i=i+1|0}g=c[41936]|0;c[(c[g+(e*40|0)+8>>2]|0)+(p<<2)>>2]=1;j=g+(e*40|0)+12|0;c[j>>2]=(c[j>>2]|0)+-1;j=g+(e*40|0)+16|0;c[j>>2]=(c[j>>2]|0)+1;j=g+(e*40|0)+24|0;h[j>>3]=+h[b>>3]*-72.0-+(c[(c[q>>2]|0)+248>>2]|0)+ +h[j>>3];j=n;i=o}else{j=n;i=o;f=f+1|0}while(0);n=j;o=i;p=p+1|0}}while(0);return}function vk(a,b){a=a|0;b=b|0;a=wk(c[a>>2]|0)|0;b=wk(c[b>>2]|0)|0;return ((b|0)<(a|0)&1)-((b|0)>(a|0)&1)|0}function wk(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;f=a+4|0;d=0;b=0;while(1){if((d|0)>=(c[f>>2]|0))break;e=c[(c[a>>2]|0)+(d<<2)>>2]|0;g=so(e)|0;e=Qm(g,e)|0;while(1){if(!e)break;e=Sm(g,e)|0;b=b+1|0}d=d+1|0}return b|0}function xk(a,b){a=a|0;b=b|0;var d=0.0,e=0.0,f=0;f=c[41936]|0;e=+h[f+((c[b>>2]|0)*40|0)+24>>3];d=+h[f+((c[a>>2]|0)*40|0)+24>>3];return (e>d&1)-(e>2]|0)+216>>2]=0;b=fo(a,b)|0}return}function zk(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=l;l=l+32|0;f=g+16|0;e=g+8|0;d=g+20|0;c[d>>2]=5;a=Jm(a,84624)|0;if(a|0?(c[e>>2]=g,c[e+4>>2]=d,(dM(a,80344,e)|0)>=1):0)$l(0,80351,f)|0;c[b+24>>2]=0;c[b+32>>2]=0;l=g;return 0}function Ak(b){b=b|0;var d=0,e=0;d=c[42234]|0;if((((d|0)!=0?(e=Km(b,d)|0,(e|0)!=0):0)?(a[e>>0]|0)!=0:0)?(JA(e)|0)<<24>>24==0:0)b=1;else b=0;return b|0}function Bk(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0;Wk(a);b=eo(a)|0;while(1){if(!b)break;d=Qm(a,b)|0;while(1){if(!d)break;do if(((c[(c[d+16>>2]|0)+172>>2]|0)==0?(Ak(d)|0)==0:0)?(e=d+48|0,f=LA(c[((c[d>>2]&3|0)==3?d:e)+40>>2]|0)|0,g=d+-48|0,h=LA(c[((c[d>>2]&3|0)==2?d:g)+40>>2]|0)|0,(f|0)!=(h|0)):0){if((c[(c[f+16>>2]|0)+212>>2]|0)==0?(c[(c[h+16>>2]|0)+212>>2]|0)==0:0){i=Tg(f,h)|0;if(!i){bh(f,h,d)|0;break}else{jh(d,i);break}}i=c[d>>2]&3;Ck(a,c[((i|0)==3?d:e)+40>>2]|0,c[((i|0)==2?d:g)+40>>2]|0,d)}while(0);d=Sm(a,d)|0}b=fo(a,b)|0}return}function Ck(b,d,f,g){b=b|0;d=d|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;j=c[g>>2]&3;h=c[(c[((j|0)==3?g:g+48|0)+40>>2]|0)+16>>2]|0;i=c[h+212>>2]|0;if(!i)k=0;else k=(c[h+232>>2]|0)-(c[(c[(c[(c[i+16>>2]|0)+264>>2]|0)+16>>2]|0)+232>>2]|0)|0;h=c[(c[((j|0)==2?g:g+-48|0)+40>>2]|0)+16>>2]|0;i=c[h+212>>2]|0;if(!i)h=0;else h=(c[(c[(c[(c[i+16>>2]|0)+264>>2]|0)+16>>2]|0)+232>>2]|0)-(c[h+232>>2]|0)|0;j=g+16|0;k=h+k+(e[(c[j>>2]|0)+170>>1]|0)|0;b=gh(b)|0;a[(c[b+16>>2]|0)+156>>0]=2;i=LA(d)|0;d=LA(f)|0;f=Ni(b,i,(k|0)>0?0.0:+(0-k|0),(c[(c[j>>2]|0)+156>>2]|0)*10|0)|0;c[(c[(Ni(b,d,+(((k|0)>0?k:0)|0),c[(c[j>>2]|0)+156>>2]|0)|0)+16>>2]|0)+116>>2]=g;c[(c[f+16>>2]|0)+116>>2]=g;return}function Dk(a,d,f,g){a=a|0;d=d|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;j=c[d>>2]&3;i=(j|0)==3?d:d+48|0;j=(j|0)==2?d:d+-48|0;j=c[(c[(c[((c[(c[(c[i+40>>2]|0)+16>>2]|0)+232>>2]|0)>(c[(c[(c[j+40>>2]|0)+16>>2]|0)+232>>2]|0)?i:j)+40>>2]|0)+16>>2]|0)+232>>2]|0;i=d+16|0;d=(c[i>>2]|0)+172|0;if(c[d>>2]|0)ma(80440,80462,148,80471);c[d>>2]=f;h=(g|0)==0;do{d=c[i>>2]|0;if(h)g=c[f+16>>2]|0;else{g=c[f+16>>2]|0;k=g+168|0;b[k>>1]=(e[k>>1]|0)+(e[d+168>>1]|0)}k=g+154|0;b[k>>1]=(e[k>>1]|0)+(e[d+154>>1]|0);g=g+156|0;c[g>>2]=(c[g>>2]|0)+(c[d+156>>2]|0);d=f+-48|0;g=c[((c[f>>2]&3|0)==2?f:d)+40>>2]|0;if((c[(c[g+16>>2]|0)+232>>2]|0)==(j|0))break;Ek(a,g);f=c[c[(c[(c[((c[f>>2]&3|0)==2?f:d)+40>>2]|0)+16>>2]|0)+180>>2]>>2]|0}while((f|0)!=0);return}function Ek(a,b){a=a|0;b=b|0;var d=0.0;d=+((c[(c[a+16>>2]|0)+248>>2]|0)/2|0|0);b=c[b+16>>2]|0;a=b+88|0;h[a>>3]=+h[a>>3]+d;b=b+96|0;h[b>>3]=+h[b>>3]+d;return}function Fk(a,b){a=a|0;b=b|0;var d=0,e=0;if(((((a|0)!=0&(b|0)!=0?(e=c[a>>2]&3,d=c[b>>2]&3,(c[((e|0)==3?a:a+48|0)+40>>2]|0)==(c[((d|0)==3?b:b+48|0)+40>>2]|0)):0)?(c[((e|0)==2?a:a+-48|0)+40>>2]|0)==(c[((d|0)==2?b:b+-48|0)+40>>2]|0):0)?(c[(c[a+16>>2]|0)+96>>2]|0)==(c[(c[b+16>>2]|0)+96>>2]|0):0)?(ij(a,b)|0)!=0:0)a=1;else a=0;return a|0}function Gk(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;r=b+16|0;d=c[r>>2]|0;c[d+192>>2]=0;c[d+232>>2]=0;Wk(b);d=1;while(1){e=c[r>>2]|0;if((d|0)>(c[e+180>>2]|0))break;Xk(b,c[(c[e+184>>2]|0)+(d<<2)>>2]|0);d=d+1|0}h=eo(b)|0;while(1){if(!h)break;g=Qm(b,h)|0;while(1){if(!g)break;d=c[g>>2]|0;e=(c[(c[((d&3|0)==2?g:g+-48|0)+40>>2]|0)+16>>2]|0)+160|0;f=a[e>>0]|0;if(f<<24>>24<3){a[e>>0]=f+1<<24>>24;d=c[g>>2]|0}d=(c[(c[((d&3|0)==3?g:g+48|0)+40>>2]|0)+16>>2]|0)+160|0;e=a[d>>0]|0;if(e<<24>>24<3)a[d>>0]=e+1<<24>>24;g=Sm(b,g)|0}h=fo(b,h)|0}m=eo(b)|0;while(1){if(!m)break;if((c[(c[m+16>>2]|0)+212>>2]|0)==0?(m|0)==(LA(m)|0):0){ch(b,m);l=(c[r>>2]|0)+232|0;c[l>>2]=(c[l>>2]|0)+1}d=0;l=Qm(b,m)|0;while(1){if(!l)break;k=l+16|0;h=c[k>>2]|0;a:do if(!(c[h+172>>2]|0)){if(Hk(l)|0){if(!(Fk(d,l)|0)){Ik(b,l);d=l;break}e=c[(c[d+16>>2]|0)+172>>2]|0;if(e|0){Dk(b,l,e,0);Zg(l);break}k=c[l>>2]&3;if((c[(c[(c[((k|0)==3?l:l+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)!=(c[(c[(c[((k|0)==2?l:l+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0))break;jh(l,d);Zg(l);break}if(d){i=c[l>>2]&3;e=l+48|0;f=c[((i|0)==3?l:e)+40>>2]|0;g=c[d>>2]&3;if((f|0)==(c[((g|0)==3?d:d+48|0)+40>>2]|0)?(n=c[((i|0)==2?l:l+-48|0)+40>>2]|0,(n|0)==(c[((g|0)==2?d:d+-48|0)+40>>2]|0)):0){if((c[(c[f+16>>2]|0)+232>>2]|0)==(c[(c[n+16>>2]|0)+232>>2]|0)){jh(l,d);Zg(l);break}if(((c[h+96>>2]|0)==0?(o=d+16|0,(c[(c[o>>2]|0)+96>>2]|0)==0):0)?(ij(l,d)|0)!=0:0)if(!(a[174080]|0)){Dk(b,l,c[(c[o>>2]|0)+172>>2]|0,1);Zg(l);break}else{a[(c[k>>2]|0)+112>>0]=6;break}else i=e}else i=e}else i=l+48|0;h=c[l>>2]&3;e=c[((h|0)==3?l:i)+40>>2]|0;j=l+-48|0;if((e|0)==(c[((h|0)==2?l:j)+40>>2]|0)){Zg(l);d=l;break}e=LA(e)|0;f=LA(c[((c[l>>2]&3|0)==2?l:j)+40>>2]|0)|0;h=c[l>>2]&3;if((c[((h|0)==3?l:i)+40>>2]|0)==(e|0)?(c[((h|0)==2?l:j)+40>>2]|0)==(f|0):0){g=c[(c[e+16>>2]|0)+232>>2]|0;h=c[(c[f+16>>2]|0)+232>>2]|0;if((g|0)==(h|0)){hh(b,l);d=l;break}if((h|0)>(g|0)){Jk(b,e,f,l);d=l;break}e=bn(b,f,e,0,0)|0;do if(e|0?(p=c[e>>2]&3,q=c[((p|0)==2?e:e+-48|0)+40>>2]|0,(q|0)!=(c[((c[l>>2]&3|0)==2?l:j)+40>>2]|0)):0){f=e+16|0;if(!(c[(c[f>>2]|0)+172>>2]|0))Jk(b,c[((p|0)==3?e:e+48|0)+40>>2]|0,q,e);if((c[(c[k>>2]|0)+96>>2]|0)==0?(c[(c[f>>2]|0)+96>>2]|0)==0:0){if(!(ij(l,e)|0))break;if(!(a[174080]|0)){Zg(l);Dk(b,l,c[(c[f>>2]|0)+172>>2]|0,1);break a}else{a[(c[k>>2]|0)+112>>0]=6;a[(c[f>>2]|0)+153>>0]=1;break a}}}while(0);d=c[l>>2]&3;Jk(b,c[((d|0)==2?l:j)+40>>2]|0,c[((d|0)==3?l:i)+40>>2]|0,l);d=l}}else d=l;while(0);l=Sm(b,l)|0}m=fo(b,m)|0}if((Wf(b)|0)!=(b|0)){d=c[(c[r>>2]|0)+216>>2]|0;if(!d)d=xw(4)|0;else d=zw(d,4)|0;r=c[r>>2]|0;c[r+216>>2]=d;c[d>>2]=c[r+192>>2]}return}function Hk(b){b=b|0;var d=0;d=c[b>>2]&3;if((a[(c[(c[((d|0)==3?b:b+48|0)+40>>2]|0)+16>>2]|0)+159>>0]|0)==7)b=1;else b=(a[(c[(c[((d|0)==2?b:b+-48|0)+40>>2]|0)+16>>2]|0)+159>>0]|0)==7&1;return b|0}function Ik(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;f=Mk(c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0)|0;g=Mk(c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)|0;i=(c[(c[f+16>>2]|0)+232>>2]|0)>(c[(c[g+16>>2]|0)+232>>2]|0);e=i?f:g;f=i?g:f;g=f+16|0;i=e+16|0;a:do if((c[(c[g>>2]|0)+212>>2]|0)!=(c[(c[i>>2]|0)+212>>2]|0)){h=Tg(f,e)|0;if(h|0){Dk(b,d,h,1);break}if((c[(c[g>>2]|0)+232>>2]|0)!=(c[(c[i>>2]|0)+232>>2]|0)){Jk(b,f,e,d);e=(c[d+16>>2]|0)+172|0;while(1){e=c[e>>2]|0;if(!e)break a;f=e+-48|0;if((c[(c[(c[((c[e>>2]&3|0)==2?e:f)+40>>2]|0)+16>>2]|0)+232>>2]|0)>(c[(c[i>>2]|0)+232>>2]|0))break a;a[(c[e+16>>2]|0)+112>>0]=5;e=c[(c[(c[((c[e>>2]&3|0)==2?e:f)+40>>2]|0)+16>>2]|0)+180>>2]|0}}}while(0);return}function Jk(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;k=e+16|0;f=c[k>>2]|0;if(!(c[f+96>>2]|0))j=-1;else j=((c[(c[d+16>>2]|0)+232>>2]|0)+(c[(c[b+16>>2]|0)+232>>2]|0)|0)/2|0;if(c[f+172>>2]|0)ma(80483,80462,89,80508);i=d+16|0;h=c[(c[b+16>>2]|0)+232>>2]|0;while(1){g=h+1|0;f=c[(c[i>>2]|0)+232>>2]|0;if((h|0)>=(f|0))break;if((g|0)<(f|0)){if((g|0)==(j|0))f=Kk(a,e)|0;else f=Lk(a)|0;c[(c[f+16>>2]|0)+232>>2]=g}else f=d;wi(bh(b,f,e)|0);h=g;b=f}if(!(c[(c[k>>2]|0)+172>>2]|0))ma(80519,80462,103,80508);else return}function Kk(b,d){b=b|0;d=d|0;var e=0.0,f=0.0,g=0,i=0,j=0.0;i=d+16|0;g=c[(c[i>>2]|0)+96>>2]|0;e=+h[g+24>>3];f=+h[g+32>>3];g=gh(b)|0;d=g+16|0;c[(c[d>>2]|0)+104>>2]=c[(c[i>>2]|0)+96>>2];j=+(c[(c[(to(g)|0)+16>>2]|0)+248>>2]|0);h[(c[d>>2]|0)+88>>3]=j;if(!(a[(c[i>>2]|0)+114>>0]|0)){b=(c[(c[(to(b)|0)+16>>2]|0)+116>>2]&1|0)==0;i=c[d>>2]|0;h[i+80>>3]=b?f:e;h[i+96>>3]=b?e:f}return g|0}function Lk(a){a=a|0;var b=0;b=gh(a)|0;Ek(a,b);return b|0}function Mk(b){b=b|0;var d=0;d=c[b+16>>2]|0;if((a[d+159>>0]|0)==7)b=c[(c[(c[(c[d+212>>2]|0)+16>>2]|0)+268>>2]|0)+(c[d+232>>2]<<2)>>2]|0;else b=LA(b)|0;return b|0}function Nk(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;j=Wf(a)|0;h=eo(a)|0;while(1){if(!h)break;b=Vm(j,h)|0;i=0;while(1){if(!b)break;l=Wm(j,b,h)|0;if(Co(a,b)|0){k=i;b=l;i=k;continue}k=(c[b>>2]&3|0)==2?b:b+-48|0;m=(Fk(i,k)|0)==0;e=c[k>>2]&3;b=c[((e|0)==3?k:k+48|0)+40>>2]|0;d=c[(c[b+16>>2]|0)+232>>2]|0;e=c[((e|0)==2?k:k+-48|0)+40>>2]|0;f=c[(c[e+16>>2]|0)+232>>2]|0;g=(d|0)==(f|0);if(!m){c[(c[k+16>>2]|0)+172>>2]=g?i:0;b=c[(c[i+16>>2]|0)+172>>2]|0;if(!b){m=i;b=l;i=m;continue}Dk(a,k,b,0);_g(k);m=i;b=l;i=m;continue}if(!g)if((f|0)>(d|0)){Ok(b,e,k);b=l;i=k;continue}else{Ok(e,b,k);b=l;i=k;continue}b=Vg(b,e)|0;if(!b){hh(j,k);b=l;i=k;continue}if((k|0)==(b|0)){m=i;b=l;i=m;continue}_g(k);if(c[(c[k+16>>2]|0)+172>>2]|0){m=i;b=l;i=m;continue}jh(k,b);m=i;b=l;i=m}h=fo(a,h)|0}return}function Ok(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;f=Pk(a)|0;e=Pk(b)|0;Qk(f,e,d,c[(c[d+16>>2]|0)+172>>2]|0,(f|0)==(a|0)&(e|0)==(b|0)?1:5);return}function Pk(b){b=b|0;var d=0,e=0,f=0;d=c[b+16>>2]|0;e=c[d+212>>2]|0;if((e|0)!=0?(f=c[e+16>>2]|0,(a[f+272>>0]|0)==0):0)b=c[(c[f+268>>2]|0)+(c[d+232>>2]<<2)>>2]|0;return b|0}function Qk(d,e,f,g,h){d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0;n=d+16|0;k=c[(c[n>>2]|0)+232>>2]|0;o=e+16|0;i=c[(c[o>>2]|0)+232>>2]|0;if((i|0)<=(k|0))ma(80544,80572,81,80582);m=c[g>>2]&3;if(!((c[((m|0)==3?g:g+48|0)+40>>2]|0)==(d|0)?(c[((m|0)==2?g:g+-48|0)+40>>2]|0)==(e|0):0))l=5;a:do if((l|0)==5){if((b[(c[g+16>>2]|0)+168>>1]|0)>1){c[(c[f+16>>2]|0)+172>>2]=0;if(((i-k|0)==1?(j=Tg(d,e)|0,j|0):0)?ij(f,j)|0:0){jh(f,j);if(a[(c[n>>2]|0)+156>>0]|0)break;if(a[(c[o>>2]|0)+156>>0]|0)break;Zg(f);break}m=h&255;h=d;l=c[(c[n>>2]|0)+232>>2]|0;while(1){i=c[(c[o>>2]|0)+232>>2]|0;if((l|0)>=(i|0))break a;if((l|0)<(i+-1|0)){i=Wf(d)|0;j=g+-48|0;i=Rk(i,c[((c[g>>2]&3|0)==2?g:j)+40>>2]|0)|0;k=g}else{i=e;j=g+-48|0;k=g}a[(c[(bh(h,i,f)|0)+16>>2]|0)+112>>0]=m;n=(c[g+16>>2]|0)+168|0;b[n>>1]=(b[n>>1]|0)+-1<<16>>16;h=i;l=l+1|0;g=c[c[(c[(c[((c[k>>2]&3|0)==2?g:j)+40>>2]|0)+16>>2]|0)+180>>2]>>2]|0}}do if((i-k|0)==1){g=Tg(d,e)|0;if(g|0?ij(f,g)|0:0){c[(c[f+16>>2]|0)+172>>2]=g;m=c[g+16>>2]|0;a[m+112>>0]=h;m=m+168|0;b[m>>1]=(b[m>>1]|0)+1<<16>>16;if(a[(c[n>>2]|0)+156>>0]|0)break;if(a[(c[o>>2]|0)+156>>0]|0)break;Zg(f);break}c[(c[f+16>>2]|0)+172>>2]=0;g=bh(d,e,f)|0;a[(c[g+16>>2]|0)+112>>0]=h}while(0);i=c[(c[o>>2]|0)+232>>2]|0;if((i-(c[(c[n>>2]|0)+232>>2]|0)|0)>1){if((c[((c[g>>2]&3|0)==3?g:g+48|0)+40>>2]|0)==(d|0))l=i;else{n=f+16|0;c[(c[n>>2]|0)+172>>2]=0;l=bh(d,c[((c[g>>2]&3|0)==2?g:g+-48|0)+40>>2]|0,f)|0;c[(c[n>>2]|0)+172>>2]=l;Yg(g);g=l;l=c[(c[o>>2]|0)+232>>2]|0}while(1){i=c[g>>2]&3;j=c[((i|0)==2?g:g+-48|0)+40>>2]|0;k=c[j+16>>2]|0;if((c[k+232>>2]|0)==(l|0))break;g=c[c[k+180>>2]>>2]|0}if((j|0)!=(e|0)){a[(c[(bh(c[((i|0)==3?g:g+48|0)+40>>2]|0,e,f)|0)+16>>2]|0)+112>>0]=h;Yg(g)}}}while(0);return}function Rk(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=b+16|0;b=c[d>>2]|0;e=c[b+232>>2]|0;Sk(a,e,c[b+236>>2]|0,2);b=gh(a)|0;d=c[d>>2]|0;f=c[b+16>>2]|0;h[f+88>>3]=+h[d+88>>3];h[f+96>>3]=+h[d+96>>3];c[f+232>>2]=c[d+232>>2];d=(c[d+236>>2]|0)+1|0;c[f+236>>2]=d;c[(c[(c[(c[a+16>>2]|0)+196>>2]|0)+(e<<6)+4>>2]|0)+(d<<2)>>2]=b;return b|0}function Sk(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;h=a+16|0;f=c[(c[h>>2]|0)+196>>2]|0;i=c[f+(b<<6)+4>>2]|0;a:do if((e|0)<1){d=d-e|0;while(1){g=d+1|0;a=c[f+(b<<6)>>2]|0;if((g|0)>=(a|0))break;a=c[i+(g<<2)>>2]|0;f=d+e|0;c[(c[a+16>>2]|0)+236>>2]=f;c[i+(f<<2)>>2]=a;d=g;f=c[(c[h>>2]|0)+196>>2]|0}g=e+-1|0;d=g+a|0;while(1){if((d|0)>=(a|0))break a;c[i+(d<<2)>>2]=0;f=c[(c[h>>2]|0)+196>>2]|0;d=d+1|0;a=c[f+(b<<6)>>2]|0}}else{g=e+-1|0;a=c[f+(b<<6)>>2]|0;while(1){a=a+-1|0;if((a|0)<=(d|0))break;j=c[i+(a<<2)>>2]|0;f=g+a|0;c[(c[j+16>>2]|0)+236>>2]=f;c[i+(f<<2)>>2]=j}f=e+d|0;a=d;while(1){a=a+1|0;if((a|0)>=(f|0))break;c[i+(a<<2)>>2]=0}a=c[(c[h>>2]|0)+196>>2]|0;f=a;a=c[a+(b<<6)>>2]|0}while(0);c[f+(b<<6)>>2]=g+a;return}function Tk(a){a=a|0;var b=0;Gk(a);b=c[a+16>>2]|0;c[b+220>>2]=1;c[c[b+216>>2]>>2]=c[b+192>>2];ti(a);_h(a,0);Uk(a);Nk(a);Vk(a);return}function Uk(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;k=Wf(d)|0;l=d+16|0;f=c[l>>2]|0;j=b[f+236>>1]|0;e=j<<16>>16;m=k+16|0;if(j<<16>>16>0)a[(c[(c[m>>2]|0)+196>>2]|0)+(e+-1<<6)+49>>0]=0;j=e;while(1){if((j|0)>(b[f+238>>1]|0))break;i=c[(c[(c[(c[f+268>>2]|0)+(j<<2)>>2]|0)+16>>2]|0)+236>>2]|0;Sk(k,j,i,c[(c[f+196>>2]|0)+(j<<6)>>2]|0);g=0;h=i;while(1){f=c[l>>2]|0;e=c[f+196>>2]|0;if((g|0)>=(c[e+(j<<6)>>2]|0))break;e=c[(c[e+(j<<6)+4>>2]|0)+(g<<2)>>2]|0;c[(c[(c[(c[m>>2]|0)+196>>2]|0)+(j<<6)+4>>2]|0)+(h<<2)>>2]=e;f=c[e+16>>2]|0;c[f+236>>2]=h;if((a[f+156>>0]|0)==1)c[e+24>>2]=to(k)|0;eh(d,e);ch(k,e);f=(c[m>>2]|0)+232|0;c[f>>2]=(c[f>>2]|0)+1;g=g+1|0;h=h+1|0}h=c[(c[m>>2]|0)+196>>2]|0;c[e+(j<<6)+4>>2]=(c[h+(j<<6)+4>>2]|0)+(i<<2);a[h+(j<<6)+49>>0]=0;j=j+1|0}e=c[m>>2]|0;if((j|0)<(b[e+238>>1]|0))a[(c[e+196>>2]|0)+(j<<6)+49>>0]=0;a[f+272>>0]=1;return}function Vk(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=a+16|0;d=c[i>>2]|0;h=b[d+236>>1]|0;while(1){if((h|0)>(b[d+238>>1]|0))break;f=c[(c[d+268>>2]|0)+(h<<2)>>2]|0;g=f+16|0;while(1){d=c[g>>2]|0;e=c[c[d+180>>2]>>2]|0;if(!e)break;Yg(e)}while(1){d=c[c[d+172>>2]>>2]|0;if(!d)break;Yg(d);d=c[g>>2]|0}eh(Wf(a)|0,f);c[(c[(c[i>>2]|0)+268>>2]|0)+(h<<2)>>2]=0;h=h+1|0;d=c[i>>2]|0}return}function Wk(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;n=o;f=eo(b)|0;while(1){if(!f)break;e=f+16|0;d=c[e>>2]|0;if((a[d+159>>0]|0)==7){NA(f);d=c[e>>2]|0}c[d+212>>2]=0;f=fo(b,f)|0}m=b+16|0;k=1;while(1){d=c[m>>2]|0;if((k|0)>(c[d+180>>2]|0))break;h=c[(c[d+184>>2]|0)+(k<<2)>>2]|0;i=h+16|0;d=eo(h)|0;a:while(1){if(!d)break;j=fo(h,d)|0;e=d+16|0;if(a[(c[e>>2]|0)+159>>0]|0){f=En(d)|0;g=En(b)|0;c[n>>2]=f;c[n+4>>2]=g;$l(0,80591,n)|0;ro(h,d)|0;d=j;continue}OA(d,c[(c[i>>2]|0)+264>>2]|0);g=c[e>>2]|0;c[g+212>>2]=h;a[g+159>>0]=7;g=Qm(h,d)|0;while(1){if(!g){d=j;continue a}d=c[(c[g+16>>2]|0)+172>>2]|0;b:do if(d|0)do{e=d+-48|0;f=c[(c[((c[d>>2]&3|0)==2?d:e)+40>>2]|0)+16>>2]|0;if((a[f+156>>0]|0)!=1)break b;c[f+212>>2]=h;d=c[c[(c[(c[((c[d>>2]&3|0)==2?d:e)+40>>2]|0)+16>>2]|0)+180>>2]>>2]|0}while((d|0)!=0);while(0);g=Sm(h,g)|0}}k=k+1|0}l=o;return}function Xk(d,e){d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;k=e+16|0;g=ww((b[(c[k>>2]|0)+238>>1]<<2)+8|0)|0;f=c[k>>2]|0;c[f+268>>2]=g;g=0;h=b[f+236>>1]|0;while(1){if((h|0)>(b[f+238>>1]|0))break;f=gh(d)|0;c[(c[(c[k>>2]|0)+268>>2]|0)+(h<<2)>>2]=f;j=c[f+16>>2]|0;c[j+232>>2]=h;a[j+159>>0]=7;c[j+212>>2]=e;if(g|0){j=(c[(bh(g,f,0)|0)+16>>2]|0)+154|0;b[j>>1]=(b[j>>1]|0)*1e3}g=f;h=h+1|0;f=c[k>>2]|0}j=eo(e)|0;while(1){f=c[k>>2]|0;if(!j)break;h=(c[(c[f+268>>2]|0)+(c[(c[j+16>>2]|0)+232>>2]<<2)>>2]|0)+16|0;f=(c[h>>2]|0)+216|0;c[f>>2]=(c[f>>2]|0)+1;f=Qm(e,j)|0;while(1){if(!f)break;i=c[f>>2]|0;d=f+-48|0;g=c[(c[(c[((i&3|0)==3?f:f+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0;while(1){if((g|0)>=(c[(c[(c[((i&3|0)==2?f:d)+40>>2]|0)+16>>2]|0)+232>>2]|0))break;i=(c[(c[c[(c[h>>2]|0)+180>>2]>>2]|0)+16>>2]|0)+168|0;b[i>>1]=(b[i>>1]|0)+1<<16>>16;g=g+1|0;i=c[f>>2]|0}f=Sm(e,f)|0}j=fo(e,j)|0}d=b[f+238>>1]|0;i=f+268|0;f=b[f+236>>1]|0;while(1){if((f|0)>(d|0))break;g=(c[(c[(c[i>>2]|0)+(f<<2)>>2]|0)+16>>2]|0)+216|0;h=c[g>>2]|0;if((h|0)>1)c[g>>2]=h+-1;f=f+1|0}return}function Yk(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;k=(c[(c[e+16>>2]|0)+212>>2]|0)+16|0;e=c[k>>2]|0;j=f+1|0;if((j|0)!=(a[e+273>>0]|0)){i=b[e+236>>1]|0;while(1){h=b[e+238>>1]|0;if((i|0)>(h<<16>>16|0))break;ni(d,c[(c[e+268>>2]|0)+(i<<2)>>2]|0);i=i+1|0;e=c[k>>2]|0}i=b[e+236>>1]|0;while(1){if((i|0)>(h<<16>>16|0))break;oi(g,c[(c[e+268>>2]|0)+(i<<2)>>2]|0,f);d=c[k>>2]|0;i=i+1|0;h=b[d+238>>1]|0;e=d}a[e+273>>0]=j}return}function Zk(b){b=b|0;var d=0,e=0,f=0,g=0,h=0;h=eo(b)|0;while(1){if(!h)break;c[(c[h+16>>2]|0)+212>>2]=0;g=Qm(b,h)|0;while(1){if(!g)break;d=c[(c[g+16>>2]|0)+172>>2]|0;a:do if(d|0)do{e=d+-48|0;f=c[(c[((c[d>>2]&3|0)==2?d:e)+40>>2]|0)+16>>2]|0;if((a[f+156>>0]|0)!=1)break a;c[f+212>>2]=0;d=c[c[(c[(c[((c[d>>2]&3|0)==2?d:e)+40>>2]|0)+16>>2]|0)+180>>2]>>2]|0}while((d|0)!=0);while(0);g=Sm(b,g)|0}h=fo(b,h)|0}_k(b);return}function _k(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;e=b+16|0;d=1;while(1){f=c[e>>2]|0;if((d|0)>(c[f+180>>2]|0))break;_k(c[(c[f+184>>2]|0)+(d<<2)>>2]|0);d=d+1|0}i=eo(b)|0;while(1){if(!i)break;d=(c[i+16>>2]|0)+212|0;if(!(c[d>>2]|0))c[d>>2]=b;h=Qm(b,i)|0;while(1){if(!h)break;d=c[(c[h+16>>2]|0)+172>>2]|0;a:do if(d|0)do{e=c[d>>2]|0;g=d+-48|0;f=c[(c[((e&3|0)==2?d:g)+40>>2]|0)+16>>2]|0;if((a[f+156>>0]|0)!=1)break a;f=f+212|0;if(!(c[f>>2]|0)){c[f>>2]=b;e=c[d>>2]|0}d=c[c[(c[(c[((e&3|0)==2?d:g)+40>>2]|0)+16>>2]|0)+180>>2]>>2]|0}while((d|0)!=0);while(0);h=Sm(b,h)|0}i=fo(b,i)|0}return}function $k(a){a=a|0;var b=0,c=0,d=0;d=jB(a)|0;c=eo(a)|0;while(1){if(!c)break;b=Qm(a,c)|0;while(1){if(!b)break;al(b,d);b=Sm(a,b)|0}c=fo(a,c)|0}Ll(d)|0;return}function al(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;M=l;l=l+320|0;H=M+296|0;G=M+280|0;x=M+136|0;w=M+120|0;n=M+104|0;i=M+88|0;f=M+80|0;E=M+16|0;z=M;j=M+264|0;k=M+248|0;m=M+232|0;o=M+216|0;A=M+200|0;B=M+184|0;y=M+168|0;D=M+152|0;g=bl(Jm(a,80645)|0,b)|0;q=bl(Jm(a,80651)|0,b)|0;r=(q|0)!=0;b=(g|0)!=0;do if(b|r?(L=a+16|0,e=c[(c[L>>2]|0)+8>>2]|0,e|0):0){if((c[e+4>>2]|0)>1){K=En(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0)|0;L=En(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0)|0;c[f>>2]=K;c[f+4>>2]=L;$l(0,80657,f)|0;break}I=c[e>>2]|0;e=c[I+4>>2]|0;p=c[a>>2]&3;s=a+-48|0;t=c[((p|0)==2?a:s)+40>>2]|0;u=a+48|0;p=c[((p|0)==3?a:u)+40>>2]|0;J=xw(48)|0;v=I+12|0;c[J+12>>2]=c[v>>2];C=I+8|0;c[J+8>>2]=c[C>>2];do if(b){h=(c[g+16>>2]|0)+16|0;g=(c[t+16>>2]|0)+16|0;c[H>>2]=c[g>>2];c[H+4>>2]=c[g+4>>2];c[H+8>>2]=c[g+8>>2];c[H+12>>2]=c[g+12>>2];if(!(cl(H,h)|0)){o=En(c[((c[a>>2]&3|0)==3?a:u)+40>>2]|0)|0;F=En(c[((c[a>>2]&3|0)==2?a:s)+40>>2]|0)|0;K=Jm(a,80645)|0;c[i>>2]=o;c[i+4>>2]=F;c[i+8>>2]=K;$l(0,80698,i)|0;K=26;break}b=c[I>>2]|0;c[H>>2]=c[b>>2];c[H+4>>2]=c[b+4>>2];c[H+8>>2]=c[b+8>>2];c[H+12>>2]=c[b+12>>2];if(cl(H,h)|0){F=(c[p+16>>2]|0)+16|0;c[H>>2]=c[F>>2];c[H+4>>2]=c[F+4>>2];c[H+8>>2]=c[F+8>>2];c[H+12>>2]=c[F+12>>2];if(cl(H,h)|0){o=En(c[((c[a>>2]&3|0)==3?a:u)+40>>2]|0)|0;F=En(c[((c[a>>2]&3|0)==2?a:s)+40>>2]|0)|0;K=Jm(a,80645)|0;c[n>>2]=o;c[n+4>>2]=F;c[n+8>>2]=K;$l(0,80741,n)|0;K=26;break}if(!(c[C>>2]|0))ma(80783,80794,369,80805);o=I+16|0;c[G>>2]=c[b>>2];c[G+4>>2]=c[b+4>>2];c[G+8>>2]=c[b+8>>2];c[G+12>>2]=c[b+12>>2];c[H>>2]=c[o>>2];c[H+4>>2]=c[o+4>>2];c[H+8>>2]=c[o+8>>2];c[H+12>>2]=c[o+12>>2];dl(z,G,H,h);F=(c[I>>2]|0)+48|0;c[F>>2]=c[z>>2];c[F+4>>2]=c[z+4>>2];c[F+8>>2]=c[z+8>>2];c[F+12>>2]=c[z+12>>2];F=(c[I>>2]|0)+16|0;c[G>>2]=c[z>>2];c[G+4>>2]=c[z+4>>2];c[G+8>>2]=c[z+8>>2];c[G+12>>2]=c[z+12>>2];c[H>>2]=c[o>>2];c[H+4>>2]=c[o+4>>2];c[H+8>>2]=c[o+8>>2];c[H+12>>2]=c[o+12>>2];el(j,G,H);c[F>>2]=c[j>>2];c[F+4>>2]=c[j+4>>2];c[F+8>>2]=c[j+8>>2];c[F+12>>2]=c[j+12>>2];F=c[I>>2]|0;b=F+16|0;c[G>>2]=c[b>>2];c[G+4>>2]=c[b+4>>2];c[G+8>>2]=c[b+8>>2];c[G+12>>2]=c[b+12>>2];c[H>>2]=c[o>>2];c[H+4>>2]=c[o+4>>2];c[H+8>>2]=c[o+8>>2];c[H+12>>2]=c[o+12>>2];el(k,G,H);c[F>>2]=c[k>>2];c[F+4>>2]=c[k+4>>2];c[F+8>>2]=c[k+8>>2];c[F+12>>2]=c[k+12>>2];F=c[I>>2]|0;b=F+32|0;F=F+16|0;c[G>>2]=c[F>>2];c[G+4>>2]=c[F+4>>2];c[G+8>>2]=c[F+8>>2];c[G+12>>2]=c[F+12>>2];c[H>>2]=c[z>>2];c[H+4>>2]=c[z+4>>2];c[H+8>>2]=c[z+8>>2];c[H+12>>2]=c[z+12>>2];el(m,G,H);c[b>>2]=c[m>>2];c[b+4>>2]=c[m+4>>2];c[b+8>>2]=c[m+8>>2];c[b+12>>2]=c[m+12>>2];b=c[v>>2]|0;if(!b){F=3;break}F=(Ot(a,c[I>>2]|0,0,0,J,b)|0)+3|0;break}g=e+-1|0;b=0;while(1){if((b|0)>=(g|0))break;if(fl((c[I>>2]|0)+(b<<4)|0,h)|0)break;b=b+3|0}e=c[v>>2]|0;f=(e|0)!=0;if((b|0)==(g|0))if(f){F=J+32|0;m=I+32|0;n=(c[I>>2]|0)+(g<<4)|0;c[G>>2]=c[m>>2];c[G+4>>2]=c[m+4>>2];c[G+8>>2]=c[m+8>>2];c[G+12>>2]=c[m+12>>2];c[H>>2]=c[n>>2];c[H+4>>2]=c[n+4>>2];c[H+8>>2]=c[n+8>>2];c[H+12>>2]=c[n+12>>2];dl(o,G,H,h);c[F>>2]=c[o>>2];c[F+4>>2]=c[o+4>>2];c[F+8>>2]=c[o+8>>2];c[F+12>>2]=c[o+12>>2];F=g;break}else ma(80822,80794,387,80805);else{if(f)b=Ot(a,c[I>>2]|0,0,b,J,e)|0;F=b+3|0;break}}else K=26;while(0);if((K|0)==26){b=e+-1|0;if(!(c[v>>2]|0))F=b;else{F=J+32|0;o=I+32|0;c[F>>2]=c[o>>2];c[F+4>>2]=c[o+4>>2];c[F+8>>2]=c[o+8>>2];c[F+12>>2]=c[o+12>>2];F=b}}do if(r){f=(c[q+16>>2]|0)+16|0;r=(c[p+16>>2]|0)+16|0;c[H>>2]=c[r>>2];c[H+4>>2]=c[r+4>>2];c[H+8>>2]=c[r+8>>2];c[H+12>>2]=c[r+12>>2];if(!(cl(H,f)|0)){G=En(c[((c[a>>2]&3|0)==3?a:u)+40>>2]|0)|0;H=En(c[((c[a>>2]&3|0)==2?a:s)+40>>2]|0)|0;K=Jm(a,80651)|0;c[w>>2]=G;c[w+4>>2]=H;c[w+8>>2]=K;$l(0,80833,w)|0;K=52;break}b=(c[I>>2]|0)+(F<<4)|0;c[H>>2]=c[b>>2];c[H+4>>2]=c[b+4>>2];c[H+8>>2]=c[b+8>>2];c[H+12>>2]=c[b+12>>2];if(cl(H,f)|0){E=(c[t+16>>2]|0)+16|0;c[H>>2]=c[E>>2];c[H+4>>2]=c[E+4>>2];c[H+8>>2]=c[E+8>>2];c[H+12>>2]=c[E+12>>2];if(cl(H,f)|0){G=En(c[((c[a>>2]&3|0)==3?a:u)+40>>2]|0)|0;H=En(c[((c[a>>2]&3|0)==2?a:s)+40>>2]|0)|0;K=Jm(a,80651)|0;c[x>>2]=G;c[x+4>>2]=H;c[x+8>>2]=K;$l(0,80876,x)|0;K=52;break}if(!(c[v>>2]|0))ma(80822,80794,429,80805);x=J+32|0;c[G>>2]=c[b>>2];c[G+4>>2]=c[b+4>>2];c[G+8>>2]=c[b+8>>2];c[G+12>>2]=c[b+12>>2];c[H>>2]=c[x>>2];c[H+4>>2]=c[x+4>>2];c[H+8>>2]=c[x+8>>2];c[H+12>>2]=c[x+12>>2];dl(z,G,H,f);d=F+-3|0;E=(c[I>>2]|0)+(d<<4)|0;c[E>>2]=c[z>>2];c[E+4>>2]=c[z+4>>2];c[E+8>>2]=c[z+8>>2];c[E+12>>2]=c[z+12>>2];E=F+-1|0;b=(c[I>>2]|0)+(E<<4)|0;c[G>>2]=c[z>>2];c[G+4>>2]=c[z+4>>2];c[G+8>>2]=c[z+8>>2];c[G+12>>2]=c[z+12>>2];c[H>>2]=c[x>>2];c[H+4>>2]=c[x+4>>2];c[H+8>>2]=c[x+8>>2];c[H+12>>2]=c[x+12>>2];el(A,G,H);c[b>>2]=c[A>>2];c[b+4>>2]=c[A+4>>2];c[b+8>>2]=c[A+8>>2];c[b+12>>2]=c[A+12>>2];b=c[I>>2]|0;D=b+(F<<4)|0;b=b+(E<<4)|0;c[G>>2]=c[b>>2];c[G+4>>2]=c[b+4>>2];c[G+8>>2]=c[b+8>>2];c[G+12>>2]=c[b+12>>2];c[H>>2]=c[x>>2];c[H+4>>2]=c[x+4>>2];c[H+8>>2]=c[x+8>>2];c[H+12>>2]=c[x+12>>2];el(B,G,H);c[D>>2]=c[B>>2];c[D+4>>2]=c[B+4>>2];c[D+8>>2]=c[B+8>>2];c[D+12>>2]=c[B+12>>2];D=c[I>>2]|0;b=D+(F+-2<<4)|0;E=D+(E<<4)|0;c[G>>2]=c[E>>2];c[G+4>>2]=c[E+4>>2];c[G+8>>2]=c[E+8>>2];c[G+12>>2]=c[E+12>>2];c[H>>2]=c[z>>2];c[H+4>>2]=c[z+4>>2];c[H+8>>2]=c[z+8>>2];c[H+12>>2]=c[z+12>>2];el(y,G,H);c[b>>2]=c[y>>2];c[b+4>>2]=c[y+4>>2];c[b+8>>2]=c[y+8>>2];c[b+12>>2]=c[y+12>>2];b=c[C>>2]|0;if(!b)break;d=Qt(a,c[I>>2]|0,d,d,J,b)|0;break}e=F;while(1){if((e|0)>0)b=0;else break;while(1){if((b|0)==4)break;B=E+(b<<4)|0;A=(c[I>>2]|0)+(e-b<<4)|0;c[B>>2]=c[A>>2];c[B+4>>2]=c[A+4>>2];c[B+8>>2]=c[A+8>>2];c[B+12>>2]=c[A+12>>2];b=b+1|0}if(fl(E,f)|0){b=0;K=43;break}e=e+-3|0}a:do if((K|0)==43)while(1){K=0;if((b|0)==4)break a;K=(c[I>>2]|0)+(e-b<<4)|0;B=E+(b<<4)|0;c[K>>2]=c[B>>2];c[K+4>>2]=c[B+4>>2];c[K+8>>2]=c[B+8>>2];c[K+12>>2]=c[B+12>>2];b=b+1|0;K=43}while(0);if(e|0){d=e+-3|0;b=c[C>>2]|0;if(!b)break;d=Qt(a,c[I>>2]|0,d,F+-3|0,J,b)|0;break}if(!(c[C>>2]|0))ma(80783,80794,452,80805);else{d=J+16|0;E=I+16|0;a=c[I>>2]|0;c[G>>2]=c[E>>2];c[G+4>>2]=c[E+4>>2];c[G+8>>2]=c[E+8>>2];c[G+12>>2]=c[E+12>>2];c[H>>2]=c[a>>2];c[H+4>>2]=c[a+4>>2];c[H+8>>2]=c[a+8>>2];c[H+12>>2]=c[a+12>>2];dl(D,G,H,f);c[d>>2]=c[D>>2];c[d+4>>2]=c[D+4>>2];c[d+8>>2]=c[D+8>>2];c[d+12>>2]=c[D+12>>2];d=0;break}}else K=52;while(0);if((K|0)==52)if(!(c[C>>2]|0))d=0;else{d=J+16|0;K=I+16|0;c[d>>2]=c[K>>2];c[d+4>>2]=c[K+4>>2];c[d+8>>2]=c[K+8>>2];c[d+12>>2]=c[K+12>>2];d=0}b=F-d+1|0;e=J+4|0;c[e>>2]=b;c[J>>2]=xw(b<<4)|0;b=0;while(1){if((b|0)>=(c[e>>2]|0))break;K=(c[J>>2]|0)+(b<<4)|0;a=(c[I>>2]|0)+(d<<4)|0;c[K>>2]=c[a>>2];c[K+4>>2]=c[a+4>>2];c[K+8>>2]=c[a+8>>2];c[K+12>>2]=c[a+12>>2];d=d+1|0;b=b+1|0}$I(c[I>>2]|0);$I(I);c[c[(c[L>>2]|0)+8>>2]>>2]=J}while(0);l=M;return}function bl(b,d){b=b|0;d=d|0;var e=0,f=0;f=l;l=l+16|0;e=f;if((b|0)!=0?(a[b>>0]|0)!=0:0){d=kB(d,b)|0;if(!d){c[e>>2]=b;$l(0,80996,e)|0;d=0}}else d=0;l=f;return d|0}function cl(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;d=+h[a>>3];if((+h[b>>3]<=d?d<=+h[b+16>>3]:0)?(c=+h[a+8>>3],+h[b+8>>3]<=c):0)a=c<=+h[b+24>>3]&1;else a=0;return a|0}function dl(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0.0,g=0.0,i=0,j=0.0,k=0.0,m=0.0,n=0,o=0.0,p=0.0,q=0.0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0,x=0,y=0.0,z=0,A=0,B=0,C=0;C=l;l=l+464|0;n=C+48|0;B=C+32|0;u=C+16|0;v=C;w=C+364|0;x=C+264|0;z=C+164|0;A=C+64|0;q=+h[b>>3];r=+h[b+8>>3];s=+h[d>>3];t=+h[d+8>>3];c[u>>2]=c[e>>2];c[u+4>>2]=c[e+4>>2];c[u+8>>2]=c[e+8>>2];c[u+12>>2]=c[e+12>>2];e=e+16|0;c[v>>2]=c[e>>2];c[v+4>>2]=c[e+4>>2];c[v+8>>2]=c[e+8>>2];c[v+12>>2]=c[e+12>>2];k=+h[u>>3];if((s=+h[u+8>>3]):0)?f<=+h[v+8>>3]:0){o=f;p=k}else i=4;do if((i|0)==4){j=+h[v>>3];if(s>j){g=r+ +(~~((j-q)*(r-t)/(q-s))|0);f=+h[u+8>>3];if(g>=f?g<=+h[v+8>>3]:0){o=g;p=j;break}}else f=+h[u+8>>3];if(t=k)|!(m<=j))):0){o=f;p=m;break}f=+h[v+8>>3];if(t>f?(y=q+ +(~~((f-r)*(q-s)/(r-t))|0),!(!(y>=k)|!(y<=j))):0){o=f;p=y;break};c[n>>2]=c[b>>2];c[n+4>>2]=c[b+4>>2];c[n+8>>2]=c[b+8>>2];c[n+12>>2]=c[b+12>>2];w=kl(n,w)|0;c[n>>2]=c[d>>2];c[n+4>>2]=c[d+4>>2];c[n+8>>2]=c[d+8>>2];c[n+12>>2]=c[d+12>>2];x=kl(n,x)|0;c[n>>2]=c[u>>2];c[n+4>>2]=c[u+4>>2];c[n+8>>2]=c[u+8>>2];c[n+12>>2]=c[u+12>>2];z=kl(n,z)|0;c[n>>2]=c[v>>2];c[n+4>>2]=c[v+4>>2];c[n+8>>2]=c[v+8>>2];c[n+12>>2]=c[v+12>>2];A=kl(n,A)|0;c[B>>2]=w;c[B+4>>2]=x;c[B+8>>2]=z;c[B+12>>2]=A;$l(1,80918,B)|0;ma(123205,80794,78,80970)}while(0);h[a>>3]=p;h[a+8>>3]=o;l=C;return}function el(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0;d=(+h[c+8>>3]+ +h[b+8>>3])*.5;h[a>>3]=(+h[c>>3]+ +h[b>>3])*.5;h[a+8>>3]=d;return}function fl(a,b){a=a|0;b=b|0;var d=0.0,e=0,f=0.0,g=0,i=0,j=0,k=0,m=0;m=l;l=l+80|0;j=m+16|0;k=m;e=0;while(1){if((e|0)==4)break;i=j+(e<<4)|0;g=a+(e<<4)|0;c[i>>2]=c[g>>2];c[i+4>>2]=c[g+4>>2];c[i+8>>2]=c[g+8>>2];c[i+12>>2]=c[g+12>>2];e=e+1|0}e=b+8|0;i=b+24|0;d=+gl(a,0.0,1.0,+h[b>>3],+h[e>>3],+h[i>>3]);if(d>=0.0&d<2.0)QA(k,j,3,d,a,0);else d=2.0;g=b+16|0;f=+gl(a,0.0,d>1.0?1.0:d,+h[g>>3],+h[e>>3],+h[i>>3]);if(f>=0.0&f1.0?1.0:d,+h[e>>3],+h[b>>3],+h[g>>3]);if(f>=0.0&f1.0?1.0:d,+h[i>>3],+h[b>>3],+h[g>>3]);if(f>=0.0&f>3]-d))<=.005){b=+h[a+56>>3];b=!(b>=e)|!(b<=f)?-1.0:c;break a}break}default:{}}QA(i,a,3,.5,j,k);g=(c+b)*.5;b=+gl(j,b,g,d,e,f);if(!(b>=0.0))b=+gl(k,g,c,d,e,f)}while(0);l=m;return +b}function hl(a,b,c,d,e,f){a=a|0;b=+b;c=+c;d=+d;e=+e;f=+f;var g=0.0,i=0,j=0,k=0,m=0;m=l;l=l+144|0;j=m+80|0;k=m+16|0;i=m;a:do if(!(b==c)){switch(il(a,d)|0){case 0:{b=-1.0;break a}case 1:{if(+B(+(+h[a+56>>3]-d))<=.005){b=+h[a+48>>3];b=!(b>=e)|!(b<=f)?-1.0:c;break a}break}default:{}}QA(i,a,3,.5,j,k);g=(c+b)*.5;b=+hl(j,b,g,d,e,f);if(!(b>=0.0))b=+hl(k,g,c,d,e,f)}while(0);l=m;return +b}function il(a,b){a=a|0;b=+b;var c=0,d=0,e=0,f=0.0,g=0,i=0;f=+h[a+8>>3];e=fb&1;c=1;d=e;e=(e|0)==0&1;while(1){if((c|0)==4)break;f=+h[a+(c<<4)+8>>3];i=fb&1;g=e+((d|0)!=0&(i|0)!=(d|0)&1)|0;c=c+1|0;d=i;e=g}return e|0}function jl(a,b){a=a|0;b=+b;var c=0,d=0,e=0,f=0.0,g=0,i=0;f=+h[a>>3];e=fb&1;c=1;d=e;e=(e|0)==0&1;while(1){if((c|0)==4)break;f=+h[a+(c<<4)>>3];i=fb&1;g=e+((d|0)!=0&(i|0)!=(d|0)&1)|0;c=c+1|0;d=i;e=g}return e|0}function kl(a,b){a=a|0;b=b|0;var c=0,d=0,e=0.0;c=l;l=l+16|0;d=c;e=+h[a+8>>3];h[d>>3]=+h[a>>3];h[d+8>>3]=e;qL(b,80984,d)|0;l=c;return b|0}function ll(a){a=a|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,q=0,r=0,s=0,t=0,u=0,v=0;v=l;l=l+16|0;s=v;u=4;t=_I(40)|0;c[t>>2]=0;r=a+16|0;e=c[r>>2]|0;a:do if(((b[e+238>>1]|0)-(b[e+236>>1]|0)|0)>=2){m=1;d=e;e=c[e+196>>2]|0;b:while(1){n=m+1|0;if(!(c[e+(n<<6)>>2]|0)){q=15;break}else k=0;while(1){h=c[e+(m<<6)>>2]|0;if((k|0)>=(h|0)){m=n;continue b}j=c[(c[e+(m<<6)+4>>2]|0)+(k<<2)>>2]|0;o=0;d=_(18,j|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,u|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){d=z;break b}if(d<<24>>24){i=k;d=h;while(1){g=i+1|0;if((g|0)>=(d|0))break;o=0;d=$(17,j|0,c[(c[e+(m<<6)+4>>2]|0)+(g<<2)>>2]|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,t|0,u|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){d=z;break b}if(!(d<<24>>24))break;d=c[(c[r>>2]|0)+196>>2]|0;i=g;e=d;d=c[d+(m<<6)>>2]|0}if((g-k|0)>1){o=0;ka(6,a|0,m|0,k|0,i|0,1);d=o;o=0;if((d|0)!=0&(p|0)!=0){e=TN(c[d>>2]|0,t|0,u|0)|0;if(!e)Ua(d|0,p|0);z=p}else e=-1;if((e|0)==1){d=z;break b}}}e=c[r>>2]|0;k=k+1|0;d=e;e=c[e+196>>2]|0}}c:do if((q|0)==15){while(1){if((m|0)>0)k=0;else break;while(1){e=c[d+196>>2]|0;h=c[e+(m<<6)>>2]|0;if((k|0)>=(h|0))break;j=c[(c[e+(m<<6)+4>>2]|0)+(k<<2)>>2]|0;o=0;d=_(19,j|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,t|0,u|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){d=z;break c}if(d<<24>>24){i=k;d=h;while(1){g=i+1|0;if((g|0)>=(d|0))break;o=0;d=$(18,j|0,c[(c[e+(m<<6)+4>>2]|0)+(g<<2)>>2]|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,t|0,u|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){d=z;break c}if(!(d<<24>>24))break;d=c[(c[r>>2]|0)+196>>2]|0;i=g;e=d;d=c[d+(m<<6)>>2]|0}if((g-k|0)>1){o=0;ka(6,a|0,m|0,k|0,i|0,0);d=o;o=0;if((d|0)!=0&(p|0)!=0){e=TN(c[d>>2]|0,t|0,u|0)|0;if(!e)Ua(d|0,p|0);z=p}else e=-1;if((e|0)==1){d=z;break c}}}k=k+1|0;d=c[r>>2]|0}m=m+-1|0;q=15}t=SN(167760,1,t|0,u|0)|0;u=z;o=0;d=o;o=0;if((d|0)!=0&(p|0)!=0){e=TN(c[d>>2]|0,t|0,u|0)|0;if(!e)Ua(d|0,p|0);z=p}else e=-1;if((e|0)==1)d=z;else d=0}while(0);d:while(1){if(d){o=0;aa(11,3,81024,s|0)|0;d=o;o=0;if((d|0)!=0&(p|0)!=0){e=TN(c[d>>2]|0,t|0,u|0)|0;if(!e)Ua(d|0,p|0);z=p}else e=-1;if((e|0)==1){d=z;continue}else break}else f=1;while(1){d=c[r>>2]|0;if((f|0)>(c[d+180>>2]|0))break a;o=0;fa(85,c[(c[d+184>>2]|0)+(f<<2)>>2]|0);d=o;o=0;if((d|0)!=0&(p|0)!=0){e=TN(c[d>>2]|0,t|0,u|0)|0;if(!e)Ua(d|0,p|0);z=p}else e=-1;if((e|0)==1){d=z;continue d}f=f+1|0}}}while(0);$I(t|0);l=v;return}function ml(b){b=b|0;b=c[b+16>>2]|0;if(((a[b+156>>0]|0)==1?(c[b+176>>2]|0)==1:0)?(c[b+184>>2]|0)==1:0)b=(c[b+104>>2]|0)==0&1;else b=0;return b|0}function nl(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+80|0;h=i+40|0;g=i;e=c[c[(c[a+16>>2]|0)+172>>2]>>2]|0;a=c[c[(c[b+16>>2]|0)+172>>2]>>2]|0;if(((ml(b)|0)<<24>>24!=0?(c[((c[e>>2]&3|0)==3?e:e+48|0)+40>>2]|0)==(c[((c[a>>2]&3|0)==3?a:a+48|0)+40>>2]|0):0)?(tl(e,a)|0)<<24>>24!=0:0){d=(c[a+16>>2]|0)+16|0;f=g;a=(c[e+16>>2]|0)+16|0;b=f+40|0;do{c[f>>2]=c[a>>2];f=f+4|0;a=a+4|0}while((f|0)<(b|0));f=h;a=d;b=f+40|0;do{c[f>>2]=c[a>>2];f=f+4|0;a=a+4|0}while((f|0)<(b|0));a=(Xf(g,h)|0)==0&1}else a=0;l=i;return a|0}function ol(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=a+16|0;q=c[(c[(c[(c[t>>2]|0)+196>>2]|0)+(b<<6)+4>>2]|0)+(d<<2)>>2]|0;p=d+1|0;m=(f|0)==1;n=q+16|0;l=p;while(1){if((l|0)>(e|0)){g=e;s=p;break}o=c[(c[(c[(c[t>>2]|0)+196>>2]|0)+(b<<6)+4>>2]|0)+(l<<2)>>2]|0;k=o+16|0;a:do if(m)while(1){d=c[k>>2]|0;j=c[c[d+180>>2]>>2]|0;if(!j)break a;h=c[(c[n>>2]|0)+180>>2]|0;i=j+-48|0;f=0;while(1){d=c[h+(f<<2)>>2]|0;if(!d){r=8;break}if((c[((c[d>>2]&3|0)==2?d:d+-48|0)+40>>2]|0)==(c[((c[j>>2]&3|0)==2?j:i)+40>>2]|0))break;else f=f+1|0}if((r|0)==8){r=0;d=bh(q,c[((c[j>>2]&3|0)==2?j:i)+40>>2]|0,j)|0}while(1){f=c[c[(c[k>>2]|0)+172>>2]>>2]|0;if(!f)break;jh(f,d);Yg(f)}Yg(j)}else while(1){d=c[k>>2]|0;j=c[c[d+172>>2]>>2]|0;if(!j)break a;h=c[(c[n>>2]|0)+172>>2]|0;i=j+48|0;f=0;while(1){d=c[h+(f<<2)>>2]|0;if(!d){r=17;break}if((c[((c[d>>2]&3|0)==3?d:d+48|0)+40>>2]|0)==(c[((c[j>>2]&3|0)==3?j:i)+40>>2]|0))break;else f=f+1|0}if((r|0)==17){r=0;d=bh(c[((c[j>>2]&3|0)==3?j:i)+40>>2]|0,q,j)|0}while(1){f=c[c[(c[k>>2]|0)+180>>2]>>2]|0;if(!f)break;jh(f,d);Yg(f)}Yg(j)}while(0);if((c[d+176>>2]|0)!=(0-(c[d+184>>2]|0)|0)){r=23;break}eh(a,o);l=l+1|0}if((r|0)==23)ma(81160,81204,115,81211);while(1){g=g+1|0;d=c[(c[t>>2]|0)+196>>2]|0;f=d+(b<<6)|0;if((g|0)>=(c[f>>2]|0))break;e=c[d+(b<<6)+4>>2]|0;r=c[e+(g<<2)>>2]|0;c[e+(s<<2)>>2]=r;c[(c[r+16>>2]|0)+236>>2]=s;s=s+1|0}c[f>>2]=s;c[(c[d+(b<<6)+4>>2]|0)+(s<<2)>>2]=0;return}function pl(b){b=b|0;b=c[b+16>>2]|0;if(((a[b+156>>0]|0)==1?(c[b+184>>2]|0)==1:0)?(c[b+176>>2]|0)==1:0)b=(c[b+104>>2]|0)==0&1;else b=0;return b|0}function ql(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+80|0;h=i+40|0;g=i;e=c[c[(c[a+16>>2]|0)+180>>2]>>2]|0;a=c[c[(c[b+16>>2]|0)+180>>2]>>2]|0;if(((pl(b)|0)<<24>>24!=0?(c[((c[e>>2]&3|0)==2?e:e+-48|0)+40>>2]|0)==(c[((c[a>>2]&3|0)==2?a:a+-48|0)+40>>2]|0):0)?(tl(e,a)|0)<<24>>24!=0:0){d=(c[a+16>>2]|0)+56|0;f=g;a=(c[e+16>>2]|0)+56|0;b=f+40|0;do{c[f>>2]=c[a>>2];f=f+4|0;a=a+4|0}while((f|0)<(b|0));f=h;a=d;b=f+40|0;do{c[f>>2]=c[a>>2];f=f+4|0;a=a+4|0}while((f|0)<(b|0));a=(Xf(g,h)|0)==0&1}else a=0;l=i;return a|0}function rl(d){d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0;r=l;l=l+32|0;p=r+16|0;o=r;m=d+16|0;f=c[m>>2]|0;e=b[f+236>>1]|0;while(1){if((e|0)>(b[f+238>>1]|0))break;c[(c[f+268>>2]|0)+(e<<2)>>2]=0;e=e+1|0;f=c[m>>2]|0}jj(d);j=eo(d)|0;while(1){if(!j)break;sl(d,j);i=Qm(d,j)|0;while(1){if(!i)break;else f=i;while(1){e=c[(c[f+16>>2]|0)+172>>2]|0;if(!e)break;else f=e}h=i+-48|0;while(1){e=f+-48|0;g=c[((c[f>>2]&3|0)==2?f:e)+40>>2]|0;if((c[(c[g+16>>2]|0)+232>>2]|0)>=(c[(c[(c[((c[i>>2]&3|0)==2?i:h)+40>>2]|0)+16>>2]|0)+232>>2]|0))break;sl(d,g);f=c[c[(c[(c[((c[f>>2]&3|0)==2?f:e)+40>>2]|0)+16>>2]|0)+180>>2]>>2]|0}i=Sm(d,i)|0}j=fo(d,j)|0}e=c[m>>2]|0;i=b[e+236>>1]|0;while(1){if((i|0)>(b[e+238>>1]|0)){k=1;n=e;break}e=c[(c[e+268>>2]|0)+(i<<2)>>2]|0;j=c[(c[(c[(Wf(d)|0)+16>>2]|0)+196>>2]|0)+(i<<6)+4>>2]|0;f=e+16|0;if((c[j+(c[(c[f>>2]|0)+236>>2]<<2)>>2]|0)!=(e|0)){q=17;break}h=c[(c[(c[(Wf(d)|0)+16>>2]|0)+196>>2]|0)+(i<<6)+4>>2]|0;e=c[m>>2]|0;f=c[e+196>>2]|0;c[f+(i<<6)+4>>2]=h+(c[(c[(c[(c[e+268>>2]|0)+(i<<2)>>2]|0)+16>>2]|0)+236>>2]<<2);e=-1;h=0;a:while(1){if((h|0)>=(c[f+(i<<6)>>2]|0))break;f=c[(c[f+(i<<6)+4>>2]|0)+(h<<2)>>2]|0;if(!f)break;g=c[f+16>>2]|0;b:do if(!(a[g+156>>0]|0))if(!(Co(d,f)|0))break a;else e=h;else{f=c[c[g+172>>2]>>2]|0;while(1){if(!f)break b;g=c[(c[f+16>>2]|0)+116>>2]|0;if(!g)break;else f=g}if(Co(d,c[((c[f>>2]&3|0)==3?f:f+48|0)+40>>2]|0)|0){j=(Co(d,c[((c[f>>2]&3|0)==2?f:f+-48|0)+40>>2]|0)|0)==0;e=j?e:h}}while(0);h=h+1|0;f=c[(c[m>>2]|0)+196>>2]|0}if((e|0)==-1){c[p>>2]=En(d)|0;c[p+4>>2]=i;$l(0,81124,p)|0}j=c[m>>2]|0;c[(c[j+196>>2]|0)+(i<<6)>>2]=e+1;i=i+1|0;e=j}if((q|0)==17){p=En(e)|0;q=c[(c[f>>2]|0)+236>>2]|0;c[o>>2]=p;c[o+4>>2]=q;c[o+8>>2]=i;$l(1,81066,o)|0;Ua(167760,1)}while(1){if((k|0)>(c[n+180>>2]|0))break;rl(c[(c[n+184>>2]|0)+(k<<2)>>2]|0);k=k+1|0;n=c[m>>2]|0}l=r;return}function sl(a,b){a=a|0;b=b|0;var d=0,e=0;d=c[b+16>>2]|0;a=(c[(c[a+16>>2]|0)+268>>2]|0)+(c[d+232>>2]<<2)|0;e=c[a>>2]|0;if(!((e|0)!=0?(c[(c[e+16>>2]|0)+236>>2]|0)<=(c[d+236>>2]|0):0))c[a>>2]=b;return}function tl(b,d){b=b|0;d=d|0;var e=0,f=0;while(1){f=c[b+16>>2]|0;if(!(a[f+112>>0]|0))break;b=c[f+116>>2]|0}while(1){e=c[d+16>>2]|0;if(!(a[e+112>>0]|0))break;d=c[e+116>>2]|0}if((a[f+153>>0]|0)==0?(a[e+153>>0]|0)==0:0){f=c[d>>2]&3;e=c[b>>2]&3;b=(O((c[(c[(c[((e|0)==3?b:b+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((e|0)==2?b:b+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)|0,(c[(c[(c[((f|0)==3?d:d+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)-(c[(c[(c[((f|0)==2?d:d+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)|0)|0)>0&1}else b=0;return b|0}function ul(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+544|0;j=k+528|0;vl(j,k+512|0,k);e=(a[173898]|0)+1<<24>>24;a[173898]=e<<24>>24==0?1:e;e=c[b+16>>2]|0;c[e+220>>2]=0;c[e+232>>2]=0;e=(d|0)>0;d=eo(b)|0;while(1){if(!d)break;if(e?(h=c[d+16>>2]|0,i=c[h+212>>2]|0,(i|0)!=0):0){g=c[(c[(c[i+16>>2]|0)+268>>2]|0)+(c[h+232>>2]<<2)>>2]|0;f=7}else f=6;if((f|0)==6?(f=0,(d|0)==(LA(d)|0)):0){g=d;f=7}if((f|0)==7?(0,(a[(c[g+16>>2]|0)+157>>0]|0)!=(a[173898]|0)):0){wl(b);xl(j,b,g);yl(b)}d=fo(b,d)|0}zl(j);l=k;return}function vl(a,b,d){a=a|0;b=b|0;d=d|0;c[b>>2]=d;c[b+4>>2]=d+512;c[b+12>>2]=0;c[b+8>>2]=0;c[a>>2]=b;c[a+4>>2]=b;c[a+8>>2]=d;return}function wl(a){a=a|0;c[(c[a+16>>2]|0)+192>>2]=0;c[41979]=0;return}function xl(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;q=l;l=l+32|0;p=q;Al(b,e);k=p+8|0;m=p+16|0;n=p+24|0;a:while(1){o=Bl(b)|0;if(!o)break;e=o+16|0;if((a[(c[e>>2]|0)+157>>0]|0)==(a[173898]|0))continue;Cl(d,o);h=c[e>>2]|0;g=h+180|0;j=c[g+4>>2]|0;i=p;c[i>>2]=c[g>>2];c[i+4>>2]=j;i=h+172|0;j=c[i+4>>2]|0;g=k;c[g>>2]=c[i>>2];c[g+4>>2]=j;g=h+188|0;j=c[g+4>>2]|0;i=m;c[i>>2]=c[g>>2];c[i+4>>2]=j;h=h+196|0;i=c[h+4>>2]|0;j=n;c[j>>2]=c[h>>2];c[j+4>>2]=i;j=3;while(1){if((j|0)<=-1)continue a;e=c[p+(j<<3)>>2]|0;b:do if(e|0){i=(c[p+(j<<3)+4>>2]|0)+-1|0;h=e+(i<<2)|0;while(1){if((i|0)<=-1)break b;f=c[h>>2]|0;g=c[f>>2]&3;e=c[((g|0)==2?f:f+-48|0)+40>>2]|0;if((e|0)==(o|0))e=c[((g|0)==3?f:f+48|0)+40>>2]|0;if((a[(c[e+16>>2]|0)+157>>0]|0)!=(a[173898]|0)?(e|0)==(LA(e)|0):0)Al(b,e);h=h+-4|0;i=i+-1|0}}while(0);j=j+-1|0}}l=q;return}function yl(a){a=a|0;var b=0,d=0,e=0,f=0;d=a+16|0;b=c[d>>2]|0;f=b+220|0;e=c[f>>2]|0;a=e+1|0;c[f>>2]=a;b=c[b+216>>2]|0;if(!b)a=xw(a<<2)|0;else a=zw(b,a<<2)|0;f=c[d>>2]|0;c[f+216>>2]=a;c[a+(e<<2)>>2]=c[f+192>>2];return}function zl(a){a=a|0;var b=0;a=c[(c[a>>2]|0)+12>>2]|0;while(1){if(!a)break;b=c[a+12>>2]|0;$I(c[a>>2]|0);$I(a);a=b}return}function Al(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;h=k+8|0;g=k;j=b+8|0;f=c[j>>2]|0;i=b+4|0;b=c[i>>2]|0;if((f|0)==(c[b+4>>2]|0)){f=c[b+12>>2]|0;if(!f){f=ww(16)|0;if(!f)$l(1,83988,g)|0;c[f+8>>2]=c[i>>2];c[f+12>>2]=0;b=ww(4e6)|0;c[f>>2]=b;if(!b){$l(1,81224,h)|0;b=c[f>>2]|0}c[f+4>>2]=b+4e6;c[(c[i>>2]|0)+12>>2]=f}c[i>>2]=f;f=c[f>>2]|0;c[j>>2]=f}a[(c[e+16>>2]|0)+157>>0]=(d[173898]|0)+1;c[j>>2]=f+4;c[f>>2]=e;l=k;return}function Bl(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;f=a+8|0;b=c[f>>2]|0;d=a+4|0;e=c[d>>2]|0;if((b|0)==(c[e>>2]|0))if((e|0)==(c[a>>2]|0))b=0;else{b=c[e+8>>2]|0;c[d>>2]=b;b=c[b+4>>2]|0;c[f>>2]=b;g=4}else g=4;if((g|0)==4){b=b+-4|0;c[f>>2]=b;b=c[b>>2]|0}return b|0}function Cl(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;f=c[b+16>>2]|0;g=f+232|0;c[g>>2]=(c[g>>2]|0)+1;g=c[d+16>>2]|0;a[g+157>>0]=a[173898]|0;b=c[41979]|0;e=g+168|0;if(!b){c[e>>2]=0;c[f+192>>2]=d}else{c[e>>2]=b;c[(c[b+16>>2]|0)+164>>2]=d}c[41979]=d;c[g+164>>2]=0;return}function Dl(b){b=b|0;var d=0,e=0,f=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0.0,o=0.0;m=b+16|0;d=(c[m>>2]|0)+192|0;while(1){d=c[d>>2]|0;if(!d)break;g=d+16|0;d=c[g>>2]|0;e=c[d+188>>2]|0;a:do if(!e)f=0;else{f=0;while(1){e=c[e+(f<<2)>>2]|0;if(!e){f=0;break a}El(e);d=c[g>>2]|0;f=f+1|0;e=c[d+188>>2]|0}}while(0);while(1){if((f|0)>=(c[d+208>>2]|0))break;e=c[(c[d+204>>2]|0)+(f<<2)>>2]|0;l=c[e>>2]&3;if((c[(c[(c[((l|0)==2?e:e+-48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)==(c[(c[(c[((l|0)==3?e:e+48|0)+40>>2]|0)+16>>2]|0)+232>>2]|0)){El(e);d=c[g>>2]|0}f=f+1|0}d=d+164|0}l=c[m>>2]|0;d=c[l+196>>2]|0;if(!((c[d+56>>2]|0)==0?(c[l+180>>2]|0)<=0:0))i=13;b:do if((i|0)==13){i=c[d+4>>2]|0;g=0;c:while(1){d=c[i+(g<<2)>>2]|0;if(!d)break b;e=c[(c[d+16>>2]|0)+196>>2]|0;d=0;while(1){f=c[e+(d<<2)>>2]|0;if(!f)break;l=c[f+16>>2]|0;if(c[l+96>>2]|0?(a[l+113>>0]|0)==0:0)break c;d=d+1|0}g=g+1|0}Fl(b)}while(0);vi(b);e=0;d=(c[m>>2]|0)+192|0;while(1){d=c[d>>2]|0;if(!d)break;l=d+16|0;d=c[l>>2]|0;f=c[d+188>>2]|0;d:do if(f){k=0;while(1){g=c[f+(k<<2)>>2]|0;if(!g){k=0;break}i=c[g+16>>2]|0;j=c[i+96>>2]|0;do if(j)if(!(a[i+113>>0]|0)){Gl(g);f=c[l>>2]|0;e=1;d=f;f=c[f+188>>2]|0;break}else{h[i+136>>3]=+h[((c[(c[m>>2]|0)+116>>2]&1|0)==0?j+24|0:j+32|0)>>3];break}while(0);k=k+1|0}while(1){if((k|0)>=(c[d+208>>2]|0))break d;i=c[(c[d+204>>2]|0)+(k<<2)>>2]|0;j=c[i>>2]&3;g=c[((j|0)==3?i:i+48|0)+40>>2]|0;j=c[((j|0)==2?i:i+-48|0)+40>>2]|0;do if(!((g|0)==(j|0)?1:(c[(c[g+16>>2]|0)+232>>2]|0)!=(c[(c[j+16>>2]|0)+232>>2]|0))){f=i;do{j=c[f+16>>2]|0;f=c[j+172>>2]|0}while((f|0)!=0);f=a[j+113>>0]|0;g=c[i+16>>2]|0;a[g+113>>0]=f;g=c[g+96>>2]|0;if(g)if(!(f<<24>>24)){Gl(i);e=1;d=c[l>>2]|0;break}else{o=+h[((c[(c[m>>2]|0)+116>>2]&1|0)==0?g+24|0:g+32|0)>>3];j=j+136|0;n=+h[j>>3];h[j>>3]=o>n?o:n;break}}while(0);k=k+1|0}}while(0);d=d+164|0}if(e|0){oh(b);Ch(b)}return e|0}function El(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;d=c[b>>2]&3;i=c[((d|0)==3?b:b+48|0)+40>>2]|0;f=i+16|0;g=c[(c[f>>2]|0)+236>>2]|0;d=c[(c[(c[((d|0)==2?b:b+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;h=(g|0)<(d|0);e=h?d:g;i=c[(c[(Wf(i)|0)+16>>2]|0)+196>>2]|0;f=i+(c[(c[f>>2]|0)+232>>2]<<6)+4|0;d=h?g:d;a:while(1){d=d+1|0;if((d|0)>=(e|0))break;g=c[(c[(c[f>>2]|0)+(d<<2)>>2]|0)+16>>2]|0;switch(a[g+156>>0]|0){case 0:break a;case 1:break;default:continue a}if(c[g+104>>2]|0)break}if((d|0)==(e|0))do{i=c[b+16>>2]|0;a[i+113>>0]=1;b=c[i+172>>2]|0}while((b|0)!=0);return}function Fl(a){a=a|0;var d=0,e=0,f=0,g=0;g=a+16|0;a=c[g>>2]|0;if(b[a+236>>1]|0)ma(81281,81264,190,81300);d=(b[a+238>>1]|0)+3|0;a=c[a+196>>2]|0;if(!a)a=xw(d<<6)|0;else a=zw(a,d<<6)|0;d=a+64|0;a=c[g>>2]|0;c[a+196>>2]=d;a=b[a+238>>1]|0;while(1){if((a|0)<=-1)break;f=a+-1|0;e=d+(a<<6)|0;a=d+(f<<6)|0;d=e+64|0;do{c[e>>2]=c[a>>2];e=e+4|0;a=a+4|0}while((e|0)<(d|0));a=f;d=c[(c[g>>2]|0)+196>>2]|0}c[d+(a<<6)+8>>2]=0;c[d+(a<<6)>>2]=0;e=ww(8)|0;g=c[g>>2]|0;f=c[g+196>>2]|0;c[f+(a<<6)+12>>2]=e;c[f+(a<<6)+4>>2]=e;c[f+(a<<6)+56>>2]=0;h[f+(a<<6)+24>>3]=1.0;h[f+(a<<6)+16>>3]=1.0;h[f+(a<<6)+40>>3]=1.0;h[f+(a<<6)+32>>3]=1.0;g=g+236|0;b[g>>1]=(b[g>>1]|0)+-1<<16>>16;return}function Gl(b){b=b|0;var d=0,e=0,f=0.0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0.0,q=0.0,r=0.0;j=b+16|0;if(c[(c[j>>2]|0)+96>>2]|0){m=b+48|0;k=Wf(c[((c[b>>2]&3|0)==3?b:m)+40>>2]|0)|0;d=c[(c[(c[((c[b>>2]&3|0)==3?b:m)+40>>2]|0)+16>>2]|0)+232>>2]|0;l=Hl(k,b)|0;n=k+16|0;e=c[n>>2]|0;g=c[e+196>>2]|0;o=d+-1|0;i=c[c[g+(o<<6)+4>>2]>>2]|0;if(!i)f=+h[g+(d<<6)+24>>3]+ +h[(c[(c[c[g+(d<<6)+4>>2]>>2]|0)+16>>2]|0)+24>>3]+ +(c[e+252>>2]|0);else f=+h[(c[i+16>>2]|0)+24>>3]-+h[g+(o<<6)+16>>3];d=Il(k,o,l)|0;k=c[(c[j>>2]|0)+96>>2]|0;q=+h[k+24>>3];p=+h[k+32>>3];j=(c[(c[n>>2]|0)+116>>2]&1|0)==0;r=j?p:q;g=d+16|0;e=c[g>>2]|0;h[e+80>>3]=r;l=~~(r*.5);p=(j?q:p)*.5;h[e+96>>3]=p;h[e+88>>3]=p;c[e+104>>2]=k;h[e+24>>3]=+(l+~~f|0);e=bh(d,c[((c[b>>2]&3|0)==3?b:m)+40>>2]|0,b)|0;e=c[e+16>>2]|0;h[e+16>>3]=-+h[(c[g>>2]|0)+88>>3];h[e+56>>3]=+h[(c[(c[((c[b>>2]&3|0)==3?b:m)+40>>2]|0)+16>>2]|0)+96>>3];a[e+112>>0]=4;e=b+-48|0;d=bh(d,c[((c[b>>2]&3|0)==2?b:e)+40>>2]|0,b)|0;g=c[g>>2]|0;d=c[d+16>>2]|0;h[d+16>>3]=+h[g+96>>3];h[d+56>>3]=+h[(c[(c[((c[b>>2]&3|0)==2?b:e)+40>>2]|0)+16>>2]|0)+88>>3];a[d+112>>0]=4;d=c[(c[n>>2]|0)+196>>2]|0;e=d+(o<<6)+16|0;f=+(l|0);if(+h[e>>3]>3]=f;d=d+(o<<6)+24|0;if(+h[d>>3]>3]=f;c[g+112>>2]=b}return}function Hl(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+32|0;j=n+8|0;f=n+4|0;g=n;d=c[b>>2]&3;e=c[((d|0)==3?b:b+48|0)+40>>2]|0;k=(c[(c[e+16>>2]|0)+232>>2]|0)+-1|0;a=c[(c[a+16>>2]|0)+196>>2]|0;h=c[a+(k<<6)+4>>2]|0;a=c[a+(k<<6)>>2]|0;k=j+8|0;c[k>>2]=-1;c[j>>2]=-1;m=j+12|0;c[m>>2]=a;i=j+4|0;c[i>>2]=a;Jl(e,c[((d|0)==2?b:b+-48|0)+40>>2]|0,f,g);f=c[f>>2]|0;g=c[g>>2]|0;d=0;e=a;b=-1;while(1){if((d|0)>=(e|0))break;e=e+-1|0;Kl(c[h+(d<<2)>>2]|0,j,f,g);if((d|0)!=(e|0))Kl(c[h+(e<<2)>>2]|0,j,f,g);a=c[i>>2]|0;b=c[j>>2]|0;if((a-b|0)<2)break;else d=d+1|0}if((b|0)>(a|0))a=(c[m>>2]|0)+(c[k>>2]|0)|0;else a=a+b|0;l=n;return (a+1|0)/2|0|0}function Il(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;g=a+16|0;f=c[(c[g>>2]|0)+196>>2]|0;e=f+(b<<6)|0;f=c[f+(b<<6)+4>>2]|0;if(!f)f=xw((c[e>>2]<<2)+8|0)|0;else f=zw(f,(c[e>>2]<<2)+8|0)|0;e=c[(c[g>>2]|0)+196>>2]|0;c[e+(b<<6)+4>>2]=f;e=c[e+(b<<6)>>2]|0;while(1){if((e|0)<=(d|0))break;h=e+-1|0;i=c[f+(h<<2)>>2]|0;c[f+(e<<2)>>2]=i;i=(c[i+16>>2]|0)+236|0;c[i>>2]=(c[i>>2]|0)+1;e=h}h=gh(a)|0;i=f+(d<<2)|0;c[i>>2]=h;h=c[h+16>>2]|0;c[h+236>>2]=d;c[h+232>>2]=b;g=(c[(c[g>>2]|0)+196>>2]|0)+(b<<6)|0;h=(c[g>>2]|0)+1|0;c[g>>2]=h;c[f+(h<<2)>>2]=0;return c[i>>2]|0}function Jl(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;a=c[(c[a+16>>2]|0)+236>>2]|0;b=c[(c[b+16>>2]|0)+236>>2]|0;f=(a|0)>(b|0);c[d>>2]=f?b:a;c[e>>2]=f?a:b;return}function Kl(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0;m=l;l=l+16|0;h=m+4|0;g=m;b=c[b+16>>2]|0;do if((a[b+156>>0]|0)==1){k=c[b+236>>2]|0;if(c[b+176>>2]|0){i=c[b+180>>2]|0;b=0;g=0;h=0;while(1){j=c[i+(h<<2)>>2]|0;if(!j)break;n=c[(c[(c[((c[j>>2]&3|0)==2?j:j+-48|0)+40>>2]|0)+16>>2]|0)+236>>2]|0;j=(n|0)>(e|0);b=j?((n|0)<(f|0)?b:1):b;g=j?g:1;h=h+1|0}if(g<<24>>24!=0&b<<24>>24==0){c[d>>2]=k+1;break}if(!(g<<24>>24==0&b<<24>>24!=0))break;c[d+4>>2]=k+-1;break}if((c[b+184>>2]|0)!=2)ma(81244,81264,63,81271);i=c[b+180>>2]|0;n=c[i>>2]|0;i=c[i+4>>2]|0;Jl(c[((c[n>>2]&3|0)==2?n:n+-48|0)+40>>2]|0,c[((c[i>>2]&3|0)==2?i:i+-48|0)+40>>2]|0,h,g);i=c[g>>2]|0;if((i|0)<=(e|0)){c[d>>2]=k;c[d+8>>2]=k;break}b=c[h>>2]|0;if((b|0)>=(f|0)){c[d+4>>2]=k;c[d+12>>2]=k;break}g=(b|0)<(e|0);h=(i|0)>(f|0);if(!(h&g)){if(!(!g?!((i|0)<(f|0)&(b|0)==(e|0)):0))c[d+8>>2]=k;if(!h?!((i|0)==(f|0)&(b|0)>(e|0)):0)break;c[d+12>>2]=k}}while(0);l=m;return}function Ll(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;do if((a|0)!=0?(c[a+24>>2]|0)<=0:0){h=c[a+4>>2]|0;g=h+32|0;b=c[g>>2]|0;if(b){b=cb[b&31](a,2,0,h)|0;if((b|0)<0){b=-1;break}}else b=0;if(c[a+28>>2]|0)Xl(a,0)|0;f=(b|0)==0;if(f){bb[c[c[a+16>>2]>>2]&31](a,0,64)|0;if((Tl(a)|0)>0){b=-1;break}d=a+8|0;b=c[d>>2]|0;if((c[b+12>>2]|0)>0){e=a+12|0;cb[c[e>>2]&31](a,c[b+8>>2]|0,0,h)|0;b=c[d>>2]|0}else e=a+12|0;cb[c[e>>2]&31](a,b,0,h)|0}b=c[a+20>>2]|0;if(b){if(f&(b|0)==1)cb[c[a+12>>2]&31](a,a,0,h)|0}else $I(a);b=c[g>>2]|0;if(!b)b=0;else{cb[b&31](a,6,0,h)|0;b=0}}else b=-1;while(0);return b|0}function Ml(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;f=a+4|0;n=c[f>>2]|0;a:do if(n)if(b){m=c[c[a+16>>2]>>2]|0;g=a+8|0;if(c[c[g>>2]>>2]&4096|0)Sl(a,0)|0;e=c[n+32>>2]|0;if(e|0?(cb[e&31](a,3,b,n)|0)<0:0){b=0;break}c[f>>2]=b;e=c[b+28>>2]|0;c[a+12>>2]=(e|0)==0?19:e;e=c[c[g>>2]>>2]|0;if(!(e&112)){do if(!(e&2))if(!(e&3))if(!(d&1))break;else{b=n;break a}else if((d&3|0)==3){b=n;break a}else break;else if(d&2|0){b=n;break a}while(0);h=Pl(a)|0;e=c[g>>2]|0;l=c[e>>2]|0;c[e>>2]=l&-4097;c[e+4>>2]=0;c[e+16>>2]=0;b:do if(l&3|0){l=c[e+8>>2]|0;f=l+(c[e+12>>2]<<2)|0;e=l;while(1){if(e>>>0>=f>>>0)break b;c[e>>2]=0;e=e+4|0}}while(0);i=(d&2|0)==0;j=b+8|0;k=b+4|0;l=b+24|0;while(1){if(!h){b=n;break a}d=c[h>>2]|0;if(i){e=c[j>>2]|0;if((e|0)<0)e=c[h+8>>2]|0;else e=h+(0-e)|0;g=c[k>>2]|0;e=e+(c[b>>2]|0)|0;if((g|0)<0)e=c[e>>2]|0;f=c[l>>2]|0;if(!f)e=Vl(0,e,g)|0;else e=bb[f&31](a,e,b)|0;c[h+4>>2]=e}bb[m&31](a,h,32)|0;h=d}}else b=n}else b=n;else{c[f>>2]=b;n=c[b+28>>2]|0;c[a+12>>2]=(n|0)==0?19:n}while(0);return b|0}function Nl(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;a=(c|0)==0;do if(!b)if(a)a=0;else a=_I(c)|0;else if(a){$I(b);a=0;break}else{a=bJ(b,c)|0;break}while(0);return a|0}function Ol(a){a=a|0;var b=0,d=0,e=0;e=a+8|0;b=c[e>>2]|0;d=c[b>>2]|0;a:do if(!(d&12)){if(!(d&3)){d=b+8|0;a=c[d>>2]|0;c[d>>2]=0;break}a=Pl(a)|0;d=c[e>>2]|0;b=c[d+8>>2]|0;d=b+(c[d+12>>2]<<2)|0;while(1){if(b>>>0>=d>>>0)break a;c[b>>2]=0;b=b+4|0}}else a=c[b+4>>2]|0;while(0);e=c[e>>2]|0;c[e>>2]=c[e>>2]&-4097;c[e+16>>2]=0;c[e+4>>2]=0;return a|0}function Pl(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;g=a+8|0;a=c[g>>2]|0;b=c[a>>2]|0;if(!(b&4096)){a:do if(!(b&3)){if(b&112|0){a=c[a+8>>2]|0;break}a=c[a+4>>2]|0;if(!a)a=0;else{while(1){b=a+4|0;d=c[b>>2]|0;if(!d){e=a;break}c[b>>2]=c[d>>2];c[d>>2]=a;a=d}while(1){b=c[e>>2]|0;if(!b)break a;d=c[b+4>>2]|0;if(!d){e=b;continue}while(1){c[b+4>>2]=c[d>>2];c[d>>2]=b;b=c[d+4>>2]|0;if(!b)break;else{f=d;d=b;b=f}}c[e>>2]=d;e=d}}}else{e=c[a+8>>2]|0;f=e+(c[a+12>>2]<<2)|0;b=0;a=0;while(1){if(e>>>0>=f>>>0)break a;d=c[e>>2]|0;if(d){if(!b){b=d;a=d}else c[b>>2]=d;while(1){d=c[b>>2]|0;if(!d)break;else b=d}c[e>>2]=b}e=e+4|0}}while(0);g=c[g>>2]|0;c[g+4>>2]=a;c[g>>2]=c[g>>2]|4096}else a=c[a+4>>2]|0;return a|0}function Ql(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;s=a+8|0;if(c[c[s>>2]>>2]&4096|0)Sl(a,0)|0;r=c[a+4>>2]|0;m=c[r>>2]|0;n=c[r+4>>2]|0;q=r+8|0;u=c[q>>2]|0;o=c[r+20>>2]|0;p=a+20|0;f=c[p>>2]&-32769;c[p>>2]=f;a:do if(!b){if(d&384|0){f=c[s>>2]|0;e=c[f+8>>2]|0;if(!e){e=0;break}if(d&256){e=c[e+4>>2]|0;c[f+4>>2]=e;if(!e){e=0;break}}else c[f+4>>2]=e;if((u|0)<0){e=c[e+8>>2]|0;break}else{e=e+(0-u)|0;break}}if(d&4098|0){e=c[s>>2]|0;if(c[e>>2]&144|0){e=0;break}e=c[e+8>>2]|0;if(!e){e=0;break}else{h=e;t=84;break}}if(!(d&64))e=0;else{i=r+16|0;b:do if((c[i>>2]|0)!=0|(u|0)<0){j=a+12|0;k=(u|0)<0;f=0-u|0;e=c[(c[s>>2]|0)+8>>2]|0;while(1){if(!e)break b;g=c[e>>2]|0;h=c[i>>2]|0;if(h|0){if(k)b=c[e+8>>2]|0;else b=e+f|0;ib[h&127](a,b,r)}if((c[q>>2]|0)>=0){e=g;continue}cb[c[j>>2]&31](a,e,0,r)|0;e=g}}while(0);e=c[s>>2]|0;c[e+4>>2]=0;c[e+8>>2]=0;c[(c[s>>2]|0)+16>>2]=0;e=0}}else{if(d&2049|0){g=r+12|0;e=c[g>>2]|0;h=(d&1|0)==0;if(!(h|(e|0)==0)){e=bb[e&31](a,b,r)|0;if(!e){e=0;break}else f=e}else f=b;do if((u|0)>-1)h=f+u|0;else{e=cb[c[a+12>>2]&31](a,0,12,r)|0;if(e|0){c[e+8>>2]=f;h=e;break}if(!(c[g>>2]|0)){e=0;break a}e=c[r+16>>2]|0;if(h|(e|0)==0){e=0;break a}ib[e&127](a,f,r);e=0;break a}while(0);g=c[s>>2]|0;e=c[g>>2]|0;do if(!(e&128)){if(!(e&16))if(!(e&32)){t=51;break}else{t=48;break}f=c[g+4>>2]|0;e=(f|0)!=0;if(!(d&8192)){if(!e){t=48;break}if((f|0)==(c[g+8>>2]|0)){t=48;break}r=f+4|0;a=c[r>>2]|0;c[h+4>>2]=a;c[a>>2]=h;c[h>>2]=f;c[r>>2]=h;break}else{if(!e){t=51;break}e=c[f>>2]|0;if(!e){t=51;break}c[h>>2]=e;c[e+4>>2]=h;c[h+4>>2]=f;c[f>>2]=h;break}}else if(!(d&8192))t=48;else t=51;while(0);if((t|0)==48){e=c[g+8>>2]|0;c[h>>2]=e;if(!e)e=h;else c[h+4>>2]=c[e+4>>2];c[e+4>>2]=h;c[(c[s>>2]|0)+8>>2]=h}else if((t|0)==51){f=g+8|0;e=c[f>>2]|0;if(!e){c[f>>2]=h;e=h}else{r=e+4|0;c[c[r>>2]>>2]=h;c[h+4>>2]=c[r>>2]}c[e+4>>2]=h;c[h>>2]=0}e=c[s>>2]|0;f=e+16|0;g=c[f>>2]|0;if((g|0)>-1)c[f>>2]=g+1;c[e+4>>2]=h;if((u|0)<0){e=c[h+8>>2]|0;break}else{e=h+(0-u)|0;break}}h=c[s>>2]|0;do if(!(d&512)){e=c[h+4>>2]|0;if(e|0){if((u|0)<0)g=c[e+8>>2]|0;else g=e+(0-u)|0;if((g|0)==(b|0))break}e=b+m|0;if((n|0)<0){b=c[e>>2]|0;t=68}else{b=e;t=68}}else t=68;while(0);if((t|0)==68){g=(u|0)<0;i=(n|0)<0;j=(o|0)==0;k=(n|0)<1;l=0-u|0;e=h+8|0;do{e=c[e>>2]|0;if(!e){e=0;break a}if(g)f=c[e+8>>2]|0;else f=e+l|0;f=f+m|0;if(i)f=c[f>>2]|0;do if(j)if(k){f=yJ(b,f)|0;break}else{f=eL(b,f,n)|0;break}else f=cb[o&31](a,b,f,r)|0;while(0)}while((f|0)!=0);f=c[p>>2]|0}c[p>>2]=f|32768;if(!(d&4098)){do if(!(d&8)){f=c[s>>2]|0;if(!(d&16)){c[f+4>>2]=e;break}if((e|0)==(c[f+8>>2]|0)){c[f+4>>2]=0;e=0;break a}else{e=e+4|0;t=108;break}}else{f=c[s>>2]|0;t=108}while(0);if((t|0)==108){e=c[e>>2]|0;c[f+4>>2]=e;if(!e){e=0;break}}if((u|0)<0){e=c[e+8>>2]|0;break}else{e=e+(0-u)|0;break}}else{h=e;t=84}}while(0);if((t|0)==84){e=c[h>>2]|0;if(e){c[e+4>>2]=c[h+4>>2];e=c[h>>2]|0}f=(c[s>>2]|0)+8|0;g=c[f>>2]|0;if((h|0)==(g|0)){c[f>>2]=e;e=c[(c[s>>2]|0)+8>>2]|0;if(e|0)c[e+4>>2]=c[h+4>>2]}else{f=h+4|0;c[c[f>>2]>>2]=e;e=g+4|0;if((h|0)==(c[e>>2]|0))c[e>>2]=c[f>>2]}e=c[s>>2]|0;f=e+4|0;if((h|0)==(c[f>>2]|0))g=c[h>>2]|0;else g=0;c[f>>2]=g;t=e+16|0;c[t>>2]=(c[t>>2]|0)+-1;if((u|0)<0)e=c[h+8>>2]|0;else e=h+(0-u)|0;f=c[r+16>>2]|0;if(!((d&2|0)==0|(f|0)==0))ib[f&127](a,e,r);if((c[q>>2]|0)<0)cb[c[a+12>>2]&31](a,h,0,r)|0}return e|0}function Rl(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+16|0;g=j;a:do if((a|0)!=0&(b|0)!=0?(f=_I(40)|0,(f|0)!=0):0){c[f>>2]=0;c[f+16>>2]=0;c[f+4>>2]=0;Ml(f,a,0)|0;d=f+20|0;i=a+32|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;c[d+16>>2]=0;d=c[i>>2]|0;do if(d){c[g>>2]=0;d=cb[d&31](f,1,g,a)|0;if((d|0)>=0)if(d){e=c[g>>2]|0;if(e|0)if(!(c[b+4>>2]&c[e>>2])){d=f;h=12;break}else{d=f;break}d=a+28|0;if(!(c[d>>2]|0)){d=f;h=12}else{$I(f);e=cb[c[d>>2]&31](0,0,40,a)|0;if(!e){d=0;break a}c[e>>2]=0;c[e+16>>2]=0;c[e+4>>2]=0;Ml(e,a,0)|0;c[e+20>>2]=1;c[e+24>>2]=0;c[e+32>>2]=0;c[e+28>>2]=0;d=e;f=e;h=11}}else{d=f;h=11}else{d=f;h=12}}else{d=f;h=11}while(0);if((h|0)==11){e=cb[c[d+12>>2]&31](d,0,28,a)|0;c[g>>2]=e;if(!e){d=f;h=12}else{c[e>>2]=c[b+4>>2];g=e+4|0;c[g>>2]=0;c[g+4>>2]=0;c[g+8>>2]=0;c[g+12>>2]=0;c[g+16>>2]=0;c[g+20>>2]=0}}if((h|0)==12){$I(d);d=0;break}c[d+8>>2]=e;c[d>>2]=c[b>>2];c[d+16>>2]=b;e=c[i>>2]|0;if(e)cb[e&31](d,5,f,a)|0}else d=0;while(0);l=j;return d|0}function Sl(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;f=c[c[a+16>>2]>>2]|0;j=a+8|0;g=c[j>>2]|0;h=c[g>>2]|0;d=h&4096;if(!b)if(!d)b=-1;else{e=d;b=c[g+4>>2]|0;i=5}else if(!(c[g+16>>2]|0)){e=0;i=5}else b=-1;a:do if((i|0)==5){c[g>>2]=h&-4097;if(!(h&3)){d=g+4|0;if(!(h&12)){c[d>>2]=0;d=g+8|0}c[d>>2]=b;if(e|0){b=0;break}c[(c[j>>2]|0)+16>>2]=-1;b=0;break}c[g+4>>2]=0;if(!e){c[g+16>>2]=0;while(1){if(!b){b=0;break a}j=c[b>>2]|0;bb[f&31](a,b,32)|0;b=j}}e=c[g+8>>2]|0;a=e+(c[g+12>>2]<<2)|0;while(1){if(e>>>0>=a>>>0){b=0;break a}d=c[e>>2]|0;if(d){c[e>>2]=b;b=c[d>>2]|0;c[d>>2]=0}e=e+4|0}}while(0);return b|0}function Tl(a){a=a|0;var b=0,d=0,e=0;b=a+8|0;d=c[b>>2]|0;if(c[d>>2]&4096){Sl(a,0)|0;d=c[b>>2]|0}e=d+16|0;a=c[e>>2]|0;do if((a|0)<0){b=c[d>>2]|0;if(b&12|0){a=Ul(c[d+4>>2]|0)|0;c[e>>2]=a;break}if(b&112){a=0;b=d+8|0;while(1){b=c[b>>2]|0;if(!b)break;a=a+1|0}c[e>>2]=a}}while(0);return a|0}function Ul(a){a=a|0;var b=0;if(!a)return 0;else{b=Ul(c[a+4>>2]|0)|0;return b+1+(Ul(c[a>>2]|0)|0)|0}return 0}function Vl(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0;g=c;if((e|0)>=1){h=c+e+-1|0;g=(h>>>0>>0?c:h)+(1-g)&-2;f=c;while(1){if(f>>>0>=h>>>0)break;b=O(((d[f>>0]|0)<<8)+b+(d[f+1>>0]|0)|0,17109811)|0;f=f+2|0}f=c+g|0;if(f>>>0>h>>>0)c=e;else{c=e;b=O(((d[f>>0]|0)<<8)+b|0,17109811)|0}}else{while(1){f=a[c>>0]|0;if(!(f<<24>>24))break;h=a[c+1>>0]|0;e=O(((f&255)<<8)+b+(h&255)|0,17109811)|0;b=e;c=c+(h<<24>>24?2:1)|0}c=c-g|0}return O(b+c|0,17109811)|0}function Wl(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;G=l;l=l+128|0;z=G+120|0;r=G;F=a+8|0;e=c[F>>2]|0;if(c[e>>2]&4096){Sl(a,0)|0;e=c[F>>2]|0}E=c[a+4>>2]|0;A=c[E>>2]|0;B=c[E+4>>2]|0;x=E+8|0;D=c[x>>2]|0;C=c[E+20>>2]|0;t=a+20|0;c[t>>2]=c[t>>2]&-32769;h=c[e+4>>2]|0;a:do if(!b)if((d&448|0)==0|(h|0)==0)e=0;else{if(!(d&64)){b:do if(!(d&256)){e=h;while(1){f=e+4|0;g=c[f>>2]|0;if(!g)break b;c[f>>2]=c[g>>2];c[g>>2]=e;e=g}}else{e=h;while(1){f=c[e>>2]|0;if(!f)break b;a=f+4|0;c[e>>2]=c[a>>2];c[a>>2]=e;e=f}}while(0);c[(c[F>>2]|0)+4>>2]=e;if((D|0)<0){e=c[e+8>>2]|0;break}else{e=e+(0-D)|0;break}}b=E+16|0;if((c[b>>2]|0)!=0|(D|0)<0){j=a+12|0;k=(D|0)<0;i=0-D|0;e=h;do{h=e;while(1){e=h+4|0;f=c[e>>2]|0;if(!f)break;c[e>>2]=c[f>>2];c[f>>2]=h;h=f}e=c[h>>2]|0;f=c[b>>2]|0;if(f|0){if(k)g=c[h+8>>2]|0;else g=h+i|0;ib[f&127](a,g,E)}if((c[x>>2]|0)<0)cb[c[j>>2]&31](a,h,0,E)|0}while((e|0)!=0);e=c[F>>2]|0}c[e+16>>2]=0;c[e+4>>2]=0;e=0}else{y=a+16|0;u=(d&4098|0)==0;c:do if(u|(c[(c[y>>2]|0)+4>>2]|0)!=8)v=45;else{k=(B|0)<0;e=b+A|0;if(k)e=c[e>>2]|0;i=(C|0)==0;j=(B|0)<1;g=bb[c[a>>2]&31](a,b,4)|0;while(1){if(!g){v=45;break c}f=g+A|0;if(k)f=c[f>>2]|0;do if(i)if(j){f=yJ(e,f)|0;break}else{f=eL(e,f,B)|0;break}else f=cb[C&31](a,e,f,E)|0;while(0);if(f|0){v=45;break c}if((g|0)==(b|0))break;g=bb[c[a>>2]&31](a,g,8)|0}h=c[(c[F>>2]|0)+4>>2]|0;c[z>>2]=c[h+4>>2];c[z+4>>2]=c[h>>2];e=z;v=180}while(0);d:do if((v|0)==45){do if(!(d&2565)){if(d&32|0){if((D|0)<0)g=c[b+8>>2]|0;else g=b+(0-D)|0;e=g+A|0;if((B|0)<0)f=c[e>>2]|0;else f=e;if(!h){e=b;f=z;h=z;v=198;break}else{e=b;s=f;j=b;v=64;break}}if(h){if((D|0)<0)e=c[h+8>>2]|0;else e=h+(0-D)|0;if((e|0)!=(b|0)){f=b+A|0;if((B|0)<0){g=b;e=0;s=c[f>>2]|0;j=0;v=64}else{g=b;e=0;s=f;j=0;v=64}}else{e=0;g=b;f=z;k=z;j=0;v=141}}else{e=0;g=b;f=z;h=z;v=198}}else{if(!(d&512)){e=b+A|0;if((B|0)<0)f=c[e>>2]|0;else f=e}else f=b;if(!h){e=0;g=b;f=z;h=z;v=198}else{g=b;e=0;s=f;j=0;v=64}}while(0);e:do if((v|0)==64){f:do if((c[(c[y>>2]|0)+4>>2]|0)==4?(q=c[(c[F>>2]|0)+24>>2]|0,!((d&516|0)==0|(q|0)==0)):0){b=(D|0)<0;m=(B|0)<0;n=(C|0)==0;o=(B|0)<1;p=0-D|0;k=0;f=h;while(1){if((k|0)>=(q|0)){f=z;k=z;m=0;break}if(b)i=c[f+8>>2]|0;else i=f+p|0;i=i+A|0;if(m)i=c[i>>2]|0;do if(n)if(o){i=yJ(s,i)|0;break}else{i=eL(s,i,B)|0;break}else i=cb[C&31](a,s,i,E)|0;while(0);if(!i){v=80;break}c[r+(k<<2)>>2]=i;f=c[((i|0)<0?f+4|0:f)>>2]|0;if(!f){e=0;break a}else k=k+1|0}if((v|0)==80)if(b){e=c[f+8>>2]|0;break a}else{e=f+p|0;break a}while(1){if((m|0)>=(q|0))break f;do if((c[r+(m<<2)>>2]|0)<0){i=h+4|0;b=c[i>>2]|0;if((c[r+((m|1)<<2)>>2]|0)<0){c[i>>2]=c[b>>2];c[b>>2]=h;c[f+4>>2]=b;f=b;h=k;i=b+4|0;break}else{c[k>>2]=b;c[f+4>>2]=h;f=h;h=b;i=b;break}}else{i=c[h>>2]|0;if((c[r+((m|1)<<2)>>2]|0)>0){p=i+4|0;c[h>>2]=c[p>>2];c[p>>2]=h;c[k>>2]=i;h=i;break}else{c[f+4>>2]=i;c[k>>2]=h;f=i;i=i+4|0;break}}while(0);k=h;m=m+2|0;h=c[i>>2]|0}}else{f=z;k=z}while(0);n=(D|0)<0;o=(B|0)<0;p=(C|0)!=0;q=(B|0)<1;r=0-D|0;i=h;g:while(1){h=i;while(1){if(n)i=c[h+8>>2]|0;else i=h+r|0;i=i+A|0;if(o)i=c[i>>2]|0;do if(!p)if(q){i=yJ(s,i)|0;break}else{i=eL(s,i,B)|0;break}else i=cb[C&31](a,s,i,E)|0;while(0);if(!i){v=140;break g}if((i|0)>=0)break;b=h+4|0;m=c[b>>2]|0;if(!m){v=121;break g}if(n)i=c[m+8>>2]|0;else i=m+r|0;i=i+A|0;if(o)i=c[i>>2]|0;do if(!p)if(q){i=yJ(s,i)|0;break}else{i=eL(s,i,B)|0;break}else i=cb[C&31](a,s,i,E)|0;while(0);if((i|0)>=0){v=118;break}c[b>>2]=c[m>>2];c[m>>2]=h;c[f+4>>2]=m;h=c[m+4>>2]|0;if(!h){f=m;h=k;v=198;break e}else f=m}if((v|0)==118){v=0;if(!i){v=119;break}c[k>>2]=m;c[f+4>>2]=h;i=c[m>>2]|0;if(!i){f=h;h=m;v=198;break e}else{f=h;k=m;continue}}b=c[h>>2]|0;if(!b){v=139;break}if(n)i=c[b+8>>2]|0;else i=b+r|0;i=i+A|0;if(o)i=c[i>>2]|0;do if(!p)if(q){i=yJ(s,i)|0;break}else{i=eL(s,i,B)|0;break}else i=cb[C&31](a,s,i,E)|0;while(0);if((i|0)>0){i=b+4|0;c[h>>2]=c[i>>2];c[i>>2]=h;c[k>>2]=b;i=c[b>>2]|0;if(!i){h=b;v=198;break e}else{k=b;continue}}if(!i){v=137;break}c[f+4>>2]=b;c[k>>2]=h;i=c[b+4>>2]|0;if(!i){f=b;v=198;break e}else{f=b;k=h}}if((v|0)==119){c[f+4>>2]=h;f=h;h=m;v=141;break}else if((v|0)==121){c[f+4>>2]=h;f=h;h=k;v=198;break}else if((v|0)==137){c[k>>2]=h;k=h;h=b;v=141;break}else if((v|0)==139){c[k>>2]=h;v=198;break}else if((v|0)==140)if(!h){h=k;v=198;break}else{v=141;break}}while(0);do if((v|0)==141){c[t>>2]=c[t>>2]|32768;i=h+4|0;c[k>>2]=c[i>>2];c[f+4>>2]=c[h>>2];if(!(d&516)){if(d&8|0){c[i>>2]=c[z>>2];c[h>>2]=0;c[z>>2]=h;v=169;break}if(d&16|0){v=z+4|0;c[h>>2]=c[v>>2];c[i>>2]=0;c[v>>2]=h;v=175;break}if(!u){e=f;v=180;break d}if(d&2049|0){if(c[(c[y>>2]|0)+4>>2]&4|0){e=h;break}c[i>>2]=0;e=z+4|0;c[h>>2]=c[e>>2];c[e>>2]=h;e=h;v=205;break}if(!(d&32)){e=0;break a}if(!(c[(c[y>>2]|0)+4>>2]&4)){c[e+4>>2]=0;x=z+4|0;c[e>>2]=c[x>>2];c[x>>2]=j;e=(c[F>>2]|0)+16|0;c[e>>2]=(c[e>>2]|0)+1;e=h;break}e=c[E+16>>2]|0;if(e|0)ib[e&127](a,g,E);if((c[x>>2]|0)<0){cb[c[a+12>>2]&31](a,j,0,E)|0;e=h}else e=h}else e=h}else if((v|0)==198){c[f+4>>2]=0;c[h>>2]=0;if(!(d&8))if(!(d&16)){if(d&516|0){e=f;break d}if(!(d&2049)){if(!(d&32)){g=0;e=f;break d}x=(c[F>>2]|0)+16|0;c[x>>2]=(c[x>>2]|0)+1}else{e=0;v=205}}else v=175;else v=169}while(0);if((v|0)==169){h=z+4|0;e=c[h>>2]|0;if(!e){e=f;break}while(1){f=e+4|0;g=c[f>>2]|0;if(!g)break;c[f>>2]=c[g>>2];c[g>>2]=e;e=g}c[h>>2]=c[e>>2]}else if((v|0)==175){e=c[z>>2]|0;if(!e){e=f;break}while(1){f=c[e>>2]|0;if(!f)break;x=f+4|0;c[e>>2]=c[x>>2];c[x>>2]=e;e=f}c[z>>2]=c[e+4>>2]}else if((v|0)==205){i=E+12|0;h=c[i>>2]|0;j=(d&1|0)==0;if(!(j|(h|0)==0))g=bb[h&31](a,g,E)|0;do if(g){if((D|0)>-1){e=g+D|0;v=215;break}e=cb[c[a+12>>2]&31](a,0,12,E)|0;if(e|0){c[e+8>>2]=g;break}if((c[i>>2]|0)!=0?(w=c[E+16>>2]|0,!(j|(w|0)==0)):0){ib[w&127](a,g,E);v=215}else v=215}else v=215;while(0);if((v|0)==215)if(!e){e=f;break}f=(c[F>>2]|0)+16|0;g=c[f>>2]|0;if((g|0)>-1)c[f>>2]=g+1}c[e+4>>2]=c[z>>2];c[e>>2]=c[z+4>>2];h:do if(!((d&516|0)==0?1:(c[(c[y>>2]|0)+4>>2]&8|0)==0)){m=(D|0)<0;if(m)f=c[e+8>>2]|0;else f=e+(0-D)|0;n=(B|0)<0;f=f+A|0;if(n)f=c[f>>2]|0;j=(C|0)==0;k=(B|0)<1;b=0-D|0;while(1){i=e+4|0;g=c[i>>2]|0;if(!g)break h;while(1){h=c[g>>2]|0;if(!h)break;z=h+4|0;c[g>>2]=c[z>>2];c[z>>2]=g;g=h}c[i>>2]=g;if(m)h=c[g+8>>2]|0;else h=g+b|0;h=h+A|0;if(n)h=c[h>>2]|0;do if(j)if(k){h=yJ(f,h)|0;break}else{h=eL(f,h,B)|0;break}else h=cb[C&31](a,f,h,E)|0;while(0);if(h|0)break h;c[i>>2]=c[g>>2];c[g>>2]=e;e=g}}while(0);c[(c[F>>2]|0)+4>>2]=e;if((D|0)<0){e=c[e+8>>2]|0;break a}else{e=e+(0-D)|0;break a}}while(0);if((v|0)==180){if((D|0)<0)g=c[h+8>>2]|0;else g=h+(0-D)|0;f=c[E+16>>2]|0;if(!((d&2|0)==0|(f|0)==0))ib[f&127](a,g,E);if((c[x>>2]|0)<0)cb[c[a+12>>2]&31](a,h,0,E)|0;a=(c[F>>2]|0)+16|0;E=c[a>>2]|0;c[a>>2]=(E|0)<1?-1:E+-1|0}do{f=e+4|0;e=c[f>>2]|0}while((e|0)!=0);c[f>>2]=c[z>>2];c[(c[F>>2]|0)+4>>2]=c[z+4>>2];e=d&2|0?g:0}while(0);l=G;return e|0}function Xl(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if(c[c[a+8>>2]>>2]&4096|0)Sl(a,0)|0;f=(b|0)!=0;if(f){if(c[c[b+8>>2]>>2]&4096|0)Sl(b,0)|0;if((c[b+16>>2]|0)==(c[a+16>>2]|0)){d=b;e=7}else b=0}else{d=0;e=7}a:do if((e|0)==7){while(1){if(!d)break;if((d|0)==(a|0)){b=0;break a}d=c[d+28>>2]|0;e=7}d=a+28|0;e=c[d>>2]|0;if(e|0){g=e+24|0;c[g>>2]=(c[g>>2]|0)+-1}c[a+32>>2]=0;c[d>>2]=0;if(f){c[d>>2]=b;c[a>>2]=12;g=b+24|0;c[g>>2]=(c[g>>2]|0)+1;break}else{c[a>>2]=c[c[a+16>>2]>>2];b=e;break}}while(0);return b|0}function Yl(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;a:do if(!(d&99)){if((d&516|0)==0?(e=c[(c[a+16>>2]|0)+4>>2]|0,!((d&384|0)!=0&(e&12|0)==0)):0){if(e&12|0){if(!(d&408)){e=0;break}o=(d&136|0)!=0;p=(d&272|0)!=0;l=0;f=0;e=0;n=a;while(1){if(!n)break;m=bb[c[c[n+16>>2]>>2]&31](n,b,d)|0;do if(!m)g=l;else{h=c[n+4>>2]|0;i=c[h+4>>2]|0;j=c[h+20>>2]|0;g=m+(c[h>>2]|0)|0;if((i|0)<0)k=c[g>>2]|0;else k=g;if(e|0){do if(!j)if((i|0)<1){g=yJ(k,f)|0;break}else{g=eL(k,f,i)|0;break}else g=cb[j&31](n,k,f,h)|0;while(0);if(!(o&(g|0)<0|p&(g|0)>0)){g=l;break}}g=n;f=k;e=m}while(0);l=g;n=c[n+28>>2]|0}c[a+32>>2]=l;break}if(!(d&24)){e=0;break}j=a+32|0;f=c[j>>2]|0;if(f){e=c[(c[f+4>>2]|0)+8>>2]|0;g=c[(c[f+8>>2]|0)+4>>2]|0;if((e|0)<0)e=c[g+8>>2]|0;else e=g+(0-e)|0;if((e|0)==(b|0))e=b;else{f=a;h=32}}else{f=a;h=32}do if((h|0)==32){while(1){if(!f){h=33;break}e=bb[c[c[f+16>>2]>>2]&31](f,b,4)|0;if(e|0){h=36;break}f=c[f+28>>2]|0;h=32}if((h|0)==33){c[j>>2]=0;e=0;break a}else if((h|0)==36){c[j>>2]=f;break}}while(0);i=(d<<4&128^128)+128|0;e=bb[c[c[f+16>>2]>>2]&31](f,e,d)|0;while(1){h=f+16|0;while(1){if(!e)break;else g=a;while(1){if((g|0)==(f|0))break a;if(bb[c[c[g+16>>2]>>2]&31](g,e,4)|0)break;g=c[g+28>>2]|0}e=bb[c[c[h>>2]>>2]&31](f,e,d)|0}f=c[f+28>>2]|0;c[j>>2]=f;if(!f){e=0;break a}e=bb[c[c[f+16>>2]>>2]&31](f,0,i)|0}}else f=a;while(1){if(!f){f=0;e=0;break}e=bb[c[c[f+16>>2]>>2]&31](f,b,d)|0;if(e|0)break;f=c[f+28>>2]|0}c[a+32>>2]=f}else e=bb[c[c[a+16>>2]>>2]&31](a,b,d)|0;while(0);return e|0}function Zl(a){a=a|0;var b=0;b=c[41980]|0;c[41980]=a;return b|0}function _l(a){a=a|0;var b=0;b=c[41981]|0;c[41981]=a;return b|0}function $l(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=l;l=l+16|0;f=e;c[f>>2]=d;d=am(a,b,f)|0;l=e;return d|0}function am(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;g=l;l=l+16|0;e=g;f=(a|0)==3;h=f?c[41983]|0:(a|0)==2?1:a;c[41983]=h;i=c[41984]|0;c[41984]=i>>>0>h>>>0?i:h;do if(h>>>0<(c[41981]|0)>>>0){a=c[41982]|0;if(!a){a=BN()|0;c[41982]=a;if(!a){a=1;break}}if(!f){EN(a)|0;a=c[41982]|0}NK(a,b,d)|0;a=0}else{if(c[41980]|0){bm(a,b,d);a=0;break}if(f)a=c[13918]|0;else{i=c[13918]|0;c[e>>2]=(a|0)==1?81312:81318;AL(i,81326,e)|0;a=i}NK(a,b,d)|0;a=0}while(0);l=g;return a|0}function bm(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;if((c[41985]|0)==0?(f=_I(c[4354]|0)|0,c[41985]=f,(f|0)==0):0)XL(81331,c[13918]|0)|0;else e=4;do if((e|0)==4){if((a|0)!=3){$a[c[41980]&31]((a|0)==1?81312:81318)|0;$a[c[41980]&31](81990)|0}while(1){a=MK(c[41985]|0,c[4354]|0,b,d)|0;e=c[4354]|0;if((a|0)>-1&(a|0)<(e|0)){e=7;break}e=e<<1;f=a+1|0;f=(e|0)>(f|0)?e:f;c[4354]=f;if(!(bJ(c[41985]|0,f)|0)){e=9;break}}if((e|0)==7){$a[c[41980]&31](c[41985]|0)|0;break}else if((e|0)==9){XL(81331,c[13918]|0)|0;break}}while(0);return}function cm(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=b;am(1,a,e)|0;l=d;return}function dm(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if(!e){e=(d|0)==0?1024:d;d=e;e=_I(e)|0;f=1}else f=0;c[b+12>>2]=f;c[b>>2]=e;c[b+8>>2]=e+d;c[b+4>>2]=e;a[e>>0]=0;return}function em(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;f=c[a>>2]|0;g=(c[h>>2]|0)-f|0;e=g<<1;g=g+b|0;e=g>>>0>e>>>0?g:e;g=a+4|0;b=f;f=(c[g>>2]|0)-f|0;d=a+12|0;if(!(c[d>>2]|0)){i=_I(e)|0;UN(i|0,b|0,f|0)|0;c[d>>2]=1;b=i}else b=bJ(b,e)|0;c[a>>2]=b;c[g>>2]=b+f;c[h>>2]=b+e;return 0}function fm(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;f=a+4|0;e=c[f>>2]|0;if((e+d|0)>>>0>(c[a+8>>2]|0)>>>0){em(a,d)|0;e=c[f>>2]|0}UN(e|0,b|0,d|0)|0;c[f>>2]=(c[f>>2]|0)+d;return d|0}function gm(a,b){a=a|0;b=b|0;return fm(a,b,sJ(b)|0)|0}function hm(a){a=a|0;if(c[a+12>>2]|0)$I(c[a>>2]|0);return}function im(a){a=a|0;var b=0,e=0;b=a+4|0;e=c[b>>2]|0;if(e>>>0>(c[a>>2]|0)>>>0){c[b>>2]=e+-1;a=d[e>>0]|0}else a=-1;return a|0}function jm(a,b,d){a=a|0;b=b|0;d=d|0;cp(c[41987]|0,c[b+8>>2]|0)|0;cp(c[41987]|0,c[b+12>>2]|0)|0;_n(c[41987]|0,b);return}function km(a,b){a=a|0;b=b|0;var c=0;c=Mo(a,81379,0)|0;if((b|0)!=0&(c|0)==0){lm(a);c=Mo(a,81379,0)|0}return c|0}function lm(a){a=a|0;var b=0,c=0,d=0;d=to(a)|0;xq(d,d,86,0,1)|0;c=eo(d)|0;while(1){if(!c)break;nm(a,c);b=Qm(d,c)|0;while(1){if(!b)break;om(a,b);b=Sm(d,b)|0}c=fo(d,c)|0}return}function mm(b){b=b|0;var c=0;c=b+24|0;a[c>>0]=a[c>>0]|64;tm(b);c=Mp(b)|0;qm((c|0)==0?b:c,b);return}function nm(a,b){a=a|0;b=b|0;var d=0;d=pm(b)|0;if(!((d|0)!=0?(c[d+8>>2]|0)!=0:0))qm(a,b);return}function om(a,b){a=a|0;b=b|0;var d=0;d=pm(b)|0;if(!((d|0)!=0?(c[d+8>>2]|0)!=0:0))qm(a,b);return}function pm(a){a=a|0;return Mo(a,81367,0)|0}function qm(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=Oo(b,81367,16,0)|0;f=rm(a,c[b>>2]&3)|0;e=d+8|0;a:do if(!(c[e>>2]|0)){a=to(a)|0;c[e>>2]=rm(a,c[b>>2]&3)|0;a=sm(b)|0;d=d+12|0;c[d>>2]=Zn(so(b)|0,((a|0)>4?a:4)<<2)|0;a=bb[c[f>>2]&31](f,0,128)|0;while(1){if(!a)break a;e=so(b)|0;e=ap(e,c[a+12>>2]|0)|0;c[(c[d>>2]|0)+(c[a+16>>2]<<2)>>2]=e;a=bb[c[f>>2]&31](f,a,8)|0}}while(0);return}function rm(a,b){a=a|0;b=b|0;var d=0,e=0;e=l;l=l+16|0;d=e;a=km(a,0)|0;a:do if(!a)a=0;else switch(b|0){case 0:{a=c[a+16>>2]|0;break a}case 1:{a=c[a+8>>2]|0;break a}case 2:case 3:{a=c[a+12>>2]|0;break a}default:{c[d>>2]=b;$l(1,81392,d)|0;a=0;break a}}while(0);l=e;return a|0}function sm(a){a=a|0;var b=0;b=to(so(a)|0)|0;a=rm(b,c[a>>2]&3)|0;if(!a)a=0;else a=Tl(a)|0;return a|0}function tm(a){a=a|0;var b=0,d=0,e=0,f=0;d=Oo(a,81379,20,0)|0;e=d+8|0;c[e>>2]=Qp(a,17420,c[4353]|0)|0;f=d+12|0;c[f>>2]=Qp(a,17420,c[4353]|0)|0;d=d+16|0;c[d>>2]=Qp(a,17420,c[4353]|0)|0;b=Mp(a)|0;if(!b){b=c[41986]|0;if(!((b|0)==0|(b|0)==(a|0))){b=km(b,0)|0;um(c[b+8>>2]|0,c[e>>2]|0,a,1);um(c[b+12>>2]|0,c[f>>2]|0,a,2);um(c[b+16>>2]|0,c[d>>2]|0,a,0)}}else{a=km(b,0)|0;Xl(c[e>>2]|0,c[a+8>>2]|0)|0;Xl(c[f>>2]|0,c[a+12>>2]|0)|0;Xl(c[d>>2]|0,c[a+16>>2]|0)|0}return}function um(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;g=bb[c[b>>2]&31](b,0,128)|0;while(1){if(!g)break;h=vm(e,c[g+8>>2]|0,c[g+12>>2]|0,c[g+16>>2]|0,f)|0;a[h+22>>0]=a[g+22>>0]|0;a[h+21>>0]=a[g+21>>0]|0;bb[c[d>>2]&31](d,h,1)|0;g=bb[c[b>>2]&31](b,g,8)|0}return}function vm(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;h=Zn(b,24)|0;a[h+20>>0]=g;c[h+8>>2]=ap(b,d)|0;c[h+12>>2]=ap(b,e)|0;c[h+16>>2]=f;return h|0}function wm(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+32|0;e=d;c[e+8>>2]=b;b=bb[c[a>>2]&31](a,e,4)|0;l=d;return b|0}function xm(a,b){a=a|0;b=b|0;var c=0;c=Xl(a,0)|0;b=wm(a,b)|0;Xl(a,c)|0;return b|0}function ym(a,b){a=a|0;b=b|0;a=pm(a)|0;if(!a)a=0;else a=wm(c[a+8>>2]|0,b)|0;return a|0}function zm(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;h=l;l=l+16|0;g=h;if(!b){b=c[41986]|0;if(!b){a[g>>0]=a[17456]|0;a[g+1>>0]=a[17457]|0;a[g+2>>0]=a[17458]|0;a[g+3>>0]=a[17459]|0;b=hn(0,g,0)|0;c[41986]=b}}if(!f)b=Bm(b,d,e)|0;else b=Am(b,d,e,f)|0;l=h;return b|0}function Am(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=to(a)|0;km(a,1)|0;g=rm(a,b)|0;f=xm(g,d)|0;a:do if(!f){f=wm(g,d)|0;if(f|0){f=vm(a,d,e,c[f+16>>2]|0,b)|0;bb[c[g>>2]&31](g,f,1)|0;h=16;break}g=rm(i,b)|0;f=vm(a,d,e,Tl(g)|0,b)|0;bb[c[g>>2]&31](g,f,1)|0;switch(b|0){case 0:{xq(i,i,52,f,1)|0;h=16;break a}case 1:{d=eo(i)|0;while(1){if(!d){h=16;break a}Cm(a,d,f);d=fo(i,d)|0}}case 2:case 3:{g=eo(i)|0;while(1){if(!g){h=16;break a}d=Qm(i,g)|0;while(1){if(!d)break;Cm(a,d,f);d=Sm(i,d)|0}g=fo(i,g)|0}}default:break a}}else{h=f+12|0;cp(a,c[h>>2]|0)|0;c[h>>2]=ap(a,e)|0;h=16}while(0);if((h|0)==16)if((b|0)==0&(f|0)!=0)Dm(a,f,e)|0;wo(a,a,f);return f|0}function Bm(a,b,c){a=a|0;b=b|0;c=c|0;a=rm(a,b)|0;if(!a)a=0;else a=wm(a,c)|0;return a|0}function Cm(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;b=pm(b)|0;f=d+16|0;e=c[f>>2]|0;if((e|0)>3){g=c[a+64>>2]|0;b=b+12|0;e=e<<2;c[b>>2]=cb[c[(c[g>>2]|0)+8>>2]&31](c[g+12>>2]|0,c[b>>2]|0,e,e+4|0)|0}else b=b+12|0;g=ap(a,c[d+12>>2]|0)|0;c[(c[b>>2]|0)+(c[f>>2]<<2)>>2]=g;return}function Dm(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;h=so(a)|0;g=(pm(a)|0)+12|0;i=b+16|0;cp(h,c[(c[g>>2]|0)+(c[i>>2]<<2)>>2]|0)|0;f=ap(h,d)|0;c[(c[g>>2]|0)+(c[i>>2]<<2)>>2]=f;do if(!(c[a>>2]&3)){e=c[(km(h,0)|0)+16>>2]|0;f=b+8|0;g=xm(e,c[f>>2]|0)|0;if(!g){i=vm(h,c[f>>2]|0,d,c[i>>2]|0,c[a>>2]&3)|0;bb[c[e>>2]&31](e,i,1)|0;break}else{i=g+12|0;cp(h,c[i>>2]|0)|0;c[i>>2]=ap(h,d)|0;break}}while(0);wo(h,a,b);return 0}function Em(a,b,d){a=a|0;b=b|0;d=d|0;a=rm(a,b)|0;do if(a){b=c[a>>2]|0;if(!d){a=bb[b&31](a,0,128)|0;break}else{a=bb[b&31](a,d,8)|0;break}}else a=0;while(0);return a|0}function Fm(a){a=a|0;var b=0;c[41987]=a;b=pm(a)|0;if(b|0){Gm(a,b);Qo(a,c[b>>2]|0)|0}b=km(a,0)|0;if(b)if(((Sp(a,c[b+8>>2]|0)|0)==0?(Sp(a,c[b+12>>2]|0)|0)==0:0)?(Sp(a,c[b+16>>2]|0)|0)==0:0){Qo(a,c[b>>2]|0)|0;b=0}else b=1;else b=0;return b|0}function Gm(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=so(a)|0;e=sm(a)|0;b=b+12|0;a=0;while(1){d=c[b>>2]|0;if((a|0)>=(e|0))break;cp(f,c[d+(a<<2)>>2]|0)|0;a=a+1|0}_n(f,d);return}function Hm(a){a=a|0;var b=0;b=pm(a)|0;if(b|0){Gm(a,b);Qo(a,81367)|0}return}function Im(a){a=a|0;var b=0;b=pm(a)|0;if(b|0){Gm(a,b);Qo(a,81367)|0}return}function Jm(a,b){a=a|0;b=b|0;b=ym(a,b)|0;if(!b)b=0;else{a=c[(pm(a)|0)+12>>2]|0;b=c[a+(c[b+16>>2]<<2)>>2]|0}return b|0}function Km(a,b){a=a|0;b=b|0;a=c[(pm(a)|0)+12>>2]|0;return c[a+(c[b+16>>2]<<2)>>2]|0}function Lm(a,b,c){a=a|0;b=b|0;c=c|0;b=ym(a,b)|0;if(!b)b=-1;else{Dm(a,b,c)|0;b=0}return b|0}function Mm(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=so(a)|0;f=zm(f,c[a>>2]&3,b,0)|0;if(!f){f=so(a)|0;f=zm(f,c[a>>2]&3,b,e)|0}Dm(a,f,d)|0;return 0}function Nm(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=so(a)|0;f=c[a>>2]|0;a:do if(!((c[b>>2]^f)&3)){d=1;e=0;while(1){e=Em(g,f&3,e)|0;if(!e)break a;d=ym(b,c[e+8>>2]|0)|0;if(!d){d=1;break a}f=Km(a,e)|0;Dm(b,d,f)|0;if(dp(f)|0)ep(Km(b,d)|0);d=0;f=c[a>>2]|0}}else d=1;while(0);return d|0}function Om(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;a=c[b+40>>2]|0;f=c[d+40>>2]|0;if((a|0)==(f|0)){e=(c[b>>2]|0)>>>4;a=(c[d>>2]|0)>>>4;if(e>>>0>=a>>>0)if(e>>>0>a>>>0)a=1;else g=6;else a=-1}else{e=(c[a>>2]|0)>>>4;a=(c[f>>2]|0)>>>4;if(e>>>0>=a>>>0)if(e>>>0>a>>>0)a=1;else g=6;else a=-1}if((g|0)==6)a=0;return a|0}function Pm(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;a=(c[b+40>>2]|0)+8|0;g=c[a>>2]|0;a=c[a+4>>2]|0;f=(c[d+40>>2]|0)+8|0;e=c[f>>2]|0;f=c[f+4>>2]|0;do if(!(a>>>0>>0|(a|0)==(f|0)&g>>>0>>0))if(a>>>0>f>>>0|(a|0)==(f|0)&g>>>0>e>>>0)a=1;else{e=b+8|0;a=c[e>>2]|0;e=c[e+4>>2]|0;if(!((a|0)==0&(e|0)==0)?(i=d+8|0,h=c[i>>2]|0,i=c[i+4>>2]|0,!((h|0)==0&(i|0)==0)):0){if(e>>>0>>0|(e|0)==(i|0)&a>>>0>>0){a=-1;break}if(e>>>0>i>>>0|(e|0)==(i|0)&a>>>0>h>>>0){a=1;break}}a=0}else a=-1;while(0);return a|0}function Qm(a,b){a=a|0;b=b|0;var d=0;b=Rm(a,b)|0;if(!b)b=0;else{d=a+44|0;a=b+32|0;Sl(c[d>>2]|0,c[a>>2]|0)|0;b=c[d>>2]|0;b=bb[c[b>>2]&31](b,0,128)|0;c[a>>2]=Ol(c[d>>2]|0)|0}return b|0}function Rm(a,b){a=a|0;b=b|0;var d=0,e=0;e=l;l=l+48|0;d=e;if((c[b+24>>2]|0)==(a|0))a=b+28|0;else{c[d+16>>2]=b;a=c[a+40>>2]|0;a=bb[c[a>>2]&31](a,d,4)|0}l=e;return a|0}function Sm(a,b){a=a|0;b=b|0;var d=0,e=0;d=Rm(a,c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0)|0;if(!d)a=0;else{e=a+44|0;d=d+32|0;Sl(c[e>>2]|0,c[d>>2]|0)|0;a=c[e>>2]|0;a=bb[c[a>>2]&31](a,b,8)|0;c[d>>2]=Ol(c[e>>2]|0)|0}return a|0}function Tm(a,b){a=a|0;b=b|0;var d=0;b=Rm(a,b)|0;if(!b)b=0;else{d=a+44|0;a=b+28|0;Sl(c[d>>2]|0,c[a>>2]|0)|0;b=c[d>>2]|0;b=bb[c[b>>2]&31](b,0,128)|0;c[a>>2]=Ol(c[d>>2]|0)|0}return b|0}function Um(a,b){a=a|0;b=b|0;var d=0,e=0;d=Rm(a,c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0)|0;if(!d)a=0;else{e=a+44|0;d=d+28|0;Sl(c[e>>2]|0,c[d>>2]|0)|0;a=c[e>>2]|0;a=bb[c[a>>2]&31](a,b,8)|0;c[d>>2]=Ol(c[e>>2]|0)|0}return a|0}function Vm(a,b){a=a|0;b=b|0;var c=0;c=Qm(a,b)|0;if(!c)c=Tm(a,b)|0;return c|0}function Wm(a,b,d){a=a|0;b=b|0;d=d|0;a:do if((c[b>>2]&3|0)==2){b=Sm(a,b)|0;if(!b){b=0;do{if(!b)b=Tm(a,d)|0;else b=Um(a,b)|0;if(!b){b=0;break a}}while((c[b+40>>2]|0)==(d|0))}}else do{b=Um(a,b)|0;if(!b){b=0;break a}}while((c[b+40>>2]|0)==(d|0));while(0);return b|0}function Xm(a,b,e){a=a|0;b=b|0;e=e|0;var f=0,g=0,h=0;h=l;l=l+32|0;f=h+16|0;g=h;if((tn(a)|0)!=0?(c[g>>2]=0,c[g+4>>2]=0,c[g+8>>2]=0,c[g+12>>2]=0,c[f>>2]=c[g>>2],c[f+4>>2]=c[g+4>>2],c[f+8>>2]=c[g+8>>2],c[f+12>>2]=c[g+12>>2],($m(a,b,e,f)|0)!=0):0)f=0;else f=((d[a+24>>0]|0)>>>2&1^1)&255|(b|0)!=(e|0);l=h;return f|0}function Ym(a,b){a=a|0;b=b|0;_m(a,b);return}function Zm(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0;jo(b,d,1)|0;jo(b,e,1)|0;h=Zn(b,96)|0;i=h+48|0;l=ln(b,2)|0;j=c[i>>2]|0;k=c[h>>2]|0;m=h+8|0;c[m>>2]=f;c[m+4>>2]=g;m=h+56|0;c[m>>2]=f;c[m+4>>2]=g;g=l<<4;c[h>>2]=k&12|g|2;c[i>>2]=j&12|g|3;c[h+88>>2]=d;c[h+40>>2]=e;_m(b,h);if(a[b+24>>0]&64){Oo(h,81367,16,0)|0;om(b,h)}uo(b,h);return h|0}function _m(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0;i=l;l=l+16|0;d=i;h=c[b>>2]&3;g=(h|0)==2?b:b+-48|0;h=(h|0)==3?b:b+48|0;e=c[h+40>>2]|0;f=c[g+40>>2]|0;while(1){if(!a)break;c[d>>2]=c[b>>2];c[d+4>>2]=c[b+4>>2];c[d+8>>2]=c[b+8>>2];c[d+12>>2]=c[b+12>>2];if($m(a,e,f,d)|0)break;j=Rm(a,e)|0;m=a+44|0;an(c[m>>2]|0,j+32|0,g);k=a+48|0;an(c[k>>2]|0,j+24|0,g);j=Rm(a,f)|0;an(c[m>>2]|0,j+28|0,h);an(c[k>>2]|0,j+20|0,h);a=Mp(a)|0}l=i;return}function $m(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;h=l;l=l+48|0;f=h;if(!((b|0)==0|(d|0)==0)?(c[f>>2]=c[e>>2],c[f+4>>2]=c[e+4>>2],c[f+8>>2]=c[e+8>>2],c[f+12>>2]=c[e+12>>2],c[f+40>>2]=b,g=Rm(a,d)|0,(g|0)!=0):0){e=a+48|0;g=g+20|0;Sl(c[e>>2]|0,c[g>>2]|0)|0;a=c[e>>2]|0;a=bb[c[a>>2]&31](a,f,4)|0;c[g>>2]=Ol(c[e>>2]|0)|0}else a=0;l=h;return a|0}function an(a,b,d){a=a|0;b=b|0;d=d|0;Sl(a,c[b>>2]|0)|0;bb[c[a>>2]&31](a,d,1)|0;c[b>>2]=Ol(a)|0;return}function bn(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;n=l;l=l+48|0;i=n+24|0;k=n+16|0;j=n;do if(!(Bn(a,2,e,k,0)|0))if(!e){if(f|0?(tn(a)|0)==0:0){m=18;break};c[j>>2]=0;c[j+4>>2]=0;c[j+8>>2]=0;c[j+12>>2]=0;m=7}else m=17;else{o=j;c[o>>2]=0;c[o+4>>2]=0;o=k;g=c[o+4>>2]|0;m=j+8|0;c[m>>2]=c[o>>2];c[m+4>>2]=g;c[j>>2]=2;m=7}while(0);a:do if((m|0)==7){c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];c[i+8>>2]=c[j+8>>2];c[i+12>>2]=c[j+12>>2];g=$m(a,b,d,i)|0;b:do if(!g){if(sn(a)|0?(c[i>>2]=c[j>>2],c[i+4>>2]=c[j+4>>2],c[i+8>>2]=c[j+8>>2],c[i+12>>2]=c[j+12>>2],h=$m(a,d,b,i)|0,h|0):0){g=h;break}do if(f|0){g=to(a)|0;c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];c[i+8>>2]=c[j+8>>2];c[i+12>>2]=c[j+12>>2];g=$m(g,b,d,i)|0;if(!g){if(!(sn(a)|0))break;g=to(a)|0;c[i>>2]=c[j>>2];c[i+4>>2]=c[j+4>>2];c[i+8>>2]=c[j+8>>2];c[i+12>>2]=c[j+12>>2];g=$m(g,d,b,i)|0;if(!g)break}Ym(a,g);break b}while(0);m=17;break a}while(0)}while(0);if((m|0)==17)if(!f)g=0;else m=18;if((m|0)==18)if((Xm(a,b,d)|0)!=0?(Bn(a,2,e,k,1)|0)!=0:0){g=k;g=Zm(a,b,d,c[g>>2]|0,c[g+4>>2]|0)|0;Fn(a,2,g)}else g=0;l=n;return g|0}function cn(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;d=(c[b>>2]&3|0)==3;g=d?b+-48|0:b;d=d?b:b+48|0;b=c[g+40>>2]|0;h=Rm(a,c[d+40>>2]|0)|0;f=a+44|0;dn(c[f>>2]|0,h+32|0,g);e=a+48|0;dn(c[e>>2]|0,h+24|0,g);b=Rm(a,b)|0;dn(c[f>>2]|0,b+28|0,d);dn(c[e>>2]|0,b+20|0,d);return}function dn(a,b,d){a=a|0;b=b|0;d=d|0;Sl(a,c[b>>2]|0)|0;bb[c[a>>2]&31](a,d,2)|0;c[b>>2]=Ol(a)|0;return}function en(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=l;l=l+16|0;f=e;d=(c[d>>2]&3|0)==2?d:d+-48|0;g=c[d>>2]&3;h=c[((g|0)==3?d:d+48|0)+40>>2]|0;g=c[((g|0)==2?d:d+-48|0)+40>>2]|0;c[f>>2]=c[d>>2];c[f+4>>2]=c[d+4>>2];c[f+8>>2]=c[d+8>>2];c[f+12>>2]=c[d+12>>2];if($m(b,h,g,f)|0){if((to(b)|0)==(b|0)){if(a[b+24>>0]&64)Im(d);yo(b,d);Wo(d);h=d+8|0;Dn(b,2,c[h>>2]|0,c[h+4>>2]|0)}if(!(xq(b,d,53,0,0)|0))if((to(b)|0)==(b|0)){_n(b,d);d=0}else d=0;else d=-1}else d=-1;l=e;return d|0}function fn(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;h=l;l=l+16|0;e=h;f=jo(a,c[((c[b>>2]&3|0)==3?b:b+48|0)+40>>2]|0,d)|0;g=jo(a,c[((c[b>>2]&3|0)==2?b:b+-48|0)+40>>2]|0,d)|0;do if((f|0)!=0&(g|0)!=0){c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];c[e+8>>2]=c[b+8>>2];c[e+12>>2]=c[b+12>>2];e=$m(a,f,g,e)|0;f=(e|0)==0;if(!((d|0)!=0&f)){if(f)break}else{_m(a,b);e=b}d=c[e>>2]&3;l=h;return ((d|0)==(c[b>>2]&3|0)?e:e+(((d|0)==3?-1:1)*48|0)|0)|0}while(0);l=h;return 0}function gn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;b=b+8|0;e=d+8|0;e=JN(c[b>>2]|0,c[b+4>>2]|0,c[e>>2]|0,c[e+4>>2]|0)|0;return ((e|0)==0?0:e>>31|1)|0}function hn(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;h=l;l=l+16|0;g=h;j=jn(e)|0;f=ab[c[(c[j>>2]|0)+4>>2]&63](c[j+12>>2]|0,72)|0;c[f>>2]=c[f>>2]&-4;i=f+64|0;c[i>>2]=j;k=f+24|0;d=c[d>>2]|0;c[k>>2]=d;a[k>>0]=d&255|8;c[f+60>>2]=f;e=ab[c[c[j+4>>2]>>2]&63](f,e)|0;c[(c[i>>2]|0)+16>>2]=e;if(Bn(f,0,b,g,1)|0){i=g;j=c[i+4>>2]|0;k=f+8|0;c[k>>2]=c[i>>2];c[k+4>>2]=j}k=kn(f)|0;Fn(k,0,f);l=h;return k|0}function jn(b){b=b|0;var d=0,e=0,f=0,g=0;d=(b|0)!=0;if(d){e=c[b>>2]|0;e=(e|0)==0?17792:e}else e=17792;g=$a[c[e>>2]&31](b)|0;f=ab[c[e+4>>2]&63](g,80)|0;c[f>>2]=e;c[f+12>>2]=g;if(d){g=c[b+4>>2]|0;c[f+4>>2]=(g|0)==0?17668:g;b=c[b+8>>2]|0;b=(b|0)==0?17768:b}else{c[f+4>>2]=17668;b=17768}c[f+8>>2]=b;a[f+52>>0]=1;return f|0}function kn(b){b=b|0;var d=0,e=0;c[b+36>>2]=Qp(b,17848,c[4353]|0)|0;c[b+40>>2]=Qp(b,17812,c[4353]|0)|0;d=(to(b)|0)==(b|0);c[b+44>>2]=Qp(b,d?17460:17496,c[4353]|0)|0;d=(to(b)|0)==(b|0);c[b+48>>2]=Qp(b,d?17532:17568,c[4353]|0)|0;c[b+52>>2]=Qp(b,17604,c[4353]|0)|0;d=Mp(b)|0;if(!((d|0)!=0?(e=ln(d,0)|0,c[b>>2]=c[b>>2]&15|e<<4,e=c[d+52>>2]|0,bb[c[e>>2]&31](e,b,1)|0,!(a[d+24>>0]&64)):0))mm(b);uo(b,b);return b|0}function ln(a,b){a=a|0;b=b|0;var d=0;d=(c[a+64>>2]|0)+24+(b<<3)|0;b=d;b=IN(c[b>>2]|0,c[b+4>>2]|0,1,0)|0;a=z;c[d>>2]=b;c[d+4>>2]=a;z=a;return b|0}function mn(b){b=b|0;var d=0,e=0,f=0,g=0;f=Mp(b)|0;g=(f|0)==0;if(g?(d=b+64|0,(c[(c[c[d>>2]>>2]|0)+16>>2]|0)!=0):0){yo(b,b);g=b+8|0;Dn(b,0,c[g>>2]|0,c[g+4>>2]|0);d=c[d>>2]|0;gb[c[(c[d>>2]|0)+16>>2]&127](c[d+12>>2]|0);d=0}else e=4;do if((e|0)==4){d=Kp(b)|0;while(1){if(!d)break;e=Lp(d)|0;mn(d)|0;d=e}d=eo(b)|0;while(1){if(!d)break;e=fo(b,d)|0;qo(b,d)|0;d=e}On(b);yo(b,b);if(((((Sp(b,c[b+40>>2]|0)|0)==0?(Sp(b,c[b+36>>2]|0)|0)==0:0)?(Sp(b,c[b+48>>2]|0)|0)==0:0)?(Sp(b,c[b+44>>2]|0)|0)==0:0)?(Sp(b,c[b+52>>2]|0)|0)==0:0){if(a[b+24>>0]&64?Fm(b)|0:0){d=-1;break}Wo(b);e=b+8|0;Dn(b,0,c[e>>2]|0,c[e+4>>2]|0);if(!g){Np(f,b)|0;_n(f,b);d=0;break}d=b+64|0;while(1){e=c[d>>2]|0;f=c[e+48>>2]|0;if(!f)break;Bo(b,c[f>>2]|0)|0}gb[c[(c[e+4>>2]|0)+20>>2]&127](c[e+16>>2]|0);if(!(Xo(b)|0)){d=c[d>>2]|0;g=c[d+12>>2]|0;f=(c[d>>2]|0)+12|0;hb[c[f>>2]&31](g,b);hb[c[f>>2]&31](g,d);d=0}else d=-1}else d=-1}while(0);return d|0}function nn(a){a=a|0;return Tl(c[a+40>>2]|0)|0}function on(a){a=a|0;var b=0,c=0,d=0;b=0;c=eo(a)|0;while(1){if(!c)break;d=(pn(a,c,0,1)|0)+b|0;b=d;c=fo(a,c)|0}return b|0}function pn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=Rm(a,b)|0;if(f){if(!e)b=0;else b=qn(c[a+44>>2]|0,f+32|0)|0;if(d)b=(qn(c[a+44>>2]|0,f+28|0)|0)+b|0}else b=0;return b|0}function qn(a,b){a=a|0;b=b|0;var d=0;Sl(a,c[b>>2]|0)|0;d=Tl(a)|0;c[b>>2]=Ol(a)|0;return d|0}function rn(b){b=b|0;return a[b+24>>0]&1|0}function sn(a){a=a|0;return (rn(a)|0)==0|0}function tn(a){a=a|0;return (d[a+24>>0]|0)>>>1&1|0}function un(a,b){a=a|0;b=b|0;return a|0}function vn(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;if(!d){f=1328;d=c[f>>2]|0;f=c[f+4>>2]|0;c[e>>2]=d;c[e+4>>2]=f;f=IN(d|0,f|0,2,0)|0;e=1328;c[e>>2]=f;c[e+4>>2]=z}else{if(!f)a=Zo(a,d)|0;else a=ap(a,d)|0;c[e>>2]=a;c[e+4>>2]=0}return 1}function wn(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return 0}function xn(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if((c&1|0)==0&0==0)cp(a,c)|0;return}function yn(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return ((c&1|0)==0&0==0?c:0)|0}function zn(a){a=a|0;return}function An(a,b,c){a=a|0;b=b|0;c=c|0;return}function Bn(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0;i=(e|0)!=0;do if(i){if((a[e>>0]|0)!=37?(h=c[b+64>>2]|0,h=db[c[(c[h+4>>2]|0)+4>>2]&3](c[h+16>>2]|0,d,e,f,g)|0,h|0):0)break;h=Gn(b,d,e,f)|0;if(!h)j=5}else j=5;while(0);if((j|0)==5)if(g){h=c[b+64>>2]|0;h=db[c[(c[h+4>>2]|0)+4>>2]&3](c[h+16>>2]|0,d,0,f,g)|0;if(i&(h|0)!=0){j=f;Hn(b,d,e,c[j>>2]|0,c[j+4>>2]|0)}}else h=0;return h|0}function Cn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=c[a+64>>2]|0;return cb[c[(c[a+4>>2]|0)+8>>2]&31](c[a+16>>2]|0,b,d,e)|0}function Dn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;Mn(a,b,d,e)|0;a=c[a+64>>2]|0;kb[c[(c[a+4>>2]|0)+12>>2]&31](c[a+16>>2]|0,b,d,e);return}function En(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;g=h;d=so(a)|0;f=a+8|0;b=f;b=Kn(d,c[a>>2]&3,c[b>>2]|0,c[b+4>>2]|0)|0;do if(!b){b=c[d+64>>2]|0;d=c[(c[b+4>>2]|0)+16>>2]|0;if(d|0?(e=f,e=cb[d&31](c[b+16>>2]|0,c[a>>2]&3,c[e>>2]|0,c[e+4>>2]|0)|0,e|0):0){b=e;break}if((c[a>>2]&3|0)==2)b=0;else{e=c[f>>2]|0;f=c[f+4>>2]|0;c[g>>2]=37;b=g+8|0;c[b>>2]=e;c[b+4>>2]=f;qL(173899,81419,g)|0;b=173899}}while(0);l=h;return b|0}function Fn(a,b,d){a=a|0;b=b|0;d=d|0;a=c[a+64>>2]|0;ib[c[(c[a+4>>2]|0)+24>>2]&127](c[a+16>>2]|0,b,d);return}function Gn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;i=l;l=l+32|0;h=i;b=c[(c[a+64>>2]|0)+56+(((b|0)==3?2:b)<<2)>>2]|0;if(((b|0)!=0?(f=Zo(a,d)|0,(f|0)!=0):0)?(c[h+24>>2]=f,g=bb[c[b>>2]&31](b,h,4)|0,(g|0)!=0):0){d=g+16|0;h=c[d+4>>2]|0;b=e;c[b>>2]=c[d>>2];c[b+4>>2]=h;b=1}else b=0;l=i;return b|0}function Hn(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;h=Zn(a,32)|0;g=h+16|0;c[g>>2]=e;c[g+4>>2]=f;c[h+24>>2]=ap(a,d)|0;e=(b|0)==3?2:b;g=a+64|0;d=c[g>>2]|0;b=c[d+56+(e<<2)>>2]|0;if(!b){f=Qp(a,17696,c[4353]|0)|0;c[(c[g>>2]|0)+56+(e<<2)>>2]=f;b=c[g>>2]|0}else{f=b;b=d}b=c[b+68+(e<<2)>>2]|0;if(!b){b=Qp(a,17732,c[4353]|0)|0;c[(c[g>>2]|0)+68+(e<<2)>>2]=b}bb[c[f>>2]&31](f,h,1)|0;bb[c[b>>2]&31](b,h,1)|0;return}function In(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=b+16|0;b=c[a>>2]|0;a=c[a+4>>2]|0;d=d+16|0;e=c[d>>2]|0;d=c[d+4>>2]|0;return (a>>>0>d>>>0|(a|0)==(d|0)&b>>>0>e>>>0?1:(a>>>0>>0|(a|0)==(d|0)&b>>>0>>0)<<31>>31)|0}function Jn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;b=c[b+24>>2]|0;e=c[d+24>>2]|0;return (b>>>0>e>>>0?1:(b>>>0>>0)<<31>>31)|0}function Kn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=Ln(a,b,d,e)|0;if(!a)a=0;else a=c[a+24>>2]|0;return a|0}function Ln(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;g=l;l=l+32|0;f=g;a=c[(c[a+64>>2]|0)+68+(((b|0)==3?2:b)<<2)>>2]|0;if(!a)a=0;else{b=f+16|0;c[b>>2]=d;c[b+4>>2]=e;a=bb[c[a>>2]&31](a,f,4)|0}l=g;return a|0}function Mn(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=(b|0)==3?2:b;b=Ln(a,f,d,e)|0;if(!b)b=0;else{e=a+64|0;d=c[(c[e>>2]|0)+56+(f<<2)>>2]|0;bb[c[d>>2]&31](d,b,2)|0;e=c[(c[e>>2]|0)+68+(f<<2)>>2]|0;bb[c[e>>2]&31](e,b,2)|0;cp(a,c[b+24>>2]|0)|0;_n(a,b);b=1}return b|0}function Nn(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;c[41987]=b;g=c[b+64>>2]|0;f=0;while(1){if((f|0)==3)break;h=g+56+(f<<2)|0;d=c[h>>2]|0;a:do if(d|0){d=bb[c[d>>2]&31](d,0,128)|0;while(1){if(!d)break a;e=c[h>>2]|0;e=bb[c[e>>2]&31](e,d,8)|0;if((a[c[d+24>>2]>>0]|0)!=37){d=e;continue}i=d+16|0;Mn(b,f,c[i>>2]|0,c[i+4>>2]|0)|0;d=e}}while(0);f=f+1|0}return}function On(a){a=a|0;c[41987]=a;a=a+64|0;Pn((c[a>>2]|0)+56|0);Pn((c[a>>2]|0)+68|0);return}function Pn(a){a=a|0;var b=0,d=0,e=0;b=0;while(1){if((b|0)==3)break;d=a+(b<<2)|0;e=c[d>>2]|0;if(e|0){Ll(e)|0;c[d>>2]=0}b=b+1|0}return}function Qn(a,b,c){a=a|0;b=b|0;c=c|0;if(!(hL(b,c,a)|0))a=0;else a=sJ(b)|0;return a|0}function Rn(a,b){a=a|0;b=b|0;return XL(b,a)|0}function Sn(a){a=a|0;return QL(a)|0}function Tn(a){a=a|0;var b=0,d=0,e=0;b=l;l=l+32|0;e=b+12|0;d=b;c[4446]=c[4443];c[4447]=c[4444];c[e>>2]=a;c[e+4>>2]=sJ(a)|0;c[e+8>>2]=0;c[d>>2]=17792;c[d+4>>2]=17668;c[d+8>>2]=17780;a=fr(e,d)|0;gp(0);l=b;return a|0}function Un(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;if((e|0)!=0?(h=b+8|0,f=c[h>>2]|0,(f|0)<(c[b+4>>2]|0)):0){i=(c[b>>2]|0)+f|0;b=0;g=a[i>>0]|0;f=d;d=i;while(1){d=d+1|0;a[f>>0]=g;b=b+1|0;if(!(g<<24>>24!=10&(b|0)<(e|0)))break;g=a[d>>0]|0;if(!(g<<24>>24))break;else f=f+1|0}c[h>>2]=(c[h>>2]|0)+b}else b=0;return b|0}function Vn(a){a=a|0;return 0}function Wn(a,b){a=a|0;b=b|0;a=_I(b)|0;WN(a|0,0,b|0)|0;return a|0}function Xn(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;a=bJ(b,d)|0;if(d>>>0>c>>>0)WN(a+c|0,0,d-c|0)|0;return a|0}function Yn(a,b){a=a|0;b=b|0;$I(b);return}function Zn(a,b){a=a|0;b=b|0;var d=0;d=l;l=l+16|0;a=c[a+64>>2]|0;a=ab[c[(c[a>>2]|0)+4>>2]&63](c[a+12>>2]|0,b)|0;if(!a)$l(1,81425,d)|0;l=d;return a|0}function _n(a,b){a=a|0;b=b|0;if(b|0){a=c[a+64>>2]|0;hb[c[(c[a>>2]|0)+12>>2]&31](c[a+12>>2]|0,b)}return}function $n(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=(c[b+16>>2]|0)+8|0;b=c[a>>2]|0;a=c[a+4>>2]|0;d=(c[d+16>>2]|0)+8|0;e=c[d>>2]|0;d=c[d+4>>2]|0;return (a>>>0>>0|(a|0)==(d|0)&b>>>0>>0?-1:(a>>>0>d>>>0|(a|0)==(d|0)&b>>>0>e>>>0)&1)|0}function ao(a,b,d){a=a|0;b=b|0;d=d|0;a=c[b+16>>2]|0;if((a+28|0)!=(b|0))_n(c[a+24>>2]|0,b);return}function bo(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;b=(c[c[b+16>>2]>>2]|0)>>>4;e=(c[c[d+16>>2]>>2]|0)>>>4;return (b>>>0>>0?-1:b>>>0>e>>>0&1)|0}function co(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=167040;c[e>>2]=b;c[e+4>>2]=d;c[41992]=167032;a=c[a+40>>2]|0;a=bb[c[a>>2]&31](a,167952,4)|0;if(!a)a=0;else a=c[a+16>>2]|0;return a|0}function eo(a){a=a|0;a=c[a+36>>2]|0;a=bb[c[a>>2]&31](a,0,128)|0;if(!a)a=0;else a=c[a+16>>2]|0;return a|0}function fo(a,b){a=a|0;b=b|0;var d=0;b=Rm(a,b)|0;if((b|0)!=0?(d=c[a+36>>2]|0,d=bb[c[d>>2]&31](d,b,8)|0,(d|0)!=0):0)b=c[d+16>>2]|0;else b=0;return b|0}function go(a){a=a|0;a=c[a+36>>2]|0;a=bb[c[a>>2]&31](a,0,256)|0;if(!a)a=0;else a=c[a+16>>2]|0;return a|0}function ho(a,b){a=a|0;b=b|0;var d=0;b=Rm(a,b)|0;if((b|0)!=0?(d=c[a+36>>2]|0,d=bb[c[d>>2]&31](d,b,16)|0,(d|0)!=0):0)b=c[d+16>>2]|0;else b=0;return b|0}function io(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=co(a,b,c)|0;do if((d|0)!=0&(e|0)==0){e=to(a)|0;if((e|0)!=(a|0)?(f=co(e,b,c)|0,f|0):0){jo(a,f,1)|0;e=f;break}if(!(Cn(a,1,b,c)|0))e=0;else{e=ln(a,1)|0;e=ko(a,b,c,e,z)|0;lo(a,e);mo(a,e)}}while(0);return e|0}function jo(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=to(a)|0;if((e|0)==(c[b+24>>2]|0)){e=b+8|0;e=co(a,c[e>>2]|0,c[e+4>>2]|0)|0;if((d|0)!=0&(e|0)==0){e=Mp(a)|0;if(!e)e=0;else{d=jo(e,b,d)|0;no(a,d);return d|0}}}else e=0;return e|0}function ko(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0;g=Zn(b,64)|0;h=c[g>>2]|0;i=g+8|0;c[i>>2]=d;c[i+4>>2]=e;c[g>>2]=h&12|f<<4|1;c[g+24>>2]=to(b)|0;if(a[(to(b)|0)+24>>0]&64)Oo(g,81367,16,0)|0;return g|0}function lo(a,b){a=a|0;b=b|0;do{no(a,b);a=Mp(a)|0}while((a|0)!=0);return}function mo(b,c){b=b|0;c=c|0;if(a[(to(b)|0)+24>>0]&64)nm(b,c);uo(b,c);return}function no(a,b){a=a|0;b=b|0;var d=0,e=0;e=a+40|0;Tl(c[e>>2]|0)|0;if((to(a)|0)==(a|0))d=b+28|0;else d=Zn(a,36)|0;c[d+16>>2]=b;e=c[e>>2]|0;bb[c[e>>2]&31](e,d,1)|0;e=c[a+36>>2]|0;bb[c[e>>2]&31](e,d,1)|0;return}function oo(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0;j=l;l=l+16|0;g=j;h=to(a)|0;if(Bn(a,1,b,g,0)|0){e=g;e=co(a,c[e>>2]|0,c[e+4>>2]|0)|0;if(!e)if(!((d|0)==0|(h|0)==(a|0))?(f=g,f=co(h,c[f>>2]|0,c[f+4>>2]|0)|0,(f|0)!=0):0)e=jo(a,f,1)|0;else i=6}else i=6;if((i|0)==6)if((d|0)!=0?(Bn(a,1,b,g,1)|0)!=0:0){i=g;h=c[i>>2]|0;i=c[i+4>>2]|0;e=ln(a,1)|0;e=ko(a,h,i,e,z)|0;lo(a,e);mo(a,e);Fn(a,1,e)}else e=0;l=j;return e|0}function po(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;c[42001]=b;d=Vm(a,b)|0;while(1){if(!d)break;e=Wm(a,d,b)|0;cn(a,d,0);d=e}e=c[a+40>>2]|0;bb[c[e>>2]&31](e,167988,2)|0;e=c[a+36>>2]|0;bb[c[e>>2]&31](e,167988,2)|0;return}function qo(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;f=d+8|0;e=f;if(co(b,c[e>>2]|0,c[e+4>>2]|0)|0){if((to(b)|0)==(b|0)){e=Vm(b,d)|0;while(1){if(!e)break;g=Wm(b,e,d)|0;en(b,e)|0;e=g}if(a[b+24>>0]&64)Hm(d);yo(b,d);Wo(d);g=f;Dn(b,1,c[g>>2]|0,c[g+4>>2]|0)}if(!(xq(b,d,54,0,0)|0))if((to(b)|0)==(b|0)){_n(b,d);e=0}else e=0;else e=-1}else e=-1;return e|0}function ro(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0;h=l;l=l+16|0;e=h;d=c[b>>2]|0;do if(!(d&3))if((Mp(b)|0)==(a|0)){d=c[b>>2]|0;g=5;break}else{$l(1,81451,e)|0;f=-1;break}else g=5;while(0);a:do if((g|0)==5)switch(d&3){case 1:{f=qo(a,b)|0;break a}case 2:case 3:{f=en(a,b)|0;break a}case 0:{f=mn(b)|0;break a}default:{}}while(0);l=h;return f|0}function so(a){a=a|0;var b=0;switch(c[a>>2]&3){case 2:case 3:{b=c[(c[a+40>>2]|0)+24>>2]|0;break}case 1:{b=c[a+24>>2]|0;break}case 0:{b=a;break}default:{}}return b|0}function to(a){a=a|0;var b=0;switch(c[a>>2]&3){case 2:case 3:{b=(c[a+40>>2]|0)+24|0;break}case 1:{b=a+24|0;break}case 0:{b=a+60|0;break}default:{}}return c[b>>2]|0}function uo(b,d){b=b|0;d=d|0;var e=0;e=c[b+64>>2]|0;if(!(a[e+52>>0]|0))Eo(b,d,100,0);else vo(b,d,c[e+48>>2]|0);return}function vo(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;a:do if(d|0){vo(a,b,c[d+8>>2]|0);switch(c[b>>2]&3){case 0:{e=c[d>>2]|0;break}case 1:{e=(c[d>>2]|0)+12|0;break}case 2:{e=(c[d>>2]|0)+24|0;break}default:break a}e=c[e>>2]|0;if(e|0)ib[e&127](a,b,c[d+4>>2]|0)}while(0);return}function wo(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;f=c[b+64>>2]|0;if(!(a[f+52>>0]|0))Eo(b,d,101,e);else xo(b,d,e,c[f+48>>2]|0);return}function xo(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;a:do if(e|0){xo(a,b,d,c[e+8>>2]|0);switch(c[b>>2]&3){case 0:{f=(c[e>>2]|0)+4|0;break}case 1:{f=(c[e>>2]|0)+16|0;break}case 2:{f=(c[e>>2]|0)+28|0;break}default:break a}f=c[f>>2]|0;if(f|0)kb[f&31](a,b,c[e+4>>2]|0,d)}while(0);return}function yo(b,d){b=b|0;d=d|0;var e=0;e=c[b+64>>2]|0;if(!(a[e+52>>0]|0))Eo(b,d,102,0);else zo(b,d,c[e+48>>2]|0);return}function zo(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;a:do if(d|0){zo(a,b,c[d+8>>2]|0);switch(c[b>>2]&3){case 0:{e=(c[d>>2]|0)+8|0;break}case 1:{e=(c[d>>2]|0)+20|0;break}case 2:{e=(c[d>>2]|0)+32|0;break}default:break a}e=c[e>>2]|0;if(e|0)ib[e&127](a,b,c[d+4>>2]|0)}while(0);return}function Ao(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=Zn(a,12)|0;c[e>>2]=b;c[e+4>>2]=d;d=(c[a+64>>2]|0)+48|0;c[e+8>>2]=c[d>>2];c[d>>2]=e;return}function Bo(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;e=(c[a+64>>2]|0)+48|0;d=c[e>>2]|0;a:do if(!d)d=-1;else{if((c[d>>2]|0)!=(b|0)){while(1){if(!d){d=-1;break a}e=d+8|0;f=c[e>>2]|0;if((c[f>>2]|0)==(b|0))break;else d=f}if(f)c[e>>2]=c[f+8>>2]}else c[e>>2]=c[d+8>>2];_n(a,d);d=0}while(0);return d|0}function Co(a,b){a=a|0;b=b|0;var d=0;d=to(a)|0;a:do if((d|0)==(to(b)|0))switch(c[b>>2]&3){case 0:{while(1){if((b|0)==(a|0)){b=1;break a}b=Mp(b)|0;if(!b){b=0;break}}break}case 1:{b=b+8|0;b=(io(a,c[b>>2]|0,c[b+4>>2]|0,0)|0)!=0;break a}default:{b=(fn(a,b,0)|0)!=0;break a}}else b=0;while(0);return b&1|0}function Do(a){a=a|0;return c[a>>2]&3|0}function Eo(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;h=l;l=l+16|0;g=h;f=Oo(a,81475,44,0)|0;switch(c|0){case 100:{e=Fo(f,b,100)|0;if(!(Go(e,b)|0))Ho(e,a,b,d)|0;break}case 101:{if(((Go(Fo(f,b,100)|0,b)|0)==0?(Go(Fo(f,b,102)|0,b)|0)==0:0)?(e=Fo(f,b,101)|0,(Go(e,b)|0)==0):0)Ho(e,a,b,d)|0;break}case 102:{Io(Fo(f,b,100)|0,b);Io(Fo(f,b,101)|0,b);e=Fo(f,b,102)|0;if(!(Go(e,b)|0))Ho(e,a,b,d)|0;break}default:$l(1,81487,g)|0}l=h;return}function Fo(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;g=l;l=l+16|0;e=g;a:do switch(c[b>>2]&3){case 0:switch(d|0){case 100:{d=a+8|0;break a}case 101:{d=a+20|0;break a}case 102:{d=a+32|0;break a}default:{f=14;break a}}case 1:switch(d|0){case 100:{d=a+12|0;break a}case 101:{d=a+24|0;break a}case 102:{d=a+36|0;break a}default:{f=14;break a}}case 2:switch(d|0){case 100:{d=a+16|0;break a}case 101:{d=a+28|0;break a}case 102:{d=a+40|0;break a}default:{f=14;break a}}default:f=14}while(0);if((f|0)==14){$l(1,81521,e)|0;d=0}a=c[d>>2]|0;if(!a){a=so(b)|0;a=Qp(a,17884,c[4353]|0)|0;c[d>>2]=a}l=g;return a|0}function Go(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=l;l=l+32|0;e=d;f=Jo(b)|0;b=e+8|0;c[b>>2]=f;c[b+4>>2]=z;b=bb[c[a>>2]&31](a,e,4)|0;l=d;return b|0}function Ho(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=Zn(so(d)|0,32)|0;c[f+20>>2]=d;g=Jo(d)|0;d=f+8|0;c[d>>2]=g;c[d+4>>2]=z;c[f+16>>2]=b;if(e|0){g=Zn(b,8)|0;c[f+24>>2]=g;c[g>>2]=e}bb[c[a>>2]&31](a,f,1)|0;return f|0}function Io(a,b){a=a|0;b=b|0;b=Go(a,b)|0;if(b|0)bb[c[a>>2]&31](a,b,2)|0;return}function Jo(a){a=a|0;a=a+8|0;z=c[a+4>>2]|0;return c[a>>2]|0}function Ko(a,b,d){a=a|0;b=b|0;d=d|0;Lo(b);_n(c[b+16>>2]|0,b);return}function Lo(a){a=a|0;var b=0,d=0;b=a+16|0;a=c[a+24>>2]|0;while(1){if(!a)break;d=c[a+4>>2]|0;_n(c[b>>2]|0,a);a=d}return}function Mo(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;i=k;h=c[b+16>>2]|0;f=h;while(1){if(!f){f=0;break}g=c[f>>2]|0;if((g|0)==(d|0)){j=7;break}if((a[d>>0]|0)==(a[g>>0]|0)?(yJ(d,g)|0)==0:0){j=7;break}f=c[f+4>>2]|0;if((f|0)==(h|0)){f=0;break}}do if((j|0)==7){if(!(c[b>>2]&4)){if((f|0)==(h|0)&(e|0)==0){f=h;break}No(b,f,e);break}if(e)if((h|0)==(f|0))f=h;else $l(1,81546,i)|0}while(0);l=k;return f|0}function No(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;c[a+16>>2]=b;e=c[a>>2]|0;d=d<<2&4;c[a>>2]=e&-5|d;if(e&2|0){e=(e&3|0)==3?-1:1;c[a+(e*48|0)+16>>2]=b;e=a+(e*48|0)|0;c[e>>2]=c[e>>2]&-5|d}return}function Oo(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;h=so(a)|0;f=Mo(a,b,0)|0;a:do if((d|0)!=0&(f|0)==0){d=Zn(h,d)|0;c[d>>2]=ap(h,b)|0;switch(c[a>>2]&3){case 0:{Po(a,d);g=d;break a}case 1:{Po(a,d);g=d;break a}case 2:case 3:{Po(a,d);g=d;break a}default:{}}}else g=f;while(0);if(e|0)Mo(a,b,1)|0;return g|0}function Po(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=c[a+16>>2]|0;do if(d){e=d+4|0;f=c[e>>2]|0;if((f|0)==(d|0)){c[e>>2]=b;e=d;d=b;break}else{c[b+4>>2]=f;e=b;break}}else{e=b;d=b}while(0);c[d+4>>2]=e;if(!(c[a>>2]&4))No(a,b,0);return}function Qo(a,b){a=a|0;b=b|0;var d=0,e=0;e=so(a)|0;d=Mo(a,b,0)|0;if(!d)b=-1;else{Ro(a,d);if(!(c[a>>2]&3)){So(e,a,d);b=d}else{xq(to(e)|0,a,55,d,0)|0;b=d}cp(e,c[d>>2]|0)|0;_n(e,b);b=0}return b|0}function Ro(a,b){a=a|0;b=b|0;var d=0;a=c[a+16>>2]|0;do{d=a+4|0;a=c[d>>2]|0}while((a|0)!=(b|0));c[d>>2]=c[b+4>>2];return}function So(a,b,d){a=a|0;b=b|0;d=d|0;if((c[b+16>>2]|0)==(d|0)){a=c[d+4>>2]|0;No(b,(a|0)==(d|0)?0:a,0)}return}function To(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;f=(d|0)>-1;g=f?d:0-d|0;a:do switch(b|0){case 0:{Oo(a,c,g,e)|0;if(!f){b=Kp(a)|0;while(1){if(!b)break a;To(b,0,c,d,e);b=Lp(b)|0}}break}case 3:case 2:case 1:{d=(b|0)==1;b=eo(a)|0;while(1){if(!b)break a;b:do if(d)Oo(b,c,g,e)|0;else{f=Qm(a,b)|0;while(1){if(!f)break b;Oo(f,c,g,e)|0;f=Sm(a,f)|0}}while(0);b=fo(a,b)|0}}default:{}}while(0);return}function Uo(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;a:do switch(b|0){case 0:{xq(a,a,56,c,1)|0;break}case 3:case 2:case 1:{e=(b|0)==1;d=eo(a)|0;while(1){if(!d)break a;b:do if(e)Qo(d,c)|0;else{b=Qm(a,d)|0;while(1){if(!b)break b;Qo(b,c)|0;b=Sm(a,b)|0}}while(0);d=fo(a,d)|0}}default:{}}while(0);return}function Vo(a,b,c){a=a|0;b=b|0;c=c|0;Qo(b,c)|0;return}function Wo(a){a=a|0;var b=0,d=0,e=0;d=so(a)|0;b=a+16|0;a=c[b>>2]|0;if(a|0)do{e=a;a=c[a+4>>2]|0;cp(d,c[e>>2]|0)|0;_n(d,e)}while((a|0)!=(c[b>>2]|0));c[b>>2]=0;return}function Xo(a){a=a|0;return Sp(a,Yo(a)|0)|0}function Yo(a){a=a|0;var b=0,d=0;if(!a)d=168024;else d=(c[a+64>>2]|0)+20|0;b=c[d>>2]|0;if(!b){b=Qp(a,17920,c[4353]|0)|0;c[d>>2]=b;a=167096;c[a>>2]=-2147483648;c[a+4>>2]=0;a=167104;c[a>>2]=2147483647;c[a+4>>2]=-1}return b|0}function Zo(a,b){a=a|0;b=b|0;return _o(Yo(a)|0,b)|0}function _o(a,b){a=a|0;b=b|0;a=$o(a,b)|0;if(!a)a=0;else a=c[a+16>>2]|0;return a|0}function $o(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+32|0;e=d;c[e+16>>2]=b;b=bb[c[a>>2]&31](a,e,4)|0;l=d;return b|0}function ap(a,b){a=a|0;b=b|0;var d=0,e=0;if(!b)d=0;else{e=Yo(a)|0;d=$o(e,b)|0;if(!d){d=(sJ(b)|0)+24|0;if(!a)d=_I(d)|0;else d=Zn(a,d)|0;a=d+8|0;c[a>>2]=1;c[a+4>>2]=0;a=d+20|0;yK(a,b)|0;c[d+16>>2]=a;bb[c[e>>2]&31](e,d,1)|0}else{e=d+8|0;b=e;b=IN(c[b>>2]|0,c[b+4>>2]|0,1,0)|0;c[e>>2]=b;c[e+4>>2]=z}d=c[d+16>>2]|0}return d|0}function bp(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if(!b)d=0;else{e=Yo(a)|0;d=$o(e,b)|0;if(!d){d=(sJ(b)|0)+24|0;if(!a)d=_I(d)|0;else d=Zn(a,d)|0;g=167096;f=c[g+4>>2]|0;a=d+8|0;c[a>>2]=c[g>>2]|1;c[a+4>>2]=f;a=d+20|0;yK(a,b)|0;c[d+16>>2]=a;bb[c[e>>2]&31](e,d,1)|0}else{g=d+8|0;f=g;f=IN(c[f>>2]|0,c[f+4>>2]|0,1,0)|0;c[g>>2]=f;c[g+4>>2]=z}d=c[d+16>>2]|0}return d|0}function cp(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;if((b|0)!=0?(d=Yo(a)|0,e=$o(d,b)|0,(e|0)!=0):0)if((c[e+16>>2]|0)==(b|0)?(b=e+8|0,g=b,g=IN(c[g>>2]|0,c[g+4>>2]|0,-1,-1)|0,f=z,b,c[b>>2]=g,c[b+4>>2]=f,b=167104,(g|0)==0&(f|0)==0|(c[b>>2]|0)==0&(c[b+4>>2]|0)==0):0){Rp(a,d,e)|0;a=0}else a=0;else a=-1;return a|0}function dp(a){a=a|0;var b=0;if(!a)a=0;else{a=a+-12|0;b=167096;a=c[b>>2]&c[a>>2]}return a|0}function ep(a){a=a|0;var b=0,d=0,e=0;if(a|0){d=167096;a=a+-12|0;e=a;b=c[e+4>>2]|c[d+4>>2];c[a>>2]=c[e>>2]|c[d>>2];c[a+4>>2]=b}return}function fp(a){a=a|0;c[4489]=a;return}function gp(a){a=a|0;c[42011]=a;c[4489]=1;return}function hp(a,b){a=a|0;b=b|0;c[42012]=a;c[42013]=b;c[42014]=0;return}function ip(){var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;if(!(c[42015]|0)){c[42015]=1;if(!(c[42016]|0))c[42016]=1;if(!(c[42007]|0))c[42007]=c[13853];if(!(c[42008]|0))c[42008]=c[13885];k=c[42017]|0;if(!((k|0)!=0?(c[k>>2]|0)!=0:0)){jp();k=kp(c[42007]|0,16384)|0;c[c[42017]>>2]=k}lp()}a:while(1){j=c[42018]|0;a[j>>0]=a[173931]|0;e=(c[(c[c[42017]>>2]|0)+28>>2]|0)+(c[42016]|0)|0;f=j;b:while(1){h=f;while(1){f=c[17960+(d[h>>0]<<2)>>2]|0;if(b[56680+(e<<1)>>1]|0){c[42019]=e;c[42020]=h}c:while(1){g=f&255;do{f=g+(b[56866+(e<<1)>>1]|0)|0;if((e|0)==(b[57076+(f<<1)>>1]|0))break c;k=b[57612+(e<<1)>>1]|0;e=k<<16>>16}while(k<<16>>16<=92);f=c[18984+(g<<2)>>2]|0}e=b[57822+(f<<1)>>1]|0;f=h+1|0;if((b[56866+(e<<1)>>1]|0)==219)break;else h=f}d:while(1){k=j;e:while(1){e=b[56680+(e<<1)>>1]|0;if(!(e<<16>>16)){e=b[56680+(c[42019]<<1)>>1]|0;f=c[42020]|0}else e=e<<16>>16;c[42009]=j;i=f;c[42010]=i-k;a[173931]=a[f>>0]|0;a[f>>0]=0;c[42018]=f;f:while(1){switch(e|0){case 1:{m=27;break a}case 12:{m=53;break a}case 13:{m=55;break a}case 14:{m=57;break a}case 15:{m=61;break a}case 16:{m=65;break a}case 17:{m=67;break a}case 18:{m=69;break a}case 19:{m=72;break a}case 20:{m=75;break a}case 21:{m=78;break a}case 23:{m=86;break a}case 33:{m=118;break a}case 39:case 38:case 37:case 36:{l=0;break a}case 2:{m=29;break b}case 3:{m=32;break b}case 4:{m=35;break b}case 5:{m=37;break b}case 6:{m=39;break b}case 7:{m=42;break b}case 8:{m=44;break b}case 9:{m=47;break b}case 10:{m=49;break b}case 11:{m=51;break b}case 22:{m=83;break b}case 24:{m=89;break b}case 25:{m=92;break b}case 26:{m=95;break b}case 27:{m=98;break b}case 28:{m=101;break b}case 29:{m=104;break b}case 30:{m=109;break b}case 31:{m=112;break b}case 32:{m=115;break b}case 34:{m=121;break b}case 0:break f;case 35:break;default:{m=134;break a}}h=c[42009]|0;a[f>>0]=a[173931]|0;e=c[42017]|0;g=c[e>>2]|0;if(!(c[g+44>>2]|0)){n=c[g+16>>2]|0;c[42022]=n;c[g>>2]=c[42007];g=c[e>>2]|0;c[g+44>>2]=1;e=n}else e=c[42022]|0;if((c[42018]|0)>>>0<=((c[g+4>>2]|0)+e|0)>>>0){m=128;break e}switch(up()|0){case 0:{m=132;break d}case 2:{m=133;break e}case 1:break;default:continue a}c[42018]=c[42009];e=(((c[42016]|0)+-1|0)/2|0)+36|0}a[f>>0]=a[173931]|0;f=c[42020]|0;e=c[42019]|0}if((m|0)==128){m=0;g=i-h|0;h=c[42009]|0;f=h+(g+-1)|0;c[42018]=f;e=sp()|0;i=tp(e)|0;j=c[42009]|0;if(!i)continue;else{m=129;break}}else if((m|0)==133){m=0;f=(c[(c[c[42017]>>2]|0)+4>>2]|0)+(c[42022]|0)|0;c[42018]=f;e=sp()|0;j=c[42009]|0;continue}}if((m|0)==129){m=0;f=h+g|0;c[42018]=f;e=i;continue}else if((m|0)==132){m=0;f=(c[42009]|0)+(i-h+-1)|0;c[42018]=f;e=sp()|0;j=c[42009]|0;continue}}switch(m|0){case 29:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;c[4489]=(c[4489]|0)+1;continue a}case 32:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;c[42016]=3;continue a}case 35:{m=0;e=c[42010]|0;if(!e)continue a;c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;continue a}case 37:{m=0;e=c[42010]|0;if(!e)continue a;c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;continue a}case 39:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;c[42016]=1;continue a}case 42:{m=0;e=c[42010]|0;if(!e)continue a;c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;continue a}case 44:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;mp();continue a}case 47:{m=0;e=c[42010]|0;if(!e)continue a;c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;continue a}case 49:{m=0;e=c[42010]|0;if(!e)continue a;c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;continue a}case 51:{m=0;e=c[42010]|0;if(!e)continue a;c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;continue a}case 83:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;c[42016]=5;op();continue a}case 89:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;qp(83714);continue a}case 92:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;qp(81579);continue a}case 95:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;c[4489]=(c[4489]|0)+1;continue a}case 98:{m=0;f=c[42010]|0;e=c[42009]|0;if(f|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[e+(f+-1)>>0]|0)==10&1;qp(e);continue a}case 101:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;c[42016]=7;c[42021]=1;op();continue a}case 104:{m=0;e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;n=(c[42021]|0)+-1|0;c[42021]=n;if(!n){m=108;break a}qp(c[42009]|0);continue a}case 109:{m=0;f=c[42010]|0;e=c[42009]|0;if(f|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[e+(f+-1)>>0]|0)==10&1;c[42021]=(c[42021]|0)+1;qp(e);continue a}case 112:{m=0;f=c[42010]|0;e=c[42009]|0;if(f|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[e+(f+-1)>>0]|0)==10&1;qp(e);c[4489]=(c[4489]|0)+1;continue a}case 115:{m=0;f=c[42010]|0;e=c[42009]|0;if(f|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[e+(f+-1)>>0]|0)==10&1;qp(e);continue a}case 121:{m=0;f=c[42010]|0;e=c[42009]|0;if(f|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[e+(f+-1)>>0]|0)==10&1;YL(e,f,1,c[42008]|0)|0;continue a}}}switch(m|0){case 27:{e=c[42010]|0;if(!e)l=-1;else{c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;l=-1}break}case 53:{e=c[42010]|0;if(!e)l=259;else{c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;l=259}break}case 55:{e=c[42010]|0;if(!e)l=260;else{c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;l=260}break}case 57:{e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;if(!(c[42014]|0)){c[42014]=258;l=258}else l=258;break}case 61:{e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;if(!(c[42014]|0)){c[42014]=261;l=261}else l=261;break}case 65:{e=c[42010]|0;if(!e)l=263;else{c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;l=263}break}case 67:{e=c[42010]|0;if(!e)l=262;else{c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;l=262}break}case 69:{e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;l=(c[42014]|0)==261?264:45;break}case 72:{e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;l=(c[42014]|0)==258?264:45;break}case 75:{f=c[42010]|0;e=c[42009]|0;if(f|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[e+(f+-1)>>0]|0)==10&1;c[42037]=ap(c[41987]|0,e)|0;l=267;break}case 78:{e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;if(np()|0){m=(c[42010]|0)+-1|0;a[f>>0]=a[173931]|0;n=j+m|0;c[42018]=n;c[42009]=j;c[42010]=m;a[173931]=a[n>>0]|0;a[n>>0]=0;c[42018]=n}c[42037]=ap(c[41987]|0,c[42009]|0)|0;l=267;break}case 86:{e=c[42010]|0;if(e|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[(c[42009]|0)+(e+-1)>>0]|0)==10&1;c[42016]=1;pp();l=268;break}case 108:{c[42016]=1;rp();l=268;break}case 118:{f=c[42010]|0;e=c[42009]|0;if(f|0)c[(c[c[42017]>>2]|0)+28>>2]=(a[e+(f+-1)>>0]|0)==10&1;l=a[e>>0]|0;break}case 134:{vp(81582);break}}return l|0}function jp(){var a=0,b=0,d=0;b=c[42017]|0;do if(!b){a=Cp(4)|0;c[42017]=a;if(!a)vp(81940);else{c[a>>2]=0;a=1;d=9;break}}else{a=c[42028]|0;if(0>=(a+-1|0)>>>0){a=a+8|0;b=wp(b,a<<2)|0;c[42017]=b;if(!b)vp(81940);else{d=b+(c[42028]<<2)|0;c[d>>2]=0;c[d+4>>2]=0;c[d+8>>2]=0;c[d+12>>2]=0;c[d+16>>2]=0;c[d+20>>2]=0;c[d+24>>2]=0;c[d+28>>2]=0;d=9;break}}}while(0);if((d|0)==9)c[42028]=a;return}function kp(a,b){a=a|0;b=b|0;var d=0;d=Cp(48)|0;if(!d)vp(81895);c[d+12>>2]=b;b=Cp(b+2|0)|0;c[d+4>>2]=b;if(!b)vp(81895);else{c[d+20>>2]=1;yp(d,a);return d|0}return 0}function lp(){var b=0,d=0;d=c[42017]|0;b=c[d>>2]|0;c[42022]=c[b+16>>2];b=c[b+8>>2]|0;c[42018]=b;c[42009]=b;c[42007]=c[c[d>>2]>>2];a[173931]=a[b>>0]|0;return}function mp(){var b=0,d=0,e=0,f=0,g=0,h=0,i=0;g=l;l=l+32|0;f=g;d=g+16|0;e=g+12|0;h=c[42009]|0;b=h+1|0;i=(WJ(b,81879,4)|0)==0;b=i?h+5|0:b;c[f>>2]=e;c[f+4>>2]=g+20;c[f+8>>2]=d;f=dM(b,81884,f)|0;if((f|0)>0?(c[4489]=(c[e>>2]|0)+-1,(f|0)!=1):0){d=b+(c[d>>2]|0)|0;b=d;a:while(1){e=a[b>>0]|0;switch(e<<24>>24){case 0:case 34:break a;default:{}}b=b+1|0}if((b|0)!=(d|0)&e<<24>>24==34){a[b>>0]=0;Bp(d,b-d|0)}}l=g;return}function np(){var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;j=l;l=l+2080|0;i=j+8|0;f=j;b=j+1056|0;d=j+32|0;h=j+16|0;k=a[(c[42009]|0)+((c[42010]|0)+-1)>>0]|0;e=k<<24>>24==46;if(e|((k&255)+-48|0)>>>0<10)if(e?(Ap()|0)!=0:0)g=4;else b=0;else g=4;if((g|0)==4){k=c[42011]|0;dm(h,1024,b);gm(h,81790)|0;gm(h,c[42009]|0)|0;c[f>>2]=c[4489];qL(d,81834,f)|0;gm(h,d)|0;gm(h,(k|0)==0?81784:k)|0;gm(h,81851)|0;d=h+4|0;b=c[d>>2]|0;if(b>>>0>=(c[h+8>>2]|0)>>>0){em(h,1)|0;b=c[d>>2]|0}a[b>>0]=0;b=c[h>>2]|0;c[d>>2]=b;c[i>>2]=b;$l(0,81876,i)|0;hm(h);b=1}l=j;return b|0}function op(){var b=0;b=c[42023]|0;if(!b){b=_I(1024)|0;c[42023]=b;c[42025]=b+1024}c[42024]=b;a[b>>0]=0;return}function pp(){c[42037]=ap(c[41987]|0,c[42023]|0)|0;a[c[42023]>>0]=0;return}function qp(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;e=c[42024]|0;d=c[42023]|0;if(e>>>0>d>>>0){e=e+-1|0;f=3}a:while(1){if((f|0)==3)c[42024]=e;f=c[42025]|0;g=f;do{h=b;b=b+1|0;h=a[h>>0]|0;i=e;e=e+1|0;a[i>>0]=h;if(!(h<<24>>24))break a}while(e>>>0>>0);c[42024]=e;f=d;i=g-f<<1;d=bJ(d,i)|0;c[42023]=d;c[42025]=d+i;e=d+(e-f)|0;f=3}c[42024]=e;return}function rp(){c[42037]=bp(c[41987]|0,c[42023]|0)|0;a[c[42023]>>0]=0;return}function sp(){var d=0,e=0,f=0,g=0,h=0;h=c[42018]|0;g=c[42009]|0;e=(c[(c[c[42017]>>2]|0)+28>>2]|0)+(c[42016]|0)|0;while(1){if(g>>>0>=h>>>0)break;d=a[g>>0]|0;if(!(d<<24>>24))d=1;else d=c[17960+((d&255)<<2)>>2]|0;if(b[56680+(e<<1)>>1]|0){c[42019]=e;c[42020]=g}a:while(1){f=d&255;do{d=f+(b[56866+(e<<1)>>1]|0)|0;if((e|0)==(b[57076+(d<<1)>>1]|0))break a;d=b[57612+(e<<1)>>1]|0;e=d<<16>>16}while(d<<16>>16<=92);d=c[18984+(f<<2)>>2]|0}g=g+1|0;e=b[57822+(d<<1)>>1]|0}return e|0}function tp(a){a=a|0;var d=0;if(b[56680+(a<<1)>>1]|0){d=c[42018]|0;c[42019]=a;c[42020]=d}while(1){d=(b[56866+(a<<1)>>1]|0)+1|0;if((a|0)==(b[57076+(d<<1)>>1]|0))break;a=b[57612+(a<<1)>>1]|0}d=b[57822+(d<<1)>>1]|0;return (d<<16>>16==92?0:d<<16>>16)|0}function up(){var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;j=c[42017]|0;g=c[j>>2]|0;i=c[g+4>>2]|0;f=c[42009]|0;l=c[42018]|0;k=l;if(l>>>0>(i+((c[42022]|0)+1)|0)>>>0)vp(81637);h=k-f|0;if(!(c[g+40>>2]|0))b=(h|0)==1?1:2;else{l=h+-1|0;h=i;g=0;while(1){if((g|0)>=(l|0))break;a[h>>0]=a[f>>0]|0;h=h+1|0;f=f+1|0;g=g+1|0}f=c[j>>2]|0;do if((c[f+44>>2]|0)==2){c[42022]=0;c[f+16>>2]=0;e=f;m=17}else{while(1){i=f+12|0;h=c[i>>2]|0;g=h-l+-1|0;if(g|0){m=16;break}g=f+4|0;j=c[g>>2]|0;if(!(c[f+20>>2]|0)){m=12;break}f=h<<1;f=(f|0)==0?(h>>>3)+h|0:f;c[i>>2]=f;f=wp(j,f+2|0)|0;c[g>>2]=f;if(!f)break;j=f+(k-j)|0;c[42018]=j;f=c[c[42017]>>2]|0;k=j}if((m|0)==12)c[g>>2]=0;else if((m|0)==16){d=bb[c[c[(c[42012]|0)+8>>2]>>2]&31](c[42013]|0,(c[f+4>>2]|0)+l|0,g>>>0<8192?g:8192)|0;e=c[c[42017]>>2]|0;c[42022]=d;c[e+16>>2]=d;if(!d){m=17;break}else{b=0;break}}vp(81693)}while(0);do if((m|0)==17)if(!l){xp(c[42007]|0);b=1;d=c[42022]|0;e=c[c[42017]>>2]|0;break}else{c[e+44>>2]=2;b=2;d=0;break}while(0);f=d+l|0;do if(f>>>0>(c[e+12>>2]|0)>>>0){m=wp(c[e+4>>2]|0,f+(d>>>1)|0)|0;d=c[42017]|0;c[(c[d>>2]|0)+4>>2]=m;d=c[(c[d>>2]|0)+4>>2]|0;if(!d)vp(81737);else{n=c[42022]|0;o=d;break}}else{n=d;o=c[e+4>>2]|0}while(0);n=n+l|0;c[42022]=n;a[o+n>>0]=0;o=c[42017]|0;a[(c[(c[o>>2]|0)+4>>2]|0)+((c[42022]|0)+1)>>0]=0;c[42009]=c[(c[o>>2]|0)+4>>2]}return b|0}function vp(a){a=a|0;var b=0,d=0;b=l;l=l+16|0;d=c[13918]|0;c[b>>2]=a;AL(d,81633,b)|0;Ma(2)}function wp(a,b){a=a|0;b=b|0;return bJ(a,b)|0}function xp(a){a=a|0;var b=0,d=0,e=0;d=c[42017]|0;if((d|0)!=0?(b=c[d>>2]|0,(b|0)!=0):0)e=4;else{jp();b=kp(c[42007]|0,16384)|0;d=c[42017]|0;c[d>>2]=b;if(!d)b=0;else e=4}yp(b,a);lp();return}function yp(a,b){a=a|0;b=b|0;var d=0;d=c[(kJ()|0)>>2]|0;zp(a);c[a>>2]=b;c[a+40>>2]=1;b=c[42017]|0;if(!b)b=0;else b=c[b>>2]|0;if((b|0)!=(a|0)){c[a+32>>2]=1;c[a+36>>2]=0}c[a+24>>2]=0;c[(kJ()|0)>>2]=d;return}function zp(b){b=b|0;var d=0;if(b|0){c[b+16>>2]=0;d=b+4|0;a[c[d>>2]>>0]=0;a[(c[d>>2]|0)+1>>0]=0;c[b+8>>2]=c[d>>2];c[b+28>>2]=1;c[b+44>>2]=0;d=c[42017]|0;if(!d)d=0;else d=c[d>>2]|0;if((d|0)==(b|0))lp()}return}function Ap(){var b=0,d=0;d=c[42009]|0;b=(c[42010]|0)+-2|0;while(1){if((b|0)<=-1){b=0;break}if((a[d+b>>0]|0)==46){b=1;break}else b=b+-1|0}return b|0}function Bp(a,b){a=a|0;b=b|0;var d=0;d=c[42026]|0;if((d|0)<(b|0)){if(!d)d=_I(b+1|0)|0;else d=bJ(c[42027]|0,b+1|0)|0;c[42027]=d;c[42026]=b}else d=c[42027]|0;yK(d,a)|0;c[42011]=c[42027];return}function Cp(a){a=a|0;return _I(a)|0}function Dp(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+2112|0;k=m+32|0;i=m+24|0;h=m+16|0;g=m+8|0;f=m;d=m+56|0;j=m+40|0;dm(j,1024,m+1080|0);e=c[42011]|0;if(e|0){gm(j,e)|0;gm(j,81990)|0}gm(j,b)|0;c[f>>2]=c[4489];qL(d,81993,f)|0;gm(j,d)|0;a:do if(!(a[c[42009]>>0]|0))switch(((c[42016]|0)+-1|0)/2|0|0){case 2:{c[g>>2]=16384;qL(d,82013,g)|0;gm(j,d)|0;b=c[42023]|0;if(!(a[b>>0]|0))break a;i=sJ(b)|0;gm(j,82075)|0;b=c[42023]|0;if((i|0)>80)a[b+80>>0]=0;gm(j,b)|0;break a}case 3:{c[h>>2]=16384;qL(d,82094,h)|0;gm(j,d)|0;b=c[42023]|0;if(!(a[b>>0]|0))break a;i=sJ(b)|0;gm(j,82162)|0;b=c[42023]|0;if((i|0)>80)a[b+80>>0]=0;gm(j,b)|0;break a}case 1:{c[i>>2]=16384;qL(d,82181,i)|0;gm(j,d)|0;break a}default:break a}else{gm(j,82005)|0;gm(j,c[42009]|0)|0;d=j+4|0;b=c[d>>2]|0;if(b>>>0>=(c[j+8>>2]|0)>>>0){em(j,1)|0;b=c[d>>2]|0}c[d>>2]=b+1;a[b>>0]=39}while(0);e=j+4|0;b=c[e>>2]|0;d=j+8|0;if(b>>>0>=(c[d>>2]|0)>>>0){em(j,1)|0;b=c[e>>2]|0}c[e>>2]=b+1;a[b>>0]=10;b=c[e>>2]|0;if(b>>>0>=(c[d>>2]|0)>>>0){em(j,1)|0;b=c[e>>2]|0}a[b>>0]=0;i=c[j>>2]|0;c[e>>2]=i;c[k>>2]=i;$l(1,81876,k)|0;hm(j);l=m;return}function Ep(){Fp(c[42009]|0);return}function Fp(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;j=c[42018]|0;a[j>>0]=a[173931]|0;i=c[42017]|0;e=c[i>>2]|0;d=c[e+4>>2]|0;if(j>>>0<(d+2|0)>>>0){f=d+((c[42022]|0)+2)|0;g=d+((c[e+12>>2]|0)+2)|0;k=d;h=e;while(1){if(f>>>0<=k>>>0)break;e=f+-1|0;k=g+-1|0;a[k>>0]=a[e>>0]|0;h=c[i>>2]|0;f=e;g=k;k=c[h+4>>2]|0}e=g-f|0;d=j+e|0;j=c[h+12>>2]|0;c[42022]=j;c[h+16>>2]=j;if(d>>>0<(k+2|0)>>>0)vp(82240);else{l=b+e|0;m=d}}else{l=b;m=j}b=m+-1|0;a[b>>0]=64;c[42009]=l;a[173931]=a[b>>0]|0;c[42018]=b;return}function Gp(){var a=0;a=c[42017]|0;if(!a)a=0;else a=c[a>>2]|0;zp(a);return}function Hp(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=l;l=l+80|0;f=e;g=a+52|0;Tp(a,c[g>>2]|0,17604);a=f+8|0;c[a>>2]=b;c[a+4>>2]=d;d=c[g>>2]|0;d=bb[c[d>>2]&31](d,f,4)|0;l=e;return d|0}function Ip(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=Hp(b,d,e)|0;if(!f){f=Zn(b,72)|0;c[f+64>>2]=c[b+64>>2];g=f+24|0;h=c[b+24>>2]|0;c[g>>2]=h;a[g>>0]=h&255&-9;c[f+56>>2]=b;c[f+60>>2]=c[b+60>>2];b=f+8|0;c[b>>2]=d;c[b+4>>2]=e;kn(f)|0}return f|0}function Jp(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;g=l;l=l+16|0;f=g;if(!(((b|0)!=0?(Bn(a,0,b,f,0)|0)!=0:0)?(e=f,e=Hp(a,c[e>>2]|0,c[e+4>>2]|0)|0,(e|0)!=0):0))if((d|0)!=0?(Bn(a,0,b,f,1)|0)!=0:0){e=f;e=Ip(a,c[e>>2]|0,c[e+4>>2]|0)|0;Fn(a,0,e)}else e=0;l=g;return e|0}function Kp(a){a=a|0;a=c[a+52>>2]|0;return bb[c[a>>2]&31](a,0,128)|0}function Lp(a){a=a|0;var b=0;b=Mp(a)|0;if(!b)a=0;else{b=c[b+52>>2]|0;a=bb[c[b>>2]&31](b,a,8)|0}return a|0}function Mp(a){a=a|0;return c[a+56>>2]|0}function Np(a,b){a=a|0;b=b|0;a=c[a+52>>2]|0;return bb[c[a>>2]&31](a,b,2)|0}function Op(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a=c[42029]|0;e=(b|0)!=0;do if(!a)if(e){$I(b);a=0;break}else{a=_I(d)|0;break}else if(e){_n(a,b);a=0;break}else{a=Zn(a,d)|0;break}while(0);return a|0}function Pp(a,b,d){a=a|0;b=b|0;d=d|0;a=c[42029]|0;if(!a)$I(b);else _n(a,b);return}function Qp(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=b+28|0;f=c[e>>2]|0;c[e>>2]=2;c[42029]=a;d=Rl(b,d)|0;c[e>>2]=f;c[42029]=0;return d|0}function Rp(a,b,d){a=a|0;b=b|0;d=d|0;c[42029]=a;return bb[c[b>>2]&31](b,d,2)|0}function Sp(a,b){a=a|0;b=b|0;var d=0,e=0;d=(Ml(b,0,0)|0)+28|0;e=c[d>>2]|0;c[d>>2]=2;c[42029]=a;if(!(Ll(b)|0)){c[d>>2]=e;c[42029]=0;a=0}else a=1;return a|0}function Tp(a,b,c){a=a|0;b=b|0;c=c|0;if(c|0?(Ml(b,0,0)|0)!=(c|0):0)Ml(b,c,0)|0;return}function Up(a,b){a=a|0;b=b|0;if(!(dp(a)|0))b=Wp(a,b)|0;else Vp(a,b)|0;return b|0}function Vp(b,c){b=b|0;c=c|0;var d=0,e=0,f=0;a[c>>0]=60;e=c;while(1){d=e+1|0;f=a[b>>0]|0;if(!(f<<24>>24))break;a[d>>0]=f;b=b+1|0;e=d}a[d>>0]=62;a[e+2>>0]=0;return c|0}function Wp(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;a:do if((b|0)!=0?(a[b>>0]|0)!=0:0){a[d>>0]=34;l=a[b>>0]|0;q=0;g=((l+-45&255)<2|((l&255)+-48|0)>>>0<10)&1;h=0;i=0;j=0;e=d+1|0;f=b+1|0;b:while(1){k=e;while(1){if(!(l<<24>>24))break b;e=l&255;c:do if(l<<24>>24==34){a[k>>0]=92;m=g;n=1;k=k+1|0}else{if(!g){n=l<<24>>24>-1&(l<<24>>24!=95&(hK(e)|0)==0);m=0;n=n?1:h;break}switch(l<<24>>24){case 45:{n=(j|0)==0;m=n?g:0;n=n?h:1;break c}case 46:{n=(i|0)==0;m=n?g:0;n=n?h:1;i=i+1|0;break c}default:{n=(e+-48|0)>>>0<10;m=n?g:0;n=n?h:1;break c}}}while(0);e=k+1|0;a[k>>0]=l;p=f+1|0;o=a[f>>0]|0;j=j+1|0;f=c[4795]|0;if(!f){g=m;h=n;k=e;f=p;l=o;continue}g=o&255;h=o<<24>>24!=0;if((q&h?!(l<<24>>24==92|l<<24>>24>-1&((l+-45&255)>1&(hK(l<<24>>24)|0)==0)^1):0)?!(o<<24>>24>-1&((o+-45&255)>1&(hK(g)|0)==0)):0)break;if((j|0)<(f|0)|h^1){g=m;h=n;k=e;f=p;l=o;continue}if(l<<24>>24==92|l<<24>>24>-1&((hK(l<<24>>24)|0)==0&(l+-45&255)>1)^1){q=1;g=m;h=n;l=o;f=p;continue b}if(o<<24>>24>-1&((o+-45&255)>1&(hK(g)|0)==0)){q=1;g=m;h=n;l=o;f=p;continue b}a[e>>0]=92;a[k+2>>0]=10;g=m;h=1;j=0;k=k+3|0;f=p;l=o}a[e>>0]=92;a[k+2>>0]=10;q=0;g=m;h=1;j=0;l=o;e=k+3|0;f=p}a[k>>0]=34;a[k+1>>0]=0;if(!h){if((j|0)==1?((a[b>>0]|0)+-45&255)<2:0){b=d;break}else e=19184;while(1){f=c[e>>2]|0;if(!f)break a;if(!(jK(f,b)|0)){b=d;break}else e=e+4|0}}else b=d}else b=82272;while(0);return b|0}function Xp(a){a=a|0;return Up(a,Yp(a)|0)|0}function Yp(a){a=a|0;var b=0;b=((sJ(a)|0)<<1)+2|0;b=b>>>0>1024?b:1024;a=c[42031]|0;if(b>>>0>(c[42030]|0)>>>0){if(!a)a=_I(b)|0;else a=bJ(a,b)|0;c[42031]=a;c[42030]=b}return a|0}function Zp(a,b){a=a|0;b=b|0;a=Kp(a)|0;while(1){if(!a){a=0;break}if((_p(a)|0)==0?jo(a,b,0)|0:0){a=1;break}a=Lp(a)|0}return a|0}function _p(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;h=En(b)|0;if((h|0)!=0?(a[h>>0]|0)!=37:0)d=0;else e=3;a:do if((e|0)==3){d=pm(b)|0;b:do if(d|0?(f=pm(Mp(b)|0)|0,f|0):0){h=Tl(c[(pm(to(b)|0)|0)+8>>2]|0)|0;g=d+12|0;e=f+12|0;d=0;while(1){if((d|0)>=(h|0))break b;f=c[(c[g>>2]|0)+(d<<2)>>2]|0;if((f|0?(i=c[(c[e>>2]|0)+(d<<2)>>2]|0,i|0):0)?yJ(f,i)|0:0){d=0;break a}d=d+1|0}}while(0);d=km(b,0)|0;if(d)if((Tl(c[d+8>>2]|0)|0)>0)d=0;else return (Tl(c[d+12>>2]|0)|0)<1|0;else d=1}while(0);return d|0}function $p(b,d){b=b|0;d=d|0;var e=0,f=0;c[42032]=0;e=Jm(b,82282)|0;if((e|0?((a[e>>0]|0)+-48|0)>>>0<10:0)?(f=CL(e,0,10)|0,(f|0)==0|(f|0)>59):0)c[4795]=f;aq(b,1);if(((bq(b,d,1)|0)!=-1?(cq(b,d)|0)!=-1:0)?(dq(b,d)|0)!=-1:0){c[4795]=128;b=$a[c[(c[(c[b+64>>2]|0)+8>>2]|0)+8>>2]&31](d)|0}else b=-1;return b|0}function aq(a,b){a=a|0;b=b|0;var d=0;c[a>>2]=c[a>>2]&-9;d=Kp(a)|0;while(1){if(!d)break;aq(d,0);d=Lp(d)|0}a:do if(b|0){b=eo(a)|0;while(1){if(!b)break a;c[b>>2]=c[b>>2]&-9;d=Qm(a,b)|0;while(1){if(!d)break;c[d>>2]=c[d>>2]&-9;d=Sm(a,d)|0}b=fo(a,b)|0}}while(0);return}function bq(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;if((e|0)==0?(Mp(b)|0)!=0:0){i=0;g=174185;k=94336}else{k=(a[b+24>>0]&1)==0?174185:82326;g=(tn(b)|0)==0;c[42033]=zm(b,2,96242,0)|0;c[42034]=zm(b,2,96251,0)|0;i=1;g=g?174185:82329}f=En(b)|0;if((f|0)!=0?(a[f>>0]|0)!=37:0){h=1;j=87638}else{h=0;j=174185;f=174185}do if((eq(b,d)|0)!=-1?(fq(b,d,g)|0)!=-1:0){g=(h|0)==0;if(h|i|0){if((fq(b,d,k)|0)==-1){f=-1;break}if((fq(b,d,87631)|0)==-1){f=-1;break}}if(!g?(qq(b,d,f)|0)==-1:0){f=-1;break}if(((fq(b,d,j)|0)!=-1?(fq(b,d,82337)|0)!=-1:0)?(c[42032]=(c[42032]|0)+1,(vq(b,d,e)|0)!=-1):0){c[b>>2]=c[b>>2]|8;f=0}else f=-1}else f=-1;while(0);return f|0}function cq(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;a:do if((gq(a,b)|0)==-1)d=-1;else{k=km(to(a)|0,0)|0;i=(k|0)==0;j=k+12|0;k=k+8|0;h=eo(a)|0;while(1){if(!h){d=0;break a}if(hq(a,h,(c[h>>2]|0)>>>4,0)|0){if(i)d=0;else d=c[k>>2]|0;if((iq(h,b,d)|0)==-1){d=-1;break a}}g=Qm(a,h)|0;d=h;while(1){if(!g)break;f=g+-48|0;e=c[((c[g>>2]&3|0)==2?g:f)+40>>2]|0;if((d|0)!=(e|0)?(hq(a,e,(c[h>>2]|0)>>>4,0)|0)!=0:0){if(i)d=0;else d=c[k>>2]|0;if((iq(c[((c[g>>2]&3|0)==2?g:f)+40>>2]|0,b,d)|0)==-1){d=-1;break a}d=c[((c[g>>2]&3|0)==2?g:f)+40>>2]|0}if(jq(a,g)|0){if(i)e=0;else e=c[j>>2]|0;if((kq(g,b,e)|0)==-1){d=-1;break a}}g=Sm(a,g)|0}h=fo(a,h)|0}}while(0);return d|0}function dq(a,b){a=a|0;b=b|0;c[42032]=(c[42032]|0)+-1;if((eq(a,b)|0)==-1)a=-1;else a=((fq(a,b,95830)|0)==-1)<<31>>31;return a|0}function eq(a,b){a=a|0;b=b|0;var d=0;d=c[42032]|0;while(1){if((d|0)<=0){d=0;break}if((fq(a,b,134899)|0)==-1){d=-1;break}else d=d+-1|0}return d|0}function fq(a,b,d){a=a|0;b=b|0;d=d|0;return ab[c[(c[(c[a+64>>2]|0)+8>>2]|0)+4>>2]&63](b,d)|0}function gq(a,b){a=a|0;b=b|0;a=Kp(a)|0;while(1){if(!a){a=0;break}if(!(_p(a)|0)){if((bq(a,b,0)|0)==-1){a=-1;break}if((cq(a,b)|0)==-1){a=-1;break}if((dq(a,b)|0)==-1){a=-1;break}}else gq(a,b)|0;a=Lp(a)|0}return a|0}function hq(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;if((Zp(a,b)|0)==0?(sq(a,b,c,d)|0)!=0:0)if((tq(a,b)|0)==0?(uq(b)|0)==0:0)e=5;else a=1;else e=5;if((e|0)==5)a=0;return a|0}function iq(a,b,c){a=a|0;b=b|0;c=c|0;var d=0;d=so(a)|0;do if((eq(d,b)|0)!=-1?(lq(a,b)|0)!=-1:0){if((nq(a)|0)==0?(oq(a,b,c)|0)==-1:0){a=-1;break}a=fq(d,b,82293)|0}else a=-1;while(0);return a|0}function jq(a,b){a=a|0;b=b|0;a=Kp(a)|0;while(1){if(!a){a=1;break}if((_p(a)|0)==0?fn(a,b,0)|0:0){a=0;break}a=Lp(a)|0}return a|0}function kq(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;e=c[a>>2]&3;g=c[((e|0)==3?a:a+48|0)+40>>2]|0;e=c[((e|0)==2?a:a+-48|0)+40>>2]|0;f=so(g)|0;do if((((((eq(f,b)|0)!=-1?(lq(g,b)|0)!=-1:0)?(mq(a,b,c[42033]|0)|0)!=-1:0)?(g=(rn(so(g)|0)|0)!=0,(fq(f,b,g?85095:85100)|0)!=-1):0)?(lq(e,b)|0)!=-1:0)?(mq(a,b,c[42034]|0)|0)!=-1:0){if(!(nq(a)|0)){if((oq(a,b,d)|0)==-1){a=-1;break}}else if((pq(a,b,1)|0)==-1){a=-1;break}a=fq(f,b,82293)|0}else a=-1;while(0);return a|0}function lq(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0;i=l;l=l+32|0;g=i;d=i+8|0;e=En(a)|0;f=so(a)|0;if(!e){j=a+8|0;a=c[j+4>>2]|0;e=g;c[e>>2]=c[j>>2];c[e+4>>2]=a;qL(d,82313,g)|0;if((fq(f,b,d)|0)==-1)a=-1;else h=4}else if((qq(f,b,e)|0)==-1)a=-1;else h=4;if((h|0)==4)a=0;l=i;return a|0}function mq(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0;a:do if((d|0)!=0?(e=so(b)|0,f=Km(b,d)|0,(a[f>>0]|0)!=0):0)if((fq(e,c,93017)|0)==-1)b=-1;else{do if(dp(f)|0){if((qq(e,c,f)|0)==-1){b=-1;break a}}else{b=XJ(f,58)|0;if(!b)if((rq(e,c,f,0)|0)==-1){b=-1;break a}else break;a[b>>0]=0;if((rq(e,c,f,0)|0)==-1){b=-1;break a}if((fq(e,c,93017)|0)==-1){b=-1;break a}if((rq(e,c,b+1|0,0)|0)==-1){b=-1;break a}a[b>>0]=58}while(0);b=0}else b=0;while(0);return b|0}function nq(a){a=a|0;return (c[a>>2]|0)>>>3&1|0}function oq(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;a:do if(!(c[a>>2]&2)){e=0;k=4}else{switch(pq(a,b,0)|0){case -1:{e=-1;break a}case 0:{e=0;k=4;break a}default:{}}e=1;k=4}while(0);b:do if((k|0)==4){f=pm(a)|0;j=so(a)|0;c:do if(f){i=f+12|0;h=bb[c[d>>2]&31](d,0,128)|0;while(1){if(!h)break c;do if(c[a>>2]&2){g=c[42033]|0;if(g|0?(c[h+16>>2]|0)==(c[g+16>>2]|0):0)break;g=c[42034]|0;if(!((g|0)!=0?(c[h+16>>2]|0)==(c[g+16>>2]|0):0))k=12}else k=12;while(0);if((k|0)==12){k=0;f=h+16|0;if((c[(c[i>>2]|0)+(c[f>>2]<<2)>>2]|0)!=(c[h+12>>2]|0)){g=e+1|0;if(e){if((fq(j,b,82308)|0)==-1){e=-1;break b}if((eq(j,b)|0)==-1){e=-1;break b}}else{if((eq(j,b)|0)==-1){e=-1;break b}if((fq(j,b,82305)|0)==-1){e=-1;break b}c[42032]=(c[42032]|0)+1}if((qq(j,b,c[h+8>>2]|0)|0)==-1){e=-1;break b}if((fq(j,b,82311)|0)==-1){e=-1;break b}if((qq(j,b,c[(c[i>>2]|0)+(c[f>>2]<<2)>>2]|0)|0)==-1){e=-1;break b}else e=g}}h=bb[c[d>>2]&31](d,h,8)|0}}while(0);if((e|0)>0){if((fq(j,b,82303)|0)==-1){e=-1;break}c[42032]=(c[42032]|0)+-1}c[a>>2]=c[a>>2]|8;e=0}while(0);return e|0}function pq(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0;e=En(b)|0;b=so(b)|0;if((e|0)!=0?(a[e>>0]|0)!=0:0)if((fq(b,c,82296)|0)!=-1?(qq(b,c,e)|0)!=-1:0)if((d|0)!=0?(fq(b,c,82303)|0)==-1:0)b=-1;else{b=1;f=7}else b=-1;else{b=0;f=7}return b|0}function qq(a,b,c){a=a|0;b=b|0;c=c|0;return rq(a,b,c,1)|0}function rq(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if(!d)c=Wp(c,Yp(c)|0)|0;else c=Xp(c)|0;return fq(a,b,c)|0}function sq(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;a:do if(0>>0|(0==(e|0)?(c[b>>2]|0)>>>4>>>0>>0:0))b=0;else{b=Tm(a,b)|0;while(1){if(!b){b=1;break a}if(0>>0|(0==(e|0)?(c[c[b+40>>2]>>2]|0)>>>4>>>0>>0:0)){b=0;break a}b=Um(a,b)|0}}while(0);return b|0}function tq(a,b){a=a|0;b=b|0;if(!(Tm(a,b)|0))a=(Qm(a,b)|0)==0&1;else a=0;return a|0}function uq(a){a=a|0;var b=0,d=0,e=0;a=pm(a)|0;a:do if(!a)a=0;else{d=a+8|0;e=c[d>>2]|0;b=a+12|0;a=bb[c[e>>2]&31](e,0,128)|0;while(1){if(!a){a=0;break a}if((c[(c[b>>2]|0)+(c[a+16>>2]<<2)>>2]|0)!=(c[a+12>>2]|0)){a=1;break a}e=c[d>>2]|0;a=bb[c[e>>2]&31](e,a,8)|0}}while(0);return a|0}function vq(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=km(a,0)|0;if(e)if(((wq(a,b,96286,c[e+16>>2]|0,d)|0)!=-1?(wq(a,b,96273,c[e+8>>2]|0,d)|0)!=-1:0)?(wq(a,b,96237,c[e+12>>2]|0,d)|0)!=-1:0)f=5;else a=-1;else f=5;if((f|0)==5)a=0;return a|0}function wq(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;m=(g|0)!=0;if(m)l=0;else l=Xl(f,0)|0;k=(l|0)==0;j=bb[c[f>>2]&31](f,0,128)|0;g=0;while(1){if(!j){n=23;break}i=j+12|0;n=c[i>>2]|0;if((n|0)!=0?(a[n>>0]|0)!=0:0)n=12;else n=7;do if((n|0)==7){n=0;if(!(a[j+22>>0]|0)){if(!k){h=bb[c[l>>2]&31](l,j,4)|0;o=c[h+12>>2]|0;if(o|0?a[o>>0]|0:0){n=12;break}if(!(a[h+22>>0]|0))n=12}}else n=12}while(0);if((n|0)==12){n=0;h=g+1|0;if(g){if((fq(b,d,82308)|0)==-1){g=-1;break}if((eq(b,d)|0)==-1){g=-1;break}}else{if((eq(b,d)|0)==-1){g=-1;break}if((fq(b,d,e)|0)==-1){g=-1;break}if((fq(b,d,82305)|0)==-1){g=-1;break}c[42032]=(c[42032]|0)+1}if((qq(b,d,c[j+8>>2]|0)|0)==-1){g=-1;break}if((fq(b,d,82311)|0)==-1){g=-1;break}if((qq(b,d,c[i>>2]|0)|0)==-1){g=-1;break}else g=h}j=bb[c[f>>2]&31](f,j,8)|0}do if((n|0)==23){if((g|0)>0){c[42032]=(c[42032]|0)+-1;if((g|0)!=1){if((fq(b,d,134901)|0)==-1){g=-1;break}if((eq(b,d)|0)==-1){g=-1;break}}g=(fq(b,d,82340)|0)==-1;if(m|g){g=g<<31>>31;break}}else if(m){g=0;break}Xl(f,l)|0;g=0}while(0);return g|0}function xq(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0;switch(c[b>>2]&3){case 0:{g=19;break}case 1:{g=20;break}case 3:case 2:{g=21;break}default:{}}b=ab[g&63](a,b)|0;if(!b)b=-1;else{Bq(a,b,d,e,g,f);b=0}return b|0}function yq(a,b){a=a|0;b=b|0;if((so(b)|0)!=(a|0))b=fn(a,b,0)|0;return b|0}function zq(a,b){a=a|0;b=b|0;if((so(b)|0)!=(a|0))b=jo(a,b,0)|0;return b|0}function Aq(a,b){a=a|0;b=b|0;return a|0}function Bq(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0;h=(f|0)!=0;if(h)ib[c&127](a,b,d);g=Kp(a)|0;while(1){if(!g)break;i=ab[e&63](g,b)|0;if(i|0)Bq(g,i,c,d,e,f);g=Lp(g)|0}if(!h)ib[c&127](a,b,d);return}function Cq(){var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=l;l=l+1200|0;r=t+800|0;g=t;c[42035]=0;c[42036]=-2;f=r;i=200;n=g;p=0;q=0;o=r;a:while(1){b[o>>1]=p;if((f+(i<<1)+-2|0)>>>0>o>>>0)k=i;else{m=o-f>>1;e=m+1|0;if(i>>>0>9999){s=75;break}k=i<<1;k=k>>>0<1e4?k:1e4;h=_I(k*6|3)|0;if(h){UN(h|0,f|0,e<<1|0)|0;i=h+(k>>>1<<2)|0;UN(i|0,n|0,e<<2|0)|0;if((f|0)==(r|0)){e=0;f=h}else{$I(f);e=0;f=h}}else{e=4;i=n}j=(e|0)==0;h=f+(m<<1)|0;switch((j?((f+(k<<1)+-2|0)>>>0>h>>>0?0:9):e)&15){case 9:{e=1;s=76;break a}case 4:{s=75;break a}case 0:{g=j?i+(m<<2)|0:g;n=i;o=j?h:o;break}default:{e=0;break a}}}if((p|0)==6){e=0;s=76;break}e=a[82344+p>>0]|0;j=e<<24>>24;do if(e<<24>>24!=-18){h=c[42036]|0;if((h|0)==-2){h=ip()|0;c[42036]=h}if((h|0)>=1)if(h>>>0<269)i=d[82424+h>>0]|0;else i=2;else{c[42036]=0;i=0}h=i+j|0;if(h>>>0<=59?(i|0)==(d[82693+h>>0]|0):0){p=a[82753+h>>0]|0;e=p<<24>>24;if(p<<24>>24<1){h=0-e|0;s=23;break}else{c[42036]=-2;g=g+4|0;c[g>>2]=c[42037];j=(q|0)==0?0:q+-1|0;h=o;break}}else s=22}else s=22;while(0);if((s|0)==22){s=0;p=a[82813+p>>0]|0;h=p&255;if(!(p<<24>>24)){h=c[42036]|0;b:do switch(q|0){case 0:{c[42035]=(c[42035]|0)+1;Dp(125369);h=o;break}case 3:if((h|0)<1)if(!h){e=1;s=76;break a}else{h=o;break b}else{c[42036]=-2;h=o;break b}default:h=o}while(0);while(1){if(e<<24>>24==18)break;if((h|0)==(f|0)){e=1;s=76;break a}e=h+-2|0;g=g+-4|0;h=e;e=a[82344+(b[e>>1]|0)>>0]|0}g=g+4|0;c[g>>2]=c[42037];e=1;j=3}else s=23}do if((s|0)==23){s=0;i=d[82893+h>>0]|0;e=c[g+(1-i<<2)>>2]|0;c:do switch(h|0){case 2:{Dq();Eq();break}case 3:{if(c[42038]|0){Dq();Eq();mn(c[42038]|0)|0;c[41987]=0;c[42038]=0}break}case 6:{Fq(c[g>>2]|0,c[g+-4>>2]|0,c[g+-8>>2]|0);break}case 7:{e=c[g>>2]|0;break}case 8:{e=0;break}case 9:{e=1;break}case 10:{e=0;break}case 11:{e=0;break}case 12:{e=1;break}case 21:if(!(c[g+-4>>2]|0)){Hq();break c}else{Gq();break c}case 24:{Iq();break}case 25:{Iq();break}case 26:{e=1;break}case 27:{e=0;break}case 30:{Jq(c[g>>2]|0,0,0);break}case 31:{Jq(c[g+-8>>2]|0,c[g>>2]|0,0);break}case 32:{Jq(c[g+-16>>2]|0,c[g+-8>>2]|0,c[g>>2]|0);break}case 33:{Kq(c[g+-8>>2]|0,c[g+-4>>2]|0);break}case 34:{Kq(258,0);break}case 35:{e=258;break}case 36:{e=259;break}case 37:{e=260;break}case 38:{e=c[g+-4>>2]|0;break}case 39:{e=0;break}case 48:{Lq(c[g+-8>>2]|0,c[g>>2]|0);break}case 49:{Lq(c[g>>2]|0,0);break}case 51:{Mq(c[g>>2]|0);break}case 52:{Nq();break}case 53:{e=c[g>>2]|0;break}case 54:{e=0;break}case 55:{e=0;break}case 59:{e=c[g>>2]|0;break}case 60:{e=c[g>>2]|0;break}case 61:{e=c[g>>2]|0;break}case 62:{e=Oq(c[g+-8>>2]|0,c[g>>2]|0)|0;break}default:{}}while(0);i=0-i|0;p=g+(i<<2)|0;i=o+(i<<1)|0;g=p+4|0;c[p+4>>2]=e;e=(d[82956+h>>0]|0)+-24|0;p=b[i>>1]|0;h=p+(a[83019+e>>0]|0)|0;if(h>>>0<60?(d[82693+h>>0]|0)==(p|0):0){e=a[82753+h>>0]|0;j=q;h=i;break}e=a[83054+e>>0]|0;j=q;h=i}while(0);i=k;p=e;q=j;o=h+2|0}if((s|0)==75){Dp(125382);e=2;s=76}if((s|0)==76)if((f|0)!=(r|0))$I(f);l=t;return e|0}function Dq(){var a=0,b=0;a=c[42039]|0;while(1){if(!a)break;Wq(a+8|0);Wq((c[42039]|0)+24|0);Wq((c[42039]|0)+16|0);b=Pq(c[42039]|0)|0;c[42039]=b;a=b}return}function Eq(){Ep();Nn(c[42038]|0);return}function Fq(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;h=l;l=l+16|0;g=h;f=c[42038]|0;if(!f){a[168160]=d&1|(e&255)<<1&2|a[168160]&-12|8;f=c[42041]|0;a[g>>0]=a[168160]|0;a[g+1>>0]=a[168161]|0;a[g+2>>0]=a[168162]|0;a[g+3>>0]=a[168163]|0;f=hn(b,g,f)|0;c[42038]=f}c[41987]=f;c[42039]=Qq(c[42039]|0,f)|0;cp(0,b)|0;l=h;return}function Gq(){var b=0,d=0,e=0,f=0,g=0,h=0;Vq(2);e=c[42039]|0;f=a[83089]|0;h=0;b=e+24|0;while(1){d=c[b>>2]|0;if(!d)break;if(((c[d>>2]|0)==267?(g=c[d+4>>2]|0,(a[g>>0]|0)==f<<24>>24):0)?(yJ(g,83089)|0)==0:0)b=c[d+8>>2]|0;else b=h;h=b;b=d+12|0}b=e+16|0;a:while(1){e=c[b>>2]|0;b=e+12|0;if(!(c[b>>2]|0))break;d=e+4|0;if((c[e>>2]|0)==262){e=c[d>>2]|0;d=eo(e)|0;while(1){if(!d)continue a;g=jo(c[c[42039]>>2]|0,d,0)|0;br(g,0,c[b>>2]|0,h);d=fo(e,d)|0}}else while(1){d=c[d>>2]|0;if(!d)continue a;br(c[d+4>>2]|0,c[d+8>>2]|0,c[b>>2]|0,h);d=d+12|0}}Wq((c[42039]|0)+8|0);Wq((c[42039]|0)+16|0);Wq((c[42039]|0)+24|0);c[(c[42039]|0)+4>>2]=0;return}function Hq(){var a=0;Vq(1);a=(c[42039]|0)+8|0;while(1){a=c[a>>2]|0;if(!a)break;ar(c[a+4>>2]|0);a=a+12|0}Wq((c[42039]|0)+8|0);Wq((c[42039]|0)+24|0);Wq((c[42039]|0)+16|0);c[(c[42039]|0)+4>>2]=0;return}function Iq(){var a=0,b=0;a=c[42039]|0;b=c[a+8>>2]|0;if(!b){b=c[a+4>>2]|0;if(!b)b=0;else{b=$q(b)|0;a=c[42039]|0}c[a+4>>2]=0}else{b=_q(b)|0;a=c[42039]|0;c[a+12>>2]=0;c[a+8>>2]=0}if(b|0)Sq(a+16|0,b);return}function Jq(a,b,d){a=a|0;b=b|0;d=d|0;if(d)b=Yq(b,d)|0;d=Zq(oo(c[c[42039]>>2]|0,a,1)|0,b)|0;Sq((c[42039]|0)+8|0,d);cp(c[42038]|0,a)|0;return}function Kq(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;if(d|0)Uq();d=(c[42039]|0)+24|0;while(1){d=c[d>>2]|0;if(!d)break;if(!(c[d+8>>2]|0))Uq();d=d+12|0}g=(b|0)==260?2:(b|0)==259&1;Vq(g);b=c[42039]|0;d=b+24|0;while(1){f=c[d>>2]|0;if(!f)break;do if((c[f>>2]|0)!=267){d=c[f+4>>2]|0;e=c[b>>2]|0;if(!((a[d+21>>0]|0)!=0&(e|0)==(c[42038]|0))){d=zm(e,g,c[d+8>>2]|0,c[f+8>>2]|0)|0;b=c[42039]|0;if((c[b>>2]|0)!=(c[42038]|0))break}a[d+22>>0]=1}while(0);d=f+12|0}Wq(b+24|0);return}function Lq(a,b){a=a|0;b=b|0;b=Rq(a,b)|0;Sq((c[42039]|0)+24|0,b);return}function Mq(a){a=a|0;var b=0;b=c[42039]|0;c[42039]=Qq(b,Jp(c[b>>2]|0,a,1)|0)|0;cp(c[42038]|0,a)|0;return}function Nq(){var a=0,b=0;a=c[42039]|0;b=c[a>>2]|0;a=Pq(a)|0;c[42039]=a;c[a+4>>2]=b;return}function Oq(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=l;l=l+1024|0;f=g;d=sJ(a)|0;d=d+1+(sJ(b)|0)|0;if(d>>>0<1025)d=f;else d=_I(d)|0;yK(d,a)|0;JL(d,b)|0;e=ap(c[42038]|0,d)|0;cp(c[42038]|0,a)|0;cp(c[42038]|0,b)|0;if((d|0)!=(f|0))$I(d);l=g;return e|0}function Pq(a){a=a|0;var b=0;b=c[(c[42039]|0)+32>>2]|0;_n(c[42038]|0,a);return b|0}function Qq(a,b){a=a|0;b=b|0;var d=0;d=Zn(c[42038]|0,36)|0;c[d+32>>2]=a;c[d>>2]=b;return d|0}function Rq(a,b){a=a|0;b=b|0;return Tq(267,a,b)|0}function Sq(a,b){a=a|0;b=b|0;var d=0,e=0;d=a+4|0;e=c[d>>2]|0;if(e|0)c[e+12>>2]=b;c[d>>2]=b;if(!(c[a>>2]|0))c[a>>2]=b;return}function Tq(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;e=Zn(c[42038]|0,16)|0;c[e>>2]=a;c[e+4>>2]=b;c[e+8>>2]=d;return e|0}function Uq(){var a=0;a=l;l=l+16|0;$l(0,83093,a)|0;l=a;return} +function EI(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,i=0.0,j=0,k=0,m=0,n=0,q=0,r=0,s=0,u=0,v=0,w=0,x=0,y=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0.0;H=l;l=l+112|0;E=H+80|0;D=H+64|0;C=H+48|0;G=4;F=_I(40)|0;c[F>>2]=0;w=H+32|0;x=H+16|0;y=H;A=H+96|0;G=SN(169984,1,F|0,G|0)|0;F=z;o=0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1)e=z;else e=0;a:while(1){if(e|0){e=-2;break}g=a+4|0;o=0;fa(94,c[g>>2]|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}c[42535]=0;c[42536]=0;o=0;fa(95,c[g>>2]<<1|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}m=(c[42538]|0)/2|0;c[42539]=m;c[42540]=m+-1;m=c[g>>2]|0;g=c[a>>2]|0;e=0;f=-1;i=t;while(1){if((e|0)>=(m|0))break;I=+h[g+(e<<4)>>3];v=i>I;u=v?e:f;e=e+1|0;f=u;i=v?I:i}v=g+(f<<4)|0;c[x>>2]=c[v>>2];c[x+4>>2]=c[v+4>>2];c[x+8>>2]=c[v+8>>2];c[x+12>>2]=c[v+12>>2];v=g+(((f|0)==0?m:f)+-1<<4)|0;c[w>>2]=c[v>>2];c[w+4>>2]=c[v+4>>2];c[w+8>>2]=c[v+8>>2];c[w+12>>2]=c[v+12>>2];v=g+(((f|0)==(m+-1|0)?0:f+1|0)<<4)|0;c[y>>2]=c[v>>2];c[y+4>>2]=c[v+4>>2];c[y+8>>2]=c[v+8>>2];c[y+12>>2]=c[v+12>>2];I=+h[x>>3];if((+h[w>>3]==I?I==+h[y>>3]:0)?+h[y+8>>3]>+h[x+8>>3]:0)v=15;else v=12;b:do if((v|0)==12){v=0;o=0;e=aa(17,w|0,x|0,y|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,G|0,F|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}if((e|0)==1){g=c[42542]|0;e=c[42543]|0;f=0;while(1){if((f|0)>=(m|0))break b;j=c[a>>2]|0;if(!(((f|0)>0?(B=f+-1|0,+h[j+(f<<4)>>3]==+h[j+(B<<4)>>3]):0)?+h[j+(f<<4)+8>>3]==+h[j+(B<<4)+8>>3]:0)){u=c[42535]|0;c[g+(u<<3)>>2]=j+(f<<4);c[g+(u<<3)+4>>2]=g+(((u|0)%(m|0)|0)<<3);c[e+(u<<2)>>2]=g+(u<<3);c[42535]=u+1}f=f+1|0}}else v=15}while(0);c:do if((v|0)==15){v=0;j=c[42542]|0;e=c[42543]|0;g=m;while(1){f=g+-1|0;if((g|0)<=0)break c;k=c[a>>2]|0;if(((g|0)<(m|0)?+h[k+(f<<4)>>3]==+h[k+(g<<4)>>3]:0)?+h[k+(f<<4)+8>>3]==+h[k+(g<<4)+8>>3]:0){g=f;continue}g=c[42535]|0;c[j+(g<<3)>>2]=k+(f<<4);c[j+(g<<3)+4>>2]=j+(((g|0)%(m|0)|0)<<3);c[e+(g<<2)>>2]=j+(g<<3);c[42535]=g+1;g=f}}while(0);o=0;ga(27,e|0,c[42535]|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}j=0;e=c[42536]|0;d:while(1){if((j|0)>=(e|0)){s=0;break}k=j+1|0;g=k;while(1){if((g|0)>=(e|0)){j=k;continue d}o=0;ga(28,j|0,g|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue a}g=g+1|0;e=c[42536]|0}}while(1){if((s|0)>=(e|0))break;o=0;f=$(39,s|0,b|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){j=TN(c[g>>2]|0,G|0,F|0)|0;if(!j)Ua(g|0,p|0);z=p}else j=-1;if((j|0)==1){e=z;continue a}if(f|0)break;s=s+1|0}if((s|0)==(e|0)){e=c[13918]|0;o=0;c[C>>2]=125503;c[C+4>>2]=192;c[C+8>>2]=125514;aa(13,e|0,125484,C|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}else{v=41;break}}u=b+16|0;k=0;while(1){if((k|0)>=(e|0))break;o=0;f=$(39,k|0,u|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){j=TN(c[g>>2]|0,G|0,F|0)|0;if(!j)Ua(g|0,p|0);z=p}else j=-1;if((j|0)==1){e=z;continue a}if(f|0)break;k=k+1|0}if((k|0)==(e|0)){e=c[13918]|0;o=0;c[D>>2]=125503;c[D+4>>2]=200;c[D+8>>2]=125547;aa(13,e|0,125484,D|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}else{v=48;break}}o=0;e=$(40,s|0,k|0)|0;f=o;o=0;if((f|0)!=0&(p|0)!=0){g=TN(c[f>>2]|0,G|0,F|0)|0;if(!g)Ua(f|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue}if(!e){e=c[13918]|0;o=0;c[E>>2]=125503;c[E+4>>2]=207;c[E+8>>2]=125585;aa(13,e|0,125484,E|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}o=0;fa(96,2);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}else{v=53;break}}if((s|0)==(k|0)){o=0;fa(96,2);e=o;o=0;if((e|0)!=0&(p|0)!=0){f=TN(c[e>>2]|0,G|0,F|0)|0;if(!f)Ua(e|0,p|0);z=p}else f=-1;if((f|0)==1){e=z;continue}else{v=56;break}}c[A>>2]=b;c[A+4>>2]=0;f=A+8|0;c[f>>2]=u;c[A+12>>2]=0;o=0;ga(29,1,A|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue}c[42541]=c[42539];q=s;e:while(1){if((q|0)==-1){g=f;e=0;break}r=c[42545]|0;c[r+(q*52|0)>>2]=2;e=0;while(1){if((e|0)>=3){v=65;break}v=c[r+(q*52|0)+4+(e<<4)+12>>2]|0;if(v|0?(c[v>>2]|0)==1:0){v=68;break}e=e+1|0}if((v|0)==65){v=0;if((e|0)==3){e=c[42537]|0;k=c[e+(c[42540]<<2)>>2]|0;o=0;e=aa(17,u|0,c[c[e+(c[42539]<<2)>>2]>>2]|0,c[k>>2]|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){j=TN(c[g>>2]|0,G|0,F|0)|0;if(!j)Ua(g|0,p|0);z=p}else j=-1;if((j|0)==1){e=z;continue a}j=(e|0)==1;n=j?f:k;j=j?k:f}else v=68}if((v|0)==68){v=0;k=c[r+(q*52|0)+4+(e<<4)>>2]|0;m=c[r+(q*52|0)+4+(e<<4)+4>>2]|0;o=0;e=aa(17,c[k>>2]|0,c[c[r+(q*52|0)+4+(((e+1|0)%3|0)<<4)+4>>2]>>2]|0,c[m>>2]|0)|0;g=o;o=0;if((g|0)!=0&(p|0)!=0){j=TN(c[g>>2]|0,G|0,F|0)|0;if(!j)Ua(g|0,p|0);z=p}else j=-1;if((j|0)==1){e=z;continue a}j=(e|0)==1;n=j?k:m;j=j?m:k}do if((q|0)==(s|0)){o=0;ga(29,2,j|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}o=0;ga(29,1,n|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}e=0}else{m=c[42537]|0;if((c[m+(c[42539]<<2)>>2]|0)!=(n|0)?(c[m+(c[42540]<<2)>>2]|0)!=(n|0):0){o=0;j=_(29,n|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}o=0;ga(30,2,j|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}o=0;ga(29,1,n|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}if((j|0)<=(c[42541]|0)){e=0;break}c[42541]=j;e=0;break}o=0;k=_(29,j|0)|0;e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}o=0;ga(30,1,k|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}o=0;ga(29,2,j|0);e=o;o=0;if((e|0)!=0&(p|0)!=0){g=TN(c[e>>2]|0,G|0,F|0)|0;if(!g)Ua(e|0,p|0);z=p}else g=-1;if((g|0)==1){e=z;continue a}if((k|0)>=(c[42541]|0)){e=0;break}c[42541]=k;e=0}while(0);while(1){if((e|0)>=3){q=-1;continue e}g=c[r+(q*52|0)+4+(e<<4)+12>>2]|0;if(g|0?(c[g>>2]|0)==1:0)break;e=e+1|0}q=(g-(c[42545]|0)|0)/52|0}while(1){if(!g)break;g=c[g+4>>2]|0;e=e+1|0}o=0;fa(96,e|0);g=o;o=0;if((g|0)!=0&(p|0)!=0){j=TN(c[g>>2]|0,G|0,F|0)|0;if(!j)Ua(g|0,p|0);z=p}else j=-1;if((j|0)==1)e=z;else{v=94;break}}if((v|0)==41)e=-1;else if((v|0)==48)e=-1;else if((v|0)==53){c[d+4>>2]=2;e=c[42544]|0;c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];c[e+8>>2]=c[b+8>>2];c[e+12>>2]=c[b+12>>2];F=e+16|0;c[F>>2]=c[u>>2];c[F+4>>2]=c[u+4>>2];c[F+8>>2]=c[u+8>>2];c[F+12>>2]=c[u+12>>2];c[d>>2]=e;e=0}else if((v|0)==56){c[d+4>>2]=2;e=c[42544]|0;c[e>>2]=c[b>>2];c[e+4>>2]=c[b+4>>2];c[e+8>>2]=c[b+8>>2];c[e+12>>2]=c[b+12>>2];F=e+16|0;c[F>>2]=c[u>>2];c[F+4>>2]=c[u+4>>2];c[F+8>>2]=c[u+8>>2];c[F+12>>2]=c[u+12>>2];c[d>>2]=e;e=0}else if((v|0)==94){c[d+4>>2]=e;g=c[42544]|0;while(1){e=e+-1|0;if(!f)break;F=g+(e<<4)|0;E=c[f>>2]|0;c[F>>2]=c[E>>2];c[F+4>>2]=c[E+4>>2];c[F+8>>2]=c[E+8>>2];c[F+12>>2]=c[E+12>>2];f=c[f+4>>2]|0}c[d>>2]=g;e=0}$I(G|0);l=H;return e|0}function FI(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;h=l;l=l+64|0;e=h+48|0;g=h+32|0;f=h+16|0;d=h;if((c[42548]|0)<(a|0)){b=c[42542]|0;if(!b){g=_I(a<<3)|0;c[42542]=g;if(!g){g=c[13918]|0;c[d>>2]=125503;c[d+4>>2]=523;c[d+8>>2]=125753;AL(g,125484,d)|0;Ua(169984,1)}g=_I(a<<2)|0;c[42543]=g;if(!g){g=c[13918]|0;c[f>>2]=125503;c[f+4>>2]=527;c[f+8>>2]=125772;AL(g,125484,f)|0;Ua(169984,1)}}else{f=bJ(b,a<<3)|0;c[42542]=f;if(!f){f=c[13918]|0;c[g>>2]=125503;c[g+4>>2]=533;c[g+8>>2]=125792;AL(f,125484,g)|0;Ua(169984,1)}g=bJ(c[42543]|0,a<<2)|0;c[42543]=g;if(!g){g=c[13918]|0;c[e>>2]=125503;c[e+4>>2]=539;c[e+8>>2]=125812;AL(g,125484,e)|0;Ua(169984,1)}}c[42548]=a}l=h;return}function GI(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+32|0;e=f+16|0;d=f;if((c[42538]|0)<(a|0)){b=c[42537]|0;if(!b){e=_I(a<<2)|0;c[42537]=e;if(!e){e=c[13918]|0;c[d>>2]=125503;c[d+4>>2]=573;c[d+8>>2]=125708;AL(e,125484,d)|0;Ua(169984,1)}}else{d=bJ(b,a<<2)|0;c[42537]=d;if(!d){d=c[13918]|0;c[e>>2]=125503;c[e+4>>2]=580;c[e+8>>2]=125730;AL(d,125484,e)|0;Ua(169984,1)}}c[42538]=a}l=f;return}function HI(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0;d=+h[b+8>>3];e=+h[b>>3];d=(+h[c>>3]-e)*(+h[a+8>>3]-d)-(+h[a>>3]-e)*(+h[c+8>>3]-d);return (d>0.0?1:d<0.0?2:3)|0}function II(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=l;l=l+16|0;h=i;a:while(1){if((b|0)>3)e=0;else{b=9;break}while(1){if((e|0)>=(b|0)){b=8;break a}f=e+1|0;d=(f|0)%(b|0)|0;g=(e+2|0)%(b|0)|0;if(!(QI(e,g,a,b)|0))e=f;else break}RI(c[a+(e<<2)>>2]|0,c[a+(d<<2)>>2]|0,c[a+(g<<2)>>2]|0);b=b+-1|0;while(1){if((d|0)>=(b|0))continue a;g=d+1|0;c[a+(d<<2)>>2]=c[a+(g<<2)>>2];d=g}}if((b|0)==8){a=c[13918]|0;c[h>>2]=125503;c[h+4>>2]=324;c[h+8>>2]=125648;AL(a,125484,h)|0}else if((b|0)==9)RI(c[a>>2]|0,c[a+4>>2]|0,c[a+8>>2]|0);l=i;return}function JI(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;i=c[42545]|0;j=i+(a*52|0)|0;k=i+(b*52|0)|0;g=0;while(1){if((g|0)==3)break;l=i+(a*52|0)+4+(g<<4)|0;m=i+(a*52|0)+4+(g<<4)+4|0;n=i+(a*52|0)+4+(g<<4)+12|0;f=0;while(1){if((f|0)==3)break;o=c[c[l>>2]>>2]|0;h=c[c[i+(b*52|0)+4+(f<<4)>>2]>>2]|0;if((o|0)==(h|0)){d=c[c[i+(b*52|0)+4+(f<<4)+4>>2]>>2]|0;if((c[c[m>>2]>>2]|0)==(d|0))e=10;else e=8}else{d=c[c[i+(b*52|0)+4+(f<<4)+4>>2]>>2]|0;e=8}if(((e|0)==8?(e=0,(o|0)==(d|0)):0)?(c[c[m>>2]>>2]|0)==(h|0):0)e=10;if((e|0)==10){c[n>>2]=k;c[i+(b*52|0)+4+(f<<4)+12>>2]=j}f=f+1|0}g=g+1|0}return}function KI(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=c[42545]|0;d=0;e=0;while(1){if((e|0)==3)break;d=d+((HI(c[c[f+(a*52|0)+4+(e<<4)>>2]>>2]|0,c[c[f+(a*52|0)+4+(e<<4)+4>>2]>>2]|0,b)|0)!=2&1)|0;e=e+1|0}return ((d|0)==3|(d|0)==0)&1|0}function LI(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=c[42545]|0;e=d+(a*52|0)|0;a:do if(!(c[e>>2]|0)){c[e>>2]=1;if((a|0)==(b|0))d=1;else{f=0;while(1){if((f|0)>=3)break;e=c[d+(a*52|0)+4+(f<<4)+12>>2]|0;if(e){if(LI((e-d|0)/52|0,b)|0){d=1;break a}d=c[42545]|0}f=f+1|0}c[d+(a*52|0)>>2]=0;d=0}}else d=0;while(0);return d|0}function MI(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+32|0;e=f+16|0;d=f;if((c[42546]|0)<(a|0)){b=c[42544]|0;if(!b){e=_I(a<<4)|0;c[42544]=e;if(!e){e=c[13918]|0;c[d>>2]=125503;c[d+4>>2]=593;c[d+8>>2]=125611;AL(e,125484,d)|0;Ua(169984,1)}}else{d=bJ(b,a<<4)|0;c[42544]=d;if(!d){d=c[13918]|0;c[e>>2]=125503;c[e+4>>2]=599;c[e+8>>2]=125629;AL(d,125484,e)|0;Ua(169984,1)}}c[42546]=a}l=f;return}function NI(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=c[42540]|0;e=c[42539]|0;f=(d|0)>=(e|0);if((a|0)==1)if(f){c[b+4>>2]=c[(c[42537]|0)+(e<<2)>>2];a=170156;d=-1}else{a=170156;d=-1}else if(f){c[b+4>>2]=c[(c[42537]|0)+(d<<2)>>2];a=170160;d=1}else{a=170160;d=1}f=(c[a>>2]|0)+d|0;c[a>>2]=f;c[(c[42537]|0)+(f<<2)>>2]=b;return}function OI(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;f=c[42541]|0;g=c[42537]|0;b=c[42539]|0;while(1){if((b|0)>=(f|0)){e=4;break}d=b+1|0;if((HI(c[c[g+(d<<2)>>2]>>2]|0,c[c[g+(b<<2)>>2]>>2]|0,c[a>>2]|0)|0)==1)break;else b=d}a:do if((e|0)==4){b=c[42540]|0;while(1){if((b|0)<=(f|0)){b=f;break a}d=b+-1|0;if((HI(c[c[g+(d<<2)>>2]>>2]|0,c[c[g+(b<<2)>>2]>>2]|0,c[a>>2]|0)|0)==2)break;else b=d}}while(0);return b|0}function PI(a,b){a=a|0;b=b|0;c[((a|0)==1?170160:170156)>>2]=b;return}function QI(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;f=c[c[d+(((a+-1+e|0)%(e|0)|0)<<2)>>2]>>2]|0;i=c[c[d+(a<<2)>>2]>>2]|0;g=c[c[d+(((a+1|0)%(e|0)|0)<<2)>>2]>>2]|0;k=(HI(f,i,g)|0)==1;j=c[c[d+(b<<2)>>2]>>2]|0;if(k)if((HI(i,j,f)|0)==1){f=HI(j,i,g)|0;g=1;h=5}else f=0;else{f=HI(i,j,g)|0;g=2;h=5}a:do if((h|0)==5)if((f|0)==(g|0)){f=0;while(1){if((f|0)>=(e|0)){f=1;break a}g=f;f=f+1|0;h=(f|0)%(e|0)|0;if((h|0)==(b|0)|((g|0)==(b|0)|((g|0)==(a|0)|(h|0)==(a|0))))continue;if(TI(i,j,c[c[d+(g<<2)>>2]>>2]|0,c[c[d+(h<<2)>>2]>>2]|0)|0){f=0;break}}}else f=0;while(0);return f|0}function RI(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=c[42536]|0;f=c[42547]|0;if((e|0)<(f|0))h=e;else{SI(f+20|0);h=c[42536]|0}g=c[42545]|0;c[42536]=h+1;f=g+(h*52|0)|0;c[f>>2]=0;c[g+(h*52|0)+4>>2]=a;c[g+(h*52|0)+8>>2]=b;c[g+(h*52|0)+16>>2]=0;c[g+(h*52|0)+20>>2]=b;c[g+(h*52|0)+24>>2]=d;c[g+(h*52|0)+32>>2]=0;c[g+(h*52|0)+36>>2]=d;c[g+(h*52|0)+40>>2]=a;c[g+(h*52|0)+48>>2]=0;e=0;while(1){if((e|0)==3)break;c[g+(h*52|0)+4+(e<<4)+8>>2]=f;e=e+1|0}return}function SI(a){a=a|0;var b=0,d=0,e=0,f=0;f=l;l=l+32|0;e=f+16|0;d=f;if((c[42547]|0)<(a|0)){b=c[42545]|0;if(!b){e=_I(a*52|0)|0;c[42545]=e;if(!e){e=c[13918]|0;c[d>>2]=125503;c[d+4>>2]=552;c[d+8>>2]=125669;AL(e,125484,d)|0;Ua(169984,1)}}else{d=bJ(b,a*52|0)|0;c[42545]=d;if(!d){d=c[13918]|0;c[e>>2]=125503;c[e+4>>2]=558;c[e+8>>2]=125688;AL(d,125484,e)|0;Ua(169984,1)}}c[42547]=a}l=f;return}function TI(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;f=HI(a,b,c)|0;if((((f|0)!=3?(g=HI(a,b,d)|0,(g|0)!=3):0)?(h=HI(c,d,a)|0,(h|0)!=3):0)?(e=HI(c,d,b)|0,(e|0)!=3):0)return ((f|0)==1^(g|0)==1)&((h|0)==1^(e|0)==1)&1|0;if(((UI(a,b,c)|0)==0?(UI(a,b,d)|0)==0:0)?(UI(c,d,a)|0)==0:0)return (UI(c,d,b)|0)!=0|0;return 1}function UI(a,b,c){a=a|0;b=b|0;c=c|0;var d=0.0,e=0.0,f=0.0,g=0.0;e=+h[a>>3];g=+h[b>>3]-e;f=+h[a+8>>3];d=+h[b+8>>3]-f;e=+h[c>>3]-e;f=+h[c+8>>3]-f;if((HI(a,b,c)|0)==3?f*d+e*g>=0.0:0)a=f*f+e*e<=d*d+g*g&1;else a=0;return a|0}function VI(a,b){a=a|0;b=b|0;var c=0,d=0.0,e=0.0,f=0.0,g=0.0,i=0.0,j=0;d=+h[a+24>>3];a:do if(d<1.0e-07&d>-1.0e-07)a=WI(a,b)|0;else{g=+h[a+16>>3]/(d*3.0);f=+h[a+8>>3]/d;e=g*g;d=g*2.0*e-g*f+ +h[a>>3]/d;e=f*.3333333333333333-e;e=e*e*4.0*e;f=d*d+e;if(!(f<0.0)){i=(+C(+f)-d)*.5;e=+KJ(i);d=+KJ(-d-i)+e;h[b>>3]=d;if(f>0.0)a=1;else{d=d*-.5;h[b+16>>3]=d;a=1;c=7}}else{i=+K(+(+C(+-f)),+-d);d=+KJ(+C(+-e)*.5)*2.0;h[b>>3]=d*+E(+(i*.3333333333333333));h[b+8>>3]=+E(+((i+6.283185307179586)*.3333333333333333))*d;d=+E(+((i+-6.283185307179586)*.3333333333333333))*d;a=2;c=7}if((c|0)==7){h[b+(a<<3)>>3]=d;a=3}c=0;while(1){if((c|0)>=(a|0))break a;j=b+(c<<3)|0;h[j>>3]=+h[j>>3]-g;c=c+1|0}}while(0);return a|0}function WI(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;c=+h[a+16>>3];do if(!(c<1.0e-07&c>-1.0e-07)){d=+h[a+8>>3]/(c*2.0);c=d*d-+h[a>>3]/c;if(!(c<0.0))if(c==0.0){h[b>>3]=-d;a=1;break}else{c=+C(+c)-d;h[b>>3]=c;h[b+8>>3]=d*-2.0-c;a=2;break}else a=0}else a=XI(a,b)|0;while(0);return a|0}function XI(a,b){a=a|0;b=b|0;var c=0.0,d=0.0;d=+h[a+8>>3];c=+h[a>>3];if(d<1.0e-07&d>-1.0e-07)a=c<1.0e-07&c>-1.0e-07?4:0;else{h[b>>3]=-c/d;a=1}return a|0}function YI(a){a=a|0;$I(c[a>>2]|0);$I(a);return}function ZI(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;e=c[a+4>>2]|0;i=(e*3|0)+-2|0;d=c[42550]|0;if((i|0)>(c[42549]|0)){if(!d)d=_I(i<<4)|0;else d=bJ(d,i<<4)|0;c[42550]=d;c[42549]=i;h=d;g=d}else{h=d;g=d}f=c[a>>2]|0;c[h>>2]=c[f>>2];c[h+4>>2]=c[f+4>>2];c[h+8>>2]=c[f+8>>2];c[h+12>>2]=c[f+12>>2];VN(h+16|0,f|0,16)|0;e=e+-1|0;d=1;a=2;while(1){if((d|0)>=(e|0))break;j=h+(a+2<<4)|0;k=h+(a+1<<4)|0;m=h+(a<<4)|0;l=f+(d<<4)|0;c[m>>2]=c[l>>2];c[m+4>>2]=c[l+4>>2];c[m+8>>2]=c[l+8>>2];c[m+12>>2]=c[l+12>>2];VN(k|0,l|0,16)|0;c[j>>2]=c[k>>2];c[j+4>>2]=c[k+4>>2];c[j+8>>2]=c[k+8>>2];c[j+12>>2]=c[k+12>>2];d=d+1|0;a=a+3|0}l=h+(a<<4)|0;m=f+(d<<4)|0;c[l>>2]=c[m>>2];c[l+4>>2]=c[m+4>>2];c[l+8>>2]=c[m+8>>2];c[l+12>>2]=c[m+12>>2];VN(h+(a+1<<4)|0,m|0,16)|0;c[b+4>>2]=i;c[b>>2]=g;return}function _I(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;x=l;l=l+16|0;p=x;do if(a>>>0<245){m=a>>>0<11?16:a+11&-8;a=m>>>3;o=c[42551]|0;d=o>>>a;if(d&3|0){b=(d&1^1)+a|0;a=170244+(b<<1<<2)|0;d=a+8|0;e=c[d>>2]|0;f=e+8|0;g=c[f>>2]|0;if((g|0)==(a|0))c[42551]=o&~(1<>2]=a;c[d>>2]=g}w=b<<3;c[e+4>>2]=w|3;w=e+w+4|0;c[w>>2]=c[w>>2]|1;w=f;l=x;return w|0}n=c[42553]|0;if(m>>>0>n>>>0){if(d|0){b=2<>>12&16;b=b>>>i;d=b>>>5&8;b=b>>>d;g=b>>>2&4;b=b>>>g;a=b>>>1&2;b=b>>>a;e=b>>>1&1;e=(d|i|g|a|e)+(b>>>e)|0;b=170244+(e<<1<<2)|0;a=b+8|0;g=c[a>>2]|0;i=g+8|0;d=c[i>>2]|0;if((d|0)==(b|0)){a=o&~(1<>2]=b;c[a>>2]=d;a=o}w=e<<3;h=w-m|0;c[g+4>>2]=m|3;f=g+m|0;c[f+4>>2]=h|1;c[g+w>>2]=h;if(n|0){e=c[42556]|0;b=n>>>3;d=170244+(b<<1<<2)|0;b=1<>2]|0}c[a>>2]=e;c[b+12>>2]=e;c[e+8>>2]=b;c[e+12>>2]=d}c[42553]=h;c[42556]=f;w=i;l=x;return w|0}j=c[42552]|0;if(j){d=(j&0-j)+-1|0;i=d>>>12&16;d=d>>>i;h=d>>>5&8;d=d>>>h;k=d>>>2&4;d=d>>>k;e=d>>>1&2;d=d>>>e;a=d>>>1&1;a=c[170508+((h|i|k|e|a)+(d>>>a)<<2)>>2]|0;d=(c[a+4>>2]&-8)-m|0;e=c[a+16+(((c[a+16>>2]|0)==0&1)<<2)>>2]|0;if(!e){k=a;h=d}else{do{i=(c[e+4>>2]&-8)-m|0;k=i>>>0>>0;d=k?i:d;a=k?e:a;e=c[e+16+(((c[e+16>>2]|0)==0&1)<<2)>>2]|0}while((e|0)!=0);k=a;h=d}i=k+m|0;if(i>>>0>k>>>0){f=c[k+24>>2]|0;b=c[k+12>>2]|0;do if((b|0)==(k|0)){a=k+20|0;b=c[a>>2]|0;if(!b){a=k+16|0;b=c[a>>2]|0;if(!b){d=0;break}}while(1){d=b+20|0;e=c[d>>2]|0;if(e|0){b=e;a=d;continue}d=b+16|0;e=c[d>>2]|0;if(!e)break;else{b=e;a=d}}c[a>>2]=0;d=b}else{d=c[k+8>>2]|0;c[d+12>>2]=b;c[b+8>>2]=d;d=b}while(0);do if(f|0){b=c[k+28>>2]|0;a=170508+(b<<2)|0;if((k|0)==(c[a>>2]|0)){c[a>>2]=d;if(!d){c[42552]=j&~(1<>2]|0)!=(k|0)&1)<<2)>>2]=d;if(!d)break}c[d+24>>2]=f;b=c[k+16>>2]|0;if(b|0){c[d+16>>2]=b;c[b+24>>2]=d}b=c[k+20>>2]|0;if(b|0){c[d+20>>2]=b;c[b+24>>2]=d}}while(0);if(h>>>0<16){w=h+m|0;c[k+4>>2]=w|3;w=k+w+4|0;c[w>>2]=c[w>>2]|1}else{c[k+4>>2]=m|3;c[i+4>>2]=h|1;c[i+h>>2]=h;if(n|0){e=c[42556]|0;b=n>>>3;d=170244+(b<<1<<2)|0;b=1<>2]|0}c[a>>2]=e;c[b+12>>2]=e;c[e+8>>2]=b;c[e+12>>2]=d}c[42553]=h;c[42556]=i}w=k+8|0;l=x;return w|0}else n=m}else n=m}else n=m}else if(a>>>0<=4294967231){a=a+11|0;m=a&-8;k=c[42552]|0;if(k){e=0-m|0;a=a>>>8;if(a)if(m>>>0>16777215)j=31;else{o=(a+1048320|0)>>>16&8;v=a<>>16&4;v=v<>>16&2;j=14-(n|o|j)+(v<>>15)|0;j=m>>>(j+7|0)&1|j<<1}else j=0;d=c[170508+(j<<2)>>2]|0;a:do if(!d){d=0;a=0;v=57}else{a=0;i=d;h=m<<((j|0)==31?0:25-(j>>>1)|0);d=0;while(1){f=(c[i+4>>2]&-8)-m|0;if(f>>>0>>0)if(!f){e=0;d=i;a=i;v=61;break a}else{a=i;e=f}f=c[i+20>>2]|0;i=c[i+16+(h>>>31<<2)>>2]|0;d=(f|0)==0|(f|0)==(i|0)?d:f;f=(i|0)==0;if(f){v=57;break}else h=h<<((f^1)&1)}}while(0);if((v|0)==57){if((d|0)==0&(a|0)==0){a=2<>>12&16;o=o>>>i;h=o>>>5&8;o=o>>>h;j=o>>>2&4;o=o>>>j;n=o>>>1&2;o=o>>>n;d=o>>>1&1;a=0;d=c[170508+((h|i|j|n|d)+(o>>>d)<<2)>>2]|0}if(!d){i=a;h=e}else v=61}if((v|0)==61)while(1){v=0;n=(c[d+4>>2]&-8)-m|0;o=n>>>0>>0;e=o?n:e;a=o?d:a;d=c[d+16+(((c[d+16>>2]|0)==0&1)<<2)>>2]|0;if(!d){i=a;h=e;break}else v=61}if((i|0)!=0?h>>>0<((c[42553]|0)-m|0)>>>0:0){g=i+m|0;if(g>>>0<=i>>>0){w=0;l=x;return w|0}f=c[i+24>>2]|0;b=c[i+12>>2]|0;do if((b|0)==(i|0)){a=i+20|0;b=c[a>>2]|0;if(!b){a=i+16|0;b=c[a>>2]|0;if(!b){b=0;break}}while(1){d=b+20|0;e=c[d>>2]|0;if(e|0){b=e;a=d;continue}d=b+16|0;e=c[d>>2]|0;if(!e)break;else{b=e;a=d}}c[a>>2]=0}else{w=c[i+8>>2]|0;c[w+12>>2]=b;c[b+8>>2]=w}while(0);do if(f){a=c[i+28>>2]|0;d=170508+(a<<2)|0;if((i|0)==(c[d>>2]|0)){c[d>>2]=b;if(!b){e=k&~(1<>2]|0)!=(i|0)&1)<<2)>>2]=b;if(!b){e=k;break}}c[b+24>>2]=f;a=c[i+16>>2]|0;if(a|0){c[b+16>>2]=a;c[a+24>>2]=b}a=c[i+20>>2]|0;if(a){c[b+20>>2]=a;c[a+24>>2]=b;e=k}else e=k}else e=k;while(0);do if(h>>>0>=16){c[i+4>>2]=m|3;c[g+4>>2]=h|1;c[g+h>>2]=h;b=h>>>3;if(h>>>0<256){d=170244+(b<<1<<2)|0;a=c[42551]|0;b=1<>2]|0}c[a>>2]=g;c[b+12>>2]=g;c[g+8>>2]=b;c[g+12>>2]=d;break}b=h>>>8;if(b)if(h>>>0>16777215)b=31;else{v=(b+1048320|0)>>>16&8;w=b<>>16&4;w=w<>>16&2;b=14-(u|v|b)+(w<>>15)|0;b=h>>>(b+7|0)&1|b<<1}else b=0;d=170508+(b<<2)|0;c[g+28>>2]=b;a=g+16|0;c[a+4>>2]=0;c[a>>2]=0;a=1<>2]=g;c[g+24>>2]=d;c[g+12>>2]=g;c[g+8>>2]=g;break}a=h<<((b|0)==31?0:25-(b>>>1)|0);d=c[d>>2]|0;while(1){if((c[d+4>>2]&-8|0)==(h|0)){v=97;break}e=d+16+(a>>>31<<2)|0;b=c[e>>2]|0;if(!b){v=96;break}else{a=a<<1;d=b}}if((v|0)==96){c[e>>2]=g;c[g+24>>2]=d;c[g+12>>2]=g;c[g+8>>2]=g;break}else if((v|0)==97){v=d+8|0;w=c[v>>2]|0;c[w+12>>2]=g;c[v>>2]=g;c[g+8>>2]=w;c[g+12>>2]=d;c[g+24>>2]=0;break}}else{w=h+m|0;c[i+4>>2]=w|3;w=i+w+4|0;c[w>>2]=c[w>>2]|1}while(0);w=i+8|0;l=x;return w|0}else n=m}else n=m}else n=-1;while(0);d=c[42553]|0;if(d>>>0>=n>>>0){b=d-n|0;a=c[42556]|0;if(b>>>0>15){w=a+n|0;c[42556]=w;c[42553]=b;c[w+4>>2]=b|1;c[a+d>>2]=b;c[a+4>>2]=n|3}else{c[42553]=0;c[42556]=0;c[a+4>>2]=d|3;w=a+d+4|0;c[w>>2]=c[w>>2]|1}w=a+8|0;l=x;return w|0}i=c[42554]|0;if(i>>>0>n>>>0){u=i-n|0;c[42554]=u;w=c[42557]|0;v=w+n|0;c[42557]=v;c[v+4>>2]=u|1;c[w+4>>2]=n|3;w=w+8|0;l=x;return w|0}if(!(c[42669]|0)){c[42671]=4096;c[42670]=4096;c[42672]=-1;c[42673]=-1;c[42674]=0;c[42662]=0;c[42669]=p&-16^1431655768;a=4096}else a=c[42671]|0;j=n+48|0;k=n+47|0;h=a+k|0;f=0-a|0;m=h&f;if(m>>>0<=n>>>0){w=0;l=x;return w|0}a=c[42661]|0;if(a|0?(o=c[42659]|0,p=o+m|0,p>>>0<=o>>>0|p>>>0>a>>>0):0){w=0;l=x;return w|0}b:do if(!(c[42662]&4)){d=c[42557]|0;c:do if(d){e=170652;while(1){a=c[e>>2]|0;if(a>>>0<=d>>>0?(s=e+4|0,(a+(c[s>>2]|0)|0)>>>0>d>>>0):0)break;a=c[e+8>>2]|0;if(!a){v=118;break c}else e=a}b=h-i&f;if(b>>>0<2147483647){a=XN(b|0)|0;if((a|0)==((c[e>>2]|0)+(c[s>>2]|0)|0)){if((a|0)!=(-1|0)){h=b;g=a;v=135;break b}}else{e=a;v=126}}else b=0}else v=118;while(0);do if((v|0)==118){d=XN(0)|0;if((d|0)!=(-1|0)?(b=d,q=c[42670]|0,r=q+-1|0,b=((r&b|0)==0?0:(r+b&0-q)-b|0)+m|0,q=c[42659]|0,r=b+q|0,b>>>0>n>>>0&b>>>0<2147483647):0){s=c[42661]|0;if(s|0?r>>>0<=q>>>0|r>>>0>s>>>0:0){b=0;break}a=XN(b|0)|0;if((a|0)==(d|0)){h=b;g=d;v=135;break b}else{e=a;v=126}}else b=0}while(0);do if((v|0)==126){d=0-b|0;if(!(j>>>0>b>>>0&(b>>>0<2147483647&(e|0)!=(-1|0))))if((e|0)==(-1|0)){b=0;break}else{h=b;g=e;v=135;break b}a=c[42671]|0;a=k-b+a&0-a;if(a>>>0>=2147483647){h=b;g=e;v=135;break b}if((XN(a|0)|0)==(-1|0)){XN(d|0)|0;b=0;break}else{h=a+b|0;g=e;v=135;break b}}while(0);c[42662]=c[42662]|4;v=133}else{b=0;v=133}while(0);if(((v|0)==133?m>>>0<2147483647:0)?(g=XN(m|0)|0,s=XN(0)|0,t=s-g|0,u=t>>>0>(n+40|0)>>>0,!((g|0)==(-1|0)|u^1|g>>>0>>0&((g|0)!=(-1|0)&(s|0)!=(-1|0))^1)):0){h=u?t:b;v=135}if((v|0)==135){b=(c[42659]|0)+h|0;c[42659]=b;if(b>>>0>(c[42660]|0)>>>0)c[42660]=b;j=c[42557]|0;do if(j){b=170652;while(1){a=c[b>>2]|0;d=b+4|0;e=c[d>>2]|0;if((g|0)==(a+e|0)){v=143;break}f=c[b+8>>2]|0;if(!f)break;else b=f}if(((v|0)==143?(c[b+12>>2]&8|0)==0:0)?g>>>0>j>>>0&a>>>0<=j>>>0:0){c[d>>2]=e+h;w=(c[42554]|0)+h|0;u=j+8|0;u=(u&7|0)==0?0:0-u&7;v=j+u|0;u=w-u|0;c[42557]=v;c[42554]=u;c[v+4>>2]=u|1;c[j+w+4>>2]=40;c[42558]=c[42673];break}if(g>>>0<(c[42555]|0)>>>0)c[42555]=g;a=g+h|0;b=170652;while(1){if((c[b>>2]|0)==(a|0)){v=151;break}b=c[b+8>>2]|0;if(!b){a=170652;break}}if((v|0)==151)if(!(c[b+12>>2]&8)){c[b>>2]=g;m=b+4|0;c[m>>2]=(c[m>>2]|0)+h;m=g+8|0;m=g+((m&7|0)==0?0:0-m&7)|0;b=a+8|0;b=a+((b&7|0)==0?0:0-b&7)|0;k=m+n|0;i=b-m-n|0;c[m+4>>2]=n|3;do if((j|0)!=(b|0)){if((c[42556]|0)==(b|0)){w=(c[42553]|0)+i|0;c[42553]=w;c[42556]=k;c[k+4>>2]=w|1;c[k+w>>2]=w;break}a=c[b+4>>2]|0;if((a&3|0)==1){h=a&-8;e=a>>>3;d:do if(a>>>0<256){a=c[b+8>>2]|0;d=c[b+12>>2]|0;if((d|0)==(a|0)){c[42551]=c[42551]&~(1<>2]=d;c[d+8>>2]=a;break}}else{g=c[b+24>>2]|0;a=c[b+12>>2]|0;do if((a|0)==(b|0)){e=b+16|0;d=e+4|0;a=c[d>>2]|0;if(!a){a=c[e>>2]|0;if(!a){a=0;break}else d=e}while(1){e=a+20|0;f=c[e>>2]|0;if(f|0){a=f;d=e;continue}e=a+16|0;f=c[e>>2]|0;if(!f)break;else{a=f;d=e}}c[d>>2]=0}else{w=c[b+8>>2]|0;c[w+12>>2]=a;c[a+8>>2]=w}while(0);if(!g)break;d=c[b+28>>2]|0;e=170508+(d<<2)|0;do if((c[e>>2]|0)!=(b|0)){c[g+16+(((c[g+16>>2]|0)!=(b|0)&1)<<2)>>2]=a;if(!a)break d}else{c[e>>2]=a;if(a|0)break;c[42552]=c[42552]&~(1<>2]=g;d=b+16|0;e=c[d>>2]|0;if(e|0){c[a+16>>2]=e;c[e+24>>2]=a}d=c[d+4>>2]|0;if(!d)break;c[a+20>>2]=d;c[d+24>>2]=a}while(0);b=b+h|0;f=h+i|0}else f=i;b=b+4|0;c[b>>2]=c[b>>2]&-2;c[k+4>>2]=f|1;c[k+f>>2]=f;b=f>>>3;if(f>>>0<256){d=170244+(b<<1<<2)|0;a=c[42551]|0;b=1<>2]|0}c[a>>2]=k;c[b+12>>2]=k;c[k+8>>2]=b;c[k+12>>2]=d;break}b=f>>>8;do if(!b)b=0;else{if(f>>>0>16777215){b=31;break}v=(b+1048320|0)>>>16&8;w=b<>>16&4;w=w<>>16&2;b=14-(u|v|b)+(w<>>15)|0;b=f>>>(b+7|0)&1|b<<1}while(0);e=170508+(b<<2)|0;c[k+28>>2]=b;a=k+16|0;c[a+4>>2]=0;c[a>>2]=0;a=c[42552]|0;d=1<>2]=k;c[k+24>>2]=e;c[k+12>>2]=k;c[k+8>>2]=k;break}a=f<<((b|0)==31?0:25-(b>>>1)|0);d=c[e>>2]|0;while(1){if((c[d+4>>2]&-8|0)==(f|0)){v=192;break}e=d+16+(a>>>31<<2)|0;b=c[e>>2]|0;if(!b){v=191;break}else{a=a<<1;d=b}}if((v|0)==191){c[e>>2]=k;c[k+24>>2]=d;c[k+12>>2]=k;c[k+8>>2]=k;break}else if((v|0)==192){v=d+8|0;w=c[v>>2]|0;c[w+12>>2]=k;c[v>>2]=k;c[k+8>>2]=w;c[k+12>>2]=d;c[k+24>>2]=0;break}}else{w=(c[42554]|0)+i|0;c[42554]=w;c[42557]=k;c[k+4>>2]=w|1}while(0);w=m+8|0;l=x;return w|0}else a=170652;while(1){b=c[a>>2]|0;if(b>>>0<=j>>>0?(w=b+(c[a+4>>2]|0)|0,w>>>0>j>>>0):0)break;a=c[a+8>>2]|0}f=w+-47|0;a=f+8|0;a=f+((a&7|0)==0?0:0-a&7)|0;f=j+16|0;a=a>>>0>>0?j:a;b=a+8|0;d=h+-40|0;u=g+8|0;u=(u&7|0)==0?0:0-u&7;v=g+u|0;u=d-u|0;c[42557]=v;c[42554]=u;c[v+4>>2]=u|1;c[g+d+4>>2]=40;c[42558]=c[42673];d=a+4|0;c[d>>2]=27;c[b>>2]=c[42663];c[b+4>>2]=c[42664];c[b+8>>2]=c[42665];c[b+12>>2]=c[42666];c[42663]=g;c[42664]=h;c[42666]=0;c[42665]=b;b=a+24|0;do{v=b;b=b+4|0;c[b>>2]=7}while((v+8|0)>>>0>>0);if((a|0)!=(j|0)){g=a-j|0;c[d>>2]=c[d>>2]&-2;c[j+4>>2]=g|1;c[a>>2]=g;b=g>>>3;if(g>>>0<256){d=170244+(b<<1<<2)|0;a=c[42551]|0;b=1<>2]|0}c[a>>2]=j;c[b+12>>2]=j;c[j+8>>2]=b;c[j+12>>2]=d;break}b=g>>>8;if(b)if(g>>>0>16777215)d=31;else{v=(b+1048320|0)>>>16&8;w=b<>>16&4;w=w<>>16&2;d=14-(u|v|d)+(w<>>15)|0;d=g>>>(d+7|0)&1|d<<1}else d=0;e=170508+(d<<2)|0;c[j+28>>2]=d;c[j+20>>2]=0;c[f>>2]=0;b=c[42552]|0;a=1<>2]=j;c[j+24>>2]=e;c[j+12>>2]=j;c[j+8>>2]=j;break}a=g<<((d|0)==31?0:25-(d>>>1)|0);d=c[e>>2]|0;while(1){if((c[d+4>>2]&-8|0)==(g|0)){v=213;break}e=d+16+(a>>>31<<2)|0;b=c[e>>2]|0;if(!b){v=212;break}else{a=a<<1;d=b}}if((v|0)==212){c[e>>2]=j;c[j+24>>2]=d;c[j+12>>2]=j;c[j+8>>2]=j;break}else if((v|0)==213){v=d+8|0;w=c[v>>2]|0;c[w+12>>2]=j;c[v>>2]=j;c[j+8>>2]=w;c[j+12>>2]=d;c[j+24>>2]=0;break}}}else{w=c[42555]|0;if((w|0)==0|g>>>0>>0)c[42555]=g;c[42663]=g;c[42664]=h;c[42666]=0;c[42560]=c[42669];c[42559]=-1;c[42564]=170244;c[42563]=170244;c[42566]=170252;c[42565]=170252;c[42568]=170260;c[42567]=170260;c[42570]=170268;c[42569]=170268;c[42572]=170276;c[42571]=170276;c[42574]=170284;c[42573]=170284;c[42576]=170292;c[42575]=170292;c[42578]=170300;c[42577]=170300;c[42580]=170308;c[42579]=170308;c[42582]=170316;c[42581]=170316;c[42584]=170324;c[42583]=170324;c[42586]=170332;c[42585]=170332;c[42588]=170340;c[42587]=170340;c[42590]=170348;c[42589]=170348;c[42592]=170356;c[42591]=170356;c[42594]=170364;c[42593]=170364;c[42596]=170372;c[42595]=170372;c[42598]=170380;c[42597]=170380;c[42600]=170388;c[42599]=170388;c[42602]=170396;c[42601]=170396;c[42604]=170404;c[42603]=170404;c[42606]=170412;c[42605]=170412;c[42608]=170420;c[42607]=170420;c[42610]=170428;c[42609]=170428;c[42612]=170436;c[42611]=170436;c[42614]=170444;c[42613]=170444;c[42616]=170452;c[42615]=170452;c[42618]=170460;c[42617]=170460;c[42620]=170468;c[42619]=170468;c[42622]=170476;c[42621]=170476;c[42624]=170484;c[42623]=170484;c[42626]=170492;c[42625]=170492;w=h+-40|0;u=g+8|0;u=(u&7|0)==0?0:0-u&7;v=g+u|0;u=w-u|0;c[42557]=v;c[42554]=u;c[v+4>>2]=u|1;c[g+w+4>>2]=40;c[42558]=c[42673]}while(0);b=c[42554]|0;if(b>>>0>n>>>0){u=b-n|0;c[42554]=u;w=c[42557]|0;v=w+n|0;c[42557]=v;c[v+4>>2]=u|1;c[w+4>>2]=n|3;w=w+8|0;l=x;return w|0}}c[(kJ()|0)>>2]=12;w=0;l=x;return w|0}function $I(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;if(!a)return;d=a+-8|0;f=c[42555]|0;a=c[a+-4>>2]|0;b=a&-8;j=d+b|0;do if(!(a&1)){e=c[d>>2]|0;if(!(a&3))return;h=d+(0-e)|0;g=e+b|0;if(h>>>0>>0)return;if((c[42556]|0)==(h|0)){a=j+4|0;b=c[a>>2]|0;if((b&3|0)!=3){i=h;b=g;break}c[42553]=g;c[a>>2]=b&-2;c[h+4>>2]=g|1;c[h+g>>2]=g;return}d=e>>>3;if(e>>>0<256){a=c[h+8>>2]|0;b=c[h+12>>2]|0;if((b|0)==(a|0)){c[42551]=c[42551]&~(1<>2]=b;c[b+8>>2]=a;i=h;b=g;break}}f=c[h+24>>2]|0;a=c[h+12>>2]|0;do if((a|0)==(h|0)){d=h+16|0;b=d+4|0;a=c[b>>2]|0;if(!a){a=c[d>>2]|0;if(!a){a=0;break}else b=d}while(1){d=a+20|0;e=c[d>>2]|0;if(e|0){a=e;b=d;continue}d=a+16|0;e=c[d>>2]|0;if(!e)break;else{a=e;b=d}}c[b>>2]=0}else{i=c[h+8>>2]|0;c[i+12>>2]=a;c[a+8>>2]=i}while(0);if(f){b=c[h+28>>2]|0;d=170508+(b<<2)|0;if((c[d>>2]|0)==(h|0)){c[d>>2]=a;if(!a){c[42552]=c[42552]&~(1<>2]|0)!=(h|0)&1)<<2)>>2]=a;if(!a){i=h;b=g;break}}c[a+24>>2]=f;b=h+16|0;d=c[b>>2]|0;if(d|0){c[a+16>>2]=d;c[d+24>>2]=a}b=c[b+4>>2]|0;if(b){c[a+20>>2]=b;c[b+24>>2]=a;i=h;b=g}else{i=h;b=g}}else{i=h;b=g}}else{i=d;h=d}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;e=c[a>>2]|0;if(!(e&1))return;if(!(e&2)){if((c[42557]|0)==(j|0)){j=(c[42554]|0)+b|0;c[42554]=j;c[42557]=i;c[i+4>>2]=j|1;if((i|0)!=(c[42556]|0))return;c[42556]=0;c[42553]=0;return}if((c[42556]|0)==(j|0)){j=(c[42553]|0)+b|0;c[42553]=j;c[42556]=h;c[i+4>>2]=j|1;c[h+j>>2]=j;return}f=(e&-8)+b|0;d=e>>>3;do if(e>>>0<256){b=c[j+8>>2]|0;a=c[j+12>>2]|0;if((a|0)==(b|0)){c[42551]=c[42551]&~(1<>2]=a;c[a+8>>2]=b;break}}else{g=c[j+24>>2]|0;a=c[j+12>>2]|0;do if((a|0)==(j|0)){d=j+16|0;b=d+4|0;a=c[b>>2]|0;if(!a){a=c[d>>2]|0;if(!a){d=0;break}else b=d}while(1){d=a+20|0;e=c[d>>2]|0;if(e|0){a=e;b=d;continue}d=a+16|0;e=c[d>>2]|0;if(!e)break;else{a=e;b=d}}c[b>>2]=0;d=a}else{d=c[j+8>>2]|0;c[d+12>>2]=a;c[a+8>>2]=d;d=a}while(0);if(g|0){a=c[j+28>>2]|0;b=170508+(a<<2)|0;if((c[b>>2]|0)==(j|0)){c[b>>2]=d;if(!d){c[42552]=c[42552]&~(1<>2]|0)!=(j|0)&1)<<2)>>2]=d;if(!d)break}c[d+24>>2]=g;a=j+16|0;b=c[a>>2]|0;if(b|0){c[d+16>>2]=b;c[b+24>>2]=d}a=c[a+4>>2]|0;if(a|0){c[d+20>>2]=a;c[a+24>>2]=d}}}while(0);c[i+4>>2]=f|1;c[h+f>>2]=f;if((i|0)==(c[42556]|0)){c[42553]=f;return}}else{c[a>>2]=e&-2;c[i+4>>2]=b|1;c[h+b>>2]=b;f=b}a=f>>>3;if(f>>>0<256){d=170244+(a<<1<<2)|0;b=c[42551]|0;a=1<>2]|0}c[b>>2]=i;c[a+12>>2]=i;c[i+8>>2]=a;c[i+12>>2]=d;return}a=f>>>8;if(a)if(f>>>0>16777215)a=31;else{h=(a+1048320|0)>>>16&8;j=a<>>16&4;j=j<>>16&2;a=14-(g|h|a)+(j<>>15)|0;a=f>>>(a+7|0)&1|a<<1}else a=0;e=170508+(a<<2)|0;c[i+28>>2]=a;c[i+20>>2]=0;c[i+16>>2]=0;b=c[42552]|0;d=1<>>1)|0);d=c[e>>2]|0;while(1){if((c[d+4>>2]&-8|0)==(f|0)){a=73;break}e=d+16+(b>>>31<<2)|0;a=c[e>>2]|0;if(!a){a=72;break}else{b=b<<1;d=a}}if((a|0)==72){c[e>>2]=i;c[i+24>>2]=d;c[i+12>>2]=i;c[i+8>>2]=i;break}else if((a|0)==73){h=d+8|0;j=c[h>>2]|0;c[j+12>>2]=i;c[h>>2]=i;c[i+8>>2]=j;c[i+12>>2]=d;c[i+24>>2]=0;break}}else{c[42552]=b|d;c[e>>2]=i;c[i+24>>2]=e;c[i+12>>2]=i;c[i+8>>2]=i}while(0);j=(c[42559]|0)+-1|0;c[42559]=j;if(!j)a=170660;else return;while(1){a=c[a>>2]|0;if(!a)break;else a=a+8|0}c[42559]=-1;return}function aJ(a,b){a=a|0;b=b|0;var d=0;if(a){d=O(b,a)|0;if((b|a)>>>0>65535)d=((d>>>0)/(a>>>0)|0|0)==(b|0)?d:-1}else d=0;a=_I(d)|0;if(!a)return a|0;if(!(c[a+-4>>2]&3))return a|0;WN(a|0,0,d|0)|0;return a|0}function bJ(a,b){a=a|0;b=b|0;var d=0,e=0;if(!a){b=_I(b)|0;return b|0}if(b>>>0>4294967231){c[(kJ()|0)>>2]=12;b=0;return b|0}d=cJ(a+-8|0,b>>>0<11?16:b+11&-8)|0;if(d|0){b=d+8|0;return b|0}d=_I(b)|0;if(!d){b=0;return b|0}e=c[a+-4>>2]|0;e=(e&-8)-((e&3|0)==0?8:4)|0;UN(d|0,a|0,(e>>>0>>0?e:b)|0)|0;$I(a);b=d;return b|0}function cJ(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;l=a+4|0;m=c[l>>2]|0;d=m&-8;i=a+d|0;if(!(m&3)){if(b>>>0<256){a=0;return a|0}if(d>>>0>=(b+4|0)>>>0?(d-b|0)>>>0<=c[42671]<<1>>>0:0)return a|0;a=0;return a|0}if(d>>>0>=b>>>0){d=d-b|0;if(d>>>0<=15)return a|0;k=a+b|0;c[l>>2]=m&1|b|2;c[k+4>>2]=d|3;m=i+4|0;c[m>>2]=c[m>>2]|1;dJ(k,d);return a|0}if((c[42557]|0)==(i|0)){k=(c[42554]|0)+d|0;d=k-b|0;e=a+b|0;if(k>>>0<=b>>>0){a=0;return a|0}c[l>>2]=m&1|b|2;c[e+4>>2]=d|1;c[42557]=e;c[42554]=d;return a|0}if((c[42556]|0)==(i|0)){e=(c[42553]|0)+d|0;if(e>>>0>>0){a=0;return a|0}d=e-b|0;if(d>>>0>15){k=a+b|0;e=a+e|0;c[l>>2]=m&1|b|2;c[k+4>>2]=d|1;c[e>>2]=d;e=e+4|0;c[e>>2]=c[e>>2]&-2;e=k}else{c[l>>2]=m&1|e|2;e=a+e+4|0;c[e>>2]=c[e>>2]|1;e=0;d=0}c[42553]=d;c[42556]=e;return a|0}e=c[i+4>>2]|0;if(e&2|0){a=0;return a|0}j=(e&-8)+d|0;if(j>>>0>>0){a=0;return a|0}k=j-b|0;f=e>>>3;do if(e>>>0<256){e=c[i+8>>2]|0;d=c[i+12>>2]|0;if((d|0)==(e|0)){c[42551]=c[42551]&~(1<>2]=d;c[d+8>>2]=e;break}}else{h=c[i+24>>2]|0;d=c[i+12>>2]|0;do if((d|0)==(i|0)){f=i+16|0;e=f+4|0;d=c[e>>2]|0;if(!d){d=c[f>>2]|0;if(!d){f=0;break}else g=f}else g=e;while(1){f=d+20|0;e=c[f>>2]|0;if(e|0){d=e;g=f;continue}e=d+16|0;f=c[e>>2]|0;if(!f)break;else{d=f;g=e}}c[g>>2]=0;f=d}else{f=c[i+8>>2]|0;c[f+12>>2]=d;c[d+8>>2]=f;f=d}while(0);if(h|0){d=c[i+28>>2]|0;e=170508+(d<<2)|0;if((c[e>>2]|0)==(i|0)){c[e>>2]=f;if(!f){c[42552]=c[42552]&~(1<>2]|0)!=(i|0)&1)<<2)>>2]=f;if(!f)break}c[f+24>>2]=h;d=i+16|0;e=c[d>>2]|0;if(e|0){c[f+16>>2]=e;c[e+24>>2]=f}d=c[d+4>>2]|0;if(d|0){c[f+20>>2]=d;c[d+24>>2]=f}}}while(0);if(k>>>0<16){c[l>>2]=j|m&1|2;m=a+j+4|0;c[m>>2]=c[m>>2]|1;return a|0}else{i=a+b|0;c[l>>2]=m&1|b|2;c[i+4>>2]=k|3;m=a+j+4|0;c[m>>2]=c[m>>2]|1;dJ(i,k);return a|0}return 0}function dJ(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;i=a+b|0;d=c[a+4>>2]|0;do if(!(d&1)){f=c[a>>2]|0;if(!(d&3))return;h=a+(0-f)|0;b=f+b|0;if((c[42556]|0)==(h|0)){a=i+4|0;d=c[a>>2]|0;if((d&3|0)!=3)break;c[42553]=b;c[a>>2]=d&-2;c[h+4>>2]=b|1;c[i>>2]=b;return}e=f>>>3;if(f>>>0<256){a=c[h+8>>2]|0;d=c[h+12>>2]|0;if((d|0)==(a|0)){c[42551]=c[42551]&~(1<>2]=d;c[d+8>>2]=a;break}}g=c[h+24>>2]|0;a=c[h+12>>2]|0;do if((a|0)==(h|0)){e=h+16|0;d=e+4|0;a=c[d>>2]|0;if(!a){a=c[e>>2]|0;if(!a){a=0;break}else d=e}while(1){e=a+20|0;f=c[e>>2]|0;if(f|0){a=f;d=e;continue}e=a+16|0;f=c[e>>2]|0;if(!f)break;else{a=f;d=e}}c[d>>2]=0}else{f=c[h+8>>2]|0;c[f+12>>2]=a;c[a+8>>2]=f}while(0);if(g){d=c[h+28>>2]|0;e=170508+(d<<2)|0;if((c[e>>2]|0)==(h|0)){c[e>>2]=a;if(!a){c[42552]=c[42552]&~(1<>2]|0)!=(h|0)&1)<<2)>>2]=a;if(!a)break}c[a+24>>2]=g;d=h+16|0;e=c[d>>2]|0;if(e|0){c[a+16>>2]=e;c[e+24>>2]=a}d=c[d+4>>2]|0;if(d){c[a+20>>2]=d;c[d+24>>2]=a}}}else h=a;while(0);a=i+4|0;e=c[a>>2]|0;if(!(e&2)){if((c[42557]|0)==(i|0)){i=(c[42554]|0)+b|0;c[42554]=i;c[42557]=h;c[h+4>>2]=i|1;if((h|0)!=(c[42556]|0))return;c[42556]=0;c[42553]=0;return}if((c[42556]|0)==(i|0)){i=(c[42553]|0)+b|0;c[42553]=i;c[42556]=h;c[h+4>>2]=i|1;c[h+i>>2]=i;return}f=(e&-8)+b|0;d=e>>>3;do if(e>>>0<256){a=c[i+8>>2]|0;b=c[i+12>>2]|0;if((b|0)==(a|0)){c[42551]=c[42551]&~(1<>2]=b;c[b+8>>2]=a;break}}else{g=c[i+24>>2]|0;b=c[i+12>>2]|0;do if((b|0)==(i|0)){d=i+16|0;a=d+4|0;b=c[a>>2]|0;if(!b){b=c[d>>2]|0;if(!b){d=0;break}else a=d}while(1){d=b+20|0;e=c[d>>2]|0;if(e|0){b=e;a=d;continue}d=b+16|0;e=c[d>>2]|0;if(!e)break;else{b=e;a=d}}c[a>>2]=0;d=b}else{d=c[i+8>>2]|0;c[d+12>>2]=b;c[b+8>>2]=d;d=b}while(0);if(g|0){b=c[i+28>>2]|0;a=170508+(b<<2)|0;if((c[a>>2]|0)==(i|0)){c[a>>2]=d;if(!d){c[42552]=c[42552]&~(1<>2]|0)!=(i|0)&1)<<2)>>2]=d;if(!d)break}c[d+24>>2]=g;b=i+16|0;a=c[b>>2]|0;if(a|0){c[d+16>>2]=a;c[a+24>>2]=d}b=c[b+4>>2]|0;if(b|0){c[d+20>>2]=b;c[b+24>>2]=d}}}while(0);c[h+4>>2]=f|1;c[h+f>>2]=f;if((h|0)==(c[42556]|0)){c[42553]=f;return}}else{c[a>>2]=e&-2;c[h+4>>2]=b|1;c[h+b>>2]=b;f=b}b=f>>>3;if(f>>>0<256){d=170244+(b<<1<<2)|0;a=c[42551]|0;b=1<>2]|0}c[a>>2]=h;c[b+12>>2]=h;c[h+8>>2]=b;c[h+12>>2]=d;return}b=f>>>8;if(b)if(f>>>0>16777215)b=31;else{g=(b+1048320|0)>>>16&8;i=b<>>16&4;i=i<>>16&2;b=14-(e|g|b)+(i<>>15)|0;b=f>>>(b+7|0)&1|b<<1}else b=0;e=170508+(b<<2)|0;c[h+28>>2]=b;c[h+20>>2]=0;c[h+16>>2]=0;a=c[42552]|0;d=1<>2]=h;c[h+24>>2]=e;c[h+12>>2]=h;c[h+8>>2]=h;return}a=f<<((b|0)==31?0:25-(b>>>1)|0);d=c[e>>2]|0;while(1){if((c[d+4>>2]&-8|0)==(f|0)){b=69;break}e=d+16+(a>>>31<<2)|0;b=c[e>>2]|0;if(!b){b=68;break}else{a=a<<1;d=b}}if((b|0)==68){c[e>>2]=h;c[h+24>>2]=d;c[h+12>>2]=h;c[h+8>>2]=h;return}else if((b|0)==69){g=d+8|0;i=c[g>>2]|0;c[i+12>>2]=h;c[g>>2]=h;c[h+8>>2]=i;c[h+12>>2]=d;c[h+24>>2]=0;return}}function eJ(a,b){a=a|0;b=b|0;if(a>>>0<9){b=_I(b)|0;return b|0}else{b=fJ(a,b)|0;return b|0}return 0}function fJ(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0;a=a>>>0>16?a:16;if(a+-1&a){d=16;while(1)if(d>>>0>>0)d=d<<1;else{a=d;break}}if((-64-a|0)>>>0<=b>>>0){c[(kJ()|0)>>2]=12;h=0;return h|0}g=b>>>0<11?16:b+11&-8;d=_I(g+12+a|0)|0;if(!d){h=0;return h|0}f=d+-8|0;do if(a+-1&d){e=(d+a+-1&0-a)+-8|0;b=f;e=(e-b|0)>>>0>15?e:e+a|0;b=e-b|0;a=d+-4|0;i=c[a>>2]|0;d=(i&-8)-b|0;if(!(i&3)){c[e>>2]=(c[f>>2]|0)+b;c[e+4>>2]=d;a=e;b=e;break}else{i=e+4|0;c[i>>2]=d|c[i>>2]&1|2;d=e+d+4|0;c[d>>2]=c[d>>2]|1;c[a>>2]=b|c[a>>2]&1|2;c[i>>2]=c[i>>2]|1;dJ(f,b);a=e;b=e;break}}else{a=f;b=f}while(0);a=a+4|0;d=c[a>>2]|0;if(d&3|0?(h=d&-8,h>>>0>(g+16|0)>>>0):0){i=h-g|0;f=b+g|0;c[a>>2]=g|d&1|2;c[f+4>>2]=i|3;h=b+h+4|0;c[h>>2]=c[h>>2]|1;dJ(f,i)}i=b+8|0;return i|0}function gJ(a){a=a|0;var b=0,d=0;b=l;l=l+16|0;d=b;c[d>>2]=lJ(c[a+60>>2]|0)|0;a=jJ(Da(6,d|0)|0)|0;l=b;return a|0}function hJ(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0;k=l;l=l+32|0;f=k;i=k+16|0;c[i>>2]=d;g=i+4|0;j=b+48|0;m=c[j>>2]|0;c[g>>2]=e-((m|0)!=0&1);h=b+44|0;c[i+8>>2]=c[h>>2];c[i+12>>2]=m;c[f>>2]=c[b+60>>2];c[f+4>>2]=i;c[f+8>>2]=2;f=jJ(ua(145,f|0)|0)|0;if((f|0)>=1){i=c[g>>2]|0;if(f>>>0>i>>>0){g=c[h>>2]|0;h=b+4|0;c[h>>2]=g;c[b+8>>2]=g+(f-i);if(!(c[j>>2]|0))f=e;else{c[h>>2]=g+1;a[d+(e+-1)>>0]=a[g>>0]|0;f=e}}}else c[b>>2]=c[b>>2]|f&48^16;l=k;return f|0}function iJ(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;f=l;l=l+32|0;g=f;e=f+20|0;c[g>>2]=c[a+60>>2];c[g+4>>2]=0;c[g+8>>2]=b;c[g+12>>2]=e;c[g+16>>2]=d;if((jJ(ta(140,g|0)|0)|0)<0){c[e>>2]=-1;a=-1}else a=c[e>>2]|0;l=f;return a|0}function jJ(a){a=a|0;if(a>>>0>4294963200){c[(kJ()|0)>>2]=0-a;a=-1}return a|0}function kJ(){return 170700}function lJ(a){a=a|0;return a|0}function mJ(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0;g=l;l=l+32|0;f=g;c[b+36>>2]=9;if((c[b>>2]&64|0)==0?(c[f>>2]=c[b+60>>2],c[f+4>>2]=21523,c[f+8>>2]=g+16,Ca(54,f|0)|0):0)a[b+75>>0]=-1;f=nJ(b,d,e)|0;l=g;return f|0}function nJ(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;n=l;l=l+48|0;k=n+16|0;g=n;f=n+32|0;i=a+28|0;e=c[i>>2]|0;c[f>>2]=e;j=a+20|0;e=(c[j>>2]|0)-e|0;c[f+4>>2]=e;c[f+8>>2]=b;c[f+12>>2]=d;e=e+d|0;h=a+60|0;c[g>>2]=c[h>>2];c[g+4>>2]=f;c[g+8>>2]=2;g=jJ(va(146,g|0)|0)|0;a:do if((e|0)!=(g|0)){b=2;while(1){if((g|0)<0)break;e=e-g|0;p=c[f+4>>2]|0;o=g>>>0>p>>>0;f=o?f+8|0:f;b=b+(o<<31>>31)|0;p=g-(o?p:0)|0;c[f>>2]=(c[f>>2]|0)+p;o=f+4|0;c[o>>2]=(c[o>>2]|0)-p;c[k>>2]=c[h>>2];c[k+4>>2]=f;c[k+8>>2]=b;g=jJ(va(146,k|0)|0)|0;if((e|0)==(g|0)){m=3;break a}}c[a+16>>2]=0;c[i>>2]=0;c[j>>2]=0;c[a>>2]=c[a>>2]|32;if((b|0)==2)d=0;else d=d-(c[f+4>>2]|0)|0}else m=3;while(0);if((m|0)==3){p=c[a+44>>2]|0;c[a+16>>2]=p+(c[a+48>>2]|0);c[i>>2]=p;c[j>>2]=p}l=n;return d|0}function oJ(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=a;c[e+4>>2]=b;b=jJ(Ea(91,e|0)|0)|0;l=d;return b|0}function pJ(){return}function qJ(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0;i=l;l=l+32|0;h=i;do if((g&4095|0)==0&(((g|0)<0)<<31>>31&-4096|0)==0){if(b>>>0>2147483646){c[(kJ()|0)>>2]=12;a=-1;break}c[h>>2]=a;c[h+4>>2]=b;c[h+8>>2]=d;c[h+12>>2]=e;c[h+16>>2]=f;c[h+20>>2]=g>>12;a=jJ(wa(192,h|0)|0)|0}else{c[(kJ()|0)>>2]=22;a=-1}while(0);l=i;return a|0}function rJ(b,d){b=b|0;d=d|0;var e=0,f=0,g=0;f=d&255;a:do if(!f)b=b+(sJ(b)|0)|0;else{if(b&3){e=d&255;do{g=a[b>>0]|0;if(g<<24>>24==0?1:g<<24>>24==e<<24>>24)break a;b=b+1|0}while((b&3|0)!=0)}f=O(f,16843009)|0;e=c[b>>2]|0;b:do if(!((e&-2139062144^-2139062144)&e+-16843009))do{g=e^f;if((g&-2139062144^-2139062144)&g+-16843009|0)break b;b=b+4|0;e=c[b>>2]|0}while(!((e&-2139062144^-2139062144)&e+-16843009|0));while(0);e=d&255;while(1){g=a[b>>0]|0;if(g<<24>>24==0?1:g<<24>>24==e<<24>>24)break;else b=b+1|0}}while(0);return b|0}function sJ(b){b=b|0;var d=0,e=0,f=0;f=b;a:do if(!(f&3))e=4;else{d=f;while(1){if(!(a[b>>0]|0)){b=d;break a}b=b+1|0;d=b;if(!(d&3)){e=4;break}}}while(0);if((e|0)==4){while(1){d=c[b>>2]|0;if(!((d&-2139062144^-2139062144)&d+-16843009))b=b+4|0;else break}if((d&255)<<24>>24)do b=b+1|0;while((a[b>>0]|0)!=0)}return b-f|0}function tJ(b,e){b=b|0;e=e|0;var f=0,g=0;g=0;while(1){if((d[125833+g>>0]|0)==(b|0)){b=2;break}f=g+1|0;if((f|0)==87){f=125921;g=87;b=5;break}else g=f}if((b|0)==2)if(!g)f=125921;else{f=125921;b=5}if((b|0)==5)while(1){do{b=f;f=f+1|0}while((a[b>>0]|0)!=0);g=g+-1|0;if(!g)break;else b=5}return uJ(f,c[e+20>>2]|0)|0}function uJ(a,b){a=a|0;b=b|0;return vJ(a,b)|0}function vJ(a,b){a=a|0;b=b|0;if(!b)b=0;else b=wJ(c[b>>2]|0,c[b+4>>2]|0,a)|0;return (b|0?b:a)|0}function wJ(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;o=(c[b>>2]|0)+1794895138|0;h=xJ(c[b+8>>2]|0,o)|0;f=xJ(c[b+12>>2]|0,o)|0;g=xJ(c[b+16>>2]|0,o)|0;a:do if((h>>>0>>2>>>0?(n=d-(h<<2)|0,f>>>0>>0&g>>>0>>0):0)?((g|f)&3|0)==0:0){n=f>>>2;m=g>>>2;l=0;while(1){j=h>>>1;k=l+j|0;i=k<<1;g=i+n|0;f=xJ(c[b+(g<<2)>>2]|0,o)|0;g=xJ(c[b+(g+1<<2)>>2]|0,o)|0;if(!(g>>>0>>0&f>>>0<(d-g|0)>>>0)){f=0;break a}if(a[b+(g+f)>>0]|0){f=0;break a}f=yJ(e,b+g|0)|0;if(!f)break;f=(f|0)<0;if((h|0)==1){f=0;break a}else{l=f?l:k;h=f?j:h-j|0}}f=i+m|0;g=xJ(c[b+(f<<2)>>2]|0,o)|0;f=xJ(c[b+(f+1<<2)>>2]|0,o)|0;if(f>>>0>>0&g>>>0<(d-f|0)>>>0)f=(a[b+(f+g)>>0]|0)==0?b+f|0:0;else f=0}else f=0;while(0);return f|0}function xJ(a,b){a=a|0;b=b|0;var c=0;c=RN(a|0)|0;return ((b|0)==0?a:c)|0}function yJ(b,c){b=b|0;c=c|0;var d=0,e=0;d=a[b>>0]|0;e=a[c>>0]|0;if(d<<24>>24==0?1:d<<24>>24!=e<<24>>24)b=e;else{do{b=b+1|0;c=c+1|0;d=a[b>>0]|0;e=a[c>>0]|0}while(!(d<<24>>24==0?1:d<<24>>24!=e<<24>>24));b=e}return (d&255)-(b&255)|0}function zJ(a){a=a|0;return tJ(a,c[(AJ()|0)+188>>2]|0)|0}function AJ(){return BJ()|0}function BJ(){return 55800}function CJ(a,b,c){a=+a;b=+b;c=c|0;var d=0.0,e=0.0,f=0.0;f=a*a;d=f*(f*f)*(f*1.58969099521155e-10+-2.5050760253406863e-08)+(f*(f*2.7557313707070068e-06+-1.984126982985795e-04)+.00833333333332249);e=f*a;if(!c)a=e*(f*d+-.16666666666666632)+a;else a=a-(e*.16666666666666632+(f*(b*.5-e*d)-b));return +a}function DJ(a){a=+a;var b=0,d=0,e=0,f=0,g=0.0,i=0.0,k=0.0,l=0.0,m=0.0;h[j>>3]=a;b=c[j>>2]|0;d=c[j+4>>2]|0;e=(d|0)<0;do if(e|d>>>0<1048576){if((b|0)==0&(d&2147483647|0)==0){a=-1.0/(a*a);break}if(e){a=(a-a)/0.0;break}else{h[j>>3]=a*18014398509481984.0;d=c[j+4>>2]|0;e=-1077;b=c[j>>2]|0;f=9;break}}else if(d>>>0<=2146435071)if((b|0)==0&0==0&(d|0)==1072693248)a=0.0;else{e=-1023;f=9}while(0);if((f|0)==9){f=d+614242|0;c[j>>2]=b;c[j+4>>2]=(f&1048575)+1072079006;m=+h[j>>3]+-1.0;k=m*(m*.5);i=m/(m+2.0);l=i*i;g=l*l;h[j>>3]=m-k;d=c[j+4>>2]|0;c[j>>2]=0;c[j+4>>2]=d;a=+h[j>>3];g=m-a-k+i*(k+(g*(g*(g*.15313837699209373+.22222198432149784)+.3999999999940942)+l*(g*(g*(g*.14798198605116586+.1818357216161805)+.2857142874366239)+.6666666666666735)));l=a*1.4426950407214463;k=+(e+(f>>>20)|0);i=l+k;a=i+(l+(k-i)+(g*1.4426950407214463+(g+a)*1.6751713164886512e-10))}return +a}function EJ(a,b){a=+a;b=b|0;var d=0,e=0,f=0;h[j>>3]=a;d=c[j>>2]|0;e=c[j+4>>2]|0;f=ON(d|0,e|0,52)|0;switch(f&2047){case 0:{if(a!=0.0){a=+EJ(a*18446744073709551616.0,b);d=(c[b>>2]|0)+-64|0}else d=0;c[b>>2]=d;break}case 2047:break;default:{c[b>>2]=(f&2047)+-1022;c[j>>2]=d;c[j+4>>2]=e&-2146435073|1071644672;a=+h[j>>3]}}return +a}function FJ(a,b){a=+a;b=+b;var c=0.0,d=0.0,e=0.0,f=0.0;c=a*a;d=c*c;e=c*.5;f=1.0-e;return +(f+(1.0-f-e+(c*(c*(c*(c*2.480158728947673e-05+-.001388888888887411)+.0416666666666666)+d*d*(c*(2.087572321298175e-09-c*1.1359647557788195e-11)+-2.7557314351390663e-07))-a*b)))}function GJ(a){a=+a;var b=0,d=0,e=0,f=0,g=0.0,i=0.0,k=0.0,l=0.0,m=0.0;h[j>>3]=a;b=c[j>>2]|0;d=c[j+4>>2]|0;e=(d|0)<0;do if(e|d>>>0<1048576){if((b|0)==0&(d&2147483647|0)==0){a=-1.0/(a*a);break}if(e){a=(a-a)/0.0;break}else{h[j>>3]=a*18014398509481984.0;d=c[j+4>>2]|0;e=-1077;b=c[j>>2]|0;f=9;break}}else if(d>>>0<=2146435071)if((b|0)==0&0==0&(d|0)==1072693248)a=0.0;else{e=-1023;f=9}while(0);if((f|0)==9){f=d+614242|0;c[j>>2]=b;c[j+4>>2]=(f&1048575)+1072079006;k=+h[j>>3]+-1.0;i=k*(k*.5);l=k/(k+2.0);m=l*l;g=m*m;h[j>>3]=k-i;d=c[j+4>>2]|0;c[j>>2]=0;c[j+4>>2]=d;a=+h[j>>3];g=k-a-i+l*(i+(g*(g*(g*.15313837699209373+.22222198432149784)+.3999999999940942)+m*(g*(g*(g*.14798198605116586+.1818357216161805)+.2857142874366239)+.6666666666666735)));m=a*.4342944818781689;i=+(e+(f>>>20)|0);l=i*.30102999566361177;k=l+m;a=k+(m+(l-k)+(g*.4342944818781689+(i*3.694239077158931e-13+(g+a)*2.5082946711645275e-11)))}return +a}function HJ(a,b){a=+a;b=b|0;var d=0,e=0.0,f=0.0,g=0.0,i=0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0.0;r=l;l=l+48|0;m=r+16|0;n=r;h[j>>3]=a;d=c[j>>2]|0;i=c[j+4>>2]|0;o=ON(d|0,i|0,63)|0;q=i&2147483647;do if(q>>>0<1074752123)if((i&1048575|0)!=598523){d=(o|0)!=0;if(q>>>0<1073928573)if(d){g=a+1.5707963267341256;k=g+6.077100506506192e-11;h[b>>3]=k;h[b+8>>3]=g-k+6.077100506506192e-11;d=-1;break}else{g=a+-1.5707963267341256;k=g+-6.077100506506192e-11;h[b>>3]=k;h[b+8>>3]=g-k+-6.077100506506192e-11;d=1;break}else if(d){g=a+3.1415926534682512;k=g+1.2154201013012384e-10;h[b>>3]=k;h[b+8>>3]=g-k+1.2154201013012384e-10;d=-2;break}else{g=a+-3.1415926534682512;k=g+-1.2154201013012384e-10;h[b>>3]=k;h[b+8>>3]=g-k+-1.2154201013012384e-10;d=2;break}}else p=21;else{if(q>>>0<1075594812)if(q>>>0<1075183037){if((q|0)==1074977148){p=21;break}if(!o){g=a+-4.712388980202377;k=g+-1.8231301519518578e-10;h[b>>3]=k;h[b+8>>3]=g-k+-1.8231301519518578e-10;d=3;break}else{g=a+4.712388980202377;k=g+1.8231301519518578e-10;h[b>>3]=k;h[b+8>>3]=g-k+1.8231301519518578e-10;d=-3;break}}else{if((q|0)==1075388923){p=21;break}if(!o){g=a+-6.2831853069365025;k=g+-2.430840202602477e-10;h[b>>3]=k;h[b+8>>3]=g-k+-2.430840202602477e-10;d=4;break}else{g=a+6.2831853069365025;k=g+2.430840202602477e-10;h[b>>3]=k;h[b+8>>3]=g-k+2.430840202602477e-10;d=-4;break}}if(q>>>0>=1094263291){if(q>>>0>2146435071){k=a-a;h[b+8>>3]=k;h[b>>3]=k;d=0;break}c[j>>2]=d;c[j+4>>2]=i&1048575|1096810496;a=+h[j>>3];d=0;do{k=+(~~a|0);h[m+(d<<3)>>3]=k;a=(a-k)*16777216.0;d=d+1|0}while((d|0)!=2);h[m+16>>3]=a;if(a==0.0){d=1;while(1)if(+h[m+(d<<3)>>3]==0.0)d=d+-1|0;else break}else d=2;d=IJ(m,n,(q>>>20)+-1046|0,d+1|0,1)|0;a=+h[n>>3];if(!o){h[b>>3]=a;h[b+8>>3]=+h[n+8>>3];break}else{h[b>>3]=-a;h[b+8>>3]=-+h[n+8>>3];d=0-d|0;break}}else p=21}while(0);if((p|0)==21){g=a*.6366197723675814+6755399441055744.0+-6755399441055744.0;d=~~g;e=a-g*1.5707963267341256;f=g*6.077100506506192e-11;a=e-f;h[b>>3]=a;h[j>>3]=a;p=ON(c[j>>2]|0,c[j+4>>2]|0,52)|0;i=q>>>20;if((i-(p&2047)|0)>16){f=g*6.077100506303966e-11;k=e-f;f=g*2.0222662487959506e-21-(e-k-f);a=k-f;h[b>>3]=a;h[j>>3]=a;q=ON(c[j>>2]|0,c[j+4>>2]|0,52)|0;s=g*2.0222662487111665e-21;e=k-s;g=g*8.4784276603689e-32-(k-e-s);if((i-(q&2047)|0)>49){a=e-g;h[b>>3]=a;f=g}else e=k}h[b+8>>3]=e-a-f}l=r;return d|0}function IJ(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0.0,i=0.0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0.0;H=l;l=l+560|0;C=H+480|0;z=H+320|0;G=H+160|0;E=H;D=c[56044+(f<<2)>>2]|0;p=e+-1|0;y=(d+-3|0)/24|0;y=(y|0)>0?y:0;B=O(y,-24)|0;j=d+-24+B|0;if((D+p|0)>=0){n=D+e|0;k=y-p|0;m=0;while(1){if((k|0)<0)g=0.0;else g=+(c[56060+(k<<2)>>2]|0);h[z+(m<<3)>>3]=g;m=m+1|0;if((m|0)==(n|0))break;else k=k+1|0}}o=(e|0)>0;n=0;while(1){if(o){m=n+p|0;g=0.0;k=0;do{g=g+ +h[a+(k<<3)>>3]*+h[z+(m-k<<3)>>3];k=k+1|0}while((k|0)!=(e|0))}else g=0.0;h[E+(n<<3)>>3]=g;if((n|0)<(D|0))n=n+1|0;else break}t=(j|0)>0;u=24-j|0;v=23-j|0;w=(e|0)>0;x=(j|0)==0;k=D;a:while(1){g=+h[E+(k<<3)>>3];o=(k|0)>0;if(o){m=k;n=0;while(1){i=+(~~(g*5.9604644775390625e-08)|0);c[C+(n<<2)>>2]=~~(g-i*16777216.0);s=m;m=m+-1|0;g=+h[E+(m<<3)>>3]+i;if((s|0)<=1)break;else n=n+1|0}}g=+JJ(g,j);g=g-+A(+(g*.125))*8.0;m=~~g;g=g-+(m|0);do if(!t)if(!x)if(!(g>=.5)){p=0;s=m;break}else{n=2;F=20;break}else{n=c[C+(k+-1<<2)>>2]>>23;F=19;break}else{s=C+(k+-1<<2)|0;n=c[s>>2]|0;F=n>>u;n=n-(F<>2]=n;n=n>>v;m=F+m|0;F=19}while(0);if((F|0)==19){F=0;if((n|0)>0)F=20;else{p=n;s=m}}if((F|0)==20){F=0;s=m+1|0;if(o){m=0;r=0;do{p=C+(r<<2)|0;q=c[p>>2]|0;if(!m)if(!q)m=0;else{m=1;o=16777216;F=23}else{o=16777215;F=23}if((F|0)==23){F=0;c[p>>2]=o-q}r=r+1|0}while((r|0)!=(k|0))}else m=0;b:do if(t){switch(j|0){case 1:{o=8388607;break}case 2:{o=4194303;break}default:break b}r=C+(k+-1<<2)|0;c[r>>2]=c[r>>2]&o}while(0);if((n|0)==2){g=1.0-g;if(!m)p=2;else{p=2;g=g-+JJ(1.0,j)}}else p=n}if(!(g==0.0)){F=42;break}if((k|0)>(D|0)){m=0;n=k;do{n=n+-1|0;m=c[C+(n<<2)>>2]|m}while((n|0)>(D|0));if(m){F=41;break}else m=1}else m=1;while(1)if(!(c[C+(D-m<<2)>>2]|0))m=m+1|0;else break;o=m+k|0;if((m|0)<=0){k=o;continue}while(1){n=k+1|0;m=k+e|0;h[z+(m<<3)>>3]=+(c[56060+(n+y<<2)>>2]|0);if(w){g=0.0;k=0;do{g=g+ +h[a+(k<<3)>>3]*+h[z+(m-k<<3)>>3];k=k+1|0}while((k|0)!=(e|0))}else g=0.0;h[E+(n<<3)>>3]=g;if((n|0)<(o|0))k=n;else{k=o;continue a}}}if((F|0)==41)while(1){F=0;j=j+-24|0;k=k+-1|0;if(!(c[C+(k<<2)>>2]|0))F=41;else{o=k;break}}else if((F|0)==42){g=+JJ(g,0-j|0);if(g>=16777216.0){i=+(~~(g*5.9604644775390625e-08)|0);c[C+(k<<2)>>2]=~~(g-i*16777216.0);j=B+d|0;k=k+1|0;g=i}c[C+(k<<2)>>2]=~~g;o=k}g=+JJ(1.0,j);n=(o|0)>-1;if(n){j=o;while(1){h[E+(j<<3)>>3]=g*+(c[C+(j<<2)>>2]|0);if((j|0)>0){g=g*5.9604644775390625e-08;j=j+-1|0}else break}if(n){k=o;while(1){m=o-k|0;j=0;g=0.0;while(1){g=g+ +h[10840+(j<<3)>>3]*+h[E+(j+k<<3)>>3];if((j|0)>=(D|0)|(j|0)>=(m|0))break;else j=j+1|0}h[G+(m<<3)>>3]=g;if((k|0)>0)k=k+-1|0;else break}}}switch(f|0){case 0:{if(n){g=0.0;j=o;while(1){g=g+ +h[G+(j<<3)>>3];if((j|0)>0)j=j+-1|0;else break}}else g=0.0;i=(p|0)==0?g:-g;F=72;break}case 2:case 1:{if(n){g=0.0;j=o;while(1){g=g+ +h[G+(j<<3)>>3];if((j|0)>0)j=j+-1|0;else break}}else g=0.0;k=(p|0)==0;h[b>>3]=k?g:-g;g=+h[G>>3]-g;if((o|0)>=1){j=1;while(1){g=g+ +h[G+(j<<3)>>3];if((j|0)==(o|0))break;else j=j+1|0}}i=k?g:-g;b=b+8|0;F=72;break}case 3:{if((o|0)>0){j=o;g=+h[G+(o<<3)>>3];do{F=j;j=j+-1|0;E=G+(j<<3)|0;i=+h[E>>3];I=g;g=i+g;h[G+(F<<3)>>3]=I+(i-g);h[E>>3]=g}while((F|0)>1);k=(o|0)>1;if(k){j=o;g=+h[G+(o<<3)>>3];do{F=j;j=j+-1|0;E=G+(j<<3)|0;I=+h[E>>3];i=g;g=I+g;h[G+(F<<3)>>3]=i+(I-g);h[E>>3]=g}while((F|0)>2);if(k){j=o;i=0.0;while(1){i=i+ +h[G+(j<<3)>>3];if((j|0)>2)j=j+-1|0;else break}}else i=0.0}else i=0.0}else i=0.0;g=+h[G>>3];if(!p){h[b>>3]=g;g=+h[G+8>>3]}else{h[b>>3]=-g;i=-i;g=-+h[G+8>>3]}h[b+8>>3]=g;b=b+16|0;F=72;break}default:{}}if((F|0)==72)h[b>>3]=i;l=H;return s&7|0}function JJ(a,b){a=+a;b=b|0;var d=0,e=0;if((b|0)<=1023){if((b|0)<-1022){a=a*2.2250738585072014e-308;e=(b|0)<-2044;d=b+2044|0;a=e?a*2.2250738585072014e-308:a;b=e?((d|0)>-1022?d:-1022):b+1022|0}}else{a=a*8988465674311579538646525.0e283;d=(b|0)>2046;e=b+-2046|0;a=d?a*8988465674311579538646525.0e283:a;b=d?((e|0)<1023?e:1023):b+-1023|0}d=PN(b+1023|0,0,52)|0;e=z;c[j>>2]=d;c[j+4>>2]=e;return +(a*+h[j>>3])}function KJ(a){a=+a;var b=0,d=0,e=0,f=0.0,g=0.0;h[j>>3]=a;d=c[j+4>>2]|0;b=d&2147483647;do if(b>>>0>2146435071)a=a+a;else{if(b>>>0<1048576){h[j>>3]=a*18014398509481984.0;d=c[j+4>>2]|0;b=d&2147483647;if(!b)break;else e=696219795}else e=715094163;c[j>>2]=0;c[j+4>>2]=((b>>>0)/3|0)+e|d&-2147483648;f=+h[j>>3];g=f*f*(f/a);h[j>>3]=(g*(g*g)*(g*.14599619288661245+-.758397934778766)+(g*(g*1.6214297201053545+-1.8849797954337717)+1.87595182427177))*f;d=IN(c[j>>2]|0,c[j+4>>2]|0,-2147483648,0)|0;e=z;c[j>>2]=d&-1073741824;c[j+4>>2]=e;f=+h[j>>3];a=a/(f*f);a=(a-f)/(f+f+a)*f+f}while(0);return +a}function LJ(a,b){a=+a;b=+b;var d=0,e=0;h[j>>3]=a;e=c[j>>2]|0;d=c[j+4>>2]|0;h[j>>3]=b;d=c[j+4>>2]&-2147483648|d&2147483647;c[j>>2]=e;c[j+4>>2]=d;return +(+h[j>>3])}function MJ(a,b){a=+a;b=+b;return +(+LJ(a,b))}function NJ(a,b){a=+a;b=b|0;return +(+JJ(a,b))}function OJ(a,b){a=+a;b=+b;return +(+PJ(a,b))}function PJ(a,b){a=+a;b=+b;var d=0,e=0,f=0,g=0,i=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;h[j>>3]=a;i=c[j>>2]|0;l=c[j+4>>2]|0;h[j>>3]=b;n=c[j>>2]|0;o=c[j+4>>2]|0;e=ON(i|0,l|0,52)|0;e=e&2047;m=ON(n|0,o|0,52)|0;m=m&2047;p=l&-2147483648;g=PN(n|0,o|0,1)|0;k=z;a:do if(!((g|0)==0&(k|0)==0)?(f=QJ(b)|0,d=z&2147483647,!((e|0)==2047|(d>>>0>2146435072|(d|0)==2146435072&f>>>0>0))):0){d=PN(i|0,l|0,1)|0;f=z;if(!(f>>>0>k>>>0|(f|0)==(k|0)&d>>>0>g>>>0))return +((d|0)==(g|0)&(f|0)==(k|0)?a*0.0:a);if(!e){d=PN(i|0,l|0,12)|0;f=z;if((f|0)>-1|(f|0)==-1&d>>>0>4294967295){e=0;do{e=e+-1|0;d=PN(d|0,f|0,1)|0;f=z}while((f|0)>-1|(f|0)==-1&d>>>0>4294967295)}else e=0;i=PN(i|0,l|0,1-e|0)|0;g=z}else g=l&1048575|1048576;if(!m){f=PN(n|0,o|0,12)|0;k=z;if((k|0)>-1|(k|0)==-1&f>>>0>4294967295){d=0;do{d=d+-1|0;f=PN(f|0,k|0,1)|0;k=z}while((k|0)>-1|(k|0)==-1&f>>>0>4294967295)}else d=0;n=PN(n|0,o|0,1-d|0)|0;m=d;l=z}else l=o&1048575|1048576;f=JN(i|0,g|0,n|0,l|0)|0;d=z;k=(d|0)>-1|(d|0)==-1&f>>>0>4294967295;b:do if((e|0)>(m|0)){while(1){if(k){if((f|0)==0&(d|0)==0)break}else{f=i;d=g}i=PN(f|0,d|0,1)|0;g=z;e=e+-1|0;f=JN(i|0,g|0,n|0,l|0)|0;d=z;k=(d|0)>-1|(d|0)==-1&f>>>0>4294967295;if((e|0)<=(m|0))break b}b=a*0.0;break a}while(0);if(k){if((f|0)==0&(d|0)==0){b=a*0.0;break}}else{d=g;f=i}if(d>>>0<1048576|(d|0)==1048576&f>>>0<0)do{f=PN(f|0,d|0,1)|0;d=z;e=e+-1|0}while(d>>>0<1048576|(d|0)==1048576&f>>>0<0);if((e|0)>0){o=IN(f|0,d|0,0,-1048576)|0;d=z;e=PN(e|0,0,52)|0;d=d|z;e=o|e}else{e=ON(f|0,d|0,1-e|0)|0;d=z}c[j>>2]=e;c[j+4>>2]=d|p;b=+h[j>>3]}else q=3;while(0);if((q|0)==3){b=a*b;b=b/b}return +b}function QJ(a){a=+a;var b=0;h[j>>3]=a;b=c[j>>2]|0;z=c[j+4>>2]|0;return b|0}function RJ(a,b){a=+a;b=+b;var d=0.0,e=0,f=0,g=0,i=0,k=0.0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;q=l;l=l+32|0;m=q+24|0;n=q+16|0;o=q+8|0;p=q;h[j>>3]=a;t=c[j>>2]|0;g=c[j+4>>2]|0;h[j>>3]=b;e=c[j>>2]|0;g=g&2147483647;f=c[j+4>>2]&2147483647;i=g>>>0>>0|(g|0)==(f|0)&t>>>0>>0;s=i?e:t;r=i?f:g;e=i?t:e;f=i?g:f;g=ON(s|0,r|0,52)|0;i=ON(e|0,f|0,52)|0;c[j>>2]=s;c[j+4>>2]=r;a=+h[j>>3];c[j>>2]=e;c[j+4>>2]=f;k=+h[j>>3];do if((i|0)!=2047){if(!((e|0)==0&(f|0)==0|(g|0)==2047)){if((g-i|0)>64){a=a+k;break}if((g|0)>1533){d=5260135901548373507240989.0e186;b=a*1.90109156629516e-211;a=k*1.90109156629516e-211}else{t=(i|0)<573;d=t?1.90109156629516e-211:1.0;b=t?a*5260135901548373507240989.0e186:a;a=t?k*5260135901548373507240989.0e186:k}SJ(m,n,b);SJ(o,p,a);a=d*+C(+(+h[p>>3]+ +h[n>>3]+ +h[o>>3]+ +h[m>>3]))}}else a=k;while(0);l=q;return +a}function SJ(a,b,c){a=a|0;b=b|0;c=+c;var d=0.0,e=0.0;e=c*134217729.0;e=e+(c-e);d=c-e;c=c*c;h[a>>3]=c;h[b>>3]=d*d+(e*e-c+e*2.0*d);return}function TJ(a,b,d){a=+a;b=b|0;d=d|0;var e=0.0,f=0,g=0,i=0.0,k=0,m=0;k=l;l=l+16|0;g=k;h[j>>3]=a;f=c[j+4>>2]&2147483647;do if(f>>>0<1072243196)if(f>>>0<1044816030){h[b>>3]=a;h[d>>3]=1.0;break}else{h[b>>3]=+CJ(a,0.0,0);h[d>>3]=+FJ(a,0.0);break}else{if(f>>>0>2146435071){i=a-a;h[d>>3]=i;h[b>>3]=i;break}f=HJ(a,g)|0;m=g+8|0;e=+CJ(+h[g>>3],+h[m>>3],1);a=+FJ(+h[g>>3],+h[m>>3]);switch(f&3){case 0:{h[b>>3]=e;i=a;break}case 1:{h[b>>3]=a;i=-e;break}case 2:{h[b>>3]=-e;i=-a;break}case 3:{h[b>>3]=-a;i=e;break}default:{}}h[d>>3]=i}while(0);l=k;return}function UJ(a,b){a=+a;b=b|0;return +(+EJ(a,b))}function VJ(a){a=a|0;if(a>>>0<131072)a=(d[127725+((d[127725+(a>>>8)>>0]|0)<<5|a>>>3&31)>>0]|0)>>>(a&7)&1;else a=0;return a|0}function WJ(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0;if(!e)f=0;else{f=a[b>>0]|0;a:do if(!(f<<24>>24))f=0;else while(1){e=e+-1|0;g=a[c>>0]|0;if(!(f<<24>>24==g<<24>>24&((e|0)!=0&g<<24>>24!=0)))break a;b=b+1|0;c=c+1|0;f=a[b>>0]|0;if(!(f<<24>>24)){f=0;break}}while(0);f=(f&255)-(d[c>>0]|0)|0}return f|0}function XJ(b,c){b=b|0;c=c|0;b=rJ(b,c)|0;return ((a[b>>0]|0)==(c&255)<<24>>24?b:0)|0}function YJ(a){a=a|0;return ((a|0)==32|(a+-9|0)>>>0<5)&1|0}function ZJ(a,b,c){a=a|0;b=b|0;c=c|0;c=aK(a,b,c,-1,0)|0;return c|0}function _J(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=d&255;f=(e|0)!=0;a:do if(f&(b&3|0)!=0){g=d&255;while(1){if((a[b>>0]|0)==g<<24>>24){i=6;break a}b=b+1|0;e=e+-1|0;f=(e|0)!=0;if(!(f&(b&3|0)!=0)){i=5;break}}}else i=5;while(0);if((i|0)==5)if(f)i=6;else e=0;b:do if((i|0)==6){g=d&255;if((a[b>>0]|0)!=g<<24>>24){f=O(h,16843009)|0;c:do if(e>>>0>3)while(1){h=c[b>>2]^f;if((h&-2139062144^-2139062144)&h+-16843009|0)break;b=b+4|0;e=e+-4|0;if(e>>>0<=3){i=11;break c}}else i=11;while(0);if((i|0)==11)if(!e){e=0;break}while(1){if((a[b>>0]|0)==g<<24>>24)break b;b=b+1|0;e=e+-1|0;if(!e){e=0;break}}}}while(0);return (e|0?b:0)|0}function $J(a){a=a|0;return (a+-48|0)>>>0<10|0}function aK(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;j=l;l=l+128|0;h=j;c[h>>2]=0;i=h+4|0;c[i>>2]=a;c[h+44>>2]=a;g=h+8|0;c[g>>2]=(a|0)<0?-1:a+2147483647|0;c[h+76>>2]=-1;bK(h,0);d=cK(h,d,1,e,f)|0;if(b|0)c[b>>2]=a+((c[i>>2]|0)+(c[h+108>>2]|0)-(c[g>>2]|0));l=j;return d|0}function bK(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;c[a+104>>2]=b;d=c[a+8>>2]|0;e=c[a+4>>2]|0;f=d-e|0;c[a+108>>2]=f;c[a+100>>2]=(b|0)!=0&(f|0)>(b|0)?e+b|0:d;return}function cK(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;a:do if(e>>>0>36){c[(kJ()|0)>>2]=22;h=0;g=0}else{r=b+4|0;q=b+100|0;do{i=c[r>>2]|0;if(i>>>0<(c[q>>2]|0)>>>0){c[r>>2]=i+1;i=d[i>>0]|0}else i=dK(b)|0}while((YJ(i)|0)!=0);b:do switch(i|0){case 43:case 45:{i=((i|0)==45)<<31>>31;j=c[r>>2]|0;if(j>>>0<(c[q>>2]|0)>>>0){c[r>>2]=j+1;p=i;i=d[j>>0]|0;break b}else{p=i;i=dK(b)|0;break b}}default:p=0}while(0);j=(e|0)==0;do if((e|16|0)==16&(i|0)==48){i=c[r>>2]|0;if(i>>>0<(c[q>>2]|0)>>>0){c[r>>2]=i+1;i=d[i>>0]|0}else i=dK(b)|0;if((i|32|0)!=120)if(j){e=8;n=46;break}else{n=32;break}i=c[r>>2]|0;if(i>>>0<(c[q>>2]|0)>>>0){c[r>>2]=i+1;i=d[i>>0]|0}else i=dK(b)|0;if((d[130894+i>>0]|0)>15){g=(c[q>>2]|0)==0;if(!g)c[r>>2]=(c[r>>2]|0)+-1;if(!f){bK(b,0);h=0;g=0;break a}if(g){h=0;g=0;break a}c[r>>2]=(c[r>>2]|0)+-1;h=0;g=0;break a}else{e=16;n=46}}else{e=j?10:e;if(e>>>0>(d[130894+i>>0]|0)>>>0)n=32;else{if(c[q>>2]|0)c[r>>2]=(c[r>>2]|0)+-1;bK(b,0);c[(kJ()|0)>>2]=22;h=0;g=0;break a}}while(0);c:do if((n|0)==32)if((e|0)==10){e=i+-48|0;if(e>>>0<10){i=0;j=e;do{i=(i*10|0)+j|0;e=c[r>>2]|0;if(e>>>0<(c[q>>2]|0)>>>0){c[r>>2]=e+1;e=d[e>>0]|0}else e=dK(b)|0;j=e+-48|0}while(j>>>0<10&i>>>0<429496729);f=0}else{e=i;i=0;f=0}k=e+-48|0;if(k>>>0<10){j=e;do{e=HN(i|0,f|0,10,0)|0;l=z;m=((k|0)<0)<<31>>31;o=~m;if(l>>>0>o>>>0|(l|0)==(o|0)&e>>>0>~k>>>0){e=10;n=72;break c}i=IN(e|0,l|0,k|0,m|0)|0;f=z;e=c[r>>2]|0;if(e>>>0<(c[q>>2]|0)>>>0){c[r>>2]=e+1;j=d[e>>0]|0}else j=dK(b)|0;k=j+-48|0}while(k>>>0<10&(f>>>0<429496729|(f|0)==429496729&i>>>0<2576980378));if(k>>>0>9){j=p;e=f}else{e=10;n=72}}else{j=p;e=f}}else n=46;while(0);d:do if((n|0)==46){if(!(e+-1&e)){n=a[131150+((e*23|0)>>>5&7)>>0]|0;f=a[130894+i>>0]|0;j=f&255;if(e>>>0>j>>>0){i=0;k=j;do{i=k|i<>2]|0;if(j>>>0<(c[q>>2]|0)>>>0){c[r>>2]=j+1;j=d[j>>0]|0}else j=dK(b)|0;f=a[130894+j>>0]|0;k=f&255}while(i>>>0<134217728&e>>>0>k>>>0);k=0}else{j=i;k=0;i=0}l=ON(-1,-1,n|0)|0;m=z;if(e>>>0<=(f&255)>>>0|(m>>>0>>0|(m|0)==(k|0)&l>>>0>>0)){f=k;n=72;break}else j=k;while(1){i=PN(i|0,j|0,n|0)|0;k=z;i=i|f&255;j=c[r>>2]|0;if(j>>>0<(c[q>>2]|0)>>>0){c[r>>2]=j+1;j=d[j>>0]|0}else j=dK(b)|0;f=a[130894+j>>0]|0;if(e>>>0<=(f&255)>>>0|(k>>>0>m>>>0|(k|0)==(m|0)&i>>>0>l>>>0)){f=k;n=72;break d}else j=k}}f=a[130894+i>>0]|0;j=f&255;if(e>>>0>j>>>0){i=0;k=j;do{i=k+(O(i,e)|0)|0;j=c[r>>2]|0;if(j>>>0<(c[q>>2]|0)>>>0){c[r>>2]=j+1;j=d[j>>0]|0}else j=dK(b)|0;f=a[130894+j>>0]|0;k=f&255}while(i>>>0<119304647&e>>>0>k>>>0);k=0}else{j=i;i=0;k=0}if(e>>>0>(f&255)>>>0){n=MN(-1,-1,e|0,0)|0;o=z;m=k;while(1){if(m>>>0>o>>>0|(m|0)==(o|0)&i>>>0>n>>>0){f=m;n=72;break d}k=HN(i|0,m|0,e|0,0)|0;l=z;f=f&255;if(l>>>0>4294967295|(l|0)==-1&k>>>0>~f>>>0){f=m;n=72;break d}i=IN(k|0,l|0,f|0,0)|0;k=z;j=c[r>>2]|0;if(j>>>0<(c[q>>2]|0)>>>0){c[r>>2]=j+1;j=d[j>>0]|0}else j=dK(b)|0;f=a[130894+j>>0]|0;if(e>>>0<=(f&255)>>>0){f=k;n=72;break}else m=k}}else{f=k;n=72}}while(0);if((n|0)==72)if(e>>>0>(d[130894+j>>0]|0)>>>0){do{i=c[r>>2]|0;if(i>>>0<(c[q>>2]|0)>>>0){c[r>>2]=i+1;i=d[i>>0]|0}else i=dK(b)|0}while(e>>>0>(d[130894+i>>0]|0)>>>0);c[(kJ()|0)>>2]=34;j=(g&1|0)==0&0==0?p:0;e=h;i=g}else{j=p;e=f}if(c[q>>2]|0)c[r>>2]=(c[r>>2]|0)+-1;if(!(e>>>0>>0|(e|0)==(h|0)&i>>>0>>0)){if(!((g&1|0)!=0|0!=0|(j|0)!=0)){c[(kJ()|0)>>2]=34;g=IN(g|0,h|0,-1,-1)|0;h=z;break}if(e>>>0>h>>>0|(e|0)==(h|0)&i>>>0>g>>>0){c[(kJ()|0)>>2]=34;break}}g=((j|0)<0)<<31>>31;g=JN(i^j|0,e^g|0,j|0,g|0)|0;h=z}while(0);z=h;return g|0}function dK(b){b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0;f=b+104|0;h=c[f>>2]|0;if((h|0)!=0?(c[b+108>>2]|0)>=(h|0):0)i=4;else{e=eK(b)|0;if((e|0)>=0){g=c[f>>2]|0;f=b+8|0;if(g){j=c[f>>2]|0;h=c[b+4>>2]|0;f=g-(c[b+108>>2]|0)|0;g=j;if((j-h|0)<(f|0))f=g;else f=h+(f+-1)|0}else{g=c[f>>2]|0;f=g}c[b+100>>2]=f;f=b+4|0;if(!g)f=c[f>>2]|0;else{f=c[f>>2]|0;j=b+108|0;c[j>>2]=g+1-f+(c[j>>2]|0)}f=f+-1|0;if((e|0)!=(d[f>>0]|0|0))a[f>>0]=e}else i=4}if((i|0)==4){c[b+100>>2]=0;e=-1}return e|0}function eK(a){a=a|0;var b=0,e=0;e=l;l=l+16|0;b=e;if((fK(a)|0)==0?(bb[c[a+32>>2]&31](a,b,1)|0)==1:0)a=d[b>>0]|0;else a=-1;l=e;return a|0}function fK(b){b=b|0;var d=0,e=0;d=b+74|0;e=a[d>>0]|0;a[d>>0]=e+255|e;d=b+20|0;e=b+28|0;if((c[d>>2]|0)>>>0>(c[e>>2]|0)>>>0)bb[c[b+36>>2]&31](b,0,0)|0;c[b+16>>2]=0;c[e>>2]=0;c[d>>2]=0;d=c[b>>2]|0;if(!(d&4)){e=(c[b+44>>2]|0)+(c[b+48>>2]|0)|0;c[b+8>>2]=e;c[b+4>>2]=e;d=d<<27>>31}else{c[b>>2]=d|32;d=-1}return d|0}function gK(a){a=a|0;return (a+-48|0)>>>0<10|0}function hK(a){a=a|0;if(!(iK(a)|0))a=($J(a)|0)!=0&1;else a=1;return a|0}function iK(a){a=a|0;return ((a|32)+-97|0)>>>0<26|0}function jK(b,c){b=b|0;c=c|0;var e=0,f=0,g=0;e=a[b>>0]|0;a:do if(!(e<<24>>24))b=0;else{g=b;b=e;f=e&255;while(1){e=a[c>>0]|0;if(!(e<<24>>24))break a;if(b<<24>>24!=e<<24>>24?(f=kK(f)|0,(f|0)!=(kK(d[c>>0]|0)|0)):0)break;b=g+1|0;c=c+1|0;e=a[b>>0]|0;if(!(e<<24>>24)){b=0;break a}else{g=b;b=e;f=e&255}}b=a[g>>0]|0}while(0);g=kK(b&255)|0;return g-(kK(d[c>>0]|0)|0)|0}function kK(a){a=a|0;var b=0;b=(lK(a)|0)==0;return (b?a:a|32)|0}function lK(a){a=a|0;return (a+-65|0)>>>0<26|0}function mK(a){a=a|0;return nK(a,0)|0}function nK(c,f){c=c|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0;k=(f<<1)+-1|0;l=f+-1|0;a:do if(!((c+-43008|0)>>>0<22272|((c+-11776|0)>>>0<30784|((c+-1536|0)>>>0<2560|(oK(c)|0)==0)))){g=(f|0)!=0;if(g&(c+-4256|0)>>>0<46){if((c|0)>4293)switch(c|0){case 4295:case 4301:break;default:break a}c=c+7264|0;break}if((c+-11520|0)>>>0<38&(g^1)){c=c+-7264|0;break}else g=0;do{i=a[59170+(g<<2)+2>>0]|0;j=i<<24>>24;h=c-(e[59170+(g<<2)>>1]|0)|0;if((h-(l&j)|0)>>>0<(d[59170+(g<<2)+3>>0]|0)>>>0){m=11;break}g=g+1|0}while((g|0)!=61);if((m|0)==11)if(i<<24>>24==1){c=f+c-(h&1)|0;break}else{c=(O(k,j)|0)+c|0;break}i=1-f|0;g=b[58682+(i<<1)>>1]|0;b:do if(g<<16>>16){h=0;while(1){if((g&65535|0)==(c|0))break;h=h+1|0;g=b[58682+(h<<2)+(i<<1)>>1]|0;if(!(g<<16>>16))break b}c=e[58682+(h<<2)+(f<<1)>>1]|0;break a}while(0);return ((c+-66600+(f*40|0)|0)>>>0<40?c+-40+(f*80|0)|0:c)|0}while(0);return c|0}function oK(a){a=a|0;if(a>>>0<131072)a=(d[131159+((d[131159+(a>>>8)>>0]|0)<<5|a>>>3&31)>>0]|0)>>>(a&7)&1;else a=a>>>0<196606&1;return a|0}function pK(a){a=a|0;var b=0;b=a;while(1)if(!(c[b>>2]|0))break;else b=b+4|0;return b-a>>2|0}function qK(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0;if(!e)b=0;else{f=a[b>>0]|0;a:do if(!(f<<24>>24))b=0;else{h=b;b=f;f=f&255;while(1){e=e+-1|0;g=a[c>>0]|0;if(!((e|0)!=0&g<<24>>24!=0))break a;if(b<<24>>24!=g<<24>>24?(g=kK(f)|0,(g|0)!=(kK(d[c>>0]|0)|0)):0)break;b=h+1|0;c=c+1|0;f=a[b>>0]|0;if(!(f<<24>>24)){b=0;break a}else{h=b;b=f;f=f&255}}b=a[h>>0]|0}while(0);b=kK(b&255)|0;b=b-(kK(d[c>>0]|0)|0)|0}return b|0}function rK(a){a=a|0;if(a>>>0>=255)if((a+-57344|0)>>>0<8185|(a>>>0<8232|(a+-8234|0)>>>0<47062))a=1;else return (a&65534|0)!=65534&(a+-65532|0)>>>0<1048580&1|0;else a=(a+1&127)>>>0>32&1;return a|0}function sK(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0;k=l;l=l+16|0;g=k;i=(f|0)==0?170768:f;f=c[i>>2]|0;a:do if(!d)if(!f)f=0;else j=17;else{h=(b|0)==0?g:b;if(!e)f=-2;else{if(!f){f=a[d>>0]|0;if(f<<24>>24>-1){c[h>>2]=f&255;f=f<<24>>24!=0&1;break}g=(c[c[(wK()|0)+188>>2]>>2]|0)==0;f=a[d>>0]|0;if(g){c[h>>2]=f<<24>>24&57343;f=1;break}f=(f&255)+-194|0;if(f>>>0>50){j=17;break}f=c[55208+(f<<2)>>2]|0;g=e+-1|0;if(g){d=d+1|0;j=11}}else{g=e;j=11}b:do if((j|0)==11){b=a[d>>0]|0;m=(b&255)>>>3;if((m+-16|m+(f>>26))>>>0>7){j=17;break a}while(1){d=d+1|0;f=(b&255)+-128|f<<6;g=g+-1|0;if((f|0)>=0)break;if(!g)break b;b=a[d>>0]|0;if((b&-64)<<24>>24!=-128){j=17;break a}}c[i>>2]=0;c[h>>2]=f;f=e-g|0;break a}while(0);c[i>>2]=f;f=-2}}while(0);if((j|0)==17){c[i>>2]=0;c[(kJ()|0)>>2]=84;f=-1}l=k;return f|0}function tK(a,b){a=a|0;b=b|0;if(!a)a=0;else a=uK(a,b,0)|0;return a|0}function uK(b,d,e){b=b|0;d=d|0;e=e|0;do if(b){if(d>>>0<128){a[b>>0]=d;b=1;break}if(!(c[c[(vK()|0)+188>>2]>>2]|0))if((d&-128|0)==57216){a[b>>0]=d;b=1;break}else{c[(kJ()|0)>>2]=84;b=-1;break}if(d>>>0<2048){a[b>>0]=d>>>6|192;a[b+1>>0]=d&63|128;b=2;break}if(d>>>0<55296|(d&-8192|0)==57344){a[b>>0]=d>>>12|224;a[b+1>>0]=d>>>6&63|128;a[b+2>>0]=d&63|128;b=3;break}if((d+-65536|0)>>>0<1048576){a[b>>0]=d>>>18|240;a[b+1>>0]=d>>>12&63|128;a[b+2>>0]=d>>>6&63|128;a[b+3>>0]=d&63|128;b=4;break}else{c[(kJ()|0)>>2]=84;b=-1;break}}else b=1;while(0);return b|0}function vK(){return BJ()|0}function wK(){return BJ()|0}function xK(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0;p=l;l=l+272|0;n=p+8|0;o=p;do if(!(a[d>>0]|0)){d=Na(134135)|0;if(d|0?a[d>>0]|0:0)break;d=Na(134142+(b*12|0)|0)|0;if(d|0?a[d>>0]|0:0)break;d=Na(134214)|0;if(d|0?a[d>>0]|0:0)break;d=134219}while(0);e=0;a:do{switch(a[d+e>>0]|0){case 47:case 0:break a;default:{}}e=e+1|0}while(e>>>0<15);f=a[d>>0]|0;if(f<<24>>24!=46?(a[d+e>>0]|0)==0:0)if(f<<24>>24==67)m=15;else{k=d;m=16}else{d=134219;m=15}if((m|0)==15)if(!(a[d+1>>0]|0))m=18;else{k=d;m=16}b:do if((m|0)==16)if((yJ(k,134219)|0)!=0?(yJ(k,134227)|0)!=0:0){d=c[42693]|0;if(d|0)do{if(!(yJ(k,d+8|0)|0))break b;d=c[d+24>>2]|0}while((d|0)!=0);pa(170776);d=c[42693]|0;c:do if(d|0){while(1){if(!(yJ(k,d+8|0)|0))break;d=c[d+24>>2]|0;if(!d)break c}Fa(170776);break b}while(0);d:do if(((c[42678]|0)==0?(g=Na(134233)|0,(g|0)!=0):0)?(a[g>>0]|0)!=0:0){i=254-e|0;j=e+1|0;f=g;while(1){h=rJ(f,58)|0;d=a[h>>0]|0;g=h-f+((d<<24>>24!=0)<<31>>31)|0;if(g>>>0>>0){UN(n|0,f|0,g|0)|0;f=n+g|0;a[f>>0]=47;UN(f+1|0,k|0,e|0)|0;a[n+(j+g)>>0]=0;f=qa(n|0,o|0)|0;if(f|0)break;d=a[h>>0]|0}f=h+(d<<24>>24!=0&1)|0;if(!(a[f>>0]|0)){m=41;break d}}d=_I(28)|0;if(!d){oJ(f,c[o>>2]|0)|0;m=41;break}else{c[d>>2]=f;c[d+4>>2]=c[o>>2];o=d+8|0;UN(o|0,k|0,e|0)|0;a[o+e>>0]=0;c[d+24>>2]=c[42693];c[42693]=d;break}}else m=41;while(0);if((m|0)==41){d=_I(28)|0;if(d){c[d>>2]=c[13790];c[d+4>>2]=c[13791];o=d+8|0;UN(o|0,k|0,e|0)|0;a[o+e>>0]=0;c[d+24>>2]=c[42693];c[42693]=d}}Fa(170776);d=(b|0)==0&(d|0)==0?55160:d}else{d=k;m=18}while(0);do if((m|0)==18){if((b|0)==0?(a[d+1>>0]|0)==46:0){d=55160;break}d=0}while(0);l=p;return d|0}function yK(a,b){a=a|0;b=b|0;zK(a,b)|0;return a|0}function zK(b,d){b=b|0;d=d|0;var e=0,f=0;e=d;a:do if(!((e^b)&3)){if(e&3)do{e=a[d>>0]|0;a[b>>0]=e;if(!(e<<24>>24))break a;d=d+1|0;b=b+1|0}while((d&3|0)!=0);e=c[d>>2]|0;if(!((e&-2139062144^-2139062144)&e+-16843009)){f=b;while(1){d=d+4|0;b=f+4|0;c[f>>2]=e;e=c[d>>2]|0;if((e&-2139062144^-2139062144)&e+-16843009|0)break;else f=b}}f=8}else f=8;while(0);if((f|0)==8){f=a[d>>0]|0;a[b>>0]=f;if(f<<24>>24)do{d=d+1|0;b=b+1|0;f=a[d>>0]|0;a[b>>0]=f}while(f<<24>>24!=0)}return b|0}function AK(a){a=a|0;return ((a|0)==32|(a|0)==9)&1|0}function BK(a){a=a|0;if(!a)a=0;else a=(CK(56324,a)|0)!=0&1;return a|0}function CK(a,b){a=a|0;b=b|0;var d=0;if(!b)a=a+((pK(a)|0)<<2)|0;else{while(1){d=c[a>>2]|0;if((d|0)==0|(d|0)==(b|0))break;else a=a+4|0}a=d|0?a:0}return a|0}function DK(a,b){a=a|0;b=b|0;do switch(b|0){case 1:{a=EK(a)|0;break}case 2:{a=oK(a)|0;break}case 3:{a=FK(a)|0;break}case 4:{a=GK(a)|0;break}case 5:{a=gK(a)|0;break}case 6:{a=HK(a)|0;break}case 7:{a=IK(a)|0;break}case 8:{a=rK(a)|0;break}case 9:{a=VJ(a)|0;break}case 10:{a=BK(a)|0;break}case 11:{a=JK(a)|0;break}case 12:{a=KK(a)|0;break}default:a=0}while(0);return a|0}function EK(a){a=a|0;if(!(gK(a)|0))a=(oK(a)|0)!=0&1;else a=1;return a|0}function FK(a){a=a|0;return AK(a)|0}function GK(a){a=a|0;return ((a+-65529|0)>>>0<3|((a&-2|0)==8232|(a>>>0<32|(a+-127|0)>>>0<33)))&1|0}function HK(a){a=a|0;if(!(BK(a)|0))a=(rK(a)|0)!=0&1;else a=0;return a|0}function IK(a){a=a|0;return (mK(a)|0)!=(a|0)|0}function JK(a){a=a|0;return (LK(a)|0)!=(a|0)|0}function KK(a){a=a|0;return ((a+-48|0)>>>0<10|((a|32)+-97|0)>>>0<6)&1|0}function LK(a){a=a|0;return nK(a,1)|0}function MK(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+128|0;g=n+124|0;m=n;h=m;i=56412;j=h+124|0;do{c[h>>2]=c[i>>2];h=h+4|0;i=i+4|0}while((h|0)<(j|0));if((d+-1|0)>>>0>2147483646)if(!d){b=g;d=1;k=4}else{c[(kJ()|0)>>2]=75;d=-1}else k=4;if((k|0)==4){k=-2-b|0;k=d>>>0>k>>>0?k:d;c[m+48>>2]=k;g=m+20|0;c[g>>2]=b;c[m+44>>2]=b;d=b+k|0;b=m+16|0;c[b>>2]=d;c[m+28>>2]=d;d=NK(m,e,f)|0;if(k){m=c[g>>2]|0;a[m+(((m|0)==(c[b>>2]|0))<<31>>31)>>0]=0}}l=n;return d|0}function NK(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=l;l=l+224|0;n=s+120|0;p=s+80|0;q=s;r=s+136|0;f=p;g=f+40|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));c[n>>2]=c[e>>2];if((OK(0,d,n,q,p)|0)<0)e=-1;else{if((c[b+76>>2]|0)>-1)o=PK(b)|0;else o=0;e=c[b>>2]|0;m=e&32;if((a[b+74>>0]|0)<1)c[b>>2]=e&-33;f=b+48|0;if(!(c[f>>2]|0)){g=b+44|0;h=c[g>>2]|0;c[g>>2]=r;i=b+28|0;c[i>>2]=r;j=b+20|0;c[j>>2]=r;c[f>>2]=80;k=b+16|0;c[k>>2]=r+80;e=OK(b,d,n,q,p)|0;if(h){bb[c[b+36>>2]&31](b,0,0)|0;e=(c[j>>2]|0)==0?-1:e;c[g>>2]=h;c[f>>2]=0;c[k>>2]=0;c[i>>2]=0;c[j>>2]=0}}else e=OK(b,d,n,q,p)|0;f=c[b>>2]|0;c[b>>2]=f|m;if(o|0)QK(b);e=(f&32|0)==0?e:-1}l=s;return e|0}function OK(d,e,f,g,i){d=d|0;e=e|0;f=f|0;g=g|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0;I=l;l=l+64|0;D=I+16|0;E=I;A=I+24|0;G=I+8|0;H=I+20|0;c[D>>2]=e;w=(d|0)!=0;x=A+40|0;y=x;A=A+39|0;B=G+4|0;j=0;e=0;m=0;a:while(1){do if((e|0)>-1)if((j|0)>(2147483647-e|0)){c[(kJ()|0)>>2]=75;e=-1;break}else{e=j+e|0;break}while(0);r=c[D>>2]|0;j=a[r>>0]|0;if(!(j<<24>>24)){v=88;break}else k=r;b:while(1){switch(j<<24>>24){case 37:{j=k;v=9;break b}case 0:{j=k;break b}default:{}}u=k+1|0;c[D>>2]=u;j=a[u>>0]|0;k=u}c:do if((v|0)==9)while(1){v=0;if((a[k+1>>0]|0)!=37)break c;j=j+1|0;k=k+2|0;c[D>>2]=k;if((a[k>>0]|0)!=37)break;else v=9}while(0);j=j-r|0;if(w)RK(d,r,j);if(j|0)continue;u=($J(a[(c[D>>2]|0)+1>>0]|0)|0)==0;k=c[D>>2]|0;if(!u?(a[k+2>>0]|0)==36:0){s=(a[k+1>>0]|0)+-48|0;n=1;j=3}else{s=-1;n=m;j=1}j=k+j|0;c[D>>2]=j;k=a[j>>0]|0;u=(k<<24>>24)+-32|0;if(u>>>0>31|(1<>24)+-32|m;j=j+1|0;c[D>>2]=j;k=a[j>>0]|0;u=(k<<24>>24)+-32|0}while(!(u>>>0>31|(1<>24==42){if(($J(a[j+1>>0]|0)|0)!=0?(F=c[D>>2]|0,(a[F+2>>0]|0)==36):0){j=F+1|0;c[i+((a[j>>0]|0)+-48<<2)>>2]=10;j=c[g+((a[j>>0]|0)+-48<<3)>>2]|0;k=1;n=F+3|0}else{if(n|0){e=-1;break}if(w){u=(c[f>>2]|0)+(4-1)&~(4-1);j=c[u>>2]|0;c[f>>2]=u+4}else j=0;k=0;n=(c[D>>2]|0)+1|0}c[D>>2]=n;t=(j|0)<0;u=t?0-j|0:j;m=t?m|8192:m;t=k;j=n}else{j=SK(D)|0;if((j|0)<0){e=-1;break}u=j;t=n;j=c[D>>2]|0}do if((a[j>>0]|0)==46){if((a[j+1>>0]|0)!=42){c[D>>2]=j+1;p=SK(D)|0;j=c[D>>2]|0;break}if($J(a[j+2>>0]|0)|0?(C=c[D>>2]|0,(a[C+3>>0]|0)==36):0){p=C+2|0;c[i+((a[p>>0]|0)+-48<<2)>>2]=10;p=c[g+((a[p>>0]|0)+-48<<3)>>2]|0;j=C+4|0;c[D>>2]=j;break}if(t|0){e=-1;break a}if(w){q=(c[f>>2]|0)+(4-1)&~(4-1);j=c[q>>2]|0;c[f>>2]=q+4}else j=0;q=(c[D>>2]|0)+2|0;c[D>>2]=q;p=j;j=q}else p=-1;while(0);q=0;while(1){if(((a[j>>0]|0)+-65|0)>>>0>57){e=-1;break a}k=j;j=j+1|0;c[D>>2]=j;k=a[(a[k>>0]|0)+-65+(134246+(q*58|0))>>0]|0;n=k&255;if((n+-1|0)>>>0>=8)break;else q=n}if(!(k<<24>>24)){e=-1;break}o=(s|0)>-1;do if(k<<24>>24==19)if(o){e=-1;break a}else v=50;else{if(o){c[i+(s<<2)>>2]=n;o=g+(s<<3)|0;s=c[o+4>>2]|0;v=E;c[v>>2]=c[o>>2];c[v+4>>2]=s;v=50;break}if(!w){e=0;break a}TK(E,n,f);j=c[D>>2]|0}while(0);if((v|0)==50){v=0;if(!w){j=0;m=t;continue}}k=a[j+-1>>0]|0;k=(q|0)!=0&(k&15|0)==3?k&-33:k;j=m&-65537;s=(m&8192|0)==0?m:j;d:do switch(k|0){case 110:switch((q&255)<<24>>24){case 0:{c[c[E>>2]>>2]=e;j=0;m=t;continue a}case 1:{c[c[E>>2]>>2]=e;j=0;m=t;continue a}case 2:{j=c[E>>2]|0;c[j>>2]=e;c[j+4>>2]=((e|0)<0)<<31>>31;j=0;m=t;continue a}case 3:{b[c[E>>2]>>1]=e;j=0;m=t;continue a}case 4:{a[c[E>>2]>>0]=e;j=0;m=t;continue a}case 6:{c[c[E>>2]>>2]=e;j=0;m=t;continue a}case 7:{j=c[E>>2]|0;c[j>>2]=e;c[j+4>>2]=((e|0)<0)<<31>>31;j=0;m=t;continue a}default:{j=0;m=t;continue a}}case 112:{k=120;j=p>>>0>8?p:8;m=s|8;v=62;break}case 88:case 120:{j=p;m=s;v=62;break}case 111:{k=E;j=c[k>>2]|0;k=c[k+4>>2]|0;o=VK(j,k,x)|0;m=y-o|0;q=0;n=134710;p=(s&8|0)==0|(p|0)>(m|0)?p:m+1|0;m=s;v=68;break}case 105:case 100:{k=E;j=c[k>>2]|0;k=c[k+4>>2]|0;if((k|0)<0){j=JN(0,0,j|0,k|0)|0;k=z;m=E;c[m>>2]=j;c[m+4>>2]=k;m=1;n=134710;v=67;break d}else{m=(s&2049|0)!=0&1;n=(s&2048|0)==0?((s&1|0)==0?134710:134712):134711;v=67;break d}}case 117:{k=E;m=0;n=134710;j=c[k>>2]|0;k=c[k+4>>2]|0;v=67;break}case 99:{a[A>>0]=c[E>>2];r=A;q=0;n=134710;o=x;k=1;break}case 109:{k=zJ(c[(kJ()|0)>>2]|0)|0;v=72;break}case 115:{k=c[E>>2]|0;k=k|0?k:134720;v=72;break}case 67:{c[G>>2]=c[E>>2];c[B>>2]=0;c[E>>2]=G;p=-1;m=G;v=76;break}case 83:{j=c[E>>2]|0;if(!p){XK(d,32,u,0,s);j=0;v=85}else{m=j;v=76}break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{j=YK(d,+h[E>>3],u,p,s,k)|0;m=t;continue a}default:{q=0;n=134710;o=x;k=p;j=s}}while(0);e:do if((v|0)==62){s=E;r=c[s>>2]|0;s=c[s+4>>2]|0;o=UK(r,s,x,k&32)|0;n=(m&8|0)==0|(r|0)==0&(s|0)==0;q=n?0:2;n=n?134710:134710+(k>>4)|0;p=j;j=r;k=s;v=68}else if((v|0)==67){o=WK(j,k,x)|0;q=m;m=s;v=68}else if((v|0)==72){v=0;s=_J(k,0,p)|0;m=(s|0)==0;r=k;q=0;n=134710;o=m?k+p|0:s;k=m?p:s-k|0}else if((v|0)==76){v=0;o=m;j=0;k=0;while(1){n=c[o>>2]|0;if(!n)break;k=tK(H,n)|0;if((k|0)<0|k>>>0>(p-j|0)>>>0)break;j=k+j|0;if(p>>>0>j>>>0)o=o+4|0;else break}if((k|0)<0){e=-1;break a}XK(d,32,u,j,s);if(!j){j=0;v=85}else{n=0;while(1){k=c[m>>2]|0;if(!k){v=85;break e}k=tK(H,k)|0;n=k+n|0;if((n|0)>(j|0)){v=85;break e}RK(d,H,k);if(n>>>0>=j>>>0){v=85;break}else m=m+4|0}}}while(0);if((v|0)==68){v=0;k=(j|0)!=0|(k|0)!=0;j=(p|0)!=0|k;k=y-o+((k^1)&1)|0;r=j?o:x;o=x;k=j?((p|0)>(k|0)?p:k):p;j=(p|0)>-1?m&-65537:m}else if((v|0)==85){v=0;XK(d,32,u,j,s^8192);j=(u|0)>(j|0)?u:j;m=t;continue}p=o-r|0;o=(k|0)<(p|0)?p:k;s=o+q|0;m=(u|0)<(s|0)?s:u;XK(d,32,m,s,j);RK(d,n,q);XK(d,48,m,s,j^65536);XK(d,48,o,p,0);RK(d,r,p);XK(d,32,m,s,j^8192);j=m;m=t}f:do if((v|0)==88)if(!d)if(m){e=1;while(1){j=c[i+(e<<2)>>2]|0;if(!j)break;TK(g+(e<<3)|0,j,f);j=e+1|0;if((e|0)<9)e=j;else{e=j;break}}if((e|0)<10)while(1){if(c[i+(e<<2)>>2]|0){e=-1;break f}if((e|0)<9)e=e+1|0;else{e=1;break}}else e=1}else e=0;while(0);l=I;return e|0}function PK(a){a=a|0;return 0}function QK(a){a=a|0;return}function RK(a,b,d){a=a|0;b=b|0;d=d|0;if(!(c[a>>2]&32))_K(b,d,a)|0;return}function SK(b){b=b|0;var d=0,e=0;if(!($J(a[c[b>>2]>>0]|0)|0))d=0;else{d=0;do{e=c[b>>2]|0;d=(d*10|0)+-48+(a[e>>0]|0)|0;e=e+1|0;c[b>>2]=e}while(($J(a[e>>0]|0)|0)!=0)}return d|0}function TK(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0.0;a:do if(b>>>0<=20)do switch(b|0){case 9:{e=(c[d>>2]|0)+(4-1)&~(4-1);b=c[e>>2]|0;c[d>>2]=e+4;c[a>>2]=b;break a}case 10:{e=(c[d>>2]|0)+(4-1)&~(4-1);b=c[e>>2]|0;c[d>>2]=e+4;e=a;c[e>>2]=b;c[e+4>>2]=((b|0)<0)<<31>>31;break a}case 11:{e=(c[d>>2]|0)+(4-1)&~(4-1);b=c[e>>2]|0;c[d>>2]=e+4;e=a;c[e>>2]=b;c[e+4>>2]=0;break a}case 12:{e=(c[d>>2]|0)+(8-1)&~(8-1);b=e;f=c[b>>2]|0;b=c[b+4>>2]|0;c[d>>2]=e+8;e=a;c[e>>2]=f;c[e+4>>2]=b;break a}case 13:{f=(c[d>>2]|0)+(4-1)&~(4-1);e=c[f>>2]|0;c[d>>2]=f+4;e=(e&65535)<<16>>16;f=a;c[f>>2]=e;c[f+4>>2]=((e|0)<0)<<31>>31;break a}case 14:{f=(c[d>>2]|0)+(4-1)&~(4-1);e=c[f>>2]|0;c[d>>2]=f+4;f=a;c[f>>2]=e&65535;c[f+4>>2]=0;break a}case 15:{f=(c[d>>2]|0)+(4-1)&~(4-1);e=c[f>>2]|0;c[d>>2]=f+4;e=(e&255)<<24>>24;f=a;c[f>>2]=e;c[f+4>>2]=((e|0)<0)<<31>>31;break a}case 16:{f=(c[d>>2]|0)+(4-1)&~(4-1);e=c[f>>2]|0;c[d>>2]=f+4;f=a;c[f>>2]=e&255;c[f+4>>2]=0;break a}case 17:{f=(c[d>>2]|0)+(8-1)&~(8-1);g=+h[f>>3];c[d>>2]=f+8;h[a>>3]=g;break a}case 18:{f=(c[d>>2]|0)+(8-1)&~(8-1);g=+h[f>>3];c[d>>2]=f+8;h[a>>3]=g;break a}default:break a}while(0);while(0);return}function UK(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;if(!((b|0)==0&(c|0)==0))do{e=e+-1|0;a[e>>0]=d[134758+(b&15)>>0]|0|f;b=ON(b|0,c|0,4)|0;c=z}while(!((b|0)==0&(c|0)==0));return e|0}function VK(b,c,d){b=b|0;c=c|0;d=d|0;if(!((b|0)==0&(c|0)==0))do{d=d+-1|0;a[d>>0]=b&7|48;b=ON(b|0,c|0,3)|0;c=z}while(!((b|0)==0&(c|0)==0));return d|0}function WK(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;if(c>>>0>0|(c|0)==0&b>>>0>4294967295){while(1){e=NN(b|0,c|0,10,0)|0;d=d+-1|0;a[d>>0]=e&255|48;e=b;b=MN(b|0,c|0,10,0)|0;if(!(c>>>0>9|(c|0)==9&e>>>0>4294967295))break;else c=z}c=b}else c=b;if(c)while(1){d=d+-1|0;a[d>>0]=(c>>>0)%10|0|48;if(c>>>0<10)break;else c=(c>>>0)/10|0}return d|0}function XK(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=l;l=l+256|0;f=g;if((c|0)>(d|0)&(e&73728|0)==0){e=c-d|0;WN(f|0,b<<24>>24|0,(e>>>0<256?e:256)|0)|0;if(e>>>0>255){b=c-d|0;do{RK(a,f,256);e=e+-256|0}while(e>>>0>255);e=b&255}RK(a,f,e)}l=g;return}function YK(b,e,f,g,h,i){b=b|0;e=+e;f=f|0;g=g|0;h=h|0;i=i|0;var j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0;H=l;l=l+560|0;m=H+8|0;u=H;G=H+524|0;F=G;n=H+512|0;c[u>>2]=0;E=n+12|0;ZK(e)|0;if((z|0)<0){e=-e;C=1;B=134727}else{C=(h&2049|0)!=0&1;B=(h&2048|0)==0?((h&1|0)==0?134728:134733):134730}ZK(e)|0;do if(0==0&(z&2146435072|0)==2146435072){G=(i&32|0)!=0;j=C+3|0;XK(b,32,f,j,h&-65537);RK(b,B,C);RK(b,e!=e|0.0!=0.0?(G?134895:134754):G?134746:134750,3);XK(b,32,f,j,h^8192)}else{r=+UJ(e,u)*2.0;j=r!=0.0;if(j)c[u>>2]=(c[u>>2]|0)+-1;w=i|32;if((w|0)==97){p=i&32;s=(p|0)==0?B:B+9|0;q=C|2;j=12-g|0;do if(!(g>>>0>11|(j|0)==0)){e=8.0;do{j=j+-1|0;e=e*16.0}while((j|0)!=0);if((a[s>>0]|0)==45){e=-(e+(-r-e));break}else{e=r+e-e;break}}else e=r;while(0);k=c[u>>2]|0;j=(k|0)<0?0-k|0:k;j=WK(j,((j|0)<0)<<31>>31,E)|0;if((j|0)==(E|0)){j=n+11|0;a[j>>0]=48}a[j+-1>>0]=(k>>31&2)+43;o=j+-2|0;a[o>>0]=i+15;m=(g|0)<1;n=(h&8|0)==0;j=G;do{D=~~e;k=j+1|0;a[j>>0]=p|d[134758+D>>0];e=(e-+(D|0))*16.0;if((k-F|0)==1?!(n&(m&e==0.0)):0){a[k>>0]=46;j=j+2|0}else j=k}while(e!=0.0);if((g|0)!=0?(-2-F+j|0)<(g|0):0){k=j-F|0;j=g+2|0}else{j=j-F|0;k=j}E=E-o|0;F=E+q+j|0;XK(b,32,f,F,h);RK(b,s,q);XK(b,48,f,F,h^65536);RK(b,G,k);XK(b,48,j-k|0,0,0);RK(b,o,E);XK(b,32,f,F,h^8192);j=F;break}k=(g|0)<0?6:g;if(j){j=(c[u>>2]|0)+-28|0;c[u>>2]=j;e=r*268435456.0}else{e=r;j=c[u>>2]|0}D=(j|0)<0?m:m+288|0;m=D;do{y=~~e>>>0;c[m>>2]=y;m=m+4|0;e=(e-+(y>>>0))*1.0e9}while(e!=0.0);if((j|0)>0){n=D;p=m;while(1){o=(j|0)<29?j:29;j=p+-4|0;if(j>>>0>=n>>>0){m=0;do{x=PN(c[j>>2]|0,0,o|0)|0;x=IN(x|0,z|0,m|0,0)|0;y=z;v=NN(x|0,y|0,1e9,0)|0;c[j>>2]=v;m=MN(x|0,y|0,1e9,0)|0;j=j+-4|0}while(j>>>0>=n>>>0);if(m){n=n+-4|0;c[n>>2]=m}}m=p;while(1){if(m>>>0<=n>>>0)break;j=m+-4|0;if(!(c[j>>2]|0))m=j;else break}j=(c[u>>2]|0)-o|0;c[u>>2]=j;if((j|0)>0)p=m;else break}}else n=D;if((j|0)<0){g=((k+25|0)/9|0)+1|0;t=(w|0)==102;do{s=0-j|0;s=(s|0)<9?s:9;if(n>>>0>>0){o=(1<>>s;q=0;j=n;do{y=c[j>>2]|0;c[j>>2]=(y>>>s)+q;q=O(y&o,p)|0;j=j+4|0}while(j>>>0>>0);j=(c[n>>2]|0)==0?n+4|0:n;if(!q){n=j;j=m}else{c[m>>2]=q;n=j;j=m+4|0}}else{n=(c[n>>2]|0)==0?n+4|0:n;j=m}m=t?D:n;m=(j-m>>2|0)>(g|0)?m+(g<<2)|0:j;j=(c[u>>2]|0)+s|0;c[u>>2]=j}while((j|0)<0);j=n;g=m}else{j=n;g=m}y=D;if(j>>>0>>0){m=(y-j>>2)*9|0;o=c[j>>2]|0;if(o>>>0>=10){n=10;do{n=n*10|0;m=m+1|0}while(o>>>0>=n>>>0)}}else m=0;t=(w|0)==103;v=(k|0)!=0;n=k-((w|0)!=102?m:0)+((v&t)<<31>>31)|0;if((n|0)<(((g-y>>2)*9|0)+-9|0)){n=n+9216|0;s=D+4+(((n|0)/9|0)+-1024<<2)|0;n=(n|0)%9|0;if((n|0)<8){o=10;while(1){o=o*10|0;if((n|0)<7)n=n+1|0;else break}}else o=10;p=c[s>>2]|0;q=(p>>>0)%(o>>>0)|0;n=(s+4|0)==(g|0);if(!(n&(q|0)==0)){r=(((p>>>0)/(o>>>0)|0)&1|0)==0?9007199254740992.0:9007199254740994.0;x=(o|0)/2|0;e=q>>>0>>0?.5:n&(q|0)==(x|0)?1.0:1.5;if(C){x=(a[B>>0]|0)==45;e=x?-e:e;r=x?-r:r}n=p-q|0;c[s>>2]=n;if(r+e!=r){x=n+o|0;c[s>>2]=x;if(x>>>0>999999999){m=s;while(1){n=m+-4|0;c[m>>2]=0;if(n>>>0>>0){j=j+-4|0;c[j>>2]=0}x=(c[n>>2]|0)+1|0;c[n>>2]=x;if(x>>>0>999999999)m=n;else break}}else n=s;m=(y-j>>2)*9|0;p=c[j>>2]|0;if(p>>>0>=10){o=10;do{o=o*10|0;m=m+1|0}while(p>>>0>=o>>>0)}}else n=s}else n=s;n=n+4|0;n=g>>>0>n>>>0?n:g;x=j}else{n=g;x=j}w=n;while(1){if(w>>>0<=x>>>0){u=0;break}j=w+-4|0;if(!(c[j>>2]|0))w=j;else{u=1;break}}g=0-m|0;do if(t){j=k+((v^1)&1)|0;if((j|0)>(m|0)&(m|0)>-5){o=i+-1|0;k=j+-1-m|0}else{o=i+-2|0;k=j+-1|0}j=h&8;if(!j){if(u?(A=c[w+-4>>2]|0,(A|0)!=0):0)if(!((A>>>0)%10|0)){n=0;j=10;do{j=j*10|0;n=n+1|0}while(!((A>>>0)%(j>>>0)|0|0))}else n=0;else n=9;j=((w-y>>2)*9|0)+-9|0;if((o|32|0)==102){s=j-n|0;s=(s|0)>0?s:0;k=(k|0)<(s|0)?k:s;s=0;break}else{s=j+m-n|0;s=(s|0)>0?s:0;k=(k|0)<(s|0)?k:s;s=0;break}}else s=j}else{o=i;s=h&8}while(0);t=k|s;p=(t|0)!=0&1;q=(o|32|0)==102;if(q){v=0;j=(m|0)>0?m:0}else{j=(m|0)<0?g:m;j=WK(j,((j|0)<0)<<31>>31,E)|0;n=E;if((n-j|0)<2)do{j=j+-1|0;a[j>>0]=48}while((n-j|0)<2);a[j+-1>>0]=(m>>31&2)+43;j=j+-2|0;a[j>>0]=o;v=j;j=n-j|0}j=C+1+k+p+j|0;XK(b,32,f,j,h);RK(b,B,C);XK(b,48,f,j,h^65536);if(q){o=x>>>0>D>>>0?D:x;s=G+9|0;p=s;q=G+8|0;n=o;do{m=WK(c[n>>2]|0,0,s)|0;if((n|0)==(o|0)){if((m|0)==(s|0)){a[q>>0]=48;m=q}}else if(m>>>0>G>>>0){WN(G|0,48,m-F|0)|0;do m=m+-1|0;while(m>>>0>G>>>0)}RK(b,m,p-m|0);n=n+4|0}while(n>>>0<=D>>>0);if(t|0)RK(b,134774,1);if(n>>>0>>0&(k|0)>0)while(1){m=WK(c[n>>2]|0,0,s)|0;if(m>>>0>G>>>0){WN(G|0,48,m-F|0)|0;do m=m+-1|0;while(m>>>0>G>>>0)}RK(b,m,(k|0)<9?k:9);n=n+4|0;m=k+-9|0;if(!(n>>>0>>0&(k|0)>9)){k=m;break}else k=m}XK(b,48,k+9|0,9,0)}else{t=u?w:x+4|0;if((k|0)>-1){u=G+9|0;s=(s|0)==0;g=u;p=0-F|0;q=G+8|0;o=x;do{m=WK(c[o>>2]|0,0,u)|0;if((m|0)==(u|0)){a[q>>0]=48;m=q}do if((o|0)==(x|0)){n=m+1|0;RK(b,m,1);if(s&(k|0)<1){m=n;break}RK(b,134774,1);m=n}else{if(m>>>0<=G>>>0)break;WN(G|0,48,m+p|0)|0;do m=m+-1|0;while(m>>>0>G>>>0)}while(0);F=g-m|0;RK(b,m,(k|0)>(F|0)?F:k);k=k-F|0;o=o+4|0}while(o>>>0>>0&(k|0)>-1)}XK(b,48,k+18|0,18,0);RK(b,v,E-v|0)}XK(b,32,f,j,h^8192)}while(0);l=H;return ((j|0)<(f|0)?f:j)|0}function ZK(a){a=+a;var b=0;h[j>>3]=a;b=c[j>>2]|0;z=c[j+4>>2]|0;return b|0}function _K(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;f=e+16|0;g=c[f>>2]|0;if(!g)if(!($K(e)|0)){g=c[f>>2]|0;h=5}else f=0;else h=5;a:do if((h|0)==5){j=e+20|0;i=c[j>>2]|0;f=i;if((g-i|0)>>>0>>0){f=bb[c[e+36>>2]&31](e,b,d)|0;break}b:do if((a[e+75>>0]|0)>-1){i=d;while(1){if(!i){h=0;g=b;break b}g=i+-1|0;if((a[b+g>>0]|0)==10)break;else i=g}f=bb[c[e+36>>2]&31](e,b,i)|0;if(f>>>0>>0)break a;h=i;g=b+i|0;d=d-i|0;f=c[j>>2]|0}else{h=0;g=b}while(0);UN(f|0,g|0,d|0)|0;c[j>>2]=(c[j>>2]|0)+d;f=h+d|0}while(0);return f|0}function $K(b){b=b|0;var d=0,e=0;d=b+74|0;e=a[d>>0]|0;a[d>>0]=e+255|e;d=c[b>>2]|0;if(!(d&8)){c[b+8>>2]=0;c[b+4>>2]=0;e=c[b+44>>2]|0;c[b+28>>2]=e;c[b+20>>2]=e;c[b+16>>2]=e+(c[b+48>>2]|0);b=0}else{c[b>>2]=d|32;b=-1}return b|0}function aL(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=a+20|0;f=c[e>>2]|0;a=(c[a+16>>2]|0)-f|0;a=a>>>0>d>>>0?d:a;UN(f|0,b|0,a|0)|0;c[e>>2]=(c[e>>2]|0)+a;return d|0}function bL(b){b=b|0;var c=0,d=0,e=0,f=0;e=a[b>>0]|0;c=1;d=134776;f=97;while(1){if(e<<24>>24==f<<24>>24?(yJ(b,d)|0)==0:0)break;d=d+6|0;f=a[d>>0]|0;if(!(f<<24>>24)){c=0;break}else c=c+1|0}return c|0}function cL(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;h=l;l=l+16|0;g=h;do if(b>>>0>6)d=0;else{pa(170784);if((b|0)!=6){d=dL(b,d)|0;Fa(170784);break}if(!d){d=176258;b=0}else{b=g;e=134849;f=b+16|0;do{a[b>>0]=a[e>>0]|0;b=b+1|0;e=e+1|0}while((b|0)<(f|0));f=0;do{b=rJ(d,59)|0;e=b-d|0;if((e|0)<16){UN(g|0,d|0,e|0)|0;a[g+e>>0]=0;d=(a[b>>0]|0)==0?d:b+1|0}dL(f,g)|0;f=f+1|0}while((f|0)!=6);d=176258;b=0}while(1){f=c[170744+(b<<2)>>2]|0;f=f|0?f+8|0:134865;e=sJ(f)|0;UN(d|0,f|0,e|0)|0;f=d+e|0;a[f>>0]=59;b=b+1|0;if((b|0)==6)break;else d=d+(e+1)|0}a[f>>0]=0;Fa(170784);d=176258}while(0);l=h;return d|0}function dL(a,b){a=a|0;b=b|0;if(!b)a=c[170744+(a<<2)>>2]|0;else{b=xK(a,b)|0;c[170744+(a<<2)>>2]=b;a=b}return (a|0?a+8|0:134865)|0}function eL(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0;a:do if(!d)b=0;else{while(1){e=a[b>>0]|0;f=a[c>>0]|0;if(e<<24>>24!=f<<24>>24)break;d=d+-1|0;if(!d){b=0;break a}else{b=b+1|0;c=c+1|0}}b=(e&255)-(f&255)|0}while(0);return b|0}function fL(a){a=a|0;return gL(a)|0}function gL(a){a=a|0;return QN(a|0)|0}function hL(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;if((c[f+76>>2]|0)>-1)m=PK(f)|0;else m=0;g=e+-1|0;if((e|0)<2){n=f+74|0;l=a[n>>0]|0;a[n>>0]=l+255|l;if(m|0)QK(f);if(!g)a[b>>0]=0;else b=0}else{a:do if(g){k=f+4|0;l=f+8|0;e=b;while(1){h=c[k>>2]|0;o=h;p=(c[l>>2]|0)-o|0;i=_J(h,10,p)|0;j=(i|0)==0;i=j?p:1-o+i|0;i=i>>>0>>0?i:g;UN(e|0,h|0,i|0)|0;h=(c[k>>2]|0)+i|0;c[k>>2]=h;e=e+i|0;i=g-i|0;if(!(j&(i|0)!=0)){n=17;break a}if(h>>>0>=(c[l>>2]|0)>>>0){g=eK(f)|0;if((g|0)<0)break;else j=g}else{c[k>>2]=h+1;j=d[h>>0]|0}g=i+-1|0;h=e+1|0;a[e>>0]=j;if(!((g|0)!=0&(j&255|0)!=10)){e=h;n=17;break a}else e=h}if((e|0)!=(b|0)?(c[f>>2]&16|0)!=0:0)n=17;else b=0}else{e=b;n=17}while(0);if((n|0)==17)if(!b)b=0;else a[e>>0]=0;if(m)QK(f)}return b|0}function iL(b,c){b=b|0;c=c|0;var d=0;d=a[c>>0]|0;do if(d<<24>>24){b=XJ(b,d<<24>>24)|0;if(b){if(a[c+1>>0]|0)if(a[b+1>>0]|0){if(!(a[c+2>>0]|0)){b=jL(b,c)|0;break}if(a[b+2>>0]|0){if(!(a[c+3>>0]|0)){b=kL(b,c)|0;break}if(a[b+3>>0]|0)if(!(a[c+4>>0]|0)){b=lL(b,c)|0;break}else{b=mL(b,c)|0;break}else b=0}else b=0}else b=0}else b=0}while(0);return b|0}function jL(b,c){b=b|0;c=c|0;var e=0,f=0,g=0;g=(d[c>>0]|0)<<8|(d[c+1>>0]|0);f=d[b>>0]|0;while(1){c=b+1|0;e=a[c>>0]|0;if(!(e<<24>>24))break;f=f<<8&65280|e&255;if((f|0)==(g|0))break;else b=c}return (e<<24>>24?b:0)|0}function kL(b,c){b=b|0;c=c|0;var e=0,f=0;f=(d[c+1>>0]|0)<<16|(d[c>>0]|0)<<24|(d[c+2>>0]|0)<<8;e=b+2|0;c=a[e>>0]|0;b=(d[b+1>>0]|0)<<16|(d[b>>0]|0)<<24|(c&255)<<8;if(!((b|0)==(f|0)|c<<24>>24==0))do{e=e+1|0;c=a[e>>0]|0;b=(b|c&255)<<8}while(!((b|0)==(f|0)|c<<24>>24==0));return (c<<24>>24?e+-2|0:0)|0}function lL(b,c){b=b|0;c=c|0;var e=0,f=0;f=(d[c+1>>0]|0)<<16|(d[c>>0]|0)<<24|(d[c+2>>0]|0)<<8|(d[c+3>>0]|0);c=b+3|0;e=a[c>>0]|0;b=(d[b+1>>0]|0)<<16|(d[b>>0]|0)<<24|(d[b+2>>0]|0)<<8|e&255;if(!(e<<24>>24==0|(b|0)==(f|0)))do{c=c+1|0;e=a[c>>0]|0;b=b<<8|e&255}while(!(e<<24>>24==0|(b|0)==(f|0)));return (e<<24>>24?c+-3|0:0)|0}function mL(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0;v=l;l=l+1056|0;t=v+1024|0;u=v;c[t>>2]=0;c[t+4>>2]=0;c[t+8>>2]=0;c[t+12>>2]=0;c[t+16>>2]=0;c[t+20>>2]=0;c[t+24>>2]=0;c[t+28>>2]=0;e=a[d>>0]|0;a:do if(e<<24>>24){s=0;do{if(!(a[b+s>>0]|0)){e=0;break a}r=t+(((e&255)>>>5&255)<<2)|0;c[r>>2]=c[r>>2]|1<<(e&31);s=s+1|0;c[u+((e&255)<<2)>>2]=s;e=a[d+s>>0]|0}while(e<<24>>24!=0);m=s>>>0>1;if(m){f=0;k=-1;g=1;b:while(1){h=1;e=f;while(1){f=g;c:while(1){j=1;while(1){g=a[d+(j+k)>>0]|0;i=a[d+f>>0]|0;if(g<<24>>24!=i<<24>>24)break c;if((j|0)==(h|0))break;j=j+1|0;f=j+e|0;if(f>>>0>=s>>>0){n=h;e=k;break b}}e=h+e|0;f=e+1|0;if(f>>>0>=s>>>0){n=h;e=k;break b}}h=f-k|0;if((g&255)<=(i&255))break;g=f+1|0;if(g>>>0>=s>>>0){n=h;e=k;break b}else e=f}g=e+2|0;if(g>>>0>=s>>>0){n=1;break}else{f=e+1|0;k=e}}if(m){h=0;m=-1;i=1;while(1){f=1;g=h;while(1){h=i;d:while(1){k=1;while(1){i=a[d+(k+m)>>0]|0;j=a[d+h>>0]|0;if(i<<24>>24!=j<<24>>24)break d;if((k|0)==(f|0))break;k=k+1|0;h=k+g|0;if(h>>>0>=s>>>0){i=n;g=m;h=26;break a}}g=f+g|0;h=g+1|0;if(h>>>0>=s>>>0){i=n;g=m;h=26;break a}}f=h-m|0;if((i&255)>=(j&255))break;i=h+1|0;if(i>>>0>=s>>>0){i=n;g=m;h=26;break a}else g=h}i=g+2|0;if(i>>>0>=s>>>0){i=n;f=1;h=26;break}else{h=g+1|0;m=g}}}else{i=n;f=1;g=-1;h=26}}else{i=1;e=-1;f=1;g=-1;h=26}}else{i=1;e=-1;s=0;f=1;g=-1;h=26}while(0);e:do if((h|0)==26){q=(g+1|0)>>>0>(e+1|0)>>>0;f=q?f:i;q=q?g:e;r=q+1|0;if(!(eL(d,d+f|0,r)|0))p=s-f|0;else{f=s-q+-1|0;p=0;f=(q>>>0>f>>>0?q:f)+1|0}k=s|63;m=s+-1|0;n=(p|0)!=0;o=s-f|0;e=b;j=0;g=b;while(1){h=e;do if((g-h|0)>>>0>>0){i=_J(g,0,k)|0;if(i)if((i-h|0)>>>0>>0){e=0;break e}else break;else{i=g+k|0;break}}else i=g;while(0);g=a[e+m>>0]|0;f:do if(!(1<<(g&31)&c[t+(((g&255)>>>5&255)<<2)>>2])){h=0;g=s}else{g=s-(c[u+((g&255)<<2)>>2]|0)|0;if(g|0){h=0;g=n&(j|0)!=0&g>>>0>>0?o:g;break}g=r>>>0>j>>>0?r:j;h=a[d+g>>0]|0;g:do if(!(h<<24>>24))g=r;else{while(1){if(h<<24>>24!=(a[e+g>>0]|0))break;g=g+1|0;h=a[d+g>>0]|0;if(!(h<<24>>24)){g=r;break g}}h=0;g=g-q|0;break f}while(0);while(1){if(g>>>0<=j>>>0)break e;g=g+-1|0;if((a[d+g>>0]|0)!=(a[e+g>>0]|0)){h=p;g=f;break}}}while(0);e=e+g|0;j=h;g=i}}while(0);l=v;return e|0}function nL(a,b,c){a=a|0;b=b|0;c=c|0;oL(a,b,c)|0;return a|0}function oL(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;g=d;a:do if(!((g^b)&3)){f=(e|0)!=0;if(f&(g&3|0)!=0)do{g=a[d>>0]|0;a[b>>0]=g;if(!(g<<24>>24))break a;e=e+-1|0;d=d+1|0;b=b+1|0;f=(e|0)!=0}while(f&(d&3|0)!=0);if(f){if(a[d>>0]|0){b:do if(e>>>0>3){f=d;while(1){d=c[f>>2]|0;if((d&-2139062144^-2139062144)&d+-16843009|0){d=f;break b}c[b>>2]=d;e=e+-4|0;d=f+4|0;b=b+4|0;if(e>>>0>3)f=d;else break}}while(0);h=11}}else e=0}else h=11;while(0);c:do if((h|0)==11)if(!e)e=0;else while(1){h=a[d>>0]|0;a[b>>0]=h;if(!(h<<24>>24))break c;e=e+-1|0;b=b+1|0;if(!e){e=0;break}else d=d+1|0}while(0);WN(b|0,0,e|0)|0;return b|0}function pL(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0;g=l;l=l+32|0;f=g;c[f>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[f+16>>2]=0;c[f+20>>2]=0;c[f+24>>2]=0;c[f+28>>2]=0;e=a[d>>0]|0;do if(!(e<<24>>24))d=0;else{if(!(a[d+1>>0]|0)){d=b;while(1)if((a[d>>0]|0)==e<<24>>24)d=d+1|0;else break;d=d-b|0;break}do{h=f+(((e&255)>>>5&255)<<2)|0;c[h>>2]=c[h>>2]|1<<(e&31);d=d+1|0;e=a[d>>0]|0}while(e<<24>>24!=0);e=a[b>>0]|0;a:do if(!(e<<24>>24))d=b;else{d=b;do{if(!(c[f+(((e&255)>>>5&255)<<2)>>2]&1<<(e&31)))break a;d=d+1|0;e=a[d>>0]|0}while(e<<24>>24!=0)}while(0);d=d-b|0}while(0);l=g;return d|0}function qL(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=l;l=l+16|0;f=e;c[f>>2]=d;d=rL(a,b,f)|0;l=e;return d|0}function rL(a,b,c){a=a|0;b=b|0;c=c|0;return MK(a,2147483647,b,c)|0}function sL(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;m=l;l=l+208|0;j=m+8|0;k=m;h=O(d,b)|0;i=k;c[i>>2]=1;c[i+4>>2]=0;a:do if(h|0){i=0-d|0;c[j+4>>2]=d;c[j>>2]=d;f=2;b=d;g=d;while(1){b=b+d+g|0;c[j+(f<<2)>>2]=b;if(b>>>0>>0){n=g;f=f+1|0;g=b;b=n}else break}g=a+h+i|0;if(g>>>0>a>>>0){h=g;f=1;b=1;do{do if((b&3|0)!=3){b=f+-1|0;if((c[j+(b<<2)>>2]|0)>>>0<(h-a|0)>>>0)tL(a,d,e,f,j);else vL(a,d,e,k,f,0,j);if((f|0)==1){wL(k,1);f=0;break}else{wL(k,b);f=1;break}}else{tL(a,d,e,f,j);uL(k,2);f=f+2|0}while(0);b=c[k>>2]|1;c[k>>2]=b;a=a+d|0}while(a>>>0>>0)}else{f=1;b=1}vL(a,d,e,k,f,0,j);g=k+4|0;while(1){if((f|0)==1&(b|0)==1){if(!(c[g>>2]|0))break a}else if((f|0)>=2){wL(k,2);n=f+-2|0;c[k>>2]=c[k>>2]^7;uL(k,1);vL(a+(0-(c[j+(n<<2)>>2]|0))+i|0,d,e,k,f+-1|0,1,j);wL(k,1);b=c[k>>2]|1;c[k>>2]=b;h=a+i|0;vL(h,d,e,k,n,1,j);a=h;f=n;continue}b=xL(k)|0;uL(k,b);a=a+i|0;f=b+f|0;b=c[k>>2]|0}}while(0);l=m;return}function tL(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+240|0;m=n;c[m>>2]=a;a:do if((e|0)>1){k=0-b|0;g=a;j=e;e=1;while(1){h=g+k|0;i=j+-2|0;g=h+(0-(c[f+(i<<2)>>2]|0))|0;if((ab[d&63](a,g)|0)>-1?(ab[d&63](a,h)|0)>-1:0)break a;a=e+1|0;e=m+(e<<2)|0;if((ab[d&63](g,h)|0)>-1){c[e>>2]=g;e=j+-1|0}else{c[e>>2]=h;g=h;e=i}if((e|0)<=1){e=a;break a}j=e;e=a;a=c[m>>2]|0}}else e=1;while(0);zL(b,m,e);l=n;return}function uL(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=a+4|0;if(b>>>0>31){e=c[f>>2]|0;c[a>>2]=e;c[f>>2]=0;b=b+-32|0;d=0}else{d=c[f>>2]|0;e=c[a>>2]|0}c[a>>2]=d<<32-b|e>>>b;c[f>>2]=d>>>b;return}function vL(a,b,d,e,f,g,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0;p=l;l=l+240|0;n=p+232|0;o=p;q=c[e>>2]|0;c[n>>2]=q;j=c[e+4>>2]|0;k=n+4|0;c[k>>2]=j;c[o>>2]=a;a:do if((q|0)!=1|(j|0)!=0?(m=0-b|0,i=a+(0-(c[h+(f<<2)>>2]|0))|0,(ab[d&63](i,a)|0)>=1):0){e=1;g=(g|0)==0;j=i;while(1){if(g&(f|0)>1){g=a+m|0;i=c[h+(f+-2<<2)>>2]|0;if((ab[d&63](g,j)|0)>-1){i=10;break a}if((ab[d&63](g+(0-i)|0,j)|0)>-1){i=10;break a}}g=e+1|0;c[o+(e<<2)>>2]=j;q=xL(n)|0;uL(n,q);f=q+f|0;if(!((c[n>>2]|0)!=1|(c[k>>2]|0)!=0)){e=g;a=j;i=10;break a}a=j+(0-(c[h+(f<<2)>>2]|0))|0;if((ab[d&63](a,c[o>>2]|0)|0)<1){a=j;e=g;g=0;i=9;break}else{q=j;e=g;g=1;j=a;a=q}}}else{e=1;i=9}while(0);if((i|0)==9?(g|0)==0:0)i=10;if((i|0)==10){zL(b,o,e);tL(a,b,d,f,h)}l=p;return}function wL(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;f=a+4|0;if(b>>>0>31){e=c[a>>2]|0;c[f>>2]=e;c[a>>2]=0;b=b+-32|0;d=0}else{d=c[a>>2]|0;e=c[f>>2]|0}c[f>>2]=d>>>(32-b|0)|e<>2]=d<>2]|0)+-1|0)|0;if(!b){b=yL(c[a+4>>2]|0)|0;return ((b|0)==0?0:b+32|0)|0}else return b|0;return 0}function yL(a){a=a|0;var b=0;if(a)if(!(a&1)){b=a;a=0;do{a=a+1|0;b=b>>>1}while(!(b&1|0))}else a=0;else a=32;return a|0}function zL(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;h=l;l=l+256|0;e=h;a:do if((d|0)>=2?(g=b+(d<<2)|0,c[g>>2]=e,a|0):0)while(1){f=a>>>0<256?a:256;UN(e|0,c[b>>2]|0,f|0)|0;e=0;do{i=b+(e<<2)|0;e=e+1|0;UN(c[i>>2]|0,c[b+(e<<2)>>2]|0,f|0)|0;c[i>>2]=(c[i>>2]|0)+f}while((e|0)!=(d|0));a=a-f|0;if(!a)break a;e=c[g>>2]|0}while(0);l=h;return}function AL(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=l;l=l+16|0;f=e;c[f>>2]=d;d=NK(a,b,f)|0;l=e;return d|0}function BL(b){b=b|0;var d=0,e=0,f=0;f=l;l=l+16|0;e=f;oa(0,e|0)|0;d=0;e=(c[e+4>>2]|0)*65537^(e>>>4)+b;while(1){a[b+d>>0]=(e&15)+65|e<<1&32;d=d+1|0;if((d|0)==6)break;else e=e>>>5}l=f;return b|0}function CL(a,b,c){a=a|0;b=b|0;c=c|0;c=aK(a,b,c,-2147483648,0)|0;return c|0}function DL(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;h=l;l=l+32|0;f=h;e=a[d>>0]|0;a:do if(e<<24>>24!=0?(a[d+1>>0]|0)!=0:0){WN(f|0,0,32)|0;e=a[d>>0]|0;if(e<<24>>24)do{i=f+(((e&255)>>>5&255)<<2)|0;c[i>>2]=c[i>>2]|1<<(e&31);d=d+1|0;e=a[d>>0]|0}while(e<<24>>24!=0);d=a[b>>0]|0;if(!(d<<24>>24))e=b;else{e=b;do{if(c[f+(((d&255)>>>5&255)<<2)>>2]&1<<(d&31)|0)break a;e=e+1|0;d=a[e>>0]|0}while(d<<24>>24!=0)}}else g=3;while(0);if((g|0)==3)e=rJ(b,e<<24>>24)|0;l=h;return e-b|0}function EL(b,d){b=b|0;d=d|0;var e=0;if(!b){b=c[42698]|0;if(!b)b=0;else e=3}else e=3;do if((e|0)==3){b=b+(pL(b,d)|0)|0;if(!(a[b>>0]|0)){c[42698]=0;b=0;break}d=b+(DL(b,d)|0)|0;c[42698]=d;if(!(a[d>>0]|0)){c[42698]=0;break}else{c[42698]=d+1;a[d>>0]=0;break}}while(0);return b|0}function FL(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;e=c&255;do{if(!d){c=0;break}d=d+-1|0;c=b+d|0}while((a[c>>0]|0)!=e<<24>>24);return c|0}function GL(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if(!b){b=c[e>>2]|0;if(!b)b=0;else f=3}else f=3;do if((f|0)==3){b=b+(pL(b,d)|0)|0;if(!(a[b>>0]|0)){c[e>>2]=0;b=0;break}d=b+(DL(b,d)|0)|0;c[e>>2]=d;if(!(a[d>>0]|0)){c[e>>2]=0;break}else{c[e>>2]=d+1;a[d>>0]=0;break}}while(0);return b|0}function HL(a){a=a|0;var b=0,c=0;b=(sJ(a)|0)+1|0;c=_I(b)|0;if(!c)a=0;else a=UN(c|0,a|0,b|0)|0;return a|0}function IL(a,b){a=a|0;b=b|0;return FL(a,b,(sJ(a)|0)+1|0)|0}function JL(a,b){a=a|0;b=b|0;yK(a+(sJ(a)|0)|0,b)|0;return a|0}function KL(b,c){b=b|0;c=c|0;c=b+(DL(b,c)|0)|0;return (a[c>>0]|0?c:0)|0}function LL(a){a=a|0;var b=0;if((c[a+76>>2]|0)>-1){b=(PK(a)|0)==0;a=(c[a>>2]|0)>>>4&1}else a=(c[a>>2]|0)>>>4&1;return a|0}function ML(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;if((c[a+76>>2]|0)>-1)f=PK(a)|0;else f=0;NL(a);g=(c[a>>2]&1|0)!=0;if(!g){e=OL()|0;d=c[a+52>>2]|0;b=a+56|0;if(d|0)c[d+56>>2]=c[b>>2];b=c[b>>2]|0;if(b|0)c[b+52>>2]=d;if((c[e>>2]|0)==(a|0))c[e>>2]=b;PL()}b=QL(a)|0;b=$a[c[a+12>>2]&31](a)|0|b;d=c[a+92>>2]|0;if(d|0)$I(d);if(g){if(f|0)QK(a)}else $I(a);return b|0}function NL(a){a=a|0;var b=0;if(c[a+68>>2]|0){b=c[a+116>>2]|0;a=a+112|0;if(b|0)c[b+112>>2]=c[a>>2];a=c[a>>2]|0;if(!a)a=(SL()|0)+232|0;else a=a+116|0;c[a>>2]=b}return}function OL(){pa(170796);return 170804}function PL(){Fa(170796);return}function QL(a){a=a|0;var b=0,d=0;do if(a){if((c[a+76>>2]|0)<=-1){b=RL(a)|0;break}d=(PK(a)|0)==0;b=RL(a)|0;if(!d)QK(a)}else{if(!(c[13917]|0))b=0;else b=QL(c[13917]|0)|0;a=c[(OL()|0)>>2]|0;if(a)do{if((c[a+76>>2]|0)>-1)d=PK(a)|0;else d=0;if((c[a+20>>2]|0)>>>0>(c[a+28>>2]|0)>>>0)b=RL(a)|0|b;if(d|0)QK(a);a=c[a+56>>2]|0}while((a|0)!=0);PL()}while(0);return b|0}function RL(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;b=a+20|0;h=a+28|0;if((c[b>>2]|0)>>>0>(c[h>>2]|0)>>>0?(bb[c[a+36>>2]&31](a,0,0)|0,(c[b>>2]|0)==0):0)a=-1;else{d=a+4|0;e=c[d>>2]|0;f=a+8|0;g=c[f>>2]|0;if(e>>>0>>0)bb[c[a+40>>2]&31](a,e-g|0,1)|0;c[a+16>>2]=0;c[h>>2]=0;c[b>>2]=0;c[f>>2]=0;c[d>>2]=0;a=0}return a|0}function SL(){return BJ()|0}function TL(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+64|0;j=k+40|0;h=k+24|0;g=k+16|0;f=k;i=k+56|0;if(XJ(134882,a[d>>0]|0)|0){e=_I(1156)|0;if(!e)e=0;else{WN(e|0,0,124)|0;if(!(XJ(d,43)|0))c[e>>2]=(a[d>>0]|0)==114?8:4;if(XJ(d,101)|0){c[f>>2]=b;c[f+4>>2]=2;c[f+8>>2]=1;za(221,f|0)|0}if((a[d>>0]|0)==97){c[g>>2]=b;c[g+4>>2]=3;d=za(221,g|0)|0;if(!(d&1024)){c[h>>2]=b;c[h+4>>2]=4;c[h+8>>2]=d|1024;za(221,h|0)|0}f=c[e>>2]|128;c[e>>2]=f}else f=c[e>>2]|0;c[e+60>>2]=b;c[e+44>>2]=e+132;c[e+48>>2]=1024;d=e+75|0;a[d>>0]=-1;if((f&8|0)==0?(c[j>>2]=b,c[j+4>>2]=21523,c[j+8>>2]=i,(Ca(54,j|0)|0)==0):0)a[d>>0]=10;c[e+32>>2]=6;c[e+36>>2]=9;c[e+40>>2]=7;c[e+12>>2]=15;if(!(c[42677]|0))c[e+76>>2]=-1;UL(e)|0}}else{c[(kJ()|0)>>2]=22;e=0}l=k;return e|0}function UL(a){a=a|0;var b=0,d=0;b=OL()|0;c[a+56>>2]=c[b>>2];d=c[b>>2]|0;if(d|0)c[d+52>>2]=a;c[b>>2]=a;PL();return a|0}function VL(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;j=l;l=l+16|0;g=j;a:do if(!e)b=0;else{do if(f|0){i=(b|0)==0?g:b;b=a[e>>0]|0;if(b<<24>>24>-1){c[i>>2]=b&255;b=b<<24>>24!=0&1;break a}h=(c[c[(WL()|0)+188>>2]>>2]|0)==0;b=a[e>>0]|0;if(h){c[i>>2]=b<<24>>24&57343;b=1;break a}b=(b&255)+-194|0;if(b>>>0<=50){g=e+1|0;h=c[55208+(b<<2)>>2]|0;if(f>>>0<4?h&-2147483648>>>((f*6|0)+-6|0)|0:0)break;b=d[g>>0]|0;f=b>>>3;if((f+-16|f+(h>>26))>>>0<=7){b=b+-128|h<<6;if((b|0)>=0){c[i>>2]=b;b=2;break a}g=(d[e+2>>0]|0)+-128|0;if(g>>>0<=63){g=g|b<<6;if((g|0)>=0){c[i>>2]=g;b=3;break a}b=(d[e+3>>0]|0)+-128|0;if(b>>>0<=63){c[i>>2]=b|g<<6;b=4;break a}}}}}while(0);c[(kJ()|0)>>2]=84;b=-1}while(0);l=j;return b|0}function WL(){return BJ()|0}function XL(a,b){a=a|0;b=b|0;var c=0;c=sJ(a)|0;return ((YL(a,1,c,b)|0)!=(c|0))<<31>>31|0}function YL(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=O(d,b)|0;d=(b|0)==0?0:d;if((c[e+76>>2]|0)>-1){g=(PK(e)|0)==0;a=_K(a,f,e)|0;if(!g)QK(e)}else a=_K(a,f,e)|0;if((a|0)!=(f|0))d=(a>>>0)/(b>>>0)|0;return d|0}function ZL(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,m=0;m=l;l=l+16|0;j=m;k=e&255;a[j>>0]=k;g=b+16|0;h=c[g>>2]|0;if(!h)if(!($K(b)|0)){h=c[g>>2]|0;i=4}else f=-1;else i=4;do if((i|0)==4){i=b+20|0;g=c[i>>2]|0;if(g>>>0>>0?(f=e&255,(f|0)!=(a[b+75>>0]|0)):0){c[i>>2]=g+1;a[g>>0]=k;break}if((bb[c[b+36>>2]&31](b,j,1)|0)==1)f=d[j>>0]|0;else f=-1}while(0);l=m;return f|0}function _L(b,c){b=b|0;c=c|0;var d=0,e=0,f=0;d=b;e=134867;f=d+15|0;do{a[d>>0]=a[e>>0]|0;d=d+1|0;e=e+1|0}while((d|0)<(f|0));if(!c){a[b+14>>0]=48;a[b+15>>0]=0}else{e=c;d=14;while(1){d=d+1|0;if(e>>>0<10)break;else e=(e>>>0)/10|0}a[b+d>>0]=0;while(1){d=d+-1|0;a[b+d>>0]=(c>>>0)%10|0|48;if(c>>>0<10)break;else c=(c>>>0)/10|0}}return}function $L(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=l;l=l+48|0;f=g+40|0;e=g+8|0;d=g;c[d>>2]=a;c[d+4>>2]=b;d=ya(197,d|0)|0;if((d|0)==-9?(c[e>>2]=a,c[e+4>>2]=1,(za(221,e|0)|0)>=0):0){_L(e,a);c[f>>2]=e;c[f+4>>2]=b;b=jJ(xa(195,f|0)|0)|0}else b=jJ(d)|0;l=g;return b|0}function aM(a,b){a=a|0;b=b|0;var d=0,e=0;d=l;l=l+16|0;e=d;c[e>>2]=a;c[e+4>>2]=b;b=jJ(Aa(33,e|0)|0)|0;l=d;return b|0}function bM(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=l;l=l+48|0;h=i+32|0;g=i+16|0;e=i;if(XJ(134882,a[d>>0]|0)|0){f=cM(d)|0;c[e>>2]=b;c[e+4>>2]=f|32768;c[e+8>>2]=438;e=jJ(Ba(5,e|0)|0)|0;if((e|0)>=0){if(f&524288|0){c[g>>2]=e;c[g+4>>2]=2;c[g+8>>2]=1;za(221,g|0)|0}b=TL(e,d)|0;if(!b){c[h>>2]=e;Da(6,h|0)|0;b=0}}else b=0}else{c[(kJ()|0)>>2]=22;b=0}l=i;return b|0}function cM(b){b=b|0;var c=0,d=0,e=0;d=(XJ(b,43)|0)==0;c=a[b>>0]|0;d=d?c<<24>>24!=114&1:2;e=(XJ(b,120)|0)==0;d=e?d:d|128;b=(XJ(b,101)|0)==0;b=b?d:d|524288;b=c<<24>>24==114?b:b|64;b=c<<24>>24==119?b|512:b;return (c<<24>>24==97?b|1024:b)|0}function dM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=l;l=l+16|0;f=e;c[f>>2]=d;d=eM(a,b,f)|0;l=e;return d|0}function eM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;g=l;l=l+128|0;e=g;f=e;h=f+124|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(h|0));c[e+32>>2]=18;c[e+44>>2]=a;c[e+76>>2]=-1;c[e+84>>2]=a;h=gM(e,b,d)|0;l=g;return h|0}function fM(a,b,c){a=a|0;b=b|0;c=c|0;return oM(a,b,c)|0}function gM(b,e,f){b=b|0;e=e|0;f=f|0;var i=0,j=0,k=0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;L=l;l=l+288|0;F=L+8|0;G=L+17|0;H=L;I=L+16|0;if((c[b+76>>2]|0)>-1)K=PK(b)|0;else K=0;i=a[e>>0]|0;a:do if(i<<24>>24){y=b+4|0;A=b+100|0;B=b+108|0;C=b+8|0;D=G+10|0;E=G+33|0;x=F+4|0;p=e;u=0;e=0;j=0;k=i;i=0;b:while(1){c:do if(!(YJ(k&255)|0)){k=(a[p>>0]|0)==37;d:do if(k){m=p+1|0;n=a[m>>0]|0;e:do switch(n<<24>>24){case 37:break d;case 42:{w=0;m=p+2|0;break}default:{if($J(n&255)|0?(a[p+2>>0]|0)==36:0){w=hM(f,(d[m>>0]|0)+-48|0)|0;m=p+3|0;break e}v=(c[f>>2]|0)+(4-1)&~(4-1);w=c[v>>2]|0;c[f>>2]=v+4}}while(0);if(!($J(d[m>>0]|0)|0))s=0;else{k=0;do{k=(k*10|0)+-48+(d[m>>0]|0)|0;m=m+1|0}while(($J(d[m>>0]|0)|0)!=0);s=k}p=a[m>>0]|0;n=m+1|0;if(p<<24>>24==109){k=(w|0)!=0&1;j=0;m=n;p=a[n>>0]|0;i=0}else k=0;n=m+1|0;switch(p<<24>>24){case 104:{v=(a[n>>0]|0)==104;p=v?-2:-1;m=v?m+2|0:n;break}case 108:{v=(a[n>>0]|0)==108;p=v?3:1;m=v?m+2|0:n;break}case 106:{p=3;m=n;break}case 116:case 122:{p=1;m=n;break}case 76:{p=2;m=n;break}case 110:case 112:case 67:case 83:case 91:case 99:case 115:case 88:case 71:case 70:case 69:case 65:case 103:case 102:case 101:case 97:case 120:case 117:case 111:case 105:case 100:{p=0;break}default:{J=136;break b}}r=d[m>>0]|0;t=(r&47|0)==3;r=t?r|32:r;t=t?1:p;q=r&255;switch(q<<24>>24){case 99:{s=(s|0)>1?s:1;break}case 91:break;case 110:{iM(w,t,u,((u|0)<0)<<31>>31);n=u;break c}default:{bK(b,0);do{n=c[y>>2]|0;if(n>>>0<(c[A>>2]|0)>>>0){c[y>>2]=n+1;n=d[n>>0]|0}else n=dK(b)|0}while((YJ(n)|0)!=0);if(!(c[A>>2]|0))n=c[y>>2]|0;else{n=(c[y>>2]|0)+-1|0;c[y>>2]=n}u=(c[B>>2]|0)+u+n-(c[C>>2]|0)|0}}bK(b,s);p=c[y>>2]|0;n=c[A>>2]|0;if(p>>>0>>0)c[y>>2]=p+1;else{if((dK(b)|0)<0){J=136;break b}n=c[A>>2]|0}if(n|0)c[y>>2]=(c[y>>2]|0)+-1;f:do switch(q<<24>>24){case 91:case 99:case 115:{v=(r|0)==99;g:do if((r|16|0)==115){WN(G|0,-1,257)|0;a[G>>0]=0;if((r|0)==115){a[E>>0]=0;a[D>>0]=0;a[D+1>>0]=0;a[D+2>>0]=0;a[D+3>>0]=0;a[D+4>>0]=0}}else{n=m+1|0;q=(a[n>>0]|0)==94;r=q&1;m=q?m+2|0:n;WN(G|0,r|0,257)|0;a[G>>0]=0;n=a[m>>0]|0;switch(n<<24>>24){case 45:{n=46;J=65;break}case 93:{n=94;J=65;break}default:{}}while(1){if((J|0)==65){J=0;a[G+n>>0]=r^1;n=m+1|0;m=n;n=a[n>>0]|0}h:do switch(n<<24>>24){case 0:{J=136;break b}case 93:break g;case 45:{q=m+1|0;n=a[q>>0]|0;switch(n<<24>>24){case 93:case 0:{n=45;break h}default:{}}m=a[m+-1>>0]|0;if((m&255)<(n&255)){p=(r^1)&255;m=m&255;do{m=m+1|0;a[G+m>>0]=p;n=a[q>>0]|0}while((m|0)<(n&255|0));m=q}else m=q;break}default:{}}while(0);n=(n&255)+1|0;J=65}}while(0);n=v?s+1|0:31;r=(t|0)==1;t=(k|0)!=0;i:do if(r){if(t){i=_I(n<<2)|0;if(!i){j=0;i=0;J=136;break b}}else i=w;c[F>>2]=0;c[x>>2]=0;q=n;j=0;j:while(1){p=(i|0)==0;do{k:while(1){n=c[y>>2]|0;if(n>>>0<(c[A>>2]|0)>>>0){c[y>>2]=n+1;n=d[n>>0]|0}else n=dK(b)|0;if(!(a[G+(n+1)>>0]|0))break j;a[I>>0]=n;switch(sK(H,I,1,F)|0){case -1:{j=0;J=136;break b}case -2:break;default:break k}}if(!p){c[i+(j<<2)>>2]=c[H>>2];j=j+1|0}}while(!(t&(j|0)==(q|0)));j=q<<1|1;n=bJ(i,j<<2)|0;if(!n){j=0;J=136;break b}else{p=q;q=j;i=n;j=p}}if(!(jM(F)|0)){j=0;J=136;break b}else{q=j;j=0;p=i}}else{if(t){j=_I(n)|0;if(!j){j=0;i=0;J=136;break b}else{p=n;i=0}while(1){do{n=c[y>>2]|0;if(n>>>0<(c[A>>2]|0)>>>0){c[y>>2]=n+1;n=d[n>>0]|0}else n=dK(b)|0;if(!(a[G+(n+1)>>0]|0)){q=i;p=0;i=0;break i}a[j+i>>0]=n;i=i+1|0}while((i|0)!=(p|0));i=p<<1|1;n=bJ(j,i)|0;if(!n){i=0;J=136;break b}else{q=p;p=i;j=n;i=q}}}if(!w)while(1){i=c[y>>2]|0;if(i>>>0<(c[A>>2]|0)>>>0){c[y>>2]=i+1;i=d[i>>0]|0}else i=dK(b)|0;if(!(a[G+(i+1)>>0]|0)){q=0;j=0;p=0;i=0;break i}}else j=0;while(1){i=c[y>>2]|0;if(i>>>0<(c[A>>2]|0)>>>0){c[y>>2]=i+1;i=d[i>>0]|0}else i=dK(b)|0;if(!(a[G+(i+1)>>0]|0)){q=j;j=w;p=0;i=0;break i}a[w+j>>0]=i;j=j+1|0}}while(0);if(!(c[A>>2]|0))n=c[y>>2]|0;else{n=(c[y>>2]|0)+-1|0;c[y>>2]=n}n=n-(c[C>>2]|0)+(c[B>>2]|0)|0;if(!n)break b;if(!((n|0)==(s|0)|v^1))break b;do if(t)if(r){c[w>>2]=p;break}else{c[w>>2]=j;break}while(0);if(!v){if(p|0)c[p+(q<<2)>>2]=0;if(!j){j=0;break f}a[j+q>>0]=0}break}case 120:case 88:case 112:{n=16;J=124;break}case 111:{n=8;J=124;break}case 117:case 100:{n=10;J=124;break}case 105:{n=0;J=124;break}case 71:case 103:case 70:case 102:case 69:case 101:case 65:case 97:{o=+kM(b,t,0);if((c[B>>2]|0)==((c[C>>2]|0)-(c[y>>2]|0)|0))break b;if(w)switch(t|0){case 0:{g[w>>2]=o;break f}case 1:{h[w>>3]=o;break f}case 2:{h[w>>3]=o;break f}default:break f}break}default:{}}while(0);do if((J|0)==124){J=0;n=cK(b,n,0,-1,-1)|0;if((c[B>>2]|0)==((c[C>>2]|0)-(c[y>>2]|0)|0))break b;if((w|0)!=0&(r|0)==112){c[w>>2]=n;break}else{iM(w,t,n,z);break}}while(0);e=e+((w|0)!=0&1)|0;n=(c[B>>2]|0)+u+(c[y>>2]|0)-(c[C>>2]|0)|0;break c}while(0);m=p+(k&1)|0;bK(b,0);k=c[y>>2]|0;if(k>>>0<(c[A>>2]|0)>>>0){c[y>>2]=k+1;k=d[k>>0]|0}else k=dK(b)|0;if((k|0)!=(d[m>>0]|0)){J=22;break b}n=u+1|0}else{m=p;while(1){k=m+1|0;if(!(YJ(d[k>>0]|0)|0))break;else m=k}bK(b,0);do{k=c[y>>2]|0;if(k>>>0<(c[A>>2]|0)>>>0){c[y>>2]=k+1;k=d[k>>0]|0}else k=dK(b)|0}while((YJ(k)|0)!=0);if(!(c[A>>2]|0))k=c[y>>2]|0;else{k=(c[y>>2]|0)+-1|0;c[y>>2]=k}n=(c[B>>2]|0)+u+k-(c[C>>2]|0)|0}while(0);p=m+1|0;k=a[p>>0]|0;if(!(k<<24>>24))break a;else u=n}if((J|0)==22){if(c[A>>2]|0)c[y>>2]=(c[y>>2]|0)+-1;if((e|0)!=0|(k|0)>-1)break;else{e=0;J=137}}else if((J|0)==136)if(!e){e=k;J=137}if((J|0)==137){k=e;e=-1}if(k){$I(j);$I(i)}}else e=0;while(0);if(K|0)QK(b);l=L;return e|0}function hM(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;e=l;l=l+16|0;d=e;c[d>>2]=c[a>>2];while(1){f=(c[d>>2]|0)+(4-1)&~(4-1);a=c[f>>2]|0;c[d>>2]=f+4;if(b>>>0>1)b=b+-1|0;else break}l=e;return a|0}function iM(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;a:do if(d|0)switch(e|0){case -2:{a[d>>0]=f;break a}case -1:{b[d>>1]=f;break a}case 0:{c[d>>2]=f;break a}case 1:{c[d>>2]=f;break a}case 3:{e=d;c[e>>2]=f;c[e+4>>2]=g;break a}default:break a}while(0);return}function jM(a){a=a|0;if(!a)a=1;else a=(c[a>>2]|0)==0&1;return a|0}function kM(b,e,f){b=b|0;e=e|0;f=f|0;var g=0.0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;switch(e|0){case 0:{l=-149;m=24;j=4;break}case 1:{l=-1074;m=53;j=4;break}case 2:{l=-1074;m=53;j=4;break}default:g=0.0}a:do if((j|0)==4){o=b+4|0;n=b+100|0;do{e=c[o>>2]|0;if(e>>>0<(c[n>>2]|0)>>>0){c[o>>2]=e+1;e=d[e>>0]|0}else e=dK(b)|0}while((YJ(e)|0)!=0);b:do switch(e|0){case 43:case 45:{i=1-(((e|0)==45&1)<<1)|0;e=c[o>>2]|0;if(e>>>0<(c[n>>2]|0)>>>0){c[o>>2]=e+1;h=d[e>>0]|0;break b}else{h=dK(b)|0;break b}}default:{h=e;i=1}}while(0);e=0;do{if((h|32|0)!=(a[134886+e>>0]|0))break;do if(e>>>0<7){h=c[o>>2]|0;if(h>>>0<(c[n>>2]|0)>>>0){c[o>>2]=h+1;h=d[h>>0]|0;break}else{h=dK(b)|0;break}}while(0);e=e+1|0}while(e>>>0<8);c:do switch(e|0){case 8:break;case 3:{j=23;break}default:{k=(f|0)!=0;if(k&e>>>0>3)if((e|0)==8)break c;else{j=23;break c}d:do if(!e){e=0;do{if((h|32|0)!=(a[134895+e>>0]|0))break d;do if(e>>>0<2){h=c[o>>2]|0;if(h>>>0<(c[n>>2]|0)>>>0){c[o>>2]=h+1;h=d[h>>0]|0;break}else{h=dK(b)|0;break}}while(0);e=e+1|0}while(e>>>0<3)}while(0);switch(e|0){case 3:{e=c[o>>2]|0;if(e>>>0<(c[n>>2]|0)>>>0){c[o>>2]=e+1;e=d[e>>0]|0}else e=dK(b)|0;if((e|0)==40)e=1;else{if(!(c[n>>2]|0)){g=s;break a}c[o>>2]=(c[o>>2]|0)+-1;g=s;break a}while(1){h=c[o>>2]|0;if(h>>>0<(c[n>>2]|0)>>>0){c[o>>2]=h+1;h=d[h>>0]|0}else h=dK(b)|0;if(!((h+-48|0)>>>0<10|(h+-65|0)>>>0<26)?!((h|0)==95|(h+-97|0)>>>0<26):0)break;e=e+1|0}if((h|0)==41){g=s;break a}h=(c[n>>2]|0)==0;if(!h)c[o>>2]=(c[o>>2]|0)+-1;if(!k){c[(kJ()|0)>>2]=22;bK(b,0);g=0.0;break a}if(!e){g=s;break a}while(1){e=e+-1|0;if(!h)c[o>>2]=(c[o>>2]|0)+-1;if(!e){g=s;break a}}}case 0:{if((h|0)==48){e=c[o>>2]|0;if(e>>>0<(c[n>>2]|0)>>>0){c[o>>2]=e+1;e=d[e>>0]|0}else e=dK(b)|0;if((e|32|0)==120){g=+lM(b,m,l,i,f);break a}if(!(c[n>>2]|0))e=48;else{c[o>>2]=(c[o>>2]|0)+-1;e=48}}else e=h;g=+mM(b,e,m,l,i,f);break a}default:{if(c[n>>2]|0)c[o>>2]=(c[o>>2]|0)+-1;c[(kJ()|0)>>2]=22;bK(b,0);g=0.0;break a}}}}while(0);if((j|0)==23){h=(c[n>>2]|0)==0;if(!h)c[o>>2]=(c[o>>2]|0)+-1;if((f|0)!=0&e>>>0>3)do{if(!h)c[o>>2]=(c[o>>2]|0)+-1;e=e+-1|0}while(e>>>0>3)}g=+(i|0)*t}while(0);return +g}function lM(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0.0,i=0,j=0,k=0.0,l=0,m=0,n=0,o=0.0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;y=a+4|0;i=c[y>>2]|0;x=a+100|0;if(i>>>0<(c[x>>2]|0)>>>0){c[y>>2]=i+1;j=d[i>>0]|0;l=0}else{j=dK(a)|0;l=0}a:while(1){switch(j|0){case 46:{w=8;break a}case 48:break;default:{s=0;n=0;o=1.0;h=0.0;i=0;m=j;t=l;v=0;u=0;l=0;j=0;break a}}i=c[y>>2]|0;if(i>>>0<(c[x>>2]|0)>>>0){c[y>>2]=i+1;j=d[i>>0]|0;l=1;continue}else{j=dK(a)|0;l=1;continue}}if((w|0)==8){i=c[y>>2]|0;if(i>>>0<(c[x>>2]|0)>>>0){c[y>>2]=i+1;j=d[i>>0]|0}else j=dK(a)|0;if((j|0)==48){l=0;j=0;do{i=c[y>>2]|0;if(i>>>0<(c[x>>2]|0)>>>0){c[y>>2]=i+1;m=d[i>>0]|0}else m=dK(a)|0;l=IN(l|0,j|0,-1,-1)|0;j=z}while((m|0)==48);s=1;n=0;o=1.0;h=0.0;i=0;t=1;v=0;u=0}else{s=1;n=0;o=1.0;h=0.0;i=0;m=j;t=l;v=0;u=0;l=0;j=0}}while(1){q=m+-48|0;p=m|32;if(q>>>0>=10){r=(m|0)==46;if(!(r|(p+-97|0)>>>0<6))break;if(r)if(!s){s=1;k=o;r=t;l=u;j=v;q=u;p=v}else{m=46;break}else w=20}else w=20;if((w|0)==20){w=0;m=(m|0)>57?p+-87|0:q;do if(!((v|0)<0|(v|0)==0&u>>>0<8))if((v|0)<0|(v|0)==0&u>>>0<14){o=o*.0625;k=o;h=h+o*+(m|0);break}else{t=(n|0)!=0|(m|0)==0;n=t?n:1;k=o;h=t?h:h+o*.5;break}else{k=o;i=m+(i<<4)|0}while(0);q=IN(u|0,v|0,1,0)|0;r=1;p=z}m=c[y>>2]|0;if(m>>>0<(c[x>>2]|0)>>>0){c[y>>2]=m+1;o=k;m=d[m>>0]|0;t=r;v=p;u=q;continue}else{o=k;m=dK(a)|0;t=r;v=p;u=q;continue}}do if(!t){i=(c[x>>2]|0)==0;if(!i)c[y>>2]=(c[y>>2]|0)+-1;if(g){if(!i)c[y>>2]=(c[y>>2]|0)+-1;if(!((s|0)==0|i))c[y>>2]=(c[y>>2]|0)+-1}else bK(a,0);h=+(f|0)*0.0}else{p=(s|0)==0;q=p?u:l;p=p?v:j;if((v|0)<0|(v|0)==0&u>>>0<8){l=u;j=v;while(1){i=i<<4;w=l;l=IN(l|0,j|0,1,0)|0;if(!((j|0)<0|(j|0)==0&w>>>0<7)){n=i;break}else j=z}}else n=i;if((m|32|0)==112){j=nM(a,g)|0;i=z;if((j|0)==0&(i|0)==-2147483648){if(!g){bK(a,0);h=0.0;break}if(!(c[x>>2]|0)){j=0;i=0}else{c[y>>2]=(c[y>>2]|0)+-1;j=0;i=0}}}else if(!(c[x>>2]|0)){j=0;i=0}else{c[y>>2]=(c[y>>2]|0)+-1;j=0;i=0}l=PN(q|0,p|0,2)|0;l=IN(l|0,z|0,-32,-1)|0;l=IN(l|0,z|0,j|0,i|0)|0;i=z;if(!n){h=+(f|0)*0.0;break}y=0-e|0;g=((y|0)<0)<<31>>31;if((i|0)>(g|0)|(i|0)==(g|0)&l>>>0>y>>>0){c[(kJ()|0)>>2]=34;h=+(f|0)*1797693134862315708145274.0e284*1797693134862315708145274.0e284;break}y=e+-106|0;g=((y|0)<0)<<31>>31;if((i|0)<(g|0)|(i|0)==(g|0)&l>>>0>>0){c[(kJ()|0)>>2]=34;h=+(f|0)*2.2250738585072014e-308*2.2250738585072014e-308;break}if((n|0)>-1){j=n;do{y=!(h>=.5);j=j<<1|(y^1)&1;h=h+(y?h:h+-1.0);l=IN(l|0,i|0,-1,-1)|0;i=z}while((j|0)>-1);o=h;m=j}else{o=h;m=n}y=((b|0)<0)<<31>>31;e=JN(32,0,e|0,((e|0)<0)<<31>>31|0)|0;i=IN(e|0,z|0,l|0,i|0)|0;e=z;if((e|0)<(y|0)|(e|0)==(y|0)&i>>>0>>0)if((i|0)>0)w=59;else{j=0;i=84;w=61}else{i=b;w=59}if((w|0)==59)if((i|0)<53){j=i;i=84-i|0;w=61}else{k=0.0;h=+(f|0)}if((w|0)==61){h=+(f|0);k=+MJ(+JJ(1.0,i),h);i=j}f=(m&1|0)==0&(o!=0.0&(i|0)<32);h=(f?0.0:o)*h+(k+h*+((m+(f&1)|0)>>>0))-k;if(!(h!=0.0))c[(kJ()|0)>>2]=34;h=+NJ(h,l)}while(0);return +h}function mM(a,b,e,f,g,h){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var i=0.0,j=0.0,k=0,m=0,n=0,o=0,p=0,q=0,r=0.0,s=0.0,t=0.0,u=0,v=0,w=0,x=0,y=0,A=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0.0;J=l;l=l+512|0;G=J;H=f+e|0;I=0-H|0;D=a+4|0;E=a+100|0;k=0;a:while(1){switch(b|0){case 46:{A=6;break a}case 48:break;default:{v=0;p=k;q=0;o=0;break a}}b=c[D>>2]|0;if(b>>>0<(c[E>>2]|0)>>>0){c[D>>2]=b+1;b=d[b>>0]|0;k=1;continue}else{b=dK(a)|0;k=1;continue}}if((A|0)==6){b=c[D>>2]|0;if(b>>>0<(c[E>>2]|0)>>>0){c[D>>2]=b+1;b=d[b>>0]|0}else b=dK(a)|0;if((b|0)==48){k=0;b=0;while(1){k=IN(k|0,b|0,-1,-1)|0;o=z;b=c[D>>2]|0;if(b>>>0<(c[E>>2]|0)>>>0){c[D>>2]=b+1;b=d[b>>0]|0}else b=dK(a)|0;if((b|0)==48)b=o;else{v=1;p=1;q=k;break}}}else{v=1;p=k;q=0;o=0}}c[G>>2]=0;n=b+-48|0;m=(b|0)==46;b:do if(m|n>>>0<10){C=G+496|0;w=0;k=0;u=0;x=v;y=p;A=n;p=0;n=0;c:while(1){do if(m)if(!x){x=1;q=p;o=n}else break c;else{p=IN(p|0,n|0,1,0)|0;n=z;v=(b|0)!=48;if((k|0)>=125){if(!v)break;c[C>>2]=c[C>>2]|1;break}m=G+(k<<2)|0;if(!w)b=A;else b=b+-48+((c[m>>2]|0)*10|0)|0;c[m>>2]=b;w=w+1|0;y=(w|0)==9;w=y?0:w;k=k+(y&1)|0;u=v?p:u;y=1}while(0);b=c[D>>2]|0;if(b>>>0<(c[E>>2]|0)>>>0){c[D>>2]=b+1;b=d[b>>0]|0}else b=dK(a)|0;A=b+-48|0;m=(b|0)==46;if(!(m|A>>>0<10)){v=x;m=y;A=29;break b}}b=w;m=(y|0)!=0;A=37}else{w=0;k=0;u=0;m=p;p=0;n=0;A=29}while(0);do if((A|0)==29){C=(v|0)==0;q=C?p:q;o=C?n:o;m=(m|0)!=0;if(!(m&(b|32|0)==101))if((b|0)>-1){b=w;A=37;break}else{b=w;A=39;break}m=nM(a,h)|0;b=z;if((m|0)==0&(b|0)==-2147483648){if(!h){bK(a,0);i=0.0;break}if(!(c[E>>2]|0)){m=0;b=0}else{c[D>>2]=(c[D>>2]|0)+-1;m=0;b=0}}y=IN(m|0,b|0,q|0,o|0)|0;b=w;o=z;A=41}while(0);if((A|0)==37)if(c[E>>2]|0){c[D>>2]=(c[D>>2]|0)+-1;if(m){y=q;A=41}else A=40}else A=39;if((A|0)==39)if(m){y=q;A=41}else A=40;do if((A|0)==40){c[(kJ()|0)>>2]=22;bK(a,0);i=0.0}else if((A|0)==41){m=c[G>>2]|0;if(!m){i=+(g|0)*0.0;break}if(((n|0)<0|(n|0)==0&p>>>0<10)&((y|0)==(p|0)&(o|0)==(n|0))?(e|0)>30|(m>>>e|0)==0:0){i=+(g|0)*+(m>>>0);break}a=(f|0)/-2|0;E=((a|0)<0)<<31>>31;if((o|0)>(E|0)|(o|0)==(E|0)&y>>>0>a>>>0){c[(kJ()|0)>>2]=34;i=+(g|0)*1797693134862315708145274.0e284*1797693134862315708145274.0e284;break}a=f+-106|0;E=((a|0)<0)<<31>>31;if((o|0)<(E|0)|(o|0)==(E|0)&y>>>0>>0){c[(kJ()|0)>>2]=34;i=+(g|0)*2.2250738585072014e-308*2.2250738585072014e-308;break}if(b){if((b|0)<9){n=G+(k<<2)|0;m=c[n>>2]|0;while(1){m=m*10|0;if((b|0)>=8)break;else b=b+1|0}c[n>>2]=m}k=k+1|0}if((u|0)<9?(u|0)<=(y|0)&(y|0)<18:0){if((y|0)==9){i=+(g|0)*+((c[G>>2]|0)>>>0);break}if((y|0)<9){i=+(g|0)*+((c[G>>2]|0)>>>0)/+(c[56536+(8-y<<2)>>2]|0);break}a=e+27+(O(y,-3)|0)|0;b=c[G>>2]|0;if((a|0)>30|(b>>>a|0)==0){i=+(g|0)*+(b>>>0)*+(c[56536+(y+-10<<2)>>2]|0);break}}b=(y|0)%9|0;if(!b){b=0;n=0}else{u=(y|0)>-1?b:b+9|0;p=c[56536+(8-u<<2)>>2]|0;if(k){q=1e9/(p|0)|0;n=0;o=0;m=y;b=0;do{D=G+(b<<2)|0;E=c[D>>2]|0;a=((E>>>0)/(p>>>0)|0)+n|0;c[D>>2]=a;n=O(q,(E>>>0)%(p>>>0)|0)|0;a=(b|0)==(o|0)&(a|0)==0;m=a?m+-9|0:m;o=a?o+1&127:o;b=b+1|0}while((b|0)!=(k|0));if(!n)n=o;else{c[G+(k<<2)>>2]=n;n=o;k=k+1|0}}else{n=0;k=0;m=y}b=0;y=9-u+m|0}d:while(1){u=(y|0)<18;v=(y|0)==18;w=G+(n<<2)|0;while(1){if(!u){if(!v){m=y;break d}if((c[w>>2]|0)>>>0>=9007199){m=18;break d}}m=0;x=k;k=k+127|0;while(1){o=k&127;p=G+(o<<2)|0;k=PN(c[p>>2]|0,0,29)|0;k=IN(k|0,z|0,m|0,0)|0;m=z;if(m>>>0>0|(m|0)==0&k>>>0>1e9){q=MN(k|0,m|0,1e9,0)|0;k=NN(k|0,m|0,1e9,0)|0}else q=0;c[p>>2]=k;a=(o|0)==(n|0);x=(k|0)==0&(((o|0)!=(x+127&127|0)|a)^1)?o:x;if(a)break;else{m=q;k=o+-1|0}}b=b+-29|0;if(q|0)break;else k=x}n=n+127&127;k=x+127&127;m=G+((x+126&127)<<2)|0;if((n|0)==(x|0))c[m>>2]=c[m>>2]|c[G+(k<<2)>>2];else k=x;c[G+(n<<2)>>2]=q;y=y+9|0}e:while(1){w=k+1&127;x=G+((k+127&127)<<2)|0;while(1){q=(m|0)==18;v=(m|0)>27?9:1;y=n;while(1){p=0;while(1){n=p+y&127;if((n|0)==(k|0)){F=2;A=88;break}n=c[G+(n<<2)>>2]|0;o=c[56568+(p<<2)>>2]|0;if(n>>>0>>0){F=2;A=88;break}if(n>>>0>o>>>0)break;n=p+1|0;if((p|0)<1)p=n;else{F=n;A=88;break}}if((A|0)==88?(A=0,q&(F|0)==2):0){i=0.0;o=0;break e}b=v+b|0;if((y|0)==(k|0))y=k;else break}q=(1<>>v;p=0;n=y;o=y;do{D=G+(o<<2)|0;E=c[D>>2]|0;a=(E>>>v)+p|0;c[D>>2]=a;p=O(E&q,u)|0;a=(o|0)==(n|0)&(a|0)==0;m=a?m+-9|0:m;n=a?n+1&127:n;o=o+1&127}while((o|0)!=(k|0));if(!p)continue;if((w|0)!=(n|0))break;c[x>>2]=c[x>>2]|1}c[G+(k<<2)>>2]=p;k=w}do{n=o+y&127;m=k+1&127;if((n|0)==(k|0)){c[G+(m+-1<<2)>>2]=0;k=m}i=i*1.0e9+ +((c[G+(n<<2)>>2]|0)>>>0);o=o+1|0}while((o|0)!=2);t=+(g|0);j=i*t;o=b+53|0;p=o-f|0;q=(p|0)<(e|0);n=q?((p|0)>0?p:0):e;if((n|0)<53){K=+MJ(+JJ(1.0,105-n|0),j);r=+OJ(j,+JJ(1.0,53-n|0));s=K;i=r;r=K+(j-r)}else{s=0.0;i=0.0;r=j}m=y+2&127;if((m|0)!=(k|0)){m=c[G+(m<<2)>>2]|0;do if(m>>>0>=5e8){if((m|0)!=5e8){i=t*.75+i;break}if((y+3&127|0)==(k|0)){i=t*.5+i;break}else{i=t*.75+i;break}}else{if((m|0)==0?(y+3&127|0)==(k|0):0)break;i=t*.25+i}while(0);if((53-n|0)>1?!(+OJ(i,1.0)!=0.0):0)j=i+1.0;else j=i}else j=i;i=r+j-s;do if((o&2147483647|0)>(-2-H|0)){H=!(+B(+i)>=9007199254740992.0);b=b+((H^1)&1)|0;i=H?i:i*.5;if((b+50|0)<=(I|0)?!(j!=0.0&(q&((n|0)!=(p|0)|H))):0)break;c[(kJ()|0)>>2]=34}while(0);i=+NJ(i,b)}while(0);l=J;return +i}function nM(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0;h=a+4|0;e=c[h>>2]|0;i=a+100|0;if(e>>>0<(c[i>>2]|0)>>>0){c[h>>2]=e+1;e=d[e>>0]|0}else e=dK(a)|0;switch(e|0){case 43:case 45:{f=(e|0)==45&1;e=c[h>>2]|0;if(e>>>0<(c[i>>2]|0)>>>0){c[h>>2]=e+1;e=d[e>>0]|0}else e=dK(a)|0;if((b|0)!=0&(e+-48|0)>>>0>9?(c[i>>2]|0)!=0:0)c[h>>2]=(c[h>>2]|0)+-1;break}default:f=0}if((e+-48|0)>>>0>9)if(!(c[i>>2]|0)){f=-2147483648;e=0}else{c[h>>2]=(c[h>>2]|0)+-1;f=-2147483648;e=0}else{g=0;do{g=e+-48+(g*10|0)|0;e=c[h>>2]|0;if(e>>>0<(c[i>>2]|0)>>>0){c[h>>2]=e+1;e=d[e>>0]|0}else e=dK(a)|0}while((e+-48|0)>>>0<10&(g|0)<214748364);b=((g|0)<0)<<31>>31;if((e+-48|0)>>>0<10)do{b=HN(g|0,b|0,10,0)|0;g=z;e=IN(e|0,((e|0)<0)<<31>>31|0,-48,-1)|0;g=IN(e|0,z|0,b|0,g|0)|0;b=z;e=c[h>>2]|0;if(e>>>0<(c[i>>2]|0)>>>0){c[h>>2]=e+1;e=d[e>>0]|0}else e=dK(a)|0}while((e+-48|0)>>>0<10&((b|0)<21474836|(b|0)==21474836&g>>>0<2061584302));if((e+-48|0)>>>0<10)do{e=c[h>>2]|0;if(e>>>0<(c[i>>2]|0)>>>0){c[h>>2]=e+1;e=d[e>>0]|0}else e=dK(a)|0}while((e+-48|0)>>>0<10);if(c[i>>2]|0)c[h>>2]=(c[h>>2]|0)+-1;i=(f|0)!=0;e=JN(0,0,g|0,b|0)|0;f=i?z:b;e=i?e:g}z=f;return e|0}function oM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;e=a+84|0;g=c[e>>2]|0;h=d+256|0;f=_J(g,0,h)|0;f=(f|0)==0?h:f-g|0;d=f>>>0>>0?f:d;UN(b|0,g|0,d|0)|0;c[a+4>>2]=g+d;b=g+f|0;c[a+8>>2]=b;c[e>>2]=b;return d|0}function pM(a,b,c){a=a|0;b=b|0;c=c|0;return qM(a,b,c)|0}function qM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;if((c[a+76>>2]|0)>-1){e=(PK(a)|0)==0;b=rM(a,b,d)|0;if(!e)QK(a)}else b=rM(a,b,d)|0;return b|0}function rM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;if((d|0)==1)b=b-(c[a+8>>2]|0)+(c[a+4>>2]|0)|0;e=a+20|0;f=a+28|0;if((c[e>>2]|0)>>>0>(c[f>>2]|0)>>>0?(bb[c[a+36>>2]&31](a,0,0)|0,(c[e>>2]|0)==0):0)b=-1;else{c[a+16>>2]=0;c[f>>2]=0;c[e>>2]=0;if((bb[c[a+40>>2]&31](a,b,d)|0)<0)b=-1;else{c[a+8>>2]=0;c[a+4>>2]=0;c[a>>2]=c[a>>2]&-17;b=0}}return b|0}function sM(b){b=b|0;var c=0,d=0,e=0,f=0,g=0;while(1){e=b+1|0;if(!(YJ(a[b>>0]|0)|0))break;else b=e}d=a[b>>0]|0;switch(d<<24>>24|0){case 45:{b=1;f=5;break}case 43:{b=0;f=5;break}default:{g=0;c=b;b=d}}if((f|0)==5){g=b;c=e;b=a[e>>0]|0}if(!($J(b<<24>>24)|0))b=0;else{b=0;do{b=(b*10|0)+48-(a[c>>0]|0)|0;c=c+1|0}while(($J(a[c>>0]|0)|0)!=0)}return (g|0?b:0-b|0)|0}function tM(a){a=a|0;return +(+uM(a,0))}function uM(a,b){a=a|0;b=b|0;return +(+vM(a,b,1))}function vM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0.0,f=0,g=0,h=0,i=0;i=l;l=l+128|0;h=i;f=h;g=f+124|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(g|0));f=h+4|0;c[f>>2]=a;g=h+8|0;c[g>>2]=-1;c[h+44>>2]=a;c[h+76>>2]=-1;bK(h,0);e=+kM(h,d,1);d=(c[f>>2]|0)-(c[g>>2]|0)+(c[h+108>>2]|0)|0;if(b|0)c[b>>2]=d|0?a+d|0:a;l=i;return +e}function wM(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;a:do if(!c)b=0;else{h=b;while(1){g=c>>>1;b=h+(O(g,d)|0)|0;f=ab[e&63](a,b)|0;if(!f)break a;if((c|0)==1){b=0;break a}f=(f|0)<0;c=f?g:c-g|0;if(!c){b=0;break}else h=f?h:b}}while(0);return b|0}function xM(a,c){a=a|0;c=c|0;var d=0,f=0,g=0;g=a+2|0;f=a+4|0;d=HN((e[c+2>>1]|0)<<16|(e[c>>1]|0)|0,e[c+4>>1]|0|0,(e[g>>1]|0)<<16|(e[a>>1]|0)|0,e[f>>1]|0|0)|0;c=IN(d|0,z|0,e[c+6>>1]|0|0,0)|0;d=z;b[a>>1]=c;a=ON(c|0,d|0,16)|0;b[g>>1]=a;b[f>>1]=d;z=d&65535;return c|0}function yM(a){a=a|0;UN(173880,58668,6)|0;UN(58668,a|0,6)|0;return 173880}function zM(a){a=a|0;var c=0,d=0;c=l;l=l+16|0;d=c;b[d>>1]=13070;b[d+2>>1]=a;b[d+4>>1]=a>>>16;yM(d)|0;l=c;return}function AM(a){a=a|0;var b=0;b=xM(a,58674)|0;b=PN(b|0,z|0,4)|0;a=z|1072693248;c[j>>2]=b;c[j+4>>2]=a;return +(+h[j>>3]+-1.0)}function BM(){return +(+AM(58668))}function CM(a,b){a=a|0;b=b|0;if(!a)b=aJ(1,24)|0;else WN(b|0,0,24)|0;return b|0}function DM(a){a=a|0;var b=0,d=0;b=c[a>>2]|0;if(b|0)do{$I(c[b>>2]|0);d=b;b=c[b+4>>2]|0;$I(d)}while((b|0)!=0);$I(a);return}function EM(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0;h=a+16|0;a:do if(!(c[h>>2]|0)){k=a+12|0;g=c[k>>2]|0;if(g>>>0>>0){do if(b)if(!d){c[h>>2]=1;b=0;break a}else{h=a+8|0;c[h>>2]=d;g=1024;b=d;break}else{g=f<<3;g=g>>>0>1024?g:1024;j=_I(8)|0;if(!j){c[h>>2]=1;b=0;break a}b=_I(g)|0;c[j>>2]=b;d=b;if(!b){$I(j);c[h>>2]=1;b=0;break a}c[j+4>>2]=0;h=a+4|0;i=c[h>>2]|0;if(i|0)c[i+4>>2]=j;if(!(c[a>>2]|0))c[a>>2]=j;c[h>>2]=j;h=a+8|0;c[h>>2]=d}while(0);c[k>>2]=g}else{h=a+8|0;b=c[h>>2]|0;d=b}d=d+f&3;d=((d|0)==0?0:4-d|0)+f|0;c[h>>2]=b+d;c[k>>2]=g-d;if(e)WN(b|0,0,d|0)|0}else b=0;while(0);return b|0}function FM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;v=l;l=l+48|0;h=v;t=GM()|0;a:do if(!t)b=12;else{u=CM(0,0)|0;if(!u){HM(t);b=12;break}WN(h|0,0,36)|0;c[h>>2]=u;c[h+4>>2]=t;c[h+16>>2]=b;c[h+32>>2]=d;e=h+28|0;c[e>>2]=-1;b=IM(h)|0;b:do if(!b){g=h+20|0;r=c[g>>2]|0;c[a>>2]=r+-1;i=c[h+8>>2]|0;if((c[e>>2]|0)<(r|0)){r=aJ(1,68)|0;if(r){q=(c[e>>2]|0)>>>31^1;c[r+60>>2]=q;c[r+64>>2]=0;c[r+28>>2]=c[g>>2];if((d&8|0)==0|(q|0)!=0){b=JM(0,t,i,r)|0;if(b|0){g=r;h=0;i=0;f=0;e=0;break}e=r+40|0;b=c[e>>2]|0;if((b|0)>0){b=_I((b<<2)+4|0)|0;if(!b){g=r;h=0;i=0;b=12;f=0;e=0;break}c[r+32>>2]=b;WN(b|0,-1,(c[e>>2]<<2)+4|0)|0;f=b;b=c[e>>2]|0}else f=0;q=aJ(b<<1|1,4)|0;c[r+36>>2]=q;if(!q){g=r;h=0;i=0;b=12;f=0;e=0;break}b=aJ(c[g>>2]|0,12)|0;if(!b){g=r;h=0;i=0;b=12;f=0;e=0;break}c[r+16>>2]=b;b=JM(u,t,i,r)|0;if(!b)b=f;else{g=r;h=0;i=0;f=0;e=0;break}}else b=0;p=h+24|0;b=KM(u,t,i,p,b)|0;if(!b){b=c[p>>2]|0;c[p>>2]=b+1;b=LM(u,0,0,b)|0;if((b|0)!=0?(s=MM(u,i,b)|0,(s|0)!=0):0){b=NM(u,t,s)|0;if(!b){o=_I(c[p>>2]<<2)|0;if(o){q=_I(c[p>>2]<<2)|0;if(q){b=c[p>>2]|0;if((b|0)>0)WN(o|0,0,b<<2|0)|0;OM(s,0,o,0)|0;f=c[p>>2]|0;if((f|0)>0){b=0;e=0;do{c[q+(e<<2)>>2]=b;n=o+(e<<2)|0;b=b+1+(c[n>>2]|0)|0;c[n>>2]=0;e=e+1|0}while((e|0)<(f|0));k=b}else k=0;m=aJ(k+1|0,32)|0;if(m){c[r>>2]=m;n=r+4|0;c[n>>2]=k;b=OM(s,m,o,q)|0;if(!b){c[r+20>>2]=0;f=s+24|0;b=c[f>>2]|0;e=0;while(1){e=e+1|0;if((c[b>>2]|0)<=-1)break;else b=b+32|0}j=aJ(e,32)|0;if(!j){g=r;h=o;i=q;b=12;f=o;e=q}else{c[r+8>>2]=j;f=c[f>>2]|0;e=c[f>>2]|0;if((e|0)>-1){b=0;do{c[j+(b<<5)+8>>2]=m+(c[q+(e<<2)>>2]<<5);c[j+(b<<5)+12>>2]=e;h=j+(b<<5)+16|0;c[h>>2]=0;i=f+12|0;g=c[i>>2]|0;if(g|0){e=0;do{w=e;e=e+1|0}while((c[g+(w<<2)>>2]|0)>-1);e=e<<2;g=_I(e)|0;c[h>>2]=g;if(!g){g=r;h=o;i=q;b=12;f=o;e=q;break b}UN(g|0,c[i>>2]|0,e|0)|0}c[j+(b<<5)+20>>2]=c[f+16>>2];b=b+1|0;f=f+32|0;e=c[f>>2]|0}while((e|0)>-1)}else b=0;c[j+(b<<5)+8>>2]=0;c[n>>2]=k;c[r+12>>2]=m+(c[q+(c[c[s+28>>2]>>2]<<2)>>2]<<5);c[r+52>>2]=c[p>>2];c[r+56>>2]=d;DM(u);HM(t);$I(o);$I(q);c[a+4>>2]=r;b=0;break a}}else{g=r;h=o;i=q;f=o;e=q}}else{g=r;h=o;i=q;b=12;f=o;e=q}}else{g=r;h=o;i=q;b=12;f=o;e=0}}else{g=r;h=o;i=0;b=12;f=0;e=0}}else{g=r;h=0;i=0;f=0;e=0}}else{g=r;h=0;i=0;b=12;f=0;e=0}}else{g=r;h=0;i=0;f=0;e=0}}else{g=r;h=0;i=0;b=12;f=0;e=0}}else{g=0;h=0;i=0;b=6;f=0;e=0}}else{g=0;h=0;i=0;f=0;e=0}while(0);DM(u);HM(t);if(h|0)$I(f);if(i|0)$I(e);c[a+4>>2]=g;PM(a)}while(0);l=v;return b|0}function GM(){var a=0,b=0;a=_I(20)|0;do if(a){b=_I(2048)|0;c[a+16>>2]=b;if(!b){$I(a);a=0;break}else{c[a>>2]=512;c[a+4>>2]=1024e3;c[a+8>>2]=128;c[a+12>>2]=0;break}}while(0);return a|0}function HM(a){a=a|0;$I(c[a+16>>2]|0);$I(a);return}function IM(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0;u=l;l=l+16|0;p=u+4|0;q=u;r=c[b+32>>2]&1;s=b+16|0;e=c[s>>2]|0;t=c[b+4>>2]|0;d=TM(t,0)|0;a:do if(!d){m=(r|0)!=0;n=b+8|0;o=b+12|0;d=0;k=1;b:while(1){g=0;h=d;f=0;c:while(1){d=a[e>>0]|0;if(m){if(d<<24>>24==40)break;if((h|0)!=0&d<<24>>24==41)j=13;else j=14}else if(d<<24>>24==92)switch(a[e+1>>0]|0){case 40:break c;case 41:{j=13;break}default:j=14}else j=14;if((j|0)==13){j=0;i=LM(c[b>>2]|0,-1,-1,-1)|0;c[n>>2]=i;if(!i){d=12;break a}else i=f}else if((j|0)==14){j=0;d=gN(b,e)|0;if(d|0)break a;i=f;e=c[o>>2]|0}d:while(1){e:while(1){d=a[e>>0]|0;switch(d<<24>>24){case 42:case 92:break;default:{if(!m)break e;switch(d<<24>>24){case 123:case 63:case 43:break;default:break e}}}d=d<<24>>24==92;if(m&d)break;f=e+1|0;if(d)switch(a[f>>0]|0){case 123:case 63:case 43:break;default:break e}e=d?f:e;if((!m?(e|0)==((c[s>>2]|0)+1|0):0)?(a[e+-1>>0]|0)==94:0)break;if((a[e>>0]|0)==123){e=hN(e+1|0,r,p,q)|0;if(!e){j=28;break b}d=c[q>>2]|0;f=c[b>>2]|0;if(!d)d=LM(f,-1,-1,-1)|0;else j=36}else{c[p>>2]=0;c[q>>2]=-1;d=a[e>>0]|0;if(d<<24>>24==43){c[p>>2]=1;d=a[e>>0]|0}if(d<<24>>24==63){c[q>>2]=1;d=1}else d=-1;e=e+1|0;f=c[b>>2]|0;j=36}if((j|0)==36){j=0;d=bN(f,c[n>>2]|0,c[p>>2]|0,d,0)|0}c[n>>2]=d;if(!d){d=12;break a}}d=MM(c[b>>2]|0,g,c[n>>2]|0)|0;f=a[e>>0]|0;f:do if(m){if(f<<24>>24==124){j=40;break d}if((h|0)!=0&f<<24>>24==41|f<<24>>24==0)j=47;else{g=d;f=i;continue c}}else{switch(f<<24>>24){case 0:{j=47;break f}case 92:break;default:{g=d;f=i;continue c}}switch(a[e+1>>0]|0){case 124:case 41:break;default:{g=d;f=i;continue c}}d=cN(c[b>>2]|0,i,d)|0;if((a[e+1>>0]|0)==124){f=2;break d}if(!h){d=8;break a}e=e+2|0;f=92}while(0);if((j|0)==47){j=0;d=cN(c[b>>2]|0,i,d)|0;e=f<<24>>24==41?e+1|0:e}d=iN(b,d,UM(t)|0)|0;if(d|0)break a;d=f<<24>>24==0;f=(h|0)<1;if(f&d){j=50;break b}if(f|d){d=8;break a}g=VM(t)|0;h=h+-1|0;i=VM(t)|0}if((j|0)==40){f=1;d=cN(c[b>>2]|0,i,d)|0}g=0;e=e+f|0;f=d}d=SM(t,f)|0;if(d|0)break a;d=SM(t,g)|0;if(d|0)break a;d=TM(t,k)|0;if(d|0)break a;d=h+1|0;k=k+1|0;e=m?e+1|0:e+2|0}if((j|0)==28){d=10;break}else if((j|0)==50){c[b+20>>2]=k;d=0;break}}while(0);l=u;return d|0}function JM(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;x=RM(d)|0;y=(b|0)==0|(f|0)==0;if(!y){c[f+48>>2]=0;c[c[f+36>>2]>>2]=-1}g=f+28|0;z=_I((c[g>>2]<<3)+8|0)|0;do if(!z)g=12;else{c[z>>2]=-1;A=_I((c[g>>2]<<2)+4|0)|0;if(!A){$I(z);g=12;break}c[A>>2]=-1;B=_I((c[g>>2]<<3)+8|0)|0;if(!B){$I(z);$I(A);g=12;break}h=c[g>>2]|0;g=0;do{c[B+(g<<3)>>2]=-1;g=g+1|0}while(g>>>0<=h>>>0);SM(d,e)|0;g=TM(d,0)|0;a:do if((g|0)!=0|(RM(d)|0)<=(x|0)){e=z;n=0;h=0;m=0;l=-1}else{u=f+32|0;v=f+36|0;w=f+16|0;e=z;n=0;h=0;m=0;t=1;l=-1;s=0;while(1){b:do switch(UM(d)|0){case 6:{i=UM(d)|0;g=0;do{j=e+(g<<2)|0;g=g+1|0}while((c[j>>2]|0)>-1);c[j>>2]=i<<1|1;c[e+(g<<2)>>2]=-1;g=0;while(1)if((c[A+(g<<2)>>2]|0)>-1)g=g+1|0;else break;c[A+(g+-1<<2)>>2]=-1;g=0;j=t;i=s;break}case 0:{q=VM(d)|0;r=q+12|0;j=c[r>>2]|0;if((j|0)>-1){g=0;do{i=e+(g<<2)|0;g=g+1|0}while((c[i>>2]|0)>-1);c[i>>2]=j<<1;c[e+(g<<2)>>2]=-1;if(!y){g=0;while(1)if((c[A+(g<<2)>>2]|0)>-1)g=g+1|0;else break;c[(c[w>>2]|0)+(j*12|0)+8>>2]=0;if((g|0)>0){g=_I((g<<2)+4|0)|0;if(!g){g=12;j=t;i=s;break b}c[(c[w>>2]|0)+(j*12|0)+8>>2]=g;i=c[A>>2]|0;if((i|0)>-1){k=0;j=g;do{c[j>>2]=i;k=k+1|0;i=c[A+(k<<2)>>2]|0;j=g+(k<<2)|0}while((i|0)>-1);g=j}c[g>>2]=-1}}g=TM(d,c[r>>2]|0)|0;if(g|0){j=t;i=s;break b}g=TM(d,6)|0;if(g|0){j=t;i=s;break b}}c:do switch(c[q>>2]|0){case 0:{p=c[c[q+4>>2]>>2]|0;if((p|0)>-1|(p|0)==-4?(c[e>>2]|0)>-1:0){if(y){c[q+20>>2]=1;g=0}else{g=dN(b,q,m)|0;c[(c[u>>2]|0)+(m<<2)>>2]=s;if((l|0)>-1){j=c[v>>2]|0;i=0;while(1){k=j+(i<<2)|0;o=i+1|0;if((c[k>>2]|0)>-1)i=o;else break}c[k>>2]=m;c[j+(o<<2)>>2]=l;c[j+(i+2<<2)>>2]=-1;h=h+1|0;l=-1}eN(e,f,m)}c[e>>2]=-1;p=t+1|0;o=s;n=n+1|0;m=t}else{p=t;g=0;o=s}break}case 1:{j=c[q+4>>2]|0;k=c[j>>2]|0;j=c[j+4>>2]|0;g=SM(d,q)|0;if(!g){g=TM(d,5)|0;if(!g){g=SM(d,j)|0;if(!g){g=TM(d,0)|0;if(!g){i=k+20|0;g=TM(d,(c[i>>2]|0)+t|0)|0;if(!g){if((c[i>>2]|0)>0){i=(c[j+20>>2]|0)>0;g=i?t:-1;i=t+(i&1)|0}else{g=-1;i=t}g=TM(d,g)|0;if(!g){g=TM(d,4)|0;if(!g){g=SM(d,k)|0;if(!g){p=i;g=TM(d,0)|0;o=s}else{p=i;o=s}}else{p=i;o=s}}else{p=i;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}break}case 2:{i=c[q+4>>2]|0;if(y){if((c[e>>2]|0)>-1)g=1;else g=(a[i+12>>0]&1)!=0;g=TM(d,g&1)|0;if(g|0){p=t;o=s;break c}}else{g=TM(d,m)|0;if(g|0){p=t;o=s;break c}g=TM(d,a[i+12>>0]&1)|0;if(g|0){p=t;o=s;break c}}g=SM(d,q)|0;if(!g){g=TM(d,1)|0;if(!g){g=SM(d,c[i>>2]|0)|0;if(!g){g=TM(d,0)|0;if(!g){if((c[e>>2]|0)<=-1?(a[i+12>>0]&1)==0:0){p=t;g=0;o=0;break c}if(y)g=0;else{g=dN(b,q,m)|0;c[(c[u>>2]|0)+(m<<2)>>2]=(a[i+12>>0]&1)==0?s:1;if((l|0)>-1){j=c[v>>2]|0;i=0;while(1){k=j+(i<<2)|0;o=i+1|0;if((c[k>>2]|0)>-1)i=o;else break}c[k>>2]=m;c[j+(o<<2)>>2]=l;c[j+(i+2<<2)>>2]=-1;h=h+1|0;l=-1}eN(e,f,m)}c[e>>2]=-1;p=t+1|0;o=0;n=n+1|0;m=t}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}break}case 3:{j=c[q+4>>2]|0;k=c[j>>2]|0;j=c[j+4>>2]|0;i=(c[e>>2]|0)>-1;p=t+1|0;g=TM(d,i?p:t)|0;if(!g){g=TM(d,i?t:m)|0;if(!g){g=SM(d,e)|0;if(!g){g=TM(d,(c[e>>2]|0)>>>31^1)|0;if(!g){g=SM(d,q)|0;if(!g){g=SM(d,j)|0;if(!g){g=SM(d,k)|0;if(!g){g=TM(d,3)|0;if(!g){g=SM(d,j)|0;if(!g){g=TM(d,0)|0;if(g|0){p=t;o=s;break c}g=TM(d,2)|0;if(g|0){p=t;o=s;break c}g=SM(d,k)|0;if(g|0){p=t;o=s;break c}g=TM(d,0)|0;if(g|0){p=t;o=s;break c}if((c[e>>2]|0)>-1){if(y)g=0;else{g=dN(b,q,m)|0;c[(c[u>>2]|0)+(m<<2)>>2]=s;if((l|0)>-1){j=c[v>>2]|0;i=0;while(1){k=j+(i<<2)|0;o=i+1|0;if((c[k>>2]|0)>-1)i=o;else break}c[k>>2]=m;c[j+(o<<2)>>2]=l;c[j+(i+2<<2)>>2]=-1;h=h+1|0;l=-1}eN(e,f,m)}c[e>>2]=-1;n=n+1|0;m=t;i=p}else{g=0;i=t}t=(c[q+16>>2]|0)>0;p=t?i+2|0:i;o=s;m=t?i+1|0:m}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}}else{p=t;o=s}break}default:{p=t;g=0;o=s}}while(0);j=c[r>>2]|0;if((j|0)>-1){i=0;do{k=A+(i<<2)|0;i=i+1|0}while((c[k>>2]|0)>-1);c[k>>2]=j;c[A+(i<<2)>>2]=-1;j=p;i=o}else{j=p;i=o}break}case 1:{g=VM(d)|0;if(y){i=c[(c[c[g+4>>2]>>2]|0)+20>>2]|0;c[g+20>>2]=(UM(d)|0)+i;i=0;l=-1}else{q=UM(d)|0;r=UM(d)|0;i=q;l=(q|0)==0?l:r}g=0;j=t;i=y?s:(i|0)==0&1;break}case 4:{i=UM(d)|0;j=UM(d)|0;g=0;m=(i|0)>-1?i:m;i=s;break}case 5:{g=VM(d)|0;if(y){j=c[g+4>>2]|0;c[g+20>>2]=(c[(c[j+4>>2]|0)+20>>2]|0)+(c[(c[j>>2]|0)+20>>2]|0);g=0;j=t;i=s}else{g=0;j=t;i=s}break}case 2:{while(1)if((c[e>>2]|0)>-1)e=e+4|0;else{g=0;j=t;i=s;break}break}case 3:{j=VM(d)|0;o=VM(d)|0;g=VM(d)|0;e=UM(d)|0;if(y){r=c[g+4>>2]|0;s=g+16|0;c[g+20>>2]=(c[(c[r>>2]|0)+20>>2]|0)+e+(c[(c[r+4>>2]|0)+20>>2]|0)+((c[s>>2]|0)>0?2:0);g=s}else g=g+16|0;e=VM(d)|0;i=UM(d)|0;k=UM(d)|0;if((c[g>>2]|0)>0){if(y)g=0;else{g=fN(b,j,i)|0;c[(c[u>>2]|0)+(i<<2)>>2]=1;if(!g)g=fN(b,o,k)|0;c[(c[u>>2]|0)+(k<<2)>>2]=1}n=n+2|0;j=t;i=1}else{g=0;j=t;i=1}break}default:{g=0;j=t;i=s}}while(0);if((g|0)!=0|(RM(d)|0)<=(x|0))break a;else{t=j;s=i}}}while(0);if(!y?(eN(e,f,m),(l|0)>-1):0){i=c[f+36>>2]|0;e=0;while(1){j=i+(e<<2)|0;k=e+1|0;if((c[j>>2]|0)>-1)e=k;else break}c[j>>2]=m;c[i+(k<<2)>>2]=l;c[i+(e+2<<2)>>2]=-1;h=h+1|0}c[f+48>>2]=n;c[f+40>>2]=n;c[f+44>>2]=h;$I(z);$I(A);$I(B)}while(0);return g|0}function KM(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;y=l;l=l+16|0;t=y+12|0;x=y+8|0;u=y+4|0;v=y;w=RM(b)|0;c[t>>2]=0;c[x>>2]=0;d=SM(b,d)|0;a:do if(!d){d=TM(b,0)|0;if(!d){b:do if((RM(b)|0)>(w|0)){g=0;i=0;j=0;c:while(1){q=UM(b)|0;r=VM(b)|0;d:do switch(q|0){case 0:{switch(c[r>>2]|0){case 0:{d=c[r+4>>2]|0;r=c[d>>2]|0;if(!((r|0)>-1|(r|0)==-4)){d=j;break d}r=d+8|0;d=(c[r>>2]|0)+j|0;c[r>>2]=d;if((d|0)<=(c[x>>2]|0)){d=j;break d}c[x>>2]=d;d=j;break d}case 3:{h=c[r+4>>2]|0;d=SM(b,c[h+4>>2]|0)|0;if(d|0)break b;d=TM(b,0)|0;if(d|0)break b;d=SM(b,c[h>>2]|0)|0;if(d|0)break b;break}case 1:{h=c[r+4>>2]|0;d=SM(b,c[h+4>>2]|0)|0;if(d|0)break b;d=TM(b,0)|0;if(d|0)break b;d=SM(b,c[h>>2]|0)|0;if(d|0)break b;break}case 2:{h=c[r+4>>2]|0;d=TM(b,j)|0;if(d|0)break b;d=SM(b,r)|0;if(d|0)break b;d=TM(b,1)|0;if(d|0)break b;d=SM(b,c[h>>2]|0)|0;if(d|0)break b;d=TM(b,0)|0;if(d|0)break b;if((c[h+4>>2]|0)<=1?(c[h+8>>2]|0)<=1:0)d=j;else{c[t>>2]=0;d=0}i=i+1|0;break d}default:{d=j;break d}}d=TM(b,0)|0;if(!d)d=j;else break b;break}case 1:{p=r+4|0;o=c[p>>2]|0;q=UM(b)|0;c[t>>2]=q;n=o+4|0;j=c[n>>2]|0;if((j|0)<=1)if((c[o+8>>2]|0)>1){c[u>>2]=0;if((j|0)>0)s=30;else{d=q;h=0;s=37}}else d=q;else{c[u>>2]=0;s=30}e:do if((s|0)==30){d=aN(a,b,c[o>>2]|0,(j|0)>1?1:2,t,f,v,x)|0;if(!d){h=0;k=q;m=1}else{s=34;break c}while(1){d=c[v>>2]|0;if(!h)h=d;else h=MM(a,h,d)|0;if(!h){d=12;s=34;break c}j=c[n>>2]|0;if((m|0)>=(j|0)){d=k;s=37;break e}k=c[t>>2]|0;m=m+1|0;d=aN(a,b,c[o>>2]|0,(m|0)<(j|0)?1:2,t,f,v,x)|0;if(d|0){s=34;break c}}}while(0);if((s|0)==37){s=0;n=o+8|0;k=c[n>>2]|0;if((k|0)==-1){k=c[t>>2]|0;d=aN(a,b,c[o>>2]|0,0,t,0,u,x)|0;if(d|0)break c;j=bN(a,c[u>>2]|0,0,-1,0)|0;c[u>>2]=j;if(!j){d=12;break c}else d=k}else if((j|0)<(k|0)){k=j;j=0;while(1){m=c[t>>2]|0;d=aN(a,b,c[o>>2]|0,0,t,0,v,x)|0;if(d|0){s=49;break c}if(!j){d=c[v>>2]|0;c[u>>2]=d}else{d=MM(a,c[v>>2]|0,j)|0;c[u>>2]=d}if(!d){d=12;s=49;break c}j=LM(a,-1,-1,-1)|0;if(!j){d=12;s=49;break c}j=cN(a,j,d)|0;c[u>>2]=j;if(!j){d=12;s=49;break c}k=k+1|0;if((k|0)>=(c[n>>2]|0)){d=m;break}}}else j=0;c[t>>2]=d;if(h){if(j){h=MM(a,h,j)|0;s=54}}else{h=j;s=54}if((s|0)==54){s=0;if(!h){d=12;break c}}c[p>>2]=c[h+4>>2];c[r>>2]=c[h>>2]}i=i+-1|0;h=d-q+g|0;if(!i){c[t>>2]=h;g=h;i=0;d=h}else g=h;break}default:d=j}while(0);if((RM(b)|0)>(w|0))j=d;else{d=0;break b}}break a}else{d=0;g=0}while(0);w=(c[e>>2]|0)+g|0;x=c[x>>2]|0;c[e>>2]=(x|0)>(w|0)?x:w}}while(0);l=y;return d|0}function LM(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=EM(a,0,0,1,20)|0;a=$M(a,0,f)|0;if(!a)a=0;else{c[f>>2]=b;c[f+4>>2]=d;c[f+8>>2]=e}return a|0}function MM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;if(b){e=EM(a,0,0,1,8)|0;a=$M(a,1,e)|0;if(!a)d=0;else{c[e>>2]=b;c[e+4>>2]=d;c[a+16>>2]=(c[d+16>>2]|0)+(c[b+16>>2]|0);d=a}}return d|0}function NM(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0;o=l;l=l+16|0;j=o+4|0;k=o;m=RM(b)|0;d=SM(b,d)|0;a:do if(!d){d=TM(b,0)|0;if(!d)if((RM(b)|0)>(m|0)){b:while(1){h=UM(b)|0;i=VM(b)|0;c:do switch(h|0){case 0:switch(c[i>>2]|0){case 0:{g=c[i+4>>2]|0;f=c[g>>2]|0;if((f|0)==-4){c[i+8>>2]=0;d=g+8|0;h=WM(a,c[d>>2]|0,0,1114111,0,0,-1)|0;c[i+24>>2]=h;if(!h){d=12;break a}h=WM(a,c[d>>2]|0,0,1114111,0,0,c[g+4>>2]|0)|0;c[i+28>>2]=h;if(!h){d=12;break a}else break c}d=i+8|0;if((f|0)<0){c[d>>2]=1;h=XM(a)|0;c[i+24>>2]=h;if(!h){d=12;break a}h=XM(a)|0;c[i+28>>2]=h;if(!h){d=12;break a}else break c}else{c[d>>2]=0;d=g+8|0;e=g+4|0;h=WM(a,c[d>>2]|0,f,c[e>>2]|0,0,0,-1)|0;c[i+24>>2]=h;if(!h){d=12;break a}h=WM(a,c[d>>2]|0,c[g>>2]|0,c[e>>2]|0,c[g+12>>2]|0,c[g+16>>2]|0,-1)|0;c[i+28>>2]=h;if(!h){d=12;break a}else break c}}case 3:{d=SM(b,i)|0;if(d|0)break a;d=TM(b,1)|0;if(d|0)break a;e=i+4|0;d=SM(b,c[(c[e>>2]|0)+4>>2]|0)|0;if(d|0)break a;d=TM(b,0)|0;if(d|0)break a;d=SM(b,c[c[e>>2]>>2]|0)|0;if(d|0)break a;d=TM(b,0)|0;if(!d)break c;else break a}case 1:{d=SM(b,i)|0;if(d|0)break a;d=TM(b,2)|0;if(d|0)break a;e=i+4|0;d=SM(b,c[(c[e>>2]|0)+4>>2]|0)|0;if(d|0)break a;d=TM(b,0)|0;if(d|0)break a;d=SM(b,c[c[e>>2]>>2]|0)|0;if(d|0)break a;d=TM(b,0)|0;if(!d)break c;else break a}case 2:{d=SM(b,i)|0;if(d|0)break a;d=TM(b,3)|0;if(d|0)break a;d=SM(b,c[c[i+4>>2]>>2]|0)|0;if(d|0)break a;d=TM(b,0)|0;if(!d)break c;else break a}default:break c}case 1:{d=c[i+4>>2]|0;e=c[d>>2]|0;f=d+4|0;g=c[f>>2]|0;if(!(c[e+8>>2]|0))h=(c[g+8>>2]|0)!=0;else h=1;c[i+8>>2]=h&1;h=YM(a,c[e+24>>2]|0,c[g+24>>2]|0,0,0)|0;c[i+24>>2]=h;if(!h){d=12;break a}h=YM(a,c[(c[d>>2]|0)+28>>2]|0,c[(c[f>>2]|0)+28>>2]|0,0,0)|0;c[i+28>>2]=h;if(!h){d=12;break a}break}case 3:{h=c[i+4>>2]|0;d=c[h>>2]|0;if(!(c[h+4>>2]|0))e=1;else e=(c[d+8>>2]|0)!=0&1;c[i+8>>2]=e;c[i+24>>2]=c[d+24>>2];c[i+28>>2]=c[d+28>>2];break}case 2:{g=c[i+4>>2]|0;d=c[g>>2]|0;e=d+8|0;if(!(c[e>>2]|0))f=0;else f=(c[(c[g+4>>2]|0)+8>>2]|0)!=0;c[i+8>>2]=f&1;if(c[e>>2]|0){d=ZM(b,d,0,0,j)|0;if(d|0)break b;e=_I((c[j>>2]<<2)+4|0)|0;if(!e){d=12;break b}c[e>>2]=-1;c[k>>2]=0;d=ZM(b,c[g>>2]|0,e,k,0)|0;if(d|0){n=45;break b}d=g+4|0;h=i+24|0;c[h>>2]=YM(a,c[(c[d>>2]|0)+24>>2]|0,c[(c[g>>2]|0)+24>>2]|0,e,c[k>>2]|0)|0;$I(e);if(!(c[h>>2]|0)){d=12;break b}else f=d}else{c[i+24>>2]=c[d+24>>2];f=g+4|0}d=c[f>>2]|0;if(c[d+8>>2]|0){d=ZM(b,d,0,0,j)|0;if(d|0)break b;e=_I((c[j>>2]<<2)+4|0)|0;if(!e){d=12;break b}c[e>>2]=-1;c[k>>2]=0;d=ZM(b,c[f>>2]|0,e,k,0)|0;if(d|0){n=52;break b}i=i+28|0;c[i>>2]=YM(a,c[(c[g>>2]|0)+28>>2]|0,c[(c[f>>2]|0)+28>>2]|0,e,c[k>>2]|0)|0;$I(e);if(!(c[i>>2]|0)){d=12;break b}}else c[i+28>>2]=c[d+28>>2];break}default:{}}while(0);if((RM(b)|0)<=(m|0)){d=0;break a}}if((n|0)==45)$I(e);else if((n|0)==52)$I(e)}else d=0}while(0);l=o;return d|0}function OM(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;a:while(1){switch(c[a>>2]|0){case 2:{a=c[a+4>>2]|0;if((c[a+8>>2]|0)==-1?(h=c[a>>2]|0,h=QM(c[h+28>>2]|0,c[h+24>>2]|0,b,d,e)|0,(h|0)!=0):0){a=h;break a}break}case 3:{f=c[a+4>>2]|0;a=OM(c[f>>2]|0,b,d,e)|0;if(a|0)break a;a=f+4|0;break}case 1:{f=c[a+4>>2]|0;g=f+4|0;a=QM(c[(c[f>>2]|0)+28>>2]|0,c[(c[g>>2]|0)+24>>2]|0,b,d,e)|0;if(a|0)break a;a=OM(c[f>>2]|0,b,d,e)|0;if(!a)a=g;else break a;break}default:{a=0;break a}}a=c[a>>2]|0}return a|0}function PM(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0;h=c[a+4>>2]|0;if(h|0){e=h+4|0;a=c[h>>2]|0;if(c[e>>2]|0){d=0;do{if(c[a+(d<<5)+8>>2]|0){b=c[a+(d<<5)+16>>2]|0;if(b){$I(b);a=c[h>>2]|0}b=c[a+(d<<5)+28>>2]|0;if(b){$I(b);a=c[h>>2]|0}}d=d+1|0}while(d>>>0<(c[e>>2]|0)>>>0)}if(a|0)$I(a);d=h+8|0;a=c[d>>2]|0;if(a|0){if(c[a+8>>2]|0){while(1){b=c[a+16>>2]|0;if(b|0)$I(b);if(!(c[a+40>>2]|0))break;else a=a+32|0}a=c[d>>2]|0}$I(a)}f=h+16|0;a=c[f>>2]|0;if(a|0){g=h+28|0;b=c[g>>2]|0;if(b){e=0;do{d=c[a+(e*12|0)+8>>2]|0;if(d){$I(d);b=c[g>>2]|0;a=c[f>>2]|0}e=e+1|0}while(e>>>0>>0)}$I(a)}a=c[h+32>>2]|0;if(a|0)$I(a);a=c[h+20>>2]|0;if(a|0)$I(a);a=c[h+36>>2]|0;if(a|0)$I(a);$I(h)}return}function QM(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;g=c[a>>2]|0;h=(g|0)>-1;a:do if(!d)if(h){h=b+32|0;do{if((c[b>>2]|0)>-1?(y=e+(g<<2)|0,c[y>>2]=(c[y>>2]|0)+1,(c[h>>2]|0)>-1):0){g=h;do{y=e+(c[a>>2]<<2)|0;c[y>>2]=(c[y>>2]|0)+1;g=g+32|0}while((c[g>>2]|0)>-1)}a=a+32|0;g=c[a>>2]|0}while((g|0)>-1);g=0}else g=0;else if(h)while(1){h=c[b>>2]|0;b:do if((h|0)>-1){p=a+4|0;q=a+8|0;r=a+16|0;s=a+20|0;t=a+24|0;u=a+28|0;v=a+12|0;e=-1;g=b;while(1){o=h;while(1){if((o|0)!=(e|0))break;g=g+32|0;h=c[g>>2]|0;if((h|0)>-1)o=h;else break b}l=d+(c[f+(c[a>>2]<<2)>>2]<<5)|0;while(1){h=l+8|0;if(!(c[h>>2]|0))break;else l=l+32|0}c[l+40>>2]=0;c[l>>2]=c[p>>2];c[l+4>>2]=c[q>>2];c[h>>2]=d+(c[f+(o<<2)>>2]<<5);c[l+12>>2]=o;h=c[s>>2]|0;e=c[g+16>>2]|c[r>>2]|(h|0?4:0)|(c[t>>2]|0?8:0);i=l+20|0;c[i>>2]=e;j=c[u>>2]|0;if((j|0)>-1){c[i>>2]=e|256;h=j}c[l+24>>2]=h;e=c[t>>2]|0;if(!e)c[l+28>>2]=0;else{h=0;do{n=h;h=h+1|0}while((c[e+(n<<2)>>2]|0)!=0);h=_I(h<<2)|0;c[l+28>>2]=h;if(!h){g=12;break a}k=c[t>>2]|0;e=c[k>>2]|0;if(e){j=0;i=h;do{c[i>>2]=e;j=j+1|0;e=c[k+(j<<2)>>2]|0;i=h+(j<<2)|0}while((e|0)!=0);h=i}c[h>>2]=0}e=c[v>>2]|0;if(!e)h=0;else{h=0;while(1)if((c[e+(h<<2)>>2]|0)>-1)h=h+1|0;else break}k=g+12|0;i=c[k>>2]|0;if(!i)e=0;else{e=0;while(1)if((c[i+(e<<2)>>2]|0)>-1)e=e+1|0;else break}j=l+16|0;i=c[j>>2]|0;if(i|0)$I(i);c[j>>2]=0;h=e+h|0;if((h|0)>0){n=_I((h<<2)+4|0)|0;c[j>>2]=n;if(!n){g=12;break a}e=c[v>>2]|0;if((e|0)!=0?(w=c[e>>2]|0,(w|0)>-1):0){h=0;i=w;do{c[n+(h<<2)>>2]=i;h=h+1|0;i=c[e+(h<<2)>>2]|0}while((i|0)>-1);m=h}else m=0;j=c[k>>2]|0;if((j|0)!=0?(x=c[j>>2]|0,(x|0)>-1):0){k=(m|0)>0;h=m;i=0;l=x;do{c:do if(k){e=0;while(1){if((c[n+(e<<2)>>2]|0)==(l|0))break c;e=e+1|0;if((e|0)>=(m|0)){y=39;break}}}else y=39;while(0);if((y|0)==39){y=0;c[n+(h<<2)>>2]=l;h=h+1|0}i=i+1|0;l=c[j+(i<<2)>>2]|0}while((l|0)>-1)}else h=m;c[n+(h<<2)>>2]=-1}g=g+32|0;h=c[g>>2]|0;if((h|0)<=-1)break;else e=o}}while(0);a=a+32|0;if((c[a>>2]|0)<=-1){g=0;break}}else g=0;while(0);return g|0}function RM(a){a=a|0;return c[a+12>>2]|0}function SM(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=l;l=l+16|0;e=d+4|0;f=d;c[f>>2]=b;c[e>>2]=c[f>>2];b=_M(a,e)|0;l=d;return b|0}function TM(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=l;l=l+16|0;e=d+4|0;f=d;c[f>>2]=b;c[e>>2]=c[f>>2];b=_M(a,e)|0;l=d;return b|0}function UM(a){a=a|0;var b=0,d=0;b=c[a+16>>2]|0;d=a+12|0;a=(c[d>>2]|0)+-1|0;c[d>>2]=a;return c[b+(a<<2)>>2]|0}function VM(a){a=a|0;var b=0,d=0;b=c[a+16>>2]|0;d=a+12|0;a=(c[d>>2]|0)+-1|0;c[d>>2]=a;return c[b+(a<<2)>>2]|0}function WM(a,b,d,e,f,g,h){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;a=EM(a,0,0,1,64)|0;if(!a)a=0;else{c[a>>2]=b;c[a+4>>2]=d;c[a+8>>2]=e;c[a+20>>2]=f;c[a+24>>2]=g;c[a+28>>2]=h;c[a+32>>2]=-1;c[a+36>>2]=-1;c[a+40>>2]=-1}return a|0}function XM(a){a=a|0;a=EM(a,0,0,1,32)|0;if(!a)a=0;else{c[a>>2]=-1;c[a+4>>2]=-1;c[a+8>>2]=-1}return a|0}function YM(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;o=(e|0)==0;if(o)n=0;else{g=0;while(1)if((c[e+(g<<2)>>2]|0)>-1)g=g+1|0;else{n=g;break}}h=0;while(1)if((c[b+(h<<5)>>2]|0)>-1)h=h+1|0;else{g=0;break}while(1)if((c[d+(g<<5)>>2]|0)>-1)g=g+1|0;else break;g=EM(a,0,0,1,(g+h<<5)+32|0)|0;a:do if(!g)g=0;else{h=c[b>>2]|0;if((h|0)>-1){m=(n|0)>0;i=0;while(1){c[g+(i<<5)>>2]=h;c[g+(i<<5)+4>>2]=c[b+(i<<5)+4>>2];c[g+(i<<5)+8>>2]=c[b+(i<<5)+8>>2];c[g+(i<<5)+16>>2]=c[b+(i<<5)+16>>2]|f;c[g+(i<<5)+20>>2]=c[b+(i<<5)+20>>2];c[g+(i<<5)+24>>2]=c[b+(i<<5)+24>>2];c[g+(i<<5)+28>>2]=c[b+(i<<5)+28>>2];l=b+(i<<5)+12|0;j=c[l>>2]|0;h=(j|0)==0;if(o&h)h=0;else{if(h)k=0;else{h=0;while(1)if((c[j+(h<<2)>>2]|0)>-1)h=h+1|0;else{k=h;break}}h=EM(a,0,0,0,(k+n<<2)+4|0)|0;if(!h){g=0;break a}if((k|0)>0){l=c[l>>2]|0;j=0;do{c[h+(j<<2)>>2]=c[l+(j<<2)>>2];j=j+1|0}while((j|0)!=(k|0))}else k=0;if(m){j=0;do{c[h+(j+k<<2)>>2]=c[e+(j<<2)>>2];j=j+1|0}while((j|0)!=(n|0));j=n}else j=0;c[h+(j+k<<2)>>2]=-1}c[g+(i<<5)+12>>2]=h;i=i+1|0;h=c[b+(i<<5)>>2]|0;if((h|0)<=-1){n=i;break}}}else n=0;i=c[d>>2]|0;h=g+(n<<5)|0;if((i|0)>-1){m=0;l=n;do{c[h>>2]=i;c[g+(l<<5)+4>>2]=c[d+(m<<5)+4>>2];c[g+(l<<5)+8>>2]=c[d+(m<<5)+8>>2];c[g+(l<<5)+16>>2]=c[d+(m<<5)+16>>2];c[g+(l<<5)+20>>2]=c[d+(m<<5)+20>>2];c[g+(l<<5)+24>>2]=c[d+(m<<5)+24>>2];c[g+(l<<5)+28>>2]=c[d+(m<<5)+28>>2];j=d+(m<<5)+12|0;h=c[j>>2]|0;if(!h)h=0;else{i=0;while(1)if((c[h+(i<<2)>>2]|0)>-1)i=i+1|0;else break;h=EM(a,0,0,0,(i<<2)+4|0)|0;if(!h){g=0;break a}if((i|0)>0){k=c[j>>2]|0;j=0;do{c[h+(j<<2)>>2]=c[k+(j<<2)>>2];j=j+1|0}while((j|0)!=(i|0))}else i=0;c[h+(i<<2)>>2]=-1}c[g+(l<<5)+12>>2]=h;m=m+1|0;i=c[d+(m<<5)>>2]|0;l=m+n|0;h=g+(l<<5)|0}while((i|0)>-1)}c[h>>2]=-1}while(0);return g|0}function ZM(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;o=RM(a)|0;p=(f|0)!=0;if(p)c[f>>2]=0;b=SM(a,b)|0;a:do if(!b){m=(d|0)==0;l=(e|0)==0;if((RM(a)|0)>(o|0))while(1){b=VM(a)|0;b:do switch(c[b>>2]|0){case 0:{b=c[b+4>>2]|0;switch(c[b>>2]|0){case -3:break;case -2:{if(l)break b;c[e>>2]=c[e>>2]|c[b+4>>2];break b}default:break b}h=c[b+4>>2]|0;if((h|0)>-1){c:do if(!m){b=0;while(1){i=d+(b<<2)|0;j=c[i>>2]|0;if((j|0)<=-1)break;if((j|0)==(h|0))break c;else b=b+1|0}c[i>>2]=h;c[d+(b+1<<2)>>2]=-1}while(0);if(p)c[f>>2]=(c[f>>2]|0)+1}break}case 3:{b=c[b+4>>2]|0;h=c[b>>2]|0;if(c[h+8>>2]|0){k=h;n=6;break b}b=c[b+4>>2]|0;if(c[b+8>>2]|0){k=b;n=6}break}case 1:{b=c[b+4>>2]|0;h=SM(a,c[b>>2]|0)|0;if(h|0){g=h;break a}k=c[b+4>>2]|0;n=6;break}case 2:{b=c[c[b+4>>2]>>2]|0;if(c[b+8>>2]|0){k=b;n=6}break}default:{}}while(0);if((n|0)==6?(n=0,g=SM(a,k)|0,g|0):0)break a;if((RM(a)|0)<=(o|0)){g=0;break a}}else g=0}else g=b;while(0);return g|0}function _M(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+16|0;g=k;d=a+12|0;e=c[d>>2]|0;j=c[a>>2]|0;if((e|0)>=(j|0)){d=c[a+4>>2]|0;if((j|0)<(d|0)?(f=(c[a+8>>2]|0)+j|0,f=(f|0)>(d|0)?d:f,h=a+16|0,i=bJ(c[h>>2]|0,f<<2)|0,(i|0)!=0):0){c[a>>2]=f;c[h>>2]=i;c[g>>2]=c[b>>2];_M(a,g)|0;d=0}else d=12}else{c[(c[a+16>>2]|0)+(e<<2)>>2]=c[b>>2];c[d>>2]=(c[d>>2]|0)+1;d=0}l=k;return d|0}function $M(a,b,d){a=a|0;b=b|0;d=d|0;a=EM(a,0,0,1,32)|0;if((d|0)!=0&(a|0)!=0){c[a+4>>2]=d;c[a>>2]=b;c[a+8>>2]=-1;c[a+12>>2]=-1}else a=0;return a|0}function aN(b,d,e,f,g,h,i,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;r=RM(d)|0;SM(d,e)|0;e=TM(d,0)|0;a:do if(!e){q=(f&1|0)==0;p=(f&2|0)!=0;o=0;l=1;e=i;while(1){if((RM(d)|0)>(r|0))n=e;else{f=o;e=0;break a}b:while(1){c:while(1){switch(UM(d)|0){case 1:{i=7;break c}case 0:{e=VM(d)|0;switch(c[e>>2]|0){case 0:{i=9;break b}case 3:{i=19;break b}case 1:{i=26;break b}case 2:{i=33;break c}default:{}}break}default:{}}if((RM(d)|0)<=(r|0)){f=o;e=0;break a}}if((i|0)==7)e=VM(d)|0;else if((i|0)==33){f=c[e+4>>2]|0;e=SM(d,c[f>>2]|0)|0;if(e|0){f=o;break a}e=TM(d,0)|0;if(e|0){f=o;break a}e=bN(b,c[f>>2]|0,c[f+4>>2]|0,c[f+8>>2]|0,a[f+12>>0]&1)|0;c[n>>2]=e;if(!e){f=o;e=12;break a}e=c[e+4>>2]|0}if((RM(d)|0)>(r|0))n=e;else{f=o;e=0;break a}}if((i|0)==9){m=c[e+4>>2]|0;i=c[m+8>>2]|0;f=c[m>>2]|0;e=c[m+4>>2]|0;if(!((f|0)>-1|(f|0)==-4))if(q|(f|0)!=-3)if((f|0)==-3)if(p&(l|0)!=0){c[h+(e<<2)>>2]=1;f=-3;k=o;l=0}else{f=-3;k=o}else k=o;else{e=-1;f=-1;i=-1;k=o}else{i=(c[g>>2]|0)+i|0;k=o+1|0}e=LM(b,f,e,i)|0;c[n>>2]=e;if(!e)e=12;else{e=c[e+4>>2]|0;c[e+12>>2]=c[m+12>>2];c[e+16>>2]=c[m+16>>2];e=0}if((i|0)>(c[j>>2]|0)){c[j>>2]=i;f=n}else f=n}else if((i|0)==19){i=c[e+4>>2]|0;f=i+4|0;e=cN(b,c[i>>2]|0,c[f>>2]|0)|0;c[n>>2]=e;if(!e){f=o;e=12;break a}m=c[e+4>>2]|0;e=SM(d,c[f>>2]|0)|0;if(e|0){f=o;break a}e=TM(d,0)|0;if(e|0){f=o;break a}e=SM(d,m+4|0)|0;if(e|0){f=o;break a}e=TM(d,1)|0;if(e|0){f=o;break a}e=SM(d,c[i>>2]|0)|0;if(e|0){f=o;break a}k=o;f=m;e=TM(d,0)|0}else if((i|0)==26){m=c[e+4>>2]|0;i=m+4|0;e=MM(b,c[m>>2]|0,c[i>>2]|0)|0;c[n>>2]=e;if(!e){f=o;e=12;break a}f=c[e+4>>2]|0;c[f>>2]=0;k=f+4|0;c[k>>2]=0;e=SM(d,c[i>>2]|0)|0;if(e|0){f=o;break a}e=TM(d,0)|0;if(e|0){f=o;break a}e=SM(d,k)|0;if(e|0){f=o;break a}e=TM(d,1)|0;if(e|0){f=o;break a}e=SM(d,c[m>>2]|0)|0;if(e|0){f=o;break a}k=o;e=TM(d,0)|0}if(!e){o=k;e=f}else{f=k;break}}}else f=0;while(0);c[g>>2]=(c[g>>2]|0)+f;return e|0}function bN(b,d,e,f,g){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;h=EM(b,0,0,1,16)|0;b=$M(b,2,h)|0;if(!b)b=0;else{c[h>>2]=d;c[h+4>>2]=e;c[h+8>>2]=f;h=h+12|0;a[h>>0]=a[h>>0]&-2|g&1;c[b+16>>2]=c[d+16>>2]}return b|0}function cN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0;if(b){e=EM(a,0,0,1,8)|0;a=$M(a,3,e)|0;if((d|0)!=0&(a|0)!=0){c[e>>2]=b;c[e+4>>2]=d;c[a+16>>2]=(c[d+16>>2]|0)+(c[b+16>>2]|0);d=a}else d=0}return d|0}function dN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=EM(a,0,0,0,8)|0;if(((e|0)!=0?(d=LM(a,-3,d,-1)|0,c[e>>2]=d,(d|0)!=0):0)?(f=EM(a,0,0,0,32)|0,c[e+4>>2]=f,(f|0)!=0):0){a=b+4|0;c[f+4>>2]=c[a>>2];c[f>>2]=c[b>>2];c[f+8>>2]=-1;c[f+12>>2]=-1;f=f+16|0;c[f>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[a>>2]=e;c[b>>2]=1;a=0}else a=12;return a|0}function eN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;f=c[a>>2]|0;if((f|0)>-1){g=c[b+16>>2]|0;e=0;b=f;do{f=b>>>1;c[((b&1|0)==0?g+(f*12|0)|0:g+(f*12|0)+4|0)>>2]=d;e=e+1|0;b=c[a+(e<<2)>>2]|0}while((b|0)>-1)}c[a>>2]=-1;return}function fN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=EM(a,0,0,0,8)|0;if(((e|0)!=0?(d=LM(a,-3,d,-1)|0,c[e+4>>2]=d,(d|0)!=0):0)?(f=EM(a,0,0,0,32)|0,c[e>>2]=f,(f|0)!=0):0){a=b+4|0;c[f+4>>2]=c[a>>2];c[f>>2]=c[b>>2];c[f+8>>2]=-1;c[f+12>>2]=-1;f=f+16|0;c[f>>2]=0;c[f+4>>2]=0;c[f+8>>2]=0;c[f+12>>2]=0;c[a>>2]=e;c[b>>2]=1;a=0}else a=12;return a|0}function gN(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0;m=l;l=l+16|0;j=m;i=b+32|0;h=c[i>>2]|0;g=h&1;a:do switch(a[d>>0]|0){case 91:{e=kN(b,d+1|0)|0;break}case 92:{e=d+1|0;f=lN(e)|0;if(f|0){e=gN(b,f)|0;c[b+12>>2]=d+2;break a}f=a[e>>0]|0;switch(f|0){case 0:{e=5;break a}case 98:{f=LM(c[b>>2]|0,-2,64,-1)|0;break}case 66:{f=LM(c[b>>2]|0,-2,128,-1)|0;break}case 60:{f=LM(c[b>>2]|0,-2,16,-1)|0;break}case 62:{f=LM(c[b>>2]|0,-2,32,-1)|0;break}case 120:{h=d+2|0;i=(a[h>>0]|0)==123;g=i?8:2;h=i?d+3|0:h;e=0;f=0;do{d=mN(a[h+e>>0]|0)|0;if((d|0)<0)break;f=d+(f<<4)|0;e=e+1|0}while((f|0)<1114112&(e|0)<(g|0));e=h+e|0;if(i){if((a[e>>0]|0)!=125){e=9;break a}e=e+1|0}j=c[b>>2]|0;i=b+24|0;k=c[i>>2]|0;c[i>>2]=k+1;f=LM(j,f,f,k)|0;e=e+-1|0;break}case 63:case 43:case 123:if(!g){e=13;break a}else{k=37;break a}case 124:{if(g|0){k=37;break a}e=LM(c[b>>2]|0,-1,-1,-1)|0;k=45;break a}default:{if(!((g|0)==0&(f+-49|0)>>>0<9)){k=37;break a}j=f+-48|0;k=c[b>>2]|0;i=b+24|0;f=c[i>>2]|0;c[i>>2]=f+1;f=LM(k,-4,j,f)|0;k=b+28|0;i=c[k>>2]|0;c[k>>2]=(j|0)<(i|0)?i:j}}d=e+1|0;e=f;k=45;break}case 46:{e=c[b>>2]|0;g=b+24|0;f=c[g>>2]|0;c[g>>2]=f+1;if(h&4){f=LM(e,0,9,f)|0;k=c[b>>2]|0;e=c[g>>2]|0;c[g>>2]=e+1;e=LM(k,11,1114111,e)|0;if((f|0)!=0&(e|0)!=0)e=cN(c[b>>2]|0,f,e)|0;else e=0}else e=LM(e,0,1114111,f)|0;d=d+1|0;k=45;break}case 94:{if((g|0)==0?(c[b+16>>2]|0)!=(d|0):0){e=d;k=37;break a}d=d+1|0;e=LM(c[b>>2]|0,-2,1,-1)|0;k=45;break}case 36:{e=d+1|0;if((g|0)==0?a[e>>0]|0:0){e=d;k=37;break a}d=e;e=LM(c[b>>2]|0,-2,2,-1)|0;k=45;break}case 63:case 43:case 123:case 42:{if(!g){e=d;k=37}else e=13;break}case 124:{if(!g){e=d;k=37}else k=36;break}case 0:{k=36;break}default:{e=d;k=37}}while(0);if((k|0)==36){e=LM(c[b>>2]|0,-1,-1,-1)|0;k=45}else if((k|0)==37){h=VL(j,e,-1)|0;if((h|0)<0)e=2;else{do if(c[i>>2]&2){if((JK(c[j>>2]|0)|0)==0?(IK(c[j>>2]|0)|0)==0:0){k=43;break}i=c[b>>2]|0;n=mK(c[j>>2]|0)|0;g=mK(c[j>>2]|0)|0;f=b+24|0;g=LM(i,n,g,c[f>>2]|0)|0;n=c[b>>2]|0;i=LK(c[j>>2]|0)|0;d=LK(c[j>>2]|0)|0;d=LM(n,i,d,c[f>>2]|0)|0;if((g|0)!=0&(d|0)!=0)g=cN(c[b>>2]|0,g,d)|0;else g=0}else k=43;while(0);if((k|0)==43){g=c[j>>2]|0;f=b+24|0;g=LM(c[b>>2]|0,g,g,c[f>>2]|0)|0}c[f>>2]=(c[f>>2]|0)+1;d=e+h|0;e=g;k=45}}if((k|0)==45)if(!e)e=12;else{c[b+8>>2]=e;c[b+12>>2]=d;e=0}l=m;return e|0}function hN(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;j=l;l=l+16|0;i=j+4|0;g=j;b=jN(b,i)|0;if((a[b>>0]|0)==44){b=jN(b+1|0,g)|0;h=c[g>>2]|0;g=c[i>>2]|0}else{i=c[i>>2]|0;c[g>>2]=i;h=i;g=i}do if(!(g>>>0>255|((h|0)>255|(h|0)>-1&(h|0)<(g|0)))){if(!d)if((a[b>>0]|0)==92)b=b+1|0;else{b=0;break}if((a[b>>0]|0)==125){c[e>>2]=g;c[f>>2]=h;b=b+1|0}else b=0}else b=0;while(0);l=j;return b|0}function iN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0;if((c[b+12>>2]|0)>-1){e=LM(c[a>>2]|0,-1,-1,-1)|0;if((e|0)!=0?(f=MM(c[a>>2]|0,e,b)|0,(f|0)!=0):0){e=c[b+16>>2]|0;c[f+16>>2]=e;g=6}else e=12}else{f=b;e=c[b+16>>2]|0;g=6}if((g|0)==6){c[f+12>>2]=d;c[f+16>>2]=e+1;c[a+8>>2]=f;e=0}return e|0}function jN(b,d){b=b|0;d=d|0;var e=0;c[d>>2]=-1;a:do if($J(a[b>>0]|0)|0){c[d>>2]=0;e=0;do{c[d>>2]=(e*10|0)+-48+(a[b>>0]|0);b=b+1|0;if(!($J(a[b>>0]|0)|0))break a;e=c[d>>2]|0}while((e|0)<=255)}while(0);return b|0}function kN(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=l;l=l+288|0;e=s+264|0;g=s;c[e>>2]=c[b>>2];h=e+8|0;c[h>>2]=0;c[e+12>>2]=32;p=_I(128)|0;r=e+4|0;c[r>>2]=p;if(!p)d=12;else{f=g+4|0;c[f>>2]=0;p=(a[d>>0]|0)==94;c[g>>2]=p&1;d=nN(b,p?d+1|0:d,e,g)|0;a:do if(!d){p=(c[g>>2]|0)==0;if(!p){sL(c[r>>2]|0,c[h>>2]|0,4,41);d=pN(e)|0;if(!d){d=12;e=0;break}c[d>>2]=1114112;c[d+4>>2]=1114112;c[d+8>>2]=-1;d=c[f>>2]|0;if(d){e=d<<2;f=EM(c[b>>2]|0,0,0,0,e+4|0)|0;if(!f){d=12;e=0;break}UN(f|0,g+8|0,e|0)|0;c[f+(d<<2)>>2]=0}else f=0}else f=0;m=c[h>>2]|0;if((m|0)>0){n=c[r>>2]|0;o=b+24|0;e=0;d=0;k=0;while(1){j=c[n+(k<<2)>>2]|0;g=c[j>>2]|0;h=j+4|0;i=c[h>>2]|0;do if(!p)if((g|0)>(d|0)){c[j>>2]=d;c[h>>2]=g+-1;d=i+1|0;q=14;break}else{j=i+1|0;d=(j|0)>=(d|0)?j:d;break}else q=14;while(0);if((q|0)==14){q=0;c[j+8>>2]=c[o>>2];c[j+16>>2]=f;j=$M(c[b>>2]|0,0,j)|0;e=cN(c[b>>2]|0,e,j)|0;if(!e){d=12;e=0;break a}}k=k+1|0;if((k|0)>=(m|0)){d=0;break}}}else{d=0;e=0}}else e=0;while(0);$I(c[r>>2]|0);r=b+24|0;c[r>>2]=(c[r>>2]|0)+1;c[b+8>>2]=e}l=s;return d|0}function lN(b){b=b|0;var d=0;d=a[b>>0]|0;b=0;while(1){if((a[56576+(b<<3)>>0]|0)==d<<24>>24)break;b=b+1|0;if((b|0)==12){b=12;break}}return c[56576+(b<<3)+4>>2]|0}function mN(a){a=a|0;var b=0;b=a+-48|0;if(b>>>0<10)return b|0;else{b=a|32;return ((b+-97|0)>>>0<6?b+-87|0:-1)|0}return 0}function nN(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;t=l;l=l+32|0;o=t;q=t+4|0;i=VL(o,d,-1)|0;g=a[d>>0]|0;a:do if((i|0)>=1){r=f+4|0;n=b+32|0;h=d;j=i;b:while(1){i=(h|0)==(d|0);if(!(i|g<<24>>24!=93)){s=5;break}c:do if(!(i|g<<24>>24!=45)){switch(a[h+1>>0]|0){case 93:break c;case 45:break;default:{g=11;break a}}if((a[h+2>>0]|0)==93){g=11;break a}}while(0);d:do if(g<<24>>24==91){switch(a[h+1>>0]|0){case 61:case 46:{g=3;break a}case 58:break;default:{s=17;break d}}i=h+2|0;g=0;e:while(1){switch(a[i+g>>0]|0){case 0:{s=16;break b}case 58:break e;default:{}}if((g|0)<13)g=g+1|0;else{s=16;break b}}UN(q|0,i|0,g|0)|0;a[q+g>>0]=0;j=bL(q)|0;if(!j){s=16;break b}h=i+(g+2)|0;if((a[i+(g+1)>>0]|0)!=93){s=16;break b}if(!(c[f>>2]|0)){g=1114111;m=0;k=1;s=25}else{g=c[r>>2]|0;if((g|0)>63){g=12;break a}c[r>>2]=g+1;c[f+8+(g<<2)>>2]=j}}else s=17;while(0);if((s|0)==17){s=0;i=c[o>>2]|0;h=h+j|0;if((a[h>>0]|0)==45?(p=h+1|0,(a[p>>0]|0)!=93):0){h=VL(o,p,-1)|0;g=c[o>>2]|0;if((h|0)<1|(i|0)>(g|0)){g=11;break a}j=0;m=i;h=p+h|0;k=0;s=25}else{j=0;g=i;m=i;k=0;s=25}}if((s|0)==25){s=0;i=pN(e)|0;if(!i){g=12;break a}c[i>>2]=m;c[i+4>>2]=g;c[i+12>>2]=j;c[i+8>>2]=-1;if(!(k|(c[n>>2]&2|0)==0)?(qN(e,m,g)|0)!=0:0){g=12;break a}}j=VL(o,h,-1)|0;g=a[h>>0]|0;if((j|0)<1){s=3;break a}}if((s|0)==5){c[b+12>>2]=h+1;g=0;break}else if((s|0)==16){g=4;break}}else s=3;while(0);if((s|0)==3)g=g<<24>>24?2:7;l=t;return g|0}function oN(a,b){a=a|0;b=b|0;return (c[c[a>>2]>>2]|0)-(c[c[b>>2]>>2]|0)|0}function pN(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0;h=a+8|0;d=c[h>>2]|0;e=a+12|0;f=c[e>>2]|0;if((d|0)>=(f|0))if((f|0)<=32767?(c[e>>2]=f<<1,g=a+4|0,b=bJ(c[g>>2]|0,f<<3)|0,(b|0)!=0):0){c[g>>2]=b;d=c[h>>2]|0;i=6}else b=0;else{b=c[a+4>>2]|0;i=6}if((i|0)==6){c[h>>2]=d+1;i=EM(c[a>>2]|0,0,0,1,20)|0;c[b+(d<<2)>>2]=i;b=i}return b|0}function qN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0;a:do if((b|0)>(d|0))b=0;else while(1){b:do if(!(IK(b)|0)){if(!(JK(b)|0)){b=b+1|0;break}f=LK(b)|0;e=f;while(1){g=b+1|0;e=e+1|0;if((b|0)>=(d|0)){h=f;b=g;g=12;break b}if((LK(g)|0)==(e|0))b=g;else{h=f;b=g;g=12;break}}}else{f=mK(b)|0;e=f;while(1){g=b+1|0;e=e+1|0;if((b|0)>=(d|0)){h=f;b=g;g=12;break b}if((mK(g)|0)==(e|0))b=g;else{h=f;b=g;g=12;break}}}while(0);if((g|0)==12){g=0;f=pN(a)|0;if(!f){b=-1;break a}c[f>>2]=h;c[f+4>>2]=e+-1;c[f+8>>2]=-1}if((b|0)>(d|0)){b=0;break}}while(0);return b|0}function rN(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0;n=l;l=l+16|0;k=n;i=c[a+4>>2]|0;j=i+56|0;h=(c[j>>2]&8|0)==0?d:0;a=c[i+40>>2]|0;if((a|0)>0&(h|0)!=0){a=_I(a<<2)|0;if(!a)a=12;else{g=a;d=a;m=3}}else{g=0;d=0;m=3}if((m|0)==3){if(!(c[i+60>>2]|0))a=tN(i,b,g,f,k)|0;else a=sN(i,b,g,f,k)|0;if(!a)uN(h,e,c[j>>2]|0,i,g,c[k>>2]|0);if(g)$I(d)}l=n;return a|0}function sN(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0;V=l;l=l+16|0;T=V;c[T>>2]=0;o=e&1;R=e&2;S=a+56|0;n=c[S>>2]&4;U=CM(0,0)|0;a:do if(U){p=EM(U,0,0,0,32)|0;if(!p){DM(U);e=12;break}c[p+24>>2]=0;c[p+28>>2]=0;Q=a+40|0;e=c[Q>>2]|0;if(e){e=_I(e<<2)|0;if(!e){m=0;k=0;j=e;e=12;i=0;h=0;g=0}else{j=e;i=e;C=6}}else{j=0;i=0;C=6}b:do if((C|0)==6){e=c[a+28>>2]|0;if(e){e=_I(e<<3)|0;if(!e){m=e;k=0;e=12;h=0;g=0;break}else{m=e;h=e}}else{m=0;h=0}P=a+52|0;e=c[P>>2]|0;if(e){e=_I(e<<2)|0;if(!e){k=e;e=12;g=0;break}else{k=e;g=e}}else{k=0;g=0}K=a+8|0;L=a+12|0;M=(d|0)==0;N=(d|0)!=0;O=a+32|0;J=(n|0)!=0;I=(o|0)==0;r=b;e=1;q=-1;v=-1;B=0;c:while(1){n=c[Q>>2]|0;if((n|0)>0){o=0;do{c[j+(o<<2)>>2]=-1;if(!M){c[d+(o<<2)>>2]=-1;n=c[Q>>2]|0}o=o+1|0}while((o|0)<(n|0))}n=c[P>>2]|0;if((n|0)>0)WN(g|0,0,n<<2|0)|0;G=e+q|0;e=VL(T,r,4)|0;if((e|0)<1)if((e|0)<0){e=1;break b}else e=1;F=r+e|0;H=c[T>>2]|0;n=c[K>>2]|0;o=n+8|0;if(c[o>>2]|0){w=(G|0)!=0;x=(B|0)==95;y=(G|0)==0;A=J&(B|0)==10;z=(G|0)<1&I;u=n;n=0;t=0;s=o;while(1){r=u+20|0;o=c[r>>2]|0;d:do if(o)if((o&1|0)==0|z|A){if(o&2|0?(E=c[T>>2]|0,!((E|R|0)==0|J&(E|0)==10)):0){q=t;break}do if(o&16|0){if(x){q=t;break d}if(EK(B)|0){q=t;break d}o=c[T>>2]|0;if((o|0)==95)break;if(!(EK(o)|0)){q=t;break d}}while(0);o=c[r>>2]|0;if(o&32){if(x){o=c[T>>2]|0;if((o|0)==95){q=t;break}}else{E=(EK(B)|0)==0;o=c[T>>2]|0;if(E|(o|0)==95){q=t;break}}if(EK(o)|0){q=t;break}o=c[r>>2]|0}q=c[T>>2]|0;do if((q|0)!=0&(w&(o&64|0)!=0)){if(x)o=1;else{o=(EK(B)|0)!=0;q=c[T>>2]|0}if((q|0)==95)if(o){q=t;break d}else break;else if(o^(EK(q)|0)!=0)break;else{q=t;break d}}while(0);if(!(c[r>>2]&128)){C=49;break}o=c[T>>2]|0;if(y|(o|0)==0){q=t;break}if(x)q=1;else{q=(EK(B)|0)!=0;o=c[T>>2]|0}if((o|0)==95)if(q){C=49;break}else{q=t;break}else if(q^(EK(o)|0)!=0){q=t;break}else{C=49;break}}else q=t;else C=49;while(0);do if((C|0)==49){C=0;if(!t){n=c[u+16>>2]|0;q=c[s>>2]|0;break}q=p+28|0;o=c[q>>2]|0;if(!o){o=EM(U,0,0,0,32)|0;if(!o){C=53;break c}c[o+24>>2]=p;c[o+28>>2]=0;E=EM(U,0,0,0,c[Q>>2]<<2)|0;c[o+20>>2]=E;if(!E){C=60;break c}c[q>>2]=o;p=o}else p=o;c[p>>2]=G;c[p+4>>2]=F;c[p+8>>2]=c[s>>2];c[p+12>>2]=c[u+12>>2];c[p+16>>2]=c[T>>2];if((c[Q>>2]|0)>0){q=c[p+20>>2]|0;o=0;do{c[q+(o<<2)>>2]=c[j+(o<<2)>>2];o=o+1|0}while((o|0)<(c[Q>>2]|0))}o=c[u+16>>2]|0;if(!o)q=t;else{q=c[o>>2]|0;if((q|0)<=-1){q=t;break}r=c[p+20>>2]|0;do{o=o+4|0;c[r+(q<<2)>>2]=G;q=c[o>>2]|0}while((q|0)>-1);q=t}}while(0);s=u+40|0;if(!(c[s>>2]|0))break;else{u=u+32|0;t=q}}if(n){o=c[n>>2]|0;if((o|0)>-1)do{c[j+(o<<2)>>2]=G;n=n+4|0;o=c[n>>2]|0}while((o|0)>-1)}else n=0;if(!q)C=171;else{s=G;r=F;w=q;x=n;C=79}}else{n=0;C=171}e:while(1){if((C|0)==79){if((w|0)==(c[L>>2]|0)){if((v|0)>=(s|0)){if(!(N&(v|0)==(s|0))){n=x;C=171;continue}n=c[Q>>2]|0;if(!(wN(n,c[O>>2]|0,j,d)|0)){n=x;C=171;continue}}else{if(M){v=s;n=x;C=171;continue}n=c[Q>>2]|0}if((n|0)>0)n=0;else{v=s;n=x;C=171;continue}while(1){c[d+(n<<2)>>2]=c[j+(n<<2)>>2];n=n+1|0;if((n|0)>=(c[Q>>2]|0)){v=s;n=x;C=171;continue e}}}u=w+8|0;if((c[u>>2]|0)!=0?(c[w+20>>2]&256|0)!=0:0){o=c[w+24>>2]|0;uN(o+1|0,m,c[S>>2]&-9,a,j,s);E=c[m+(o<<3)>>2]|0;o=(c[m+(o<<3)+4>>2]|0)-E|0;if(WJ(b+E|0,r+-1|0,o)|0){n=x;C=171;continue}E=(o|0)==0;n=E&1;q=c[w+12>>2]|0;if(E?c[k+(q<<2)>>2]|0:0){n=x;C=171;continue}c[k+(q<<2)>>2]=n;o=o+-1|0;r=r+o|0;o=o+s|0;q=c[T>>2]|0;n=VL(T,r,4)|0;if((n|0)<1)if((n|0)<0){e=1;break b}else n=1;D=r+n|0;E=n}else{q=c[T>>2]|0;if(!q){n=x;C=171;continue}n=VL(T,r,4)|0;if((n|0)<1)if((n|0)<0){e=1;break b}else n=1;o=s;D=r+n|0;E=n}s=o+e|0;if(!(c[u>>2]|0)){e=E;n=x;C=171;continue}y=(s|0)!=0;z=(q|0)==95;A=(s|0)==0;C=J&(q|0)==10;B=(s|0)<1&I;t=0;n=x;while(1){f:do if((c[w>>2]|0)>>>0<=q>>>0){if((c[w+4>>2]|0)>>>0>>0)break;r=w+20|0;e=c[r>>2]|0;do if(e|0){if(!((e&1|0)==0|B|C))break f;if(e&2|0?(x=c[T>>2]|0,!((x|R|0)==0|J&(x|0)==10)):0)break f;do if(e&16|0){if(z)break f;if(EK(q)|0)break f;e=c[T>>2]|0;if((e|0)==95)break;if(!(EK(e)|0))break f}while(0);e=c[r>>2]|0;if(e&32){if(z){e=c[T>>2]|0;if((e|0)==95)break f}else{x=(EK(q)|0)==0;e=c[T>>2]|0;if(x|(e|0)==95)break f}if(EK(e)|0)break f;e=c[r>>2]|0}o=c[T>>2]|0;do if((o|0)!=0&(y&(e&64|0)!=0)){if(z)e=1;else{e=(EK(q)|0)!=0;o=c[T>>2]|0}if((o|0)==95)if(e)break f;else break;else if(e^(EK(o)|0)!=0)break;else break f}while(0);do if(c[r>>2]&128|0){e=c[T>>2]|0;if(A|(e|0)==0)break f;if(z)o=1;else{o=(EK(q)|0)!=0;e=c[T>>2]|0}if((e|0)==95)if(o)break;else break f;else if(o^(EK(e)|0)!=0)break f;else break}while(0);e=c[r>>2]|0;do if(e&4){if(c[S>>2]&2|0)break;if(!(DK(q,c[w+24>>2]|0)|0))break f;e=c[r>>2]|0}while(0);do if(e&4|0){if(!(c[S>>2]&2))break;x=LK(q)|0;e=w+24|0;if(DK(x,c[e>>2]|0)|0)break;x=mK(q)|0;if(!(DK(x,c[e>>2]|0)|0))break f}while(0);if(!(c[r>>2]&8))break;if(vN(c[w+28>>2]|0,q,c[S>>2]&2)|0)break f}while(0);if(!t){t=c[u>>2]|0;n=c[w+16>>2]|0;break}o=p+28|0;e=c[o>>2]|0;if(!e){e=EM(U,0,0,0,32)|0;if(!e){C=145;break c}c[e+24>>2]=p;c[e+28>>2]=0;x=EM(U,0,0,0,c[Q>>2]<<2)|0;c[e+20>>2]=x;if(!x){C=152;break c}c[o>>2]=e;p=e}else p=e;c[p>>2]=s;c[p+4>>2]=D;c[p+8>>2]=c[u>>2];c[p+12>>2]=c[w+12>>2];c[p+16>>2]=c[T>>2];if((c[Q>>2]|0)>0){o=c[p+20>>2]|0;e=0;do{c[o+(e<<2)>>2]=c[j+(e<<2)>>2];e=e+1|0}while((e|0)<(c[Q>>2]|0))}e=c[w+16>>2]|0;if(!e)break;o=c[e>>2]|0;if((o|0)<=-1)break;r=c[p+20>>2]|0;do{c[r+(o<<2)>>2]=s;e=e+4|0;o=c[e>>2]|0}while((o|0)>-1)}while(0);u=w+40|0;if(!(c[u>>2]|0))break;else w=w+32|0}if(!t){e=E;C=171;continue}if(n){e=c[n>>2]|0;if((e|0)>-1){do{n=n+4|0;c[j+(e<<2)>>2]=s;e=c[n>>2]|0}while((e|0)>-1);q=v;o=D;e=E}else{q=v;o=D;e=E}}else{q=v;o=D;e=E;n=0}}else if((C|0)==171){C=0;r=c[p+24>>2]|0;if(!r)break;t=c[p+8>>2]|0;if(c[t+20>>2]&256|0)c[k+(c[p+12>>2]<<2)>>2]=0;s=c[p>>2]|0;u=c[p+4>>2]|0;c[T>>2]=c[p+16>>2];q=c[Q>>2]|0;if((q|0)>0){p=c[p+20>>2]|0;o=0;do{c[j+(o<<2)>>2]=c[p+(o<<2)>>2];o=o+1|0}while((o|0)<(q|0));p=r;q=v;o=u}else{p=r;q=v;o=u}}r=o;v=q;w=t;x=n;C=79}n=(v|0)>-1;if(n|(c[T>>2]|0)==0){C=180;break}c[T>>2]=H;r=F;q=G;B=H}if((C|0)==53){DM(U);if(j|0)$I(i);if(m|0)$I(h);if(!k){e=12;break a}$I(g);e=12;break a}else if((C|0)==60){DM(U);if(j|0)$I(i);if(m|0)$I(h);if(!k){e=12;break a}$I(g);e=12;break a}else if((C|0)==145){DM(U);if(j|0)$I(i);if(m|0)$I(h);if(!k){e=12;break a}$I(g);e=12;break a}else if((C|0)==152){DM(U);if(j|0)$I(i);if(m|0)$I(h);if(!k){e=12;break a}$I(g);e=12;break a}else if((C|0)==180){c[f>>2]=v;e=(n^1)&1;break}}while(0);DM(U);if(j|0)$I(i);if(m|0)$I(h);if(k)$I(g)}else e=12;while(0);l=V;return e|0} +function tN(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0;W=l;l=l+16|0;T=W;c[T>>2]=0;k=e&1;Q=e&2;R=a+56|0;j=c[R>>2]&4;if(!d)N=0;else N=c[a+40>>2]|0;P=N<<2;i=a+52|0;e=c[i>>2]|0;h=e<<3;g=h+8|0;e=P+12+h+(g+(O(P,e)|0)<<1)|0;U=_I(e)|0;if(!U)e=12;else{WN(U|0,0,e|0)|0;e=U+P|0;m=e&3;m=e+((m|0)==0?0:4-m|0)|0;e=m+g|0;n=e&3;n=e+((n|0)==0?0:4-n|0)|0;e=n+g|0;M=e&3;M=e+((M|0)==0?0:4-M|0)|0;e=M+h|0;g=e&3;i=c[i>>2]|0;h=(i|0)>0;if(h){e=e+((g|0)==0?0:4-g|0)|0;g=0;while(1){c[n+(g<<3)+4>>2]=e;e=e+P|0;c[m+(g<<3)+4>>2]=e;g=g+1|0;if((g|0)>=(i|0))break;else e=e+P|0}if(h){e=0;do{c[M+(e<<3)>>2]=-1;e=e+1|0}while((e|0)<(i|0))}}e=VL(T,b,4)|0;if((e|0)<1)if((e|0)<0)e=1;else{i=1;V=11}else{i=e;V=11}a:do if((V|0)==11){L=a+8|0;K=(j|0)!=0;E=(k|0)==0;F=(N|0)>0;G=a+12|0;H=(N|0)<1;I=a+44|0;J=a+32|0;C=a+36|0;D=(N|0)==0;h=0;v=b+i|0;u=0;j=0;e=-1;g=m;A=U;x=m;w=n;while(1){if((e|0)<0){a=c[L>>2]|0;k=a+8|0;b:do if(c[k>>2]|0){p=(u|0)!=0;q=(h|0)==95;r=(u|0)==0;t=K&(h|0)==10;s=(u|0)<1&E;while(1){c:while(1){o=a+12|0;if((c[M+(c[o>>2]<<3)>>2]|0)>=(u|0))break;n=a+20|0;b=c[n>>2]|0;if(!b){V=46;break}d:do if((b&1|0)==0|s|t){if(b&2|0?(B=c[T>>2]|0,!((B|Q|0)==0|K&(B|0)==10)):0)break;do if(b&16|0){if(q)break d;if(EK(h)|0)break d;b=c[T>>2]|0;if((b|0)==95)break;if(!(EK(b)|0))break d}while(0);b=c[n>>2]|0;if(b&32){if(q){b=c[T>>2]|0;if((b|0)==95)break}else{B=(EK(h)|0)==0;b=c[T>>2]|0;if(B|(b|0)==95)break}if(EK(b)|0)break;b=c[n>>2]|0}m=c[T>>2]|0;do if((m|0)!=0&(p&(b&64|0)!=0)){if(q)b=1;else{b=(EK(h)|0)!=0;m=c[T>>2]|0}if((m|0)==95)if(b)break d;else break;else if(b^(EK(m)|0)!=0)break;else break d}while(0);if(!(c[n>>2]&128)){V=46;break c}b=c[T>>2]|0;if(r|(b|0)==0)break;if(q)m=1;else{m=(EK(h)|0)!=0;b=c[T>>2]|0}if((b|0)==95)if(m){V=46;break c}else break;else if(m^(EK(b)|0)!=0)break;else{V=46;break c}}while(0);k=a+40|0;if(!(c[k>>2]|0))break b;else a=a+32|0}if((V|0)==46){V=0;c[g>>2]=c[k>>2];if(F)WN(c[g+4>>2]|0,-1,P|0)|0;k=c[a+16>>2]|0;if(k|0?(S=c[k>>2]|0,(S|0)>-1):0){m=g+4|0;b=S;do{if((b|0)<(N|0))c[(c[m>>2]|0)+(b<<2)>>2]=u;k=k+4|0;b=c[k>>2]|0}while((b|0)>-1)}k=(c[g>>2]|0)!=(c[G>>2]|0);if(k|H){j=k?j:1;e=k?e:u;k=g+4|0}else{k=g+4|0;j=c[k>>2]|0;e=0;do{c[d+(e<<2)>>2]=c[j+(e<<2)>>2];e=e+1|0}while((e|0)!=(N|0));j=1;e=u}B=c[o>>2]|0;c[M+(B<<3)>>2]=u;c[M+(B<<3)+4>>2]=k;g=g+8|0}k=a+40|0;if(!(c[k>>2]|0))break;else a=a+32|0}}while(0);c[g>>2]=0;g=c[T>>2]|0;if(!g)break;else h=g}else{if(D)break;h=c[T>>2]|0;if(!((g|0)!=(x|0)&(h|0)!=0))break}B=u+i|0;g=VL(T,v,4)|0;if((g|0)<1)if((g|0)<0){e=1;break a}else i=1;else i=g;z=v+i|0;if((j|0)!=0&(c[I>>2]|0)!=0){if(!(c[x>>2]|0))g=w;else{o=c[C>>2]|0;p=c[o>>2]|0;q=(p|0)>-1;n=x;g=w;do{m=n+4|0;e:do if(q){k=0;b=p;do{a=c[o+((k|1)<<2)>>2]|0;if((b|0)>=(N|0))break e;j=c[m>>2]|0;if((c[j+(a<<2)>>2]|0)==(c[d+(a<<2)>>2]|0)?(c[j+(b<<2)>>2]|0)<(c[d+(b<<2)>>2]|0):0)break e;k=k+2|0;b=c[o+(k<<2)>>2]|0}while((b|0)>-1);k=m;V=75}else{k=m;j=c[m>>2]|0;V=75}while(0);if((V|0)==75){V=0;c[g>>2]=c[n>>2];v=g+4|0;y=c[v>>2]|0;c[v>>2]=j;c[k>>2]=y;g=g+8|0}n=n+8|0}while((c[n>>2]|0)!=0)}c[g>>2]=0;y=x;j=0}else{y=w;w=x}k=c[w>>2]|0;if(!k){k=A;g=y}else{r=(B|0)!=0;s=(h|0)==95;t=(B|0)==0;v=K&(h|0)==10;u=(B|0)<1&E;q=w;a=A;g=y;while(1){b=k+8|0;if(c[b>>2]|0){p=q+4|0;o=a;n=b;while(1){f:do if((c[k>>2]|0)>>>0<=h>>>0?(c[k+4>>2]|0)>>>0>=h>>>0:0){m=k+20|0;a=c[m>>2]|0;do if(a|0){if(!((a&1|0)==0|u|v)){a=o;break f}if(a&2|0?(A=c[T>>2]|0,!((A|Q|0)==0|K&(A|0)==10)):0){a=o;break f}do if(a&16|0){if(s){a=o;break f}if(EK(h)|0){a=o;break f}a=c[T>>2]|0;if((a|0)==95)break;if(!(EK(a)|0)){a=o;break f}}while(0);a=c[m>>2]|0;if(a&32){if(s){a=c[T>>2]|0;if((a|0)==95){a=o;break f}}else{A=(EK(h)|0)==0;a=c[T>>2]|0;if(A|(a|0)==95){a=o;break f}}if(EK(a)|0){a=o;break f}a=c[m>>2]|0}b=c[T>>2]|0;do if((b|0)!=0&(r&(a&64|0)!=0)){if(s)a=1;else{a=(EK(h)|0)!=0;b=c[T>>2]|0}if((b|0)==95)if(a){a=o;break f}else break;else if(a^(EK(b)|0)!=0)break;else{a=o;break f}}while(0);do if(c[m>>2]&128|0){a=c[T>>2]|0;if(t|(a|0)==0){a=o;break f}if(s)b=1;else{b=(EK(h)|0)!=0;a=c[T>>2]|0}if((a|0)==95)if(b)break;else{a=o;break f}else if(b^(EK(a)|0)!=0){a=o;break f}else break}while(0);a=c[m>>2]|0;do if(a&4){if(c[R>>2]&2|0)break;if(!(DK(h,c[k+24>>2]|0)|0)){a=o;break f}a=c[m>>2]|0}while(0);do if(a&4|0){if(!(c[R>>2]&2))break;A=LK(h)|0;a=k+24|0;if(DK(A,c[a>>2]|0)|0)break;A=mK(h)|0;if(!(DK(A,c[a>>2]|0)|0)){a=o;break f}}while(0);if(!(c[m>>2]&8))break;if(vN(c[k+28>>2]|0,h,c[R>>2]&2)|0){a=o;break f}}while(0);if(F){b=c[p>>2]|0;a=0;do{c[o+(a<<2)>>2]=c[b+(a<<2)>>2];a=a+1|0}while((a|0)!=(N|0))}a=c[k+16>>2]|0;do if(a|0){b=c[a>>2]|0;if((b|0)<=-1)break;do{if((b|0)<(N|0))c[o+(b<<2)>>2]=B;a=a+4|0;b=c[a>>2]|0}while((b|0)>-1)}while(0);a=c[k+12>>2]|0;b=M+(a<<3)|0;if((c[b>>2]|0)>=(B|0)){a=c[M+(a<<3)+4>>2]|0;b=c[a>>2]|0;if(!(wN(N,c[J>>2]|0,o,b)|0)){a=o;break}c[a>>2]=o;if((c[n>>2]|0)!=(c[G>>2]|0)){a=b;break}if(F)e=0;else{j=1;a=b;e=B;break}while(1){c[d+(e<<2)>>2]=c[o+(e<<2)>>2];e=e+1|0;if((e|0)==(N|0)){j=1;a=b;e=B;break f}}}A=c[n>>2]|0;c[g>>2]=A;x=g+4|0;m=c[x>>2]|0;c[x>>2]=o;c[b>>2]=B;c[M+(a<<3)+4>>2]=x;do if((c[G>>2]|0)==(A|0)){if((e|0)==-1)if(F)e=0;else{e=B;j=1;break}else{if(!F)break;if((c[o>>2]|0)>(c[d>>2]|0))break;else e=0}do{c[d+(e<<2)>>2]=c[o+(e<<2)>>2];e=e+1|0}while((e|0)<(N|0));e=B;j=1}while(0);a=m;g=g+8|0}else a=o;while(0);n=k+40|0;if(!(c[n>>2]|0))break;else{k=k+32|0;o=a}}}q=q+8|0;k=c[q>>2]|0;if(!k){k=a;break}}}c[g>>2]=0;v=z;u=B;A=k;x=y}c[f>>2]=e;e=e>>>31}while(0);$I(U)}l=W;return e|0}function uN(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;if((d&8|0)==0&(g|0)>-1?(m=c[e+16>>2]|0,n=c[e+28>>2]|0,l=(a|0)!=0&(n|0)!=0,l):0){k=c[e+48>>2]|0;j=0;do{d=c[m+(j*12|0)>>2]|0;if((d|0)==(k|0))i=g;else i=c[f+(d<<2)>>2]|0;h=b+(j<<3)|0;c[h>>2]=i;d=c[m+(j*12|0)+4>>2]|0;if((d|0)==(k|0))d=g;else d=c[f+(d<<2)>>2]|0;e=b+(j<<3)+4|0;c[e>>2]=d;if((d|0)==-1|(i|0)==-1){c[e>>2]=-1;c[h>>2]=-1}j=j+1|0}while(j>>>0>>0&j>>>0>>0);if(l){d=0;do{i=b+(d<<3)+4|0;j=c[m+(d*12|0)+8>>2]|0;if(j|0?(o=c[j>>2]|0,(o|0)>-1):0){k=b+(d<<3)|0;h=0;f=o;e=c[k>>2]|0;do{if(!((e|0)>=(c[b+(f<<3)>>2]|0)?(c[i>>2]|0)<=(c[b+(f<<3)+4>>2]|0):0)){c[i>>2]=-1;c[k>>2]=-1;e=-1}h=h+1|0;f=c[j+(h<<2)>>2]|0}while((f|0)>-1)}d=d+1|0}while(d>>>0>>0&d>>>0>>0)}else d=0}else d=0;if(d>>>0>>0)WN(b+(d<<3)|0,-1,a-d<<3|0)|0;return}function vN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=c[a>>2]|0;a:do if(!e)d=0;else{f=(d|0)==0;d=e;while(1){if(f){if(DK(b,d)|0){d=1;break a}}else{e=mK(b)|0;if(DK(e,c[a>>2]|0)|0){d=1;break a}e=LK(b)|0;if(DK(e,c[a>>2]|0)|0){d=1;break a}}a=a+4|0;d=c[a>>2]|0;if(!d){d=0;break}}}while(0);return d|0}function wN(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;a:do if((a|0)>0){f=0;while(1){h=c[d+(f<<2)>>2]|0;g=c[e+(f<<2)>>2]|0;if(!(c[b+(f<<2)>>2]|0)){if((h|0)<(g|0)){f=1;break a}if((h|0)>(g|0)){f=0;break a}}else{if((h|0)>(g|0)){f=1;break a}if((h|0)<(g|0)){f=0;break a}}f=f+1|0;if((f|0)>=(a|0)){f=0;break}}}else f=0;while(0);return f|0}function xN(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0;k=O(e,d)|0;e=(d|0)==0?0:e;if((c[f+76>>2]|0)>-1)j=PK(f)|0;else j=0;g=f+74|0;h=a[g>>0]|0;a[g>>0]=h+255|h;g=f+4|0;h=c[g>>2]|0;i=(c[f+8>>2]|0)-h|0;if((i|0)>0){i=i>>>0>>0?i:k;UN(b|0,h|0,i|0)|0;c[g>>2]=(c[g>>2]|0)+i;g=k-i|0;b=b+i|0}else g=k;a:do if(!g)l=13;else{i=f+32|0;while(1){if(fK(f)|0)break;h=bb[c[i>>2]&31](f,b,g)|0;if((h+1|0)>>>0<2)break;g=g-h|0;if(!g){l=13;break a}else b=b+h|0}if(j|0)QK(f);e=((k-g|0)>>>0)/(d>>>0)|0}while(0);if((l|0)==13)if(j)QK(f);return e|0}function yN(a){a=a|0;var b=0;if((c[a+76>>2]|0)>-1){b=(PK(a)|0)==0;a=zN(a)|0}else a=zN(a)|0;return a|0}function zN(a){a=a|0;var b=0;if(!(c[a>>2]&128))b=1;else b=(c[a+20>>2]|0)>>>0>(c[a+28>>2]|0)>>>0?2:1;b=bb[c[a+40>>2]&31](a,0,b)|0;if((b|0)>=0)b=b-(c[a+8>>2]|0)+(c[a+4>>2]|0)+(c[a+20>>2]|0)-(c[a+28>>2]|0)|0;return b|0}function AN(a){a=a|0;(c[a+76>>2]|0)>-1?PK(a)|0:0;return c[a+60>>2]|0}function BN(){var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;k=l;l=l+48|0;i=k+24|0;h=k+16|0;g=k;d=k+28|0;b=d;e=134988;f=b+20|0;do{a[b>>0]=a[e>>0]|0;b=b+1|0;e=e+1|0}while((b|0)<(f|0));e=d+13|0;b=0;while(1){BL(e)|0;c[g>>2]=d;c[g+4>>2]=32962;c[g+8>>2]=384;f=jJ(Ba(5,g|0)|0)|0;if((f|0)>-1){j=4;break}if((b|0)<99)b=b+1|0;else{b=0;break}}if((j|0)==4){c[h>>2]=d;sa(10,h|0)|0;b=TL(f,135008)|0;if(!b){c[i>>2]=f;Da(6,i|0)|0;b=0}}l=k;return b|0}function CN(a){a=a|0;var b=0,e=0,f=0;if((c[a+76>>2]|0)>=0?(PK(a)|0)!=0:0){b=a+4|0;e=c[b>>2]|0;if(e>>>0<(c[a+8>>2]|0)>>>0){c[b>>2]=e+1;b=d[e>>0]|0}else b=eK(a)|0}else f=3;do if((f|0)==3){b=a+4|0;e=c[b>>2]|0;if(e>>>0<(c[a+8>>2]|0)>>>0){c[b>>2]=e+1;b=d[e>>0]|0;break}else{b=eK(a)|0;break}}while(0);return b|0}function DN(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0;if((c[d+76>>2]|0)>=0?(PK(d)|0)!=0:0){f=b&255;e=b&255;if((e|0)!=(a[d+75>>0]|0)?(i=d+20|0,j=c[i>>2]|0,j>>>0<(c[d+16>>2]|0)>>>0):0){c[i>>2]=j+1;a[j>>0]=f}else e=ZL(d,b)|0;QK(d)}else k=3;do if((k|0)==3){f=b&255;e=b&255;if((e|0)!=(a[d+75>>0]|0)?(g=d+20|0,h=c[g>>2]|0,h>>>0<(c[d+16>>2]|0)>>>0):0){c[g>>2]=h+1;a[h>>0]=f;break}e=ZL(d,b)|0}while(0);return e|0}function EN(a){a=a|0;return yN(a)|0}function FN(){}function GN(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,f=0;f=a&65535;e=b&65535;c=O(e,f)|0;d=a>>>16;a=(c>>>16)+(O(e,d)|0)|0;e=b>>>16;b=O(e,f)|0;return (z=(a>>>16)+(O(e,d)|0)+(((a&65535)+b|0)>>>16)|0,a+b<<16|c&65535|0)|0}function HN(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=a;f=c;c=GN(e,f)|0;a=z;return (z=(O(b,f)|0)+(O(d,e)|0)+a|a&0,c|0|0)|0}function IN(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return (z=b+d+(c>>>0>>0|0)>>>0,c|0)|0}function JN(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (z=d,a-c>>>0|0)|0}function KN(b){b=b|0;var c=0;c=a[n+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[n+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (a[n+(b>>>24)>>0]|0)+24|0}function LN(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;l=a;j=b;k=j;h=d;n=e;i=n;if(!k){g=(f|0)!=0;if(!i){if(g){c[f>>2]=(l>>>0)%(h>>>0);c[f+4>>2]=0}n=0;f=(l>>>0)/(h>>>0)>>>0;return (z=n,f)|0}else{if(!g){n=0;f=0;return (z=n,f)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;n=0;f=0;return (z=n,f)|0}}g=(i|0)==0;do if(h){if(!g){g=(R(i|0)|0)-(R(k|0)|0)|0;if(g>>>0<=31){m=g+1|0;i=31-g|0;b=g-31>>31;h=m;a=l>>>(m>>>0)&b|k<>>(m>>>0)&b;g=0;i=l<>2]=a|0;c[f+4>>2]=j|b&0;n=0;f=0;return (z=n,f)|0}g=h-1|0;if(g&h|0){i=(R(h|0)|0)+33-(R(k|0)|0)|0;p=64-i|0;m=32-i|0;j=m>>31;o=i-32|0;b=o>>31;h=i;a=m-1>>31&k>>>(o>>>0)|(k<>>(i>>>0))&b;b=b&k>>>(i>>>0);g=l<>>(o>>>0))&j|l<>31;break}if(f|0){c[f>>2]=g&l;c[f+4>>2]=0}if((h|0)==1){o=j|b&0;p=a|0|0;return (z=o,p)|0}else{p=KN(h|0)|0;o=k>>>(p>>>0)|0;p=k<<32-p|l>>>(p>>>0)|0;return (z=o,p)|0}}else{if(g){if(f|0){c[f>>2]=(k>>>0)%(h>>>0);c[f+4>>2]=0}o=0;p=(k>>>0)/(h>>>0)>>>0;return (z=o,p)|0}if(!l){if(f|0){c[f>>2]=0;c[f+4>>2]=(k>>>0)%(i>>>0)}o=0;p=(k>>>0)/(i>>>0)>>>0;return (z=o,p)|0}g=i-1|0;if(!(g&i)){if(f|0){c[f>>2]=a|0;c[f+4>>2]=g&k|b&0}o=0;p=k>>>((KN(i|0)|0)>>>0);return (z=o,p)|0}g=(R(i|0)|0)-(R(k|0)|0)|0;if(g>>>0<=30){b=g+1|0;i=31-g|0;h=b;a=k<>>(b>>>0);b=k>>>(b>>>0);g=0;i=l<>2]=a|0;c[f+4>>2]=j|b&0;o=0;p=0;return (z=o,p)|0}while(0);if(!h){k=i;j=0;i=0}else{m=d|0|0;l=n|e&0;k=IN(m|0,l|0,-1,-1)|0;d=z;j=i;i=0;do{e=j;j=g>>>31|j<<1;g=i|g<<1;e=a<<1|e>>>31|0;n=a>>>31|b<<1|0;JN(k|0,d|0,e|0,n|0)|0;p=z;o=p>>31|((p|0)<0?-1:0)<<1;i=o&1;a=JN(e|0,n|0,o&m|0,(((p|0)<0?-1:0)>>31|((p|0)<0?-1:0)<<1)&l|0)|0;b=z;h=h-1|0}while((h|0)!=0);k=j;j=0}h=0;if(f|0){c[f>>2]=a;c[f+4>>2]=b}o=(g|0)>>>31|(k|h)<<1|(h<<1|g>>>31)&0|j;p=(g<<1|0>>>31)&-2|i;return (z=o,p)|0}function MN(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return LN(a,b,c,d,0)|0}function NN(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;g=l;l=l+16|0;f=g|0;LN(a,b,d,e,f)|0;l=g;return (z=c[f+4>>2]|0,c[f>>2]|0)|0}function ON(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){z=b>>>c;return a>>>c|(b&(1<>>c-32|0}function PN(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){z=b<>>32-c;return a<>8&255|0}function RN(a){a=a|0;return (a&255)<<24|(a>>8&255)<<16|(a>>16&255)<<8|a>>>24|0}function SN(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;q=q+1|0;c[a>>2]=q;while((f|0)<(e|0)){if(!(c[d+(f<<3)>>2]|0)){c[d+(f<<3)>>2]=q;c[d+((f<<3)+4)>>2]=b;c[d+((f<<3)+8)>>2]=0;z=e;return d|0}f=f+1|0}e=e*2|0;d=bJ(d|0,8*(e+1|0)|0)|0;d=SN(a|0,b|0,d|0,e|0)|0;z=e;return d|0}function TN(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;while((f|0)<(d|0)){e=c[b+(f<<3)>>2]|0;if(!e)break;if((e|0)==(a|0))return c[b+((f<<3)+4)>>2]|0;f=f+1|0}return 0}function UN(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;if((e|0)>=8192)return La(b|0,d|0,e|0)|0;h=b|0;g=b+e|0;if((b&3)==(d&3)){while(b&3){if(!e)return h|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}e=g&-4|0;f=e-64|0;while((b|0)<=(f|0)){c[b>>2]=c[d>>2];c[b+4>>2]=c[d+4>>2];c[b+8>>2]=c[d+8>>2];c[b+12>>2]=c[d+12>>2];c[b+16>>2]=c[d+16>>2];c[b+20>>2]=c[d+20>>2];c[b+24>>2]=c[d+24>>2];c[b+28>>2]=c[d+28>>2];c[b+32>>2]=c[d+32>>2];c[b+36>>2]=c[d+36>>2];c[b+40>>2]=c[d+40>>2];c[b+44>>2]=c[d+44>>2];c[b+48>>2]=c[d+48>>2];c[b+52>>2]=c[d+52>>2];c[b+56>>2]=c[d+56>>2];c[b+60>>2]=c[d+60>>2];b=b+64|0;d=d+64|0}while((b|0)<(e|0)){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}}else{e=g-4|0;while((b|0)<(e|0)){a[b>>0]=a[d>>0]|0;a[b+1>>0]=a[d+1>>0]|0;a[b+2>>0]=a[d+2>>0]|0;a[b+3>>0]=a[d+3>>0]|0;b=b+4|0;d=d+4|0}}while((b|0)<(g|0)){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0}return h|0}function VN(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;if((c|0)<(b|0)&(b|0)<(c+d|0)){e=b;c=c+d|0;b=b+d|0;while((d|0)>0){b=b-1|0;c=c-1|0;d=d-1|0;a[b>>0]=a[c>>0]|0}b=e}else UN(b,c,d)|0;return b|0}function WN(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;h=b+e|0;d=d&255;if((e|0)>=67){while(b&3){a[b>>0]=d;b=b+1|0}f=h&-4|0;g=f-64|0;i=d|d<<8|d<<16|d<<24;while((b|0)<=(g|0)){c[b>>2]=i;c[b+4>>2]=i;c[b+8>>2]=i;c[b+12>>2]=i;c[b+16>>2]=i;c[b+20>>2]=i;c[b+24>>2]=i;c[b+28>>2]=i;c[b+32>>2]=i;c[b+36>>2]=i;c[b+40>>2]=i;c[b+44>>2]=i;c[b+48>>2]=i;c[b+52>>2]=i;c[b+56>>2]=i;c[b+60>>2]=i;b=b+64|0}while((b|0)<(f|0)){c[b>>2]=i;b=b+4|0}}while((b|0)<(h|0)){a[b>>0]=d;b=b+1|0}return h-e|0}function XN(a){a=a|0;var b=0,d=0;d=c[i>>2]|0;b=d+a|0;if((a|0)>0&(b|0)<(d|0)|(b|0)<0){W()|0;ra(12);return -1}c[i>>2]=b;if((b|0)>(V()|0)?(U()|0)==0:0){c[i>>2]=d;ra(12);return -1}return d|0}function YN(a){a=a|0;return +Ya[a&1]()}function ZN(a,b,c,d){a=a|0;b=+b;c=+c;d=+d;return +Za[a&7](+b,+c,+d)}function _N(a){a=a|0;return _a[a&3]()|0}function $N(a,b){a=a|0;b=b|0;return $a[a&31](b|0)|0}function aO(a,b,c){a=a|0;b=b|0;c=c|0;return ab[a&63](b|0,c|0)|0}function bO(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return bb[a&31](b|0,c|0,d|0)|0}function cO(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return cb[a&31](b|0,c|0,d|0,e|0)|0}function dO(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return db[a&3](b|0,c|0,d|0,e|0,f|0)|0}function eO(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return eb[a&1](b|0,c|0,d|0,e|0,f|0,g|0)|0}function fO(a){a=a|0;fb[a&15]()}function gO(a,b){a=a|0;b=b|0;gb[a&127](b|0)}function hO(a,b,c){a=a|0;b=b|0;c=c|0;hb[a&31](b|0,c|0)}function iO(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ib[a&127](b|0,c|0,d|0)}function jO(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=+e;f=+f;g=g|0;jb[a&15](b|0,c|0,d|0,+e,+f,g|0)}function kO(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;kb[a&31](b|0,c|0,d|0,e|0)}function lO(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;lb[a&7](b|0,c|0,d|0,e|0,f|0)}function mO(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;mb[a&15](b|0,c|0,d|0,e|0,f|0,g|0)}function nO(){S(0);return 0.0}function oO(a,b,c){a=+a;b=+b;c=+c;S(1);return 0.0}function pO(){S(2);return 0}function qO(a){a=a|0;S(3);return 0}function rO(a,b){a=a|0;b=b|0;S(4);return 0}function sO(a,b,c){a=a|0;b=b|0;c=c|0;S(5);return 0}function tO(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;S(6);return 0}function uO(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;S(7);return 0}function vO(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;S(8);return 0}function wO(){S(9)}function xO(a){a=a|0;S(10)}function yO(a,b){a=a|0;b=b|0;S(11)}function zO(a,b,c){a=a|0;b=b|0;c=c|0;S(12)}function AO(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=+d;e=+e;f=f|0;S(13)}function BO(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;S(14)}function CO(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;S(15)}function DO(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;S(16)} + +// EMSCRIPTEN_END_FUNCS +var Ya=[nO,zA];var Za=[oO,Vu,Uu,Wu,Xu,oO,oO,oO];var _a=[pO,Gw,xx,pO];var $a=[qO,Sg,lg,Sn,Vn,aC,bC,SD,TD,UD,VD,WD,XD,YD,ZD,gJ,ub,pr,ml,pl,Cw,Hw,on,xw,eo,OB,ww,TB,UB,OI,qO,qO];var ab=[rO,un,Rn,Wn,zz,Az,rz,nz,Xy,nr,bg,Rg,sh,Wh,mi,xk,vk,nl,ql,Aq,zq,yq,Es,Us,Ps,Qs,Pt,XL,DN,tA,vB,Jm,xG,Qm,Sm,fo,PB,yJ,YE,KI,LI,oN,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO,rO];var bb=[sO,Ql,Wl,Qn,Un,hG,hJ,iJ,mJ,nJ,aL,$l,Yl,AL,vA,Fx,aD,HI,fM,sO,sO,sO,sO,sO,sO,sO,sO,sO,sO,sO,sO,sO];var cb=[tO,Om,Op,Pm,gn,wn,yn,Jn,In,Xn,$n,bo,zx,DC,BC,xE,jG,FG,EG,Nl,xA,tO,tO,tO,tO,tO,tO,tO,tO,tO,tO,tO];var db=[uO,vn,Yy,sz];var eb=[vO,lI];var fb=[wO,yA,Dw,Ew,Fw,Jw,Kw,Lw,nG,wO,wO,wO,wO,wO,wO,wO];var gb=[xO,Ab,Bb,Fb,Gb,Hb,$b,ac,yc,zc,Ac,Bc,Cc,Dc,Ec,Qc,Rc,Uc,Vc,Wc,Xc,Yc,Zc,_c,kd,ld,md,od,pd,qd,rd,sd,td,ud,vd,Gd,Hd,Id,Kd,Ld,Md,Nd,Od,Pd,Qd,Rd,Sd,Ud,fe,ge,he,ie,te,ue,ve,xe,Ke,Le,Me,Oe,Pe,Qe,Re,Se,Te,Ue,Ve,We,df,ef,ff,gf,Kf,Ff,zn,Dy,Vy,Fy,Ey,pz,by,ey,_D,dE,yf,rl,mm,mG,VC,WB,Ax,$I,GG,kI,FI,GI,MI,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO,xO];var hb=[yO,Gc,Lc,ad,fd,Cd,_d,oe,De,af,nf,Yn,Zy,Bz,tz,oz,Ty,Uy,xz,yz,bE,fE,cm,ss,Iw,NB,jI,II,JI,NI,PI,yO];var ib=[zO,Ib,Jb,Mb,xc,Fc,Hc,Kc,$c,bd,ed,xd,yd,Bd,Vd,Wd,Zd,je,ke,ne,ye,ze,Ce,Xe,Ye,$e,hf,jf,mf,ck,dk,ek,jm,An,ao,Ko,Pp,ks,Fv,yx,dy,nB,CC,AC,$D,aE,cE,eE,gE,iG,XH,WH,Cm,cn,po,So,Vo,Bw,wA,Dx,RB,VB,YH,_H,$H,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO,zO];var jb=[AO,Gt,Ht,It,Jt,Kt,Lt,Mt,Nt,AO,AO,AO,AO,AO,AO,AO];var kb=[BO,Kb,Ic,cd,nd,zd,Jd,Xd,le,Ae,Ne,Ze,kf,Bf,Af,zf,xf,wf,vf,_b,uf,tf,xn,Wy,qz,sL,QB,SB,BO,BO,BO,BO];var lb=[CO,Sc,wd,Dd,Td,we,ol,XB];var mb=[DO,Lb,Jc,dd,Ad,Yd,me,Be,_e,lf,YB,DO,DO,DO,DO,DO];return{___errno_location:kJ,___muldi3:HN,___udivdi3:MN,___uremdi3:NN,_bitshift64Lshr:ON,_bitshift64Shl:PN,_dtdisc:Ml,_dtextract:Ol,_dtopen:Rl,_free:$I,_htons:fL,_i64Add:IN,_i64Subtract:JN,_llvm_bswap_i16:QN,_llvm_bswap_i32:RN,_malloc:_I,_memalign:eJ,_memcpy:UN,_memmove:VN,_memset:WN,_realloc:bJ,_saveSetjmp:SN,_sbrk:XN,_testSetjmp:TN,_vizCreateFile:wb,_vizLastErrorMessage:vb,_vizRenderFromString:zb,_vizSetNop:yb,_vizSetY_invert:xb,dynCall_d:YN,dynCall_dddd:ZN,dynCall_i:_N,dynCall_ii:$N,dynCall_iii:aO,dynCall_iiii:bO,dynCall_iiiii:cO,dynCall_iiiiii:dO,dynCall_iiiiiii:eO,dynCall_v:fO,dynCall_vi:gO,dynCall_vii:hO,dynCall_viii:iO,dynCall_viiiddi:jO,dynCall_viiii:kO,dynCall_viiiii:lO,dynCall_viiiiii:mO,establishStackSpace:qb,getTempRet0:tb,runPostSets:FN,setTempRet0:sb,setThrew:rb,stackAlloc:nb,stackRestore:pb,stackSave:ob}}) + + +// EMSCRIPTEN_END_ASM +(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var ___errno_location=Module["___errno_location"]=asm["___errno_location"];var ___muldi3=Module["___muldi3"]=asm["___muldi3"];var ___udivdi3=Module["___udivdi3"]=asm["___udivdi3"];var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _dtdisc=Module["_dtdisc"]=asm["_dtdisc"];var _dtextract=Module["_dtextract"]=asm["_dtextract"];var _dtopen=Module["_dtopen"]=asm["_dtopen"];var _free=Module["_free"]=asm["_free"];var _htons=Module["_htons"]=asm["_htons"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _llvm_bswap_i16=Module["_llvm_bswap_i16"]=asm["_llvm_bswap_i16"];var _llvm_bswap_i32=Module["_llvm_bswap_i32"]=asm["_llvm_bswap_i32"];var _malloc=Module["_malloc"]=asm["_malloc"];var _memalign=Module["_memalign"]=asm["_memalign"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _memmove=Module["_memmove"]=asm["_memmove"];var _memset=Module["_memset"]=asm["_memset"];var _realloc=Module["_realloc"]=asm["_realloc"];var _saveSetjmp=Module["_saveSetjmp"]=asm["_saveSetjmp"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _testSetjmp=Module["_testSetjmp"]=asm["_testSetjmp"];var _vizCreateFile=Module["_vizCreateFile"]=asm["_vizCreateFile"];var _vizLastErrorMessage=Module["_vizLastErrorMessage"]=asm["_vizLastErrorMessage"];var _vizRenderFromString=Module["_vizRenderFromString"]=asm["_vizRenderFromString"];var _vizSetNop=Module["_vizSetNop"]=asm["_vizSetNop"];var _vizSetY_invert=Module["_vizSetY_invert"]=asm["_vizSetY_invert"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var getTempRet0=Module["getTempRet0"]=asm["getTempRet0"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var setTempRet0=Module["setTempRet0"]=asm["setTempRet0"];var setThrew=Module["setThrew"]=asm["setThrew"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var stackSave=Module["stackSave"]=asm["stackSave"];var dynCall_d=Module["dynCall_d"]=asm["dynCall_d"];var dynCall_dddd=Module["dynCall_dddd"]=asm["dynCall_dddd"];var dynCall_i=Module["dynCall_i"]=asm["dynCall_i"];var dynCall_ii=Module["dynCall_ii"]=asm["dynCall_ii"];var dynCall_iii=Module["dynCall_iii"]=asm["dynCall_iii"];var dynCall_iiii=Module["dynCall_iiii"]=asm["dynCall_iiii"];var dynCall_iiiii=Module["dynCall_iiiii"]=asm["dynCall_iiiii"];var dynCall_iiiiii=Module["dynCall_iiiiii"]=asm["dynCall_iiiiii"];var dynCall_iiiiiii=Module["dynCall_iiiiiii"]=asm["dynCall_iiiiiii"];var dynCall_v=Module["dynCall_v"]=asm["dynCall_v"];var dynCall_vi=Module["dynCall_vi"]=asm["dynCall_vi"];var dynCall_vii=Module["dynCall_vii"]=asm["dynCall_vii"];var dynCall_viii=Module["dynCall_viii"]=asm["dynCall_viii"];var dynCall_viiiddi=Module["dynCall_viiiddi"]=asm["dynCall_viiiddi"];var dynCall_viiii=Module["dynCall_viiii"]=asm["dynCall_viiii"];var dynCall_viiiii=Module["dynCall_viiiii"]=asm["dynCall_viiiii"];var dynCall_viiiiii=Module["dynCall_viiiiii"]=asm["dynCall_viiiiii"];Module["asm"]=asm;Module["ccall"]=ccall;Module["Pointer_stringify"]=Pointer_stringify;Module["UTF8ToString"]=UTF8ToString;if(memoryInitializer){if(!isDataURI(memoryInitializer)){if(typeof Module["locateFile"]==="function"){memoryInitializer=Module["locateFile"](memoryInitializer)}else if(Module["memoryInitializerPrefixURL"]){memoryInitializer=Module["memoryInitializerPrefixURL"]+memoryInitializer}}if(ENVIRONMENT_IS_NODE||ENVIRONMENT_IS_SHELL){var data=Module["readBinary"](memoryInitializer);HEAPU8.set(data,GLOBAL_BASE)}else{addRunDependency("memory initializer");var applyMemoryInitializer=(function(data){if(data.byteLength)data=new Uint8Array(data);HEAPU8.set(data,GLOBAL_BASE);if(Module["memoryInitializerRequest"])delete Module["memoryInitializerRequest"].response;removeRunDependency("memory initializer")});function doBrowserLoad(){Module["readAsync"](memoryInitializer,applyMemoryInitializer,(function(){throw"could not load memory initializer "+memoryInitializer}))}var memoryInitializerBytes=tryParseAsDataURI(memoryInitializer);if(memoryInitializerBytes){applyMemoryInitializer(memoryInitializerBytes.buffer)}else if(Module["memoryInitializerRequest"]){function useRequest(){var request=Module["memoryInitializerRequest"];var response=request.response;if(request.status!==200&&request.status!==0){var data=tryParseAsDataURI(Module["memoryInitializerRequestURL"]);if(data){response=data.buffer}else{console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+request.status+", retrying "+memoryInitializer);doBrowserLoad();return}}applyMemoryInitializer(response)}if(Module["memoryInitializerRequest"].response){setTimeout(useRequest,0)}else{Module["memoryInitializerRequest"].addEventListener("load",useRequest)}}else{doBrowserLoad()}}}function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};function run(args){args=args||Module["arguments"];if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]&&status===0){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["exit"](status)}Module["quit"](status,new ExitStatus(status))}Module["exit"]=exit;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}Module["noExitRuntime"]=true;run() + + + + + return Module; +}; + +function render(instance, src, options) { + var i; + for (i = 0; i < options.files.length; i++) { + instance['ccall']('vizCreateFile', 'number', ['string', 'string'], [options.files[i].path, options.files[i].data]); + } + + instance['ccall']('vizSetY_invert', 'number', ['number'], [options.yInvert ? 1 : 0]); + instance['ccall']('vizSetNop', 'number', ['number'], [options.nop ? options.nop : 0]); + + var resultPointer = instance['ccall']('vizRenderFromString', 'number', ['string', 'string', 'string'], [src, options.format, options.engine]); + var resultString = instance['Pointer_stringify'](resultPointer); + instance['ccall']('free', 'number', ['number'], [resultPointer]); + + var errorMessagePointer = instance['ccall']('vizLastErrorMessage', 'number', [], []); + var errorMessageString = instance['Pointer_stringify'](errorMessagePointer); + instance['ccall']('free', 'number', ['number'], [errorMessagePointer]); + + if (errorMessageString != '') { + throw new Error(errorMessageString); + } + + return resultString; +} + +if (typeof importScripts === "function") { + var instance = Module(); + + onmessage = function(event) { + var id = event.data.id; + var src = event.data.src; + var options = event.data.options; + + try { + var result = render(instance, src, options); + postMessage({ id: id, result: result }); + } catch (e) { + var error; + if (e instanceof Error) { + error = { message: e.message, fileName: e.fileName, lineNumber: e.lineNumber }; + } else { + error = { message: e.toString() }; + } + postMessage({ id: id, error: error }); + } + } +} + +if (typeof exports === 'object' && typeof module !== 'undefined') { + module.exports = { render: render, Module: Module }; +} else if (typeof define === 'function' && define.amd) { + define(function() { return { render: render, Module: Module }; }); +} + +if (typeof global.Viz !== 'undefined') { + global.Viz.render = render; + global.Viz.Module = Module; +} + +})(typeof self !== 'undefined' ? self : this); diff --git a/assets/js/graphviz/viz.js b/assets/js/graphviz/viz.js new file mode 100644 index 0000000000..d9e55bd5f6 --- /dev/null +++ b/assets/js/graphviz/viz.js @@ -0,0 +1,333 @@ +/* +Viz.js 2.1.2 (Graphviz 2.40.1, Expat 2.2.5, Emscripten 1.37.36) +Copyright (c) 2014-2018 Michael Daines +Licensed under MIT license + +This distribution contains other software in object code form: + +Graphviz +Licensed under Eclipse Public License - v 1.0 +http://www.graphviz.org + +Expat +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers. +Licensed under MIT license +http://www.libexpat.org + +zlib +Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler +http://www.zlib.net/zlib_license.html +*/ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.Viz = factory()); +}(this, (function () { 'use strict'; + + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + + var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + var _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + var WorkerWrapper = function () { + function WorkerWrapper(worker) { + var _this = this; + + classCallCheck(this, WorkerWrapper); + + this.worker = worker; + this.listeners = []; + this.nextId = 0; + + this.worker.addEventListener('message', function (event) { + var id = event.data.id; + var error = event.data.error; + var result = event.data.result; + + _this.listeners[id](error, result); + delete _this.listeners[id]; + }); + } + + createClass(WorkerWrapper, [{ + key: 'render', + value: function render(src, options) { + var _this2 = this; + + return new Promise(function (resolve, reject) { + var id = _this2.nextId++; + + _this2.listeners[id] = function (error, result) { + if (error) { + reject(new Error(error.message, error.fileName, error.lineNumber)); + return; + } + resolve(result); + }; + + _this2.worker.postMessage({ id: id, src: src, options: options }); + }); + } + }]); + return WorkerWrapper; + }(); + + var ModuleWrapper = function ModuleWrapper(module, render) { + classCallCheck(this, ModuleWrapper); + + var instance = module(); + this.render = function (src, options) { + return new Promise(function (resolve, reject) { + try { + resolve(render(instance, src, options)); + } catch (error) { + reject(error); + } + }); + }; + }; + + // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding + + + function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { + return String.fromCharCode('0x' + p1); + })); + } + + function defaultScale() { + if ('devicePixelRatio' in window && window.devicePixelRatio > 1) { + return window.devicePixelRatio; + } else { + return 1; + } + } + + function svgXmlToImageElement(svgXml) { + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$scale = _ref.scale, + scale = _ref$scale === undefined ? defaultScale() : _ref$scale, + _ref$mimeType = _ref.mimeType, + mimeType = _ref$mimeType === undefined ? "image/png" : _ref$mimeType, + _ref$quality = _ref.quality, + quality = _ref$quality === undefined ? 1 : _ref$quality; + + return new Promise(function (resolve, reject) { + var svgImage = new Image(); + + svgImage.onload = function () { + var canvas = document.createElement('canvas'); + canvas.width = svgImage.width * scale; + canvas.height = svgImage.height * scale; + + var context = canvas.getContext("2d"); + context.drawImage(svgImage, 0, 0, canvas.width, canvas.height); + + canvas.toBlob(function (blob) { + var image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = svgImage.width; + image.height = svgImage.height; + + resolve(image); + }, mimeType, quality); + }; + + svgImage.onerror = function (e) { + var error; + + if ('error' in e) { + error = e.error; + } else { + error = new Error('Error loading SVG'); + } + + reject(error); + }; + + svgImage.src = 'data:image/svg+xml;base64,' + b64EncodeUnicode(svgXml); + }); + } + + function svgXmlToImageElementFabric(svgXml) { + var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref2$scale = _ref2.scale, + scale = _ref2$scale === undefined ? defaultScale() : _ref2$scale, + _ref2$mimeType = _ref2.mimeType, + mimeType = _ref2$mimeType === undefined ? 'image/png' : _ref2$mimeType, + _ref2$quality = _ref2.quality, + quality = _ref2$quality === undefined ? 1 : _ref2$quality; + + var multiplier = scale; + + var format = void 0; + if (mimeType == 'image/jpeg') { + format = 'jpeg'; + } else if (mimeType == 'image/png') { + format = 'png'; + } + + return new Promise(function (resolve, reject) { + fabric.loadSVGFromString(svgXml, function (objects, options) { + // If there's something wrong with the SVG, Fabric may return an empty array of objects. Graphviz appears to give us at least one element back even given an empty graph, so we will assume an error in this case. + if (objects.length == 0) { + reject(new Error('Error loading SVG with Fabric')); + } + + var element = document.createElement("canvas"); + element.width = options.width; + element.height = options.height; + + var canvas = new fabric.Canvas(element, { enableRetinaScaling: false }); + var obj = fabric.util.groupSVGElements(objects, options); + canvas.add(obj).renderAll(); + + var image = new Image(); + image.src = canvas.toDataURL({ format: format, multiplier: multiplier, quality: quality }); + image.width = options.width; + image.height = options.height; + + resolve(image); + }); + }); + } + + var Viz = function () { + function Viz() { + var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + workerURL = _ref3.workerURL, + worker = _ref3.worker, + Module = _ref3.Module, + render = _ref3.render; + + classCallCheck(this, Viz); + + if (typeof workerURL !== 'undefined') { + this.wrapper = new WorkerWrapper(new Worker(workerURL)); + } else if (typeof worker !== 'undefined') { + this.wrapper = new WorkerWrapper(worker); + } else if (typeof Module !== 'undefined' && typeof render !== 'undefined') { + this.wrapper = new ModuleWrapper(Module, render); + } else if (typeof Viz.Module !== 'undefined' && typeof Viz.render !== 'undefined') { + this.wrapper = new ModuleWrapper(Viz.Module, Viz.render); + } else { + throw new Error('Must specify workerURL or worker option, Module and render options, or include one of full.render.js or lite.render.js after viz.js.'); + } + } + + createClass(Viz, [{ + key: 'renderString', + value: function renderString(src) { + var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref4$format = _ref4.format, + format = _ref4$format === undefined ? 'svg' : _ref4$format, + _ref4$engine = _ref4.engine, + engine = _ref4$engine === undefined ? 'dot' : _ref4$engine, + _ref4$files = _ref4.files, + files = _ref4$files === undefined ? [] : _ref4$files, + _ref4$images = _ref4.images, + images = _ref4$images === undefined ? [] : _ref4$images, + _ref4$yInvert = _ref4.yInvert, + yInvert = _ref4$yInvert === undefined ? false : _ref4$yInvert, + _ref4$nop = _ref4.nop, + nop = _ref4$nop === undefined ? 0 : _ref4$nop; + + for (var i = 0; i < images.length; i++) { + files.push({ + path: images[i].path, + data: '\n\n' + }); + } + + return this.wrapper.render(src, { format: format, engine: engine, files: files, images: images, yInvert: yInvert, nop: nop }); + } + }, { + key: 'renderSVGElement', + value: function renderSVGElement(src) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + return this.renderString(src, _extends({}, options, { format: 'svg' })).then(function (str) { + var parser = new DOMParser(); + return parser.parseFromString(str, 'image/svg+xml').documentElement; + }); + } + }, { + key: 'renderImageElement', + value: function renderImageElement(src) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var scale = options.scale, + mimeType = options.mimeType, + quality = options.quality; + + + return this.renderString(src, _extends({}, options, { format: 'svg' })).then(function (str) { + if ((typeof fabric === 'undefined' ? 'undefined' : _typeof(fabric)) === "object" && fabric.loadSVGFromString) { + return svgXmlToImageElementFabric(str, { scale: scale, mimeType: mimeType, quality: quality }); + } else { + return svgXmlToImageElement(str, { scale: scale, mimeType: mimeType, quality: quality }); + } + }); + } + }, { + key: 'renderJSONObject', + value: function renderJSONObject(src) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var format = options.format; + + + if (format !== 'json' || format !== 'json0') { + format = 'json'; + } + + return this.renderString(src, _extends({}, options, { format: format })).then(function (str) { + return JSON.parse(str); + }); + } + }]); + return Viz; + }(); + + return Viz; + +}))); diff --git a/assets/js/search/pagination.js b/assets/js/search/pagination.js new file mode 100644 index 0000000000..989151c0e5 --- /dev/null +++ b/assets/js/search/pagination.js @@ -0,0 +1,26 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file contains JavaScript that makes the search boxes work better. +// It causes the entire
  • to be clickable instead of just the link. +// (We do not control the HTML so this is the best option.) +$.when($.ready).then(() => { + $(document).on( + 'click', + '#tipue_search_foot_boxes li:not(.current)', + function () { + $(this).children('a').eq(0).click(); + } + ); +}); diff --git a/assets/js/search/tipuesearch.min.js b/assets/js/search/tipuesearch.min.js new file mode 100644 index 0000000000..e6e80aa162 --- /dev/null +++ b/assets/js/search/tipuesearch.min.js @@ -0,0 +1,178 @@ +(function($){$.fn.tipuesearch=function(options){var set=$.extend({'contentLocation':'tipuesearch/tipuesearch_content.json','contextBuffer':60,'contextLength':60,'contextStart':90,'debug':false,'descriptiveWords':25,'highlightTerms':true,'liveContent':'*','liveDescription':'*','minimumLength':3,'mode':'static','newWindow':false,'show':9,'showContext':true,'showRelated':true,'showTime':true,'showTitleCount':true,'showURL':true,'wholeWords':true},options);return this.each(function(){var tipuesearch_in={pages:[]};$.ajaxSetup({async:false});var tipuesearch_t_c=0;$('#tipue_search_content').hide().html('
    ').show();if(set.mode=='live') +{for(var i=0;i');var t_2=html.toLowerCase().indexOf('',t_1+7);if(t_1!=-1&&t_2!=-1) +{var tit=html.slice(t_1+7,t_2);} +else +{var tit=tipuesearch_string_1;} +tipuesearch_in.pages.push({"title":tit,"text":desc,"tags":cont,"url":tipuesearch_pages[i]});});}} +if(set.mode=='json') +{$.getJSON(set.contentLocation).done(function(json) +{tipuesearch_in=$.extend({},json);});} +if(set.mode=='static') +{tipuesearch_in=$.extend({},tipuesearch);} +var tipue_search_w='';if(set.newWindow) +{tipue_search_w=' target="_blank"';} +function getURLP(name) +{var _locSearch=location.search;var _splitted=(new RegExp('[?|&]'+name+'='+'([^&;]+?)(&|#|;|$)').exec(_locSearch)||[,""]);var searchString=_splitted[1].replace(/\+/g,'%20');try +{searchString=decodeURIComponent(searchString);} +catch(e) +{searchString=unescape(searchString);} +return searchString||null;} +if(getURLP('q')) +{$('#tipue_search_input').val(getURLP('q'));getTipueSearch(0,true);} +$(this).keyup(function(event) +{if(event.keyCode=='13') +{getTipueSearch(0,true);}});function getTipueSearch(start,replace) +{var out='';var show_replace=false;var show_stop=false;var standard=true;var c=0;found=[];var d_o=$('#tipue_search_input').val();var d=d_o.toLowerCase();d=$.trim(d);if((d.match("^\"")&&d.match("\"$"))||(d.match("^'")&&d.match("'$"))) +{standard=false;} +var d_w=d.split(' ');if(standard) +{d='';for(var i=0;i=set.minimumLength) +{if(standard) +{if(replace) +{var d_r=d;for(var i=0;i'+d_r+'
    ';} +if(c==1) +{out+='
    '+tipuesearch_string_4;} +else +{c_c=c.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",");out+='
    '+c_c+' '+tipuesearch_string_5;} +if(set.showTime) +{var endTimer=new Date().getTime();var time=(endTimer-startTimer)/ 1000;out+=' ('+time.toFixed(2)+' '+tipuesearch_string_14+')';set.showTime=false;} +out+='
    ';found.sort(function(a,b){return b.score-a.score});var l_o=0;for(var i=0;i=start&&l_o'+found[i].title+'
    ';if(set.debug) +{out+='
    Score: '+found[i].score+'
    ';} +if(set.showURL) +{var s_u=found[i].url.toLowerCase();if(s_u.indexOf('http://')==0) +{s_u=s_u.slice(7);} +out+='';} +if(found[i].desc) +{var t=found[i].desc;if(set.showContext) +{d_w=d.split(' ');var s_1=found[i].desc.toLowerCase().indexOf(d_w[0]);if(s_1>set.contextStart) +{var t_1=t.substr(s_1-set.contextBuffer);var s_2=t_1.indexOf(' ');t_1=t.substr(s_1-set.contextBuffer+s_2);t_1=$.trim(t_1);if(t_1.length>set.contextLength) +{t='... '+t_1;}}} +if(standard) +{d_w=d.split(' ');for(var f=0;f$1");}}} +else if(set.highlightTerms) +{var patr=new RegExp('('+d+')','gi');t=t.replace(patr,"$1");} +var t_d='';var t_w=t.split(' ');if(t_w.length'+t_d+'';}} +l_o++;} +if(set.showRelated&&standard) +{f=0;for(var i=0;i'+d_o+'';}} +if(c>set.show) +{var pages=Math.ceil(c / set.show);var page=(start / set.show);out+='';}} +else +{out+='
    '+tipuesearch_string_8+'
    ';}} +else +{if(show_stop) +{out+='
    '+tipuesearch_string_8+'. '+tipuesearch_string_9+'
    ';} +else +{out+='
    '+tipuesearch_string_10+'
    ';if(set.minimumLength==1) +{out+='
    '+tipuesearch_string_11+'
    ';} +else +{out+='
    '+tipuesearch_string_12+' '+set.minimumLength+' '+tipuesearch_string_13+'
    ';}}} +$('#tipue_search_content').hide().html(out).slideDown(200);$('#tipue_search_replaced').click(function() +{getTipueSearch(0,false);});$('.tipue_search_related').click(function() +{$('#tipue_search_input').val($(this).attr('id'));getTipueSearch(0,true);});$('.tipue_search_foot_box').click(function() +{var id_v=$(this).attr('id');var id_a=id_v.split('_');getTipueSearch(parseInt(id_a[0]),id_a[1]);});}});};})(jQuery); \ No newline at end of file diff --git a/assets/js/search/tipuesearch_content.js b/assets/js/search/tipuesearch_content.js new file mode 100644 index 0000000000..78ae7c8424 --- /dev/null +++ b/assets/js/search/tipuesearch_content.js @@ -0,0 +1,704 @@ +var tipuesearch = {'pages': [ +{ + 'title': "AIP Purpose and Guidelines", + 'text': "AIP Purpose and Guidelines As the corpus of Google APIs has grown and the API Governance team has grown to meet the demand of supporting them, it is increasingly necessary to have a corpus of documentation for API producers, reviewers, and other interested parties to reference. The API style guide and introductory One Platform documentation are intentionally terse and high-level. The AIP collection offers a method to provide consistent documentation for API design guidance. What is an AIP? AIP stands for API Improvement Proposal, which is a design document providing high-level, concise documentation for API development. They are to serve as the source of truth for API-related documentation at Google and the means by which API teams discuss and come to consensus on API guidance. AIPs are maintained as Markdown files in the AIP GitHub repository. Types of AIPs There are several different types of AIPs, described below. The list of AIP types may evolve over time as necessary. Guidance These AIPs describe guidance on API design. These are provided as instruction for API producers to help write simple, intuitive, and consistent APIs, and are used by API reviewers as a basis for review comments. Process These AIPs describe a process surrounding API design. They often affect the AIP process itself and are used to enhance the way in which AIPs are handled. Stakeholders As with any process there are many different stakeholders when it comes to reviewing and working with AIPs. Below is a summary of the escalation path starting with the API producer. digraph d_front_back { rankdir=BT; ranksep=0.3; node [ style=\"filled,solid\" shape=box fontname=\"Roboto\" ]; producer [ label=\"API Producer\" ]; editors [ label=\"AIP Editors\" ]; tl_infra [ label=\"Infrastructure TL\" ]; tl_design [ label=\"Design TL\" ]; tl [ label=\"TL\" ]; producer -\u003e editors; editors -\u003e tl_infra -\u003e tl; editors -\u003e tl_design -\u003e tl; } As noted in the diagram above, the TL is the final decision-maker on the AIP process and the final point of escalation if necessary. Editors The editors are the set of people who make decisions on AIPs. The general goal is that the AIP process is collaborative and that we largely work on the basis of consensus. However, a limited number of designated approvers is necessary, and these Googlers will be approvers for each AIP in the general scope. The list of AIP editors is currently: Angie Lin (@alin04) Jon Skeet (@jskeet) Jose Juan Zavala Iglesias (@itsStrobe) Louis Dejardin (@loudej) Noah Dietz (@noahdietz) Sam Levenick (@slevenick) Sam Woodard (@shwoodard) The editors are also responsible for the administrative and editorial aspects of shepherding AIPs and managing the AIP pipeline and workflow. They approve PRs to AIPs, assign proposal numbers, manage the agenda, set AIP states, and so forth. They also ensure that AIPs are readable (proper spelling, grammar, sentence structure, markup, etc.). AIP editorship is by invitation of the current editors. Domain-specific AIPs Some AIPs may be specific to a particular domain (for example, only to APIs within a certain PA, or even a certain team). In this situation, the group will be given a particular block of AIPs to use in accordance with AIP-2, and the applicable AIPs will clearly indicate their scope. States At any given time, AIPs may exist in a variety of states as they work their way through the process. The following is a summary of each state. Draft The initial state for an AIP is the \"Draft\" state. This means that the AIP is being discussed and iterated upon, primarily by the original authors. While the editors may get involved at this stage, it is not necessary. Note: If significant, high-level iteration is required, it is recommended to draft AIPs in a Google doc instead of a PR. AIPs that are migrated into the AIP system from Google Docs may skip the draft state and go directly to reviewing provided there is sufficient approval. Reviewing Once discussion on an AIP has generally concluded, but before it is formally accepted it moves to the \"Reviewing\" state. This means that the authors have reached a general consensus on the proposal and the editors are now involved. At this stage the editors may request changes or suggest alternatives to the proposal before moving forward. Note: As a formal matter, one AIP approver (other than the author) must provide formal signoff to advance an AIP to the reviewing state. Additionally, there must not be formal objections (\"changes requested\" on the GitHub PR) from other approvers. Approved Once an approved AIP has been agreed upon, it enters \"approved\" state and is considered \"best current practice\". Note: As a formal matter, two AIP approvers (other than the author) must provide formal signoff to advance an AIP to the approved state. Additionally, there must not be formal objections (\"changes requested\" on the GitHub PR) from other approvers. Withdrawn If an AIP is withdrawn by the author or champion, it enters \"withdrawn\" state. AIPs that are withdrawn may be taken up by another champion. Rejected If an AIP is rejected by the AIP editors, it enters \"rejected\" state. AIPs that are rejected remain, and provide documentation and reference to inform future discussions. Deferred If an AIP has not been acted upon for a significant period of time, the editors may mark it as \"deferred\". Replaced If an AIP has been replaced by another AIP, it enters \"replaced\" state. AIP editors are responsible to provide a notice explaining the replacement and rationale (the replacement AIP should also clearly explain the rationale). In general, API producers should rely primarily on AIPs in the \"approved\" state. Workflow The following workflow describes the process for proposing an AIP, and moving an AIP from proposal to implementation to final acceptance. Overview digraph d_front_back { rankdir=LR; node [ style=\"filled,solid\" shape=box fontname=\"Roboto\" ]; draft [ label=\"Draft\" fillcolor=\"orange\" ]; reviewing [ label=\"Reviewing\" fillcolor=\"lightskyblue\" ]; approved [ label=\"Approved\" fillcolor=\"palegreen\" ]; withdrawn [ label=\"Withdrawn\" fillcolor=\"mistyrose\" ]; rejected [ label=\"Rejected\" fillcolor=\"mistyrose\" ]; deferred [ label=\"Deferred\" fillcolor=\"lightsteelblue\" ]; replaced [ label=\"Replaced\" fillcolor=\"lightsteelblue\" ]; draft -\u003e reviewing; draft -\u003e withdrawn [ style=dashed, color=mistyrose3 ]; draft -\u003e rejected [ style=dashed, color=mistyrose3 ]; reviewing -\u003e approved; reviewing -\u003e withdrawn [ style=dashed, color=mistyrose3 ]; reviewing -\u003e rejected [ style=dashed, color=mistyrose3 ]; draft -\u003e deferred [ style=dashed, color=lightsteelblue3 ]; reviewing -\u003e deferred [ style=dashed, color=lightsteelblue3 ]; approved -\u003e replaced [ style=dashed, color=lightsteelblue3 ]; reviewing -\u003e replaced [ style=dashed, color=lightsteelblue3 ]; } Proposing an AIP In order to propose an AIP, first open an issue to circulate the fundamental idea for initial feedback. It should generally be possible to describe the idea in a couple of pages. When proposing a new AIP or changes to an existing one, it is best to reference prior art and/or example use cases that the proposal will impact, so as to ensure that the proposal is grounded in a realistic problem space. So, proposals should provide concrete references and/or well-defined examples. Appropriate material includes, but is not limited to, the following: Existing external RFCs or standards A corpus of APIs that have aligned on a similar pattern e.g. Search methods A concrete use case that has yet to be solved that exists or could exist in one or more APIs e.g. adding an AIP-202 Format for AIP-143 Unicode CLDR region codes Once ready, create a PR with a new file in the AIP directory using a file titled aip/new.md. Ensure that the PR is editable by maintainers. In most circumstances, the editors will assign the proposal an AIP number and submit the PR with the AIP in the \"Reviewing\" state. The editors may reject an AIP outright if they have an obvious reason to do so (e.g. the proposal was already discussed and rejected in another AIP or is fundamentally unsound), in which case the PR is not merged. Discussing an AIP Once the PR is merged, the AIP author is responsible for championing the AIP on a follow-up approval pull request. This means that the author is responsible for pushing towards consensus around the proposal. This may involve a discussion at the regularly scheduled meetings for the API Governance team. The AIP author may modify the AIP over the course of discussion by submitting follow-up commits to the PR. Accepting an AIP The editors will work together to ensure that qualified proposals do not linger in review. To gain final approval, an AIP must be approved by, at minimum, the TL with responsibility over the domain covered by the AIP (either design or infrastructure) and at least one other editor, with no editors actively requesting changes. Note: If an AIP editor is the primary author of an AIP, then at least two other editors must approve it. Once the AIP is approved, the editors will update the state of the AIP to reflect this and submit the PR. Withdrawing or Rejecting an AIP The author of an AIP may decide, after further consideration, that an AIP should not advance. If so, the author may withdraw the AIP by updating the PR adding a notice of withdrawal with an explanation of the rationale. Additionally, the author may be unable to get consensus among the group and the AIP editors may elect to reject the AIP. In this situation, the AIP editors shall amend the PR adding a notice of rejection with an explanation of the rationale. In both cases, the AIP editors update the state accordingly and submit the PR. Replacing an AIP In rare cases, it may be necessary to replace an AIP with another one. This is not general practice: minor edits to approved AIPs are acceptable, and will be the common way to tweak guidance. However, if new guidance fundamentally alters the old guidance in some way, then the AIP editors shall create a new AIP that, once approved, will replace the old one. The old one then enters \"Replaced\" state, and will link to the new, current AIP. Changelog 2025-01-09: Add requirement to include references/examples in proposals. 2024-09-04: Updated names of current editors and remove TLs. 2023-05-10: Updated names of current and editors and TLs. 2019-07-30: Further clarified AIP quorum requirements. 2019-05-12: Collapsed AIP approvers and editors into a single position, relaxed approval rules from full quorum. 2019-05-04: Updated the AIP to refer to GitHub processes, rather than internal processes.", + 'tags': '', + 'url': '/1', + }, +{ + 'title': "AIP Numbering", + 'text': "AIP Numbering The AIP system provides a mechanism to index and have a single source of truth for API Improvement Proposals, as well as iterate on them collaboratively and transparently. This document describes the AIP numbering system. Assigning AIP Numbers The AIP editors (see AIP-1) are responsible for assigning a number to each AIP when it is accepted as a draft for review. Importantly, all AIPs have numbers, not just approved ones. The AIP Index clearly delineates which AIPs are approved and binding and which are under discussion. The editors may decide to reserve a specific block of numbers for groups of AIPs that are related in some way (for example, that are only scoped to a specific subset of APIs). Beyond this, AIP numbers are assigned arbitrarily. In general, the editors will take the next AIP number off of the stack to assign to a draft AIP, but occasionally may use a special/joke number if useful for mnemonic or other reasons. AIP Blocks Currently recognized blocks of AIP numbers are: Generally Applicable 1-99: Reserved for meta-AIPs (generally process-related). 100-999: General API design guidance Google Product Areas 2700-2799: Apps (Google Workspace) 2500-2599: Cloud 3000-3099: Actions on Google 3200-3299: Firebase 4100-4199: Auth libraries 4200-4299: Client libraries 4600-4699: Geo To request a block for a specific team that is publishing API guidance or documentation germane to that specific team, reach out to api-editors@. Changelog 2019-10-03: The 3000-3099 block was assigned to Actions on Google. 2019-01-26: The general API design guidance block was expanded to include 100-199. 2018-10-24: The 4600-4699 block was assigned to Google Geo. 2018-10-02: The 2500-2599 block was assigned to Google Cloud Platform. 2018-10-02: The 2700-2799 block was assigned to Google Workspace.", + 'tags': '', + 'url': '/2', + }, +{ + 'title': "AIP Versioning", + 'text': "AIP Versioning This AIP defines the versioning scheme of the AIPs. Guidance The AIPs must be versioned by date, using the ISO-8601 format of YYYY-MM-DD, that corresponds to the date the version was added. AIPs versions must be available as a tag on the source control system used to store the AIPs, of the format v{version}. Example: v2023-03-28. The AIPs must have a new version when there is a significant change to one or more AIPs. Each AIP must include a changelog section, with the date the change was made and a short description. Rationale Versions serve as reference points to AIPs at a specific point in time. They are crucial since guidance on an AIP can be reversed, or include significant changes such that they are no longer similar to the original design. APIs using AIPs may need to reference older AIP guidance to justify their design choice. Rationale for date-based versioning With date-based versioning, a client can easily find the AIP guidance at the time an API was authored. Why not individually versioned AIPs An alternative to a universal version is to have specific versions attached to each AIP. AIPs often cross-reference one another. If each AIP had a specific version, then cross-references would also have to specify specific versions of those referenced AIPs to provide complete guidance.", + 'tags': '', + 'url': '/3', + }, +{ + 'title': "AIP Style and Guidance", + 'text': "AIP Style and Guidance AIP stands for API Improvement Proposal, which is a design document providing high-level, concise documentation for API design and development. The goal is for these documents to serve as the source of truth for API-related documentation at Google and the way API teams discuss and come to consensus on API guidance. AIPs are most useful when they are clear and concise, and cover a single topic or inquiry well. In the same way that AIPs describe consistent patterns and style for use in APIs, they also follow consistent patterns and style. Guidance AIPs must cover a single, discrete topic, and provide clear, actionable guidance. AIPs must not duplicate or contradict guidance in another AIP. AIPs may also cover what not to do, but should not cover only anti-patterns. If AIP guidance is conditional (e.g. a design pattern such as Jobs), the guidance must clearly explain under what conditions the guidance should be followed. Guidance contained within an AIP must be beneficial to one or more types of clients or their authors, including but not limited to: Asset inventories which can be used to audit and analyze resources. Command line interfaces for exploration and simple automation. Custom controllers (e.g. auto-scalers) which poll live state and adjust resource configuration accordingly. IaC clients for orchestration and automation of multiple resources. Recommendation tools which provide guidance on which APIs are useful for specific use cases, and how to use them. SDKs to interact with an API from a programming language, often used heavily for data-plane operations. Security orchestration, automation, and remediation tools. Simple scripts to automate or orchestrate tasks. Test frameworks. Tools that operate on resource data at rest. Visual User Interfaces for visualization and one-off manual actions. Users. Examples of improvements include: Requiring new proto annotations that enable more descriptive interfaces on clients (e.g. requiring singular and plural on a google.api.resource annotation). AIP guidance must not be a significant detriment to a client\u0027s usability or implementation difficulty, or maintenance difficulty. Examples of detriments include: Introduction of a non-uniform pattern in a standard method such that all clients must introduce additional code without sufficient benefit (e.g. List behaves like this except for resources that start with the name Foo). Renames of well-established fields for minor improvements in readability (e.g. rename expire_time to lapse_time since lapse is a common term in my service). While the length of AIPs will necessarily vary based on the complexity of the question, most AIPs should be able to cover their content in roughly two printed pages. File structure AIPs must be written in Markdown, and must be named using their four-digit number (example: 0008.md). AIPs that serve a specific scope must be in the subdirectory for that scope. AIPs must have appropriate front matter. --- id: 8 state: reviewing created: 2019-05-28 permalink: /8 redirect_from: - /08 - /008 - /0008 --- Front matter for AIPs must include: The aip key: id: Required. The ID for the given AIP, as an integer. state: Required. The current state of the AIP, in all lower-case. The valid states are listed in AIP-1, and common states are draft, reviewing, and approved. created: Required. The ISO-8601 date (yyyy-mm-dd) when the AIP was originally drafted, with no quotes. updated: The ISO-8601 date (yyyy-mm-dd) when the AIP was last revised. scope: The scope for the AIP. This must match the directory name for that scope. Required for AIPs with IDs \u003e= 1000, prohibited otherwise. The permalink key (required): This must be set to /{aip.scope}/{aip.id}. If there is no scope, use /{aip.id} instead. The redirect_from key: This should include a list of any /{aip.id} permutations that a reader would be likely to enter, including: /{aip.id} (for AIPs where the permalink includes the scope) AIP IDs with zero-padding, for each level of zero-padding up to four digits (for example: /08, /008, /0008). Document structure AIPs must begin with a top-level heading with the AIP\u0027s title (# Title). The title should be a noun (not an imperative). For example, \"Bad API precedents\" not \"Avoid breaking API precedent\". AIPs should then begin with an introduction (with no additional heading), followed by a ## Guidance heading. If necessary, the AIP may include any of the following after the guidance, in the following order: \"Further reading\" is a bulleted list of links to other AIPs that are useful to fully understand the current AIP. \"Appendices\" covering further explanation in the same AIP. These are relatively rare but are important in cases where an AIP requires a lot of justification for the decision. Often this is primarily an explanation of alternatives considered to help explain the guidance. \"Changelog\" is a bulleted list of changes made to the AIP since the first writing. The guidance section may include subsections that elaborate further on details. Subsections will automatically create an entry in the table of contents, and an anchor for citations. Below is an example AIP shell that uses each major section: # AIP title The introductory text explains the background and reason why the AIP exists. It lays out the basic question, but does not tell the reader what to do. ## Guidance The \"guidance\" section helps the reader know what to do. A common format for the guidance section is a high-level imperative, followed by an example, followed by a bulleted list explaining the example. ### Subsection Individual subsections can be cited individually, and further elaborate details. ## Rationale The \"rationale\" section is optional, and helps the reader understand the motivation behind specific guidance within the AIP. Deeper explanations of design justification and tradeoffs **must** be in the rationale instead of other sections, to ensure the rest of the document acts as an easily actionable reference. ## History The \"history\" section is optional, and documents events and context around a significant edit to an AIP. For example, explanation of rewrite would be included in this section While the changelog is a dotted list of one-line summaries of changes to an AIP, the history section should elaborate on significant events in a descriptive format. The section **must not** be used to exhaustively enumerate all changes. This is what the changelog provides. ## Further reading A bulleted list of (usually) other AIPs, in the following format: - [AIP-1](/1): AIP purpose and guidelines ## Changelog A bulleted list of changes in reverse chronological order, using the following format: - **2020-02-18**: Specified ordering. - **2019-07-01**: Added a subsection clarifying XYZ. AIPs should attempt to follow this overall format if possible, but AIPs may deviate from it if necessary (in particular, if the AIP would be more difficult to understand, even for a reader already accustomed to reading AIPs in the usual format). Note: Except for the title, AIPs must only use the second heading level (##) and above. AIPs should only use the second and third heading levels (##, ###). Requirement keywords AIPs should use the following requirement level keywords: \"MUST\", \"MUST NOT\", \"SHOULD\", \"SHOULD NOT\", and \"MAY\", which are to be interpreted as described in RFC 2119. When using these terms in AIPs, they must be lower-case and bold. These terms should not be used in other ways. If \"SHOULD\" or \"SHOULD NOT\" are used, they must include valid examples of where other concerns may override the guidance. Important: If rationale is used, it exists to provide background and a more complete understanding, but must not contain guidance (and RFC-2119 terms must not be used). Code examples API design examples in AIPs should use protocol buffers. Examples should cover only enough syntax to explain the concept. When using RPCs in examples, a google.api.http annotation should be included. Referencing AIPs When AIPs reference other AIPs, the prosaic text must use the format AIP-XXXX without zero-padding (e.g., [AIP-8](/8), not AIP-0008), and must link to the relevant AIP. AIP links may point to a particular section of the AIP if appropriate. Important: AIP links must use the relative path to the file in the repository (such as /8 for core AIPs, or /8 for AIPs in a subdirectory); this ensures that the link works both on the AIP site, when viewing the Markdown file on GitHub, using the local development server, or a branch. Rationale Designing for a broad set of clients API guidance, similar to any software, is most beneficial when there is a clear purpose and target beneficiary. The beneficiaries of improved API design are users. These users interact with APIs via a variety of clients, depending on their use case as enumerated above. API guidance must in turn consider the impact broadly across these clients. Changelog 2023-05-20: Increase API guidance scope to include broad set of clients. 2023-03-30: Removed appendix, added rationale and history to the template. 2020-02-18: Specified reverse chronological ordering for changelog items. 2019-08-23: Added guidance for internal AIP links.", + 'tags': '', + 'url': '/8', + }, +{ + 'title': "Glossary", + 'text': "Glossary In the name of brevity, this AIP defines some common terminology here rather than in each AIP individually. Guidance The following terminology should be used consistently throughout AIPs. API Application programming interface. This can be a local interface (such as a client library) or a Network API (defined below). API backend A set of servers and related infrastructure that implements the business logic for an API service. An individual API backend server is often called an API server. API consumer The entity that consumes an API service. For Google APIs, it typically is a Google project that owns the client application or the server resource. API definition The definition of an API, usually defined in a Protocol Buffer service. An API definition can be implemented by any number of API services. API frontend A set of servers plus related infrastructure that provides common functionality across API services, such as load balancing and authentication. An individual API frontend server is often called an API proxy. Note: the API frontend and the API backend may run next to each other or far away from each other. In some cases, they can be compiled into a single application binary and run inside a single process. API interface The element of an API specification IDL that groups API methods, such as a Protocol Buffers service definition. It is typically mapped to a similar high level grouping mechanism in most programming languages, like a class or interface. API method An individual operation within an API. It is typically represented in Protocol Buffers by an rpc definition, and is mapped to a function in the API in most programming languages. API producer The entity that produces an API service. For Google APIs, it typically is a Google team responsible for the API service. API product An API service and its related components, such as Terms of Service, documentation, client libraries, and service support, are collectively presented to customers as a API product. For example, Google Calendar API. Note: people sometimes refer to an API product simply as an API. API service A deployed implementation of one or more APIs, exposed on one or more network addresses, such as the Cloud Pub/Sub API. API service definition The combination of API definitions (.proto files) and API service configurations (.yaml files) used to define an API service. The schema for Google API service definition is google.api.Service. API service endpoint Refers to a network address that an API service uses to handle incoming API requests. One API service may have multiple API service endpoints, such as https://pubsub.googleapis.com and https://content-pubsub.googleapis.com. API service name Refers to the logical identifier of an API service. Google APIs use RFC 1035 DNS compatible names as their API service names, such as pubsub.googleapis.com. API title Refers to the user-facing product title of an API service, such as \"Cloud Pub/Sub API\". API request A single invocation of an API method. It is often used as the unit for billing, logging, monitoring, and rate limiting. API version The version of an API or a group of APIs if they are defined together. An API version is often represented by a string, such as \"v1\", and presents in API requests and Protocol Buffers package names. Client Clients are programs that perform a specific tasks by calling an API or generic tools, such as CLIs, that expose the API in a user-accessible fashion or operate on resource data at rest. Examples of clients include the following: Command line interfaces Libraries, such as an SDK for a particular programming language Scripts that operates on a JSON representation of a resource after reading it from an API Tools, such as a Declarative clients Visual UIs, such as a web application Google API A Network API exposed by a Google service. Most of these are hosted on the googleapis.com domain. It does not include other types of APIs, such as client libraries and SDKs. Declarative Clients Declarative Clients, also known as Infrastructure as Code (IaC), describes a category of clients that consumes a markup language or code that represents resources exposed by an API, and executes the appropriate imperative actions to drive the resource to that desired state. To determine what changes to make and if a set of updates was successful a declarative client compares server side resource attributes with client defined values. The comparison feature ensures accuracy of a creation or an update but it requires services to treat the client set fields as read-only and diligently preserve those values. Examples of complexities that declarative clients abstract away include: Determining the appropriate imperative action (create / update / delete) to achieve desired state. Ordering of these imperative actions. Terraform is an example of such a client. User A human being which is using an API directly, such as with cURL. This term is defined to differentiate usage in the AIPs between a human user and a programmatic client. Network API An API that operates across a network of computers. Network APIs communicate using network protocols including HTTP, and are frequently produced by organizations separate from those that consume them. Changelog 2025-08-13: Add API inteface entry 2024-12-18: Downcase headings and terms as per dev docs style 2024-10-23: Add API Title entry 2023-07-24: Rename IaC to Declarative Clients 2023-04-01: Adding definition of IaC 2023-03-24: Reformatting content to include anchor links.", + 'tags': '', + 'url': '/9', + }, +{ + 'title': "API Design Review FAQ", + 'text': "API Design Review FAQ API design review exists to ensure a simple, intuitive, and consistent API experience throughout our API corpus. Do I need API design approval? TL;DR: You usually need API design approval if you are launching an API that users can code against (either now or in the future) at the beta or GA quality level. API design review is fundamentally about ensuring we provide a simple and consistent experience for our users, and therefore is only expected for APIs that users code directly against. The following flowchart illustrates whether or not your API needs to go through the design review process: digraph { node [ style=\"filled,solid\" shape=box fontname=\"Roboto\" ]; graph [ splines=ortho, nodesep=0.2 ]; audience [ label=\"Who should code directly\\nagainst this API?\" shape=diamond fillcolor=bisque ]; subgraph audience_responses { rank = \"same\"; node [ shape=oval fillcolor=orange ]; googlers [ label=\"Googlers\\nOnly\" fillcolor=lightcoral ]; public [ label=\"Anyone\" fillcolor=limegreen ]; partners [ label=\"Partners\\nOnly\" fillcolor=deepskyblue ]; partners -\u003e public -\u003e googlers [ style=invisible arrowhead=none ]; } subgraph and_ever { rank = \"same\"; node [ shape=diamond fillcolor=bisque ]; forever_partners [ label=\"Forever?\" shape=diamond fillcolor=bisque ]; forever_googlers [ label=\"Forever?\" shape=diamond fillcolor=bisque ]; } subgraph forever_responses { rank = \"same\"; node [ shape=oval fillcolor=orange ]; forever_partners_yes [ label=\"Yes\" fillcolor=deepskyblue ]; forever_no [ label=\"No, anyone\\neventually\" fillcolor=limegreen ]; forever_googlers_yes [ label=\"Yes\" fillcolor=lightcoral ]; } release_level [ label=\"What release\\nlevel?\" shape=diamond fillcolor=bisque ]; # Not required is not in the subgraph with the other outcomes because # it makes the graph much smaller if it can be higher in the image. subgraph release_levels { rank = \"same\"; node [ shape=oval ]; alpha [ label=\"Alpha\" fillcolor=darkorange ]; beta [ label=\"Beta\" fillcolor=goldenrod1 ]; ga [ label=\"GA\" fillcolor=limegreen ]; alpha -\u003e beta -\u003e ga [ style=invisible arrowhead=none ]; } changes [ label=\"Any changes\\nfrom beta?\" shape=diamond fillcolor=bisque ]; subgraph changes_bool { rank = \"same\"; node [ shape=oval ]; changes_yes [ label=\"Yes\" fillcolor=goldenrod1 ]; changes_no [ label=\"No\" fillcolor=limegreen ]; } subgraph outcome { rank = \"same\"; node [ style=\"rounded,filled\" ]; fyi [ label=\"FYI\" fillcolor=lightblue ]; recommended [ label=\"Recommended\" fillcolor=limegreen ]; required [ label=\"\u26a0 Required\" fillcolor=goldenrod1 ]; not_required [ label=\"Not Required\" fillcolor=lightgrey style=\"rounded,filled\" ]; recommended -\u003e required -\u003e fyi -\u003e not_required [style=invisible arrowhead=none]; } audience -\u003e googlers [ arrowhead=none style=dashed color=grey ]; audience -\u003e partners [ arrowhead=none ]; audience -\u003e public [ arrowhead=none ]; partners -\u003e forever_partners; googlers -\u003e forever_googlers [ style=dashed color=grey ]; public -\u003e release_level; forever_partners -\u003e forever_partners_yes [ arrowhead=none ]; forever_googlers -\u003e forever_googlers_yes [ arrowhead=none style=dashed color=grey ]; forever_partners -\u003e forever_no [ arrowhead=none ]; forever_googlers -\u003e forever_no [ arrowhead=none ]; forever_partners_yes -\u003e recommended; forever_googlers_yes -\u003e not_required [ style=dashed color=grey ]; forever_no -\u003e release_level; release_level -\u003e alpha [ arrowhead=none ]; release_level -\u003e beta [ arrowhead=none ]; release_level -\u003e ga [ arrowhead=none ]; alpha -\u003e recommended; beta -\u003e required; ga -\u003e changes; changes -\u003e changes_yes [ arrowhead=none ]; changes -\u003e changes_no [ arrowhead=none ]; changes_yes -\u003e required; changes_no -\u003e fyi; } Who should code directly against it? One of the more complex questions is, \"Who should code directly against this API?\" API design review is primarily concerned about the API\u0027s audience. This means we care about who is permitted to write their own HTTP/gRPC calls against the service, and who is able to see the documentation. (We do not care about questions such as whether the service is exposed on the public network.) Design review is expected if the general public is intended to read documentation and write code that interacts with the service. The following situations do not require design review: An API which will only ever be used by Googlers, or internal tools (for example, Pantheon). An API which will only ever be called by an executable program released by Google (even if the API could be reverse-engineered from the executable). An API which will only ever be called by a single customer or small set of customers under contract, and which will never be made more widely available. (Design review is still recommended in this case, but not required.) Alpha For alpha, API design review is optional but recommended. It may often make sense to endeavor to get initial feedback from customers quickly, and launching an alpha can be a way of gaining data to determine the best answer to some usability questions; therefore, bypassing review may be expedient. On the other hand, launching an alpha requires building an implementation which then takes engineering effort to update if the API design review at the beta stage raises concerns. Because API design review can precede implementation work, we recommend a design review for alpha. Why is design review important? TL;DR: Product excellence. Our design review process exists to ensure that the APIs that we present to customers are simple, intuitive, and consistent. Your reviewer approaches your API from the standpoint of a na\u00efve user, thinks through the resources and actions that your API provides, and attempts to make the surface as accessible and extensible as possible. Your design reviewer is not only evaluating your API, but also checking to ensure that your API is consistent with Google\u0027s existing corpus of APIs. Many customers use multiple APIs, and therefore it is important that our conventions and naming choices line up with customer expectations. What should I expect? How long does the review process take? Reviewers make an effort to keep up with their assigned reviews and offer feedback frequently, so as not to cause unnecessary delay, but it\u0027s generally best to begin the review process early in case there are delays. The design review process varies based on the size and complexity of the underlying API surface: Incremental changes to existing APIs generally take a few days. Small APIs usually take around a week. Entirely new APIs with large surfaces tend to take no less than a week. In cases with extraordinarily large surfaces (e.g., Cloud AutoML), reviews may take a month or more to go through design review. How do reviewers approach my API? API reviewers seek to approach your API the same way that your users will, by focusing primarily on the API surface and its user-facing documentation. In an ideal world, your API reviewer will ask the types of design questions that users will ask (and nudge the API toward raising fewer of those questions in the first place). What is precedent? In general, we want Google APIs to be as consistent as possible. Once customers learn their first Google API, it should be easier to learn the second (and then the third, and so on) because we are using the same patterns consistently. We refer to precedent to mean decisions that have already been made by previous APIs, which generally should be binding upon newer APIs in similar situations. The most common example of this is naming: we have a list of standard fields that dictate how we use common terms like name, create_time, and so forth, and which also dictates that we always attach the same name to the same concept. Precedent also applies to patterns. All APIs should implement pagination the same way. Ditto for long-running operations, import and export, and so on. Once a pattern has been established, we seek to implement that pattern the same way wherever it is germane. What should I do? ...if I have a launch on a tight deadline? The best thing that you can do is to engage design review as early as possible. Additionally, make your reviewers aware of your timeline so that they are aware, and can endeavor to provide you the best possible service. We want you to make your deadline if at all possible. For time-sensitive alpha launches, an API may launch without receiving design review approval. Such launches must be limited to a known set of users. In this case, the reviewers will provide notes for the API team to take under consideration for subsequent stages. Warning: Launching an API in alpha with an incomplete design review does not enshrine that API\u0027s decisions. Design review will be required to promote the API to beta, and API reviewers will block your beta launch if there are issues. For launch stages after alpha, the API design review is mandatory due to its impact on user experience across the board. Your team\u0027s inconsistencies affect more than just your team. In some cases, there is a difficult choice to be made between product excellence and either engineering effort or deadlines. These are difficult business decisions and we understand that they are sometimes necessary; however, a director or VP must make an explicit choice to put these other concerns ahead of product excellence when choosing to bypass design review or disregard reviewers\u0027 feedback. ...to make my review go faster? A few tips: Begin API review as early as possible, and follow up frequently. Run the API linter beforehand. (If you are disabling the linter at any point, explain why. Reviewers often find that the linter is disabled because it did its job.) Ensure that every message, RPC, and field is usefully commented. Comments should be in valid American English and say something meaningful. If your API reviewer asks you to explain something, add the explanation in the proto comments, rather than the code review conversation. This will very often save you a round trip. ...if one of my API reviewers is unresponsive? Reach out to the reviewer on Chat. If that fails, reach out to the other reviewer, who will coordinate accordingly. If that fails also, escalate according to AIP-1. ...if I have a design question? The first places to look at the API style guide, the AIP index, and other public APIs within Google. Other public APIs are particularly valuable; it is common that someone has encountered a situation that is germane to your question. ...if I have a question not covered there? Reach out to api-design@google.com with your question. This generally works best when you are seeking guidance on a specific question related to API design, and when you clearly explain your use case and provide examples. Note: The membership of this list comprises almost exclusively volunteers, who spend the majority of their time doing something else. We do our best to be responsive, but please be patient with us. ...if a question is complex and languishing in a CL? While the code review interface is the best way to resolve questions when practical, sometimes there are issues that are sufficiently complicated that working them out in the code review tool is not feasible. In this situation, reach out to your reviewers and ask to schedule a meeting. In general, most issues can be discussed in 30 minutes. When this happens, make sure that someone documents what is discussed in the CL, so that the history is preserved. ...if my API needs to violate a standard? Clearly document (using an internal comment in the proto) that you are violating an API design guideline and your rationale for doing so. This comment must be prefixed with aip.dev/not-precedent. In general, your rationale for the design guideline violation should be in accordance with one of the enumerated reasons listed in AIP-200. If it is not, work together with your API reviewer to determine the right thing to do. ...if a reviewer is bringing up a previously-settled issue? If you have a different reviewer from your API\u0027s previous stages, this might happen. In general, the best approach is simply to reference the code review where the issue was decided. Reviewers want to avoid causing you churn, and therefore usually give deference to previous reviews. This is usually sufficient to resolve the question promptly. Occasionally, the reviewer may believe that the previous reviewer made a significant mistake, and that correcting it is important. In this case, you and your reviewer should work together to determine the best course of action. ...if the team and the reviewers strongly disagree? Escalate according to AIP-1. Does my PA or team have any particular guidelines? The Cloud PA has specific guidelines to ensure additional uniformity across Cloud, and Cloud APIs have their own reviewer pool. Other teams may adopt similar (but not necessarily identical) rules and systems. Some teams that produce multiple APIs (for example, machine learning) may also have guidelines that apply to that group of APIs. In all cases, we endeavor to make these guidelines available as AIPs; the higher AIP numbers are reserved for specific PA and team use (see AIP-2), and these AIPs are listed in the AIP index.", + 'tags': '', + 'url': '/100', + }, +{ + 'title': "Planes", + 'text': "Planes Resources and methods on an API can be divided into the plane that they reside or perform operations upon. For the context of APIs, the following planes are defined: Management plane: a uniform, resource-oriented API that primarily configures and allows retrieval of resources. Data plane: a heterogenous API (ideally resource-oriented) that reads and write user data. Often connects to entities provisioned by the management plane, such as virtual machines. The term \"plane\" was originally used in networking architecture. Although system and network architecture often defines additional planes (e.g. control plane or power planes), as the AIPs are focused on the interface, they are not defined in this AIP. Guidance Management Plane Management resources and methods exist primarily to provision, configure, and audit the resources that the data plane interfaces with. As an example, the following are considered management resources for a cloud provider: virtual machines virtual private networks virtual disks a blob store instance a project or account Data Plane Methods on the data plane operate on user data in a variety of data formats, and generally interface with a resource provisioned via a management plane API. Examples of data plane methods include: writing and reading rows in a table pushing to or pulling from a message queue uploading blobs to or downloading blobs from a blob store instance Data plane APIs may be heterogenous across a larger API surface, due to requirements including high throughput, low latency, or the need to adhere to an existing interface specification (e.g. ANSI SQL). For convenience, resources and methods that operate on the data plane may expose themselves via resource-oriented management APIs. If so, those resources and methods must adhere to the requirements of the management plane as specified in the other AIPs (AIP-131 through AIP-135). Major distinctions between management and data plane Declarative clients operate on the management plane exclusively. Data planes are often on the critical path of user-facing functionality, and therefore: Have higher availability requirements than management planes. Are more performance-sensitive than management planes. Require higher-throughput than management planes. Changelog 2023-06-10: Introduction of this AIP.", + 'tags': '', + 'url': '/111', + }, +{ + 'title': "Resource-oriented design", + 'text': "Resource-oriented design Resource-oriented design is a pattern for specifying RPC APIs, based on several high-level design principles (most of which are common to recent public HTTP APIs): The fundamental building blocks of an API are individually-named resources (nouns) and the relationships and hierarchy that exist between them. A small number of standard methods (verbs) provide the semantics for most common operations. However, custom methods are available in situations where the standard methods do not fit. Stateless protocol: Each interaction between the client and the server is independent, and both the client and server have clear roles. Readers might notice similarities between these principles and some principles of REST; resource-oriented design borrows many principles from REST, while also defining its own patterns where appropriate. Guidance When designing an API, consider the following (roughly in logical order): The resources (nouns) the API will provide The relationships and hierarchies between those resources The schema of each resource The methods (verbs) each resource provides, relying as much as possible on the standard verbs. Resources A resource-oriented API should generally be modeled as a resource hierarchy, where each node is either a simple resource or a collection of resources. A collection contains resources of the same type. For example, a publisher has the collection of books that it publishes. A resource usually has fields, and resources may have any number of sub-resources (usually collections). Note: While there is some conceptual alignment between storage systems and APIs, a service with a resource-oriented API is not necessarily a database, and has enormous flexibility in how it interprets resources and methods. API designers should not expect that their API will be reflective of their database schema. In fact, having an API that is identical to the underlying database schema is actually an anti-pattern, as it tightly couples the surface to the underlying system. Methods Resource-oriented APIs emphasize resources (data model) over the methods performed on those resources (functionality). A typical resource-oriented API exposes a large number of resources with a small number of methods on each resource. The methods can be either the standard methods (Get, List, Create, Update, Delete), or custom methods. If the request to or the response from a standard method (or a custom method in the same service) is the resource or contains the resource, the resource schema for that resource across all methods must be the same. Standard method Request Response Create Contains the resource Is the resource Get None Is the resource Update Contains the resource Is the resource Delete None None List None Contains the resources The table above describes each standard method\u0027s relationship to the resource, where \"None\" indicates that the resource neither is nor is contained in the request or the response A resource must support at minimum Get: clients must be able to validate the state of resources after performing a mutation such as Create, Update, or Delete. A resource must also support List, except for singleton resources where more than one resource is not possible. Note: A custom method in resource-oriented design does not entail defining a new or custom HTTP verb. Custom methods use traditional HTTP verbs (usually POST) and define the custom verb in the URI. APIs should prefer standard methods over custom methods; the purpose of custom methods is to define functionality that does not cleanly map to any of the standard methods. Custom methods offer the same design freedom as traditional RPC APIs, which can be used to implement common programming patterns, such as database transactions, import and export, or data analysis. Strong Consistency For methods that operate on the management plane, the completion of those operations (either successful or with an error, long-running operation, or synchronous) must mean that the state of the resource\u0027s existence and all user-settable values have reached a steady-state. Output only values unrelated to the resource state should also have reached a steady-state for values that are related to the resource state. Examples include: Following a successful create that is the latest mutation on a resource, a get request for a resource must return the resource. Following a successful update that is the latest mutation on a resource, a get request for a resource must return the final values from the update request. Following a successful delete that is the latest mutation on a resource, a get request for a resource must return NOT_FOUND (or the resource with the DELETED state value in the case of soft delete) Clients of resource-oriented APIs often need to orchestrate multiple operations in sequence (e.g. create resource A, create resource B which depends on A), and ensuring that resources immediately reflect steady user state after an operation is complete ensures clients can rely on method completion as a signal to begin the next operation. Output only fields ideally would follow the same guidelines, but as these fields can often represent a resource\u0027s live state, it\u0027s sometimes necessary for these values to change after a successful mutation operation to reflect a state change. Stateless protocol As with most public APIs available today, resource-oriented APIs must operate over a stateless protocol: The fundamental behavior of any individual request is independent of other requests made by the caller. This is to say, each request happens in isolation of other requests made by that client or another, and resources exposed by an API are directly addressable without needing to apply a series of specific requests to \"reach\" the desired resource. In an API with a stateless protocol, the server has the responsibility for persisting data, which may be shared between multiple clients, while clients have sole responsibility and authority for maintaining the application state. Cyclic References The relationship between resources, such as with resource references, must be representable via a directed acyclic graph. The parent-child relationship also must be acyclic, and as per AIP-124 a given resource instance will only have one canonical parent resource. A cyclic relationship between resources increases the complexity of managing resources. Consider resources A and B that refer to each other. The process to create said resources are: create resource A without a reference to B. Retrieve id for resource A. create resource B with a reference to A. Retrieve id for resource B. update resource A with the reference to B. The delete operation may also become more complex, due to reasoning about which resource must be dereferenced first for a successful deletion. This requirement does not apply to relationships that are expressed via output only fields, as they do not require the user to specify the values and in turn do not increase resource management complexity. Changelog 2024-07-08: Clarify acyclic nature of parent-child relationship. 2023-08-24: Added guidance on consistency guarantees of methods. 2023-07-23: Clarify stateless protocol definition. 2023-01-21: Explicitly require matching schema across standard methods. 2022-12-19: Added a section requiring Get and List. 2022-11-02: Added a section restricting resource references. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/121', + }, +{ + 'title': "Resource names", + 'text': "Resource names Most APIs expose resources (their primary nouns) which users are able to create, retrieve, and manipulate. Additionally, resources are named: each resource has a unique identifier that users use to reference that resource, and these names are what users should store as the canonical names for the resources. Guidance All resource names defined by an API must be unique within that API. (See the section on full resource names below for more information on referring to resources across APIs.) Resource names are formatted according to the URI path schema, but without the leading slash: publishers/123/books/les-miserables users/vhugo1802 Resource name components should usually alternate between collection identifiers (example: publishers, books, users) and resource IDs (example: 123, les-miserables, vhugo1802). Resource names must use the / character to separate individual segments of the resource name. Non-terminal segments of a resource name must not contain a / character. The terminal segment of a resource name should not contain a / character. Resource names should only use characters available in DNS names, as defined by RFC-1123. Additionally, resource IDs should not use upper-case letters. If additional characters are necessary, resource names should not use characters that require URL-escaping, or characters outside of ASCII. If Unicode characters can not be avoided, resource names must be stored in Normalization Form C (see AIP-210). Resources must expose a name field that contains its resource name. Resources may provide the resource ID as a separate field (e.g. book_id). This field must apply the OUTPUT_ONLY field behavior classification. Resources may expose a separate, system-generated unique ID field (uid). This field must apply the OUTPUT_ONLY field behavior classification. Resources must not expose tuples, self-links, or other forms of resource identification. All ID fields should be strings. Note: Resource names as described here are used within the scope of a single API (or else in situations where the owning API is clear from the context), and are only required to be unique within that scope. For this reason, they are sometimes called relative resource names to distinguish them from full resource names (discussed below). Collection identifiers The collection identifier segments in a resource name must be the plural form of the noun used for the resource. (For example, a collection of Publisher resources is called publishers in the resource name.) Collection identifiers must be concise American English terms. Collection identifiers must be in camelCase. Collection identifiers must begin with a lower-cased letter and contain only ASCII letters and numbers (/[a-z][a-zA-Z0-9]*/). Collection identifiers must be plural. In situations where there is no plural word (\"info\"), or where the singular and plural terms are the same (\"moose\"), the non-pluralized (singular) form is correct. Collection segments must not \"coin\" words by adding \"s\" in such cases (e.g, avoid \"infos\"). Within any given single resource name, collection identifiers must be unique. (e.g. people/xyz/people/abc is invalid) Nested collections If a resource name contains multiple levels of a hierarchy, and a parent collection\u0027s name is used as a prefix for the child resource\u0027s name, the child collection\u0027s name may omit the prefix. For example, given a collection of UserEvent resources that would normally be nested underneath users: users/vhugo1802/userEvents/birthday-dinner-226 An API should use the less-redundant form: users/vhugo1802/events/birthday-dinner-226 In this situation, the message and resource type are still called UserEvent; only the collection and resource identifiers in the pattern(s) are shortened. Since the resource type is not shortened, the singular and plural are similarly not shortened. message UserEvent { option (google.api.resource) = { type: \"example.googleapis.com/UserEvent\" // Only the collection \u0026 resource identfiers in the `pattern` are shortened. pattern: \"projects/{project}/users/{user}/events/{event}\" singular: \"userEvent\" plural: \"userEvents\" }; string name = 1; } Note: APIs wishing to do this must follow this format consistently throughout all of its pattern entries defined and anywhere else the resource is referenced in the API, or else not at all. Resource ID segments A resource ID segment identifies the resource within its parent collection. In the resource name publishers/123/books/les-miserables, 123 is the resource ID for the publisher, and les-miserables is the resource ID for the book. If resource IDs are user-specified, the API must document allowed formats. User-specified resource IDs should conform to RFC-1034; which restricts to letters, numbers, and hyphen, with the first character a letter, the last a letter or a number, and a 63 character maximum. Additionally, user-specified resource IDs should restrict letters to lower-case (^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$). Characters outside of ASCII should not be permitted; however, if Unicode characters are necessary, APIs must follow guidance in AIP-210. If resource IDs are not user-settable, the API should document the basic format, and any upper boundaries (for example, \"at most 63 characters\"). For more information, see the create standard method. Resource ID aliases It is sometimes valuable to provide an alias for common lookup patterns for resource IDs. For example, an API with users at the top of its resource hierarchy may wish to provide users/me as a shortcut for retrieving information for the authenticated user. APIs may provide programmatic aliases for common lookup patterns. However, all data returned from the API must use the canonical resource name. Full resource names In most cases, resource names are used within a single API only, or else they are used in contexts where the owning API is clear (for example, string pubsub_topic). However, sometimes it is necessary for services to refer to resources in an arbitrary API. In this situation, the service should use the full resource name, a schemeless URI with the owning API\u0027s service name, followed by the relative resource name: //library.googleapis.com/publishers/123/books/les-miserables //calendar.googleapis.com/users/vhugo1802 Note: The full resource name should not be used for cross-API references where the owning API is clear; it is only used if a field refers to resources in multiple APIs where ambiguity is possible. Resource URIs The full resource name is a schemeless URI, but slightly distinct from the full URIs we use to access a resource. The latter includes the protocol (HTTPS), the API version, and the specific service endpoint to target: https://library.googleapis.com/v1/publishers/123/books/les-miserables https://calendar.googleapis.com/v3/users/vhugo1802 The version is not included in the full resource name because the full resource name is expected to persist from version to version. Even though the API surface may change between major versions, multiple major versions of the same API are expected to use the same underlying data. Note: The correlation between the full resource name and the service\u0027s endpoint is by convention. In particular, one service is able to have multiple endpoints (example use cases include regionalization, MTLS, and private access), and the full resource name does not change between these. Fields representing resource names When defining a resource, the first field should be the resource name, which must be of type string and must be called name for the resource name. The message should include a google.api.resource annotation declaring the type (see AIP-123 for more on this). // A representation of a book in the library. message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; // The resource name of the book. // Format: publishers/{publisher}/books/{book} string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // Other fields... } When defining a method that retrieves or acts on an already-existing resource (such as GetBook or ArchiveBook), the first field of the request message should be the resource name, which must be of type string and must be called name for the resource name. The field should also be annotated with the google.api.resource_reference annotation, referencing the resource type (AIP-123). // Request message for ArchiveBook message ArchiveBookRequest { // The book to archive. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; // Other fields... } Note: Fields must not be called name except for this purpose. For other use cases, either use a different term or prepend an adjective (for example: display_name). Fields representing a resource\u0027s parent When defining a method that retrieves resources from a collection or adds a new resource to a collection (such as ListBooks or CreateBook), the first field of the request message should be of type string and should be called parent for the resource name of the collection. The parent field should also be annotated with the google.api.resource_reference annotation, referencing the parent\u0027s resource type (AIP-123). // Request message for ListBooks. message ListBooksRequest { // The publisher to list books from. // Format: publishers/{publisher_id} string parent = 1 [(google.api.resource_reference) = { type: \"library.googleapis.com/Publisher\" }]; // Other fields (e.g. page_size, page_token, filter, etc.)... } If there is more than one possible parent type, the parent field should be annotated with the child_type key on google.api.resource_reference instead: // Request message for ListBooks. message ListBooksRequest { // The parent to list books from. // Format: // - publishers/{publisher_id} // - authors/{author_id} string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // Other fields (e.g. page_size, page_token, filter, etc.)... } Note: Fields should not be called parent except for this purpose. For other use cases, use a synonymous term if possible. Fields representing another resource When a field represents another resource, the field should be of type string and accept the resource name of the other resource. The field name should be equivalent to the corresponding message\u0027s name in snake case. Field names may include a leading adjective if appropriate (such as string dusty_book). Field names should not use the _name suffix unless the field would be ambiguous without it (e.g., crypto_key_name) Fields representing another resource should provide the google.api.resource_reference annotation with the resource type being referenced. If using the resource name is not possible and using the ID component alone is strictly necessary, the field should use an _id suffix (e.g. shelf_id). The field should not be of type message using the message that implements the resource, except for one of following conditions: The API is internal-only, has tight lifecycle relationships, and has a permission model that enables inherited access to embedded resources. The embedding of the resource is done as part of the AIP-162 revisions pattern. Example of a resource reference: // A representation of a book in a library. message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; // Name of the book. // Format is `publishers/{publisher}/books/{book}` string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The shelf where the book currently sits. // Format is `shelves/{shelf}`. string shelf = 2 [(google.api.resource_reference) = { type: \"library.googleapis.com/Shelf\" }]; // Other fields... } Further reading For evolving resource names over time, see AIP-180. For resource types, see AIP-123. Rationale Using names instead of IDs For any large system, there are many kinds of resources. To use simple resource IDs to identify a resource, we\u0027d actually need use a resource-specific tuple to reliably identify it, such as (bucket, object) or (user, album, photo). This creates several issues: Developers have to understand and remember such anonymous tuples. Passing tuples is generally harder than passing strings. Centralized infrastructures, such as logging and access control systems, don\u0027t understand specialized tuples. Specialized tuples limit API design flexibility, such as providing reusable API interfaces. For example, Long Running Operations can work with many other API interfaces because they use flexible resource names. Standardizing on name The concept of resource names is not a new one, and is formalized in Uniform Resource Names (URN) in conjunction with Uniform Resource Identifiers (URI) and Uniform Resource Locators (URL). Considering that the term \"name\" is so heavily overloaded in general, usage outside of a very well-defined meaning would be confusing for developers. So, the field name name is reserved in the context of AIP-compliant APIs so as to eliminate any confusion with resource names, and force other would be \"name\" fields to use a more specific field name. Disallow embedding of resources Using a resource message directly as the type of a field within another resource is problematic for a number of reasons, which are as follows: Complicates the resource lifecycle: If the dependency resource is deleted, what happens to the embedded reference in the dependent resource? Data retention and clean up operations will be significantly complicated. Bypasses permissions: If every resource has its own set of permissions, a user with read permission on the dependent resource that doesn\u0027t have the same permission on the dependency resource suddenly cannot see the full resource. Tightly couples resources in all aspects: Changing the requirements in the schema, permissions, or otherwise for either resource impacts the other, significantly increasing complexity of roll outs. Referencing by name, as is recommended, eliminates all of this complexity by preventing resource data duplication, and forcing the owning service to be involved in the resolution of the reference (via Standard Methods), guaranteeing isolation of logical concerns per-resource. History Disallowing UUIDs in user-specified IDs As part of an effort to make APIs more declarative-friendly, APIs were required to allow user-specified resource ID on creation. As part of this, a supporting field string uid containing a UUID was also encouraged. Guidance was then added to discourage the user-specified resource ID from being a UUID or even resembling one. Ostensibly, the fact that uid contained a service-generated UUID motivated this restriction on the user-specified resource ID, forcing the user-specified resource ID to be a more \"meaningful\" value. However, we no longer saw value in this requirement, hence its removal. Changelog 2025-03-10: Drop guidance disallowing UUID in user-specified ID. 2024-10-15: Add some rationale we found for use of name as a field and instead of IDs as an identifier. 2024-06-14: Clarify resource annotation shortening rules for nested collections. 2023-09-19: Prohibit duplicate collection identifiers. 2023-09-01: Add a clause that allows embedding for revision resource messages. 2023-08-10: Explicitly disallow embedding resource messages in a resource. 2023-03-24: Correction: full resource name contains the service name rather than the service endpoint 2023-03-17: Add OUTPUT_ONLY guidance for resource ID fields. 2020-10-06: Added declarative-friendly guidance, and tightened character set restrictions. 2020-10-05: Clarified when full resource names are used. 2020-05-19: Clarified that resource IDs avoid capital characters, not the entire resource name. 2020-04-27: Tighten the restriction on valid characters. 2019-12-05: Added guidance for resource annotations. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership. Also changed the final example from a Pub/Sub example to the usual Book example. 2019-07-30: Changed the nested collection brevity suggestion from \"may\" to \"should\"", + 'tags': '', + 'url': '/122', + }, +{ + 'title': "Resource types", + 'text': "Resource types Most APIs expose resources (their primary nouns) which users are able to create, retrieve, and manipulate. APIs are allowed to name their resource types reasonably freely (within the requirements of this AIP), and are only required to ensure uniqueness within that API. This means that it is possible (and often desirable) for different APIs to use the same type name. For example, a Memcache and Redis API would both want to use Instance as a type name. When mapping the relationships between APIs and their resources, however, it becomes important to have a single, globally-unique type name. Additionally, tools such as Kubernetes or GraphQL interact with APIs from multiple providers. Terminology In the guidance below, we use the following terms: Service Name: This is the name defined in the service configuration. This usually (but not necessarily) matches the hostname that users use to call the service. Example: pubsub.googleapis.com. This is equivalent to an API Group in Kubernetes. Type: This is the name used for the type within the API e.g. the name of the Protobuf message. This is equivalent to an Object in Kubernetes. Guidance APIs must define a resource type for each resource in the API, according to the following pattern: {Service Name}/{Type}. The type name must: Match the containing API type\u0027s name. Start with an uppercase letter. Only contain alphanumeric characters. Be of the singular form of the noun. Use PascalCase (UpperCamelCase). Examples Examples of resource types include: pubsub.googleapis.com/Topic pubsub.googleapis.com/Subscription spanner.googleapis.com/Database spanner.googleapis.com/Instance networking.istio.io/Instance Annotating resource types APIs should annotate the resource types for each resource in the API using the google.api.resource annotation: // A representation of a Pub/Sub topic. message Topic { option (google.api.resource) = { type: \"pubsub.googleapis.com/Topic\" pattern: \"projects/{project}/topics/{topic}\" singular: \"topic\" plural: \"topics\" }; // Name and other fields... } Patterns must correspond to the resource name. Pattern variables (the segments within braces) must use snake_case, and must not use an _id suffix. Pattern variables must conform to the format [a-z][_a-z0-9]*[a-z0-9]. Pattern variables must be unique within any given pattern. (e.g. projects/{abc}/topics/{abc} is invalid; this is usually a natural corollary of collection identifiers being unique within a pattern.) Resources with multiple patterns must preserve ordering: new patterns must be added at the end of the list, and existing patterns must not be removed or re-ordered, as this breaks client library backward compatibility. Singular must be the lower camel case of the type. Pattern variables must be the singular form of the resource type e.g. a pattern variable representing a Topic resource ID is named {topic}. Plural must be the lower camel case plural of the singular. Pattern collection identifier segments must match the plural of the resources, except in the case of nested collections. Pattern uniqueness When multiple patterns are defined within a resource, these patterns must be mutually unique, where uniqueness is defined as being by-character identical once all resource ID path segments have been removed, leaving all / separators. Therefore the following two patterns must not be defined within the same resource: user/{user} user/{user_part_1}~{user_part_2} Rationale Type and message name alignment In addition to simple schema-resource coherence and alignment, a number of consumers benefit from the {Type} and message names matching. Consumers have simpler lookups, client libraries get the same in addition to aligned user experience where resource-oriented code has naming aligned with the generated message code, generated reference documentation aligns resources with message docs, etc. Singular and Plural Well-defined singular and plurals of a resource enable clients to determine the proper name to use in code and documentation. lowerCamelCase can be translated into other common forms of a resource name such as UpperCamelCase and snake_case. Changelog 2025-01-09: Strongly align resource type and message naming. 2024-08-07: Added multi-pattern ordering compatibility requirements. 2023-09-19: Prohibited duplicate pattern variables. 2023-05-06: Added requirement of singular and plural. 2023-01-28: Clarified guidance for the resource type name. 2022-10-28: Added pattern variable format guidance. 2020-05-14: Added pattern uniqueness. 2019-12-05: Added guidance on patterns. 2019-07-17: Fleshed out the annotation example somewhat.", + 'tags': '', + 'url': '/123', + }, +{ + 'title': "Resource association", + 'text': "Resource association APIs sometimes have resource hierarchies that can not be cleanly expressed in the usual tree structure. For example, a resource may have a many-to-one relationship with two other resource types instead of just one. Alternatively, a resource may have a many-to-many relationship with another resource type. Guidance A resource must have at most one canonical parent, and List requests must not require two distinct \"parents\" to work. Multiple many-to-one associations If a resource has a many-to-one relationship with multiple resource types, it must choose at most one of them to be the canonical parent. The resource may be associated with other resources through other fields on the resource. message Book { // The resource name pattern for Book indicates that Publisher is the // canonical parent. option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; // The resource name for the book. string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The resource name for the book\u0027s author. string author = 2 [(google.api.resource_reference) = { type: \"library.googleapis.com/Author\" }]; } When listing resources with multiple associations in this way, the RPC must treat the string parent field as required as discussed in AIP-132, and must not add additional required arguments. The RPC should include a string filter field that allows users to filter by other resource associations as discussed in AIP-160. Note: Resource reference fields must accept the same resource name format that is used in the name field of the referenced resource. Many-to-many associations Many-to-many associations are less common in APIs than they are in relational databases, in part because they are more difficult to model and present over network interfaces. An API may contain many-to-many relationships, and should use a repeated field containing a list of resource names, following the principles described for repeated fields in AIP-144. message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The resource names for the book\u0027s authors. repeated string authors = 2 [(google.api.resource_reference) = { type: \"library.googleapis.com/Author\" }]; } Note: See AIP-144 for more information on repeated fields, including how to handle common issues such as atomic changes. If the use of a repeated field is too restrictive, or if more metadata is required along with the association, an API may model a many-to-many relationship using a sub-resource with two one-to-many associations. message BookAuthor { // The resource pattern for BookAuthor indicates that Book is the // canonical parent. option (google.api.resource) = { type: \"library.googleapis.com/BookAuthor\" pattern: \"publishers/{publisher}/books/{book}/authors/{book_author}\" }; // The resource name for the book-author association. string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The resource name for the author. string author = 2 [(google.api.resource_reference) = { type: \"library.googleapis.com/Author\" }]; // Other fields... } Note: Using subresources to model an association between resources is only recommended if additional metadata is required in the relationship, or if the restrictions around the use of a repeated field preclude the use of that approach. Changelog 2021-04-07: Clarified that resource reference fields accept resource names with the same format as the name field of the resource.", + 'tags': '', + 'url': '/124', + }, +{ + 'title': "Enumerations", + 'text': "Enumerations It is common for a field to only accept or provide a discrete and limited set of values. In these cases, it can be useful to use enumerations (generally abbreviated \"enums\") in order to clearly communicate what the set of allowed values are. Guidance APIs may expose enum objects for sets of values that are expected to change infrequently: // A representation of a book. message Book { // Other fields... // Possible formats in which the book may be published. enum Format { // Default value. This value is unused. FORMAT_UNSPECIFIED = 0; // The printed format, in hardback. HARDBACK = 1; // The printed format, in paperback. PAPERBACK = 2; // An electronic book format. EBOOK = 3; // An audio recording. AUDIOBOOK = 4; } // The format of the book. Format format = 99; // Other fields... } All enum values must use UPPER_SNAKE_CASE. The first value of the enum should be the name of the enum itself followed by the suffix _UNSPECIFIED. An exception to this rule is if there is a clearly useful zero value. In particular, if an enum needs to present an UNKNOWN, it is usually clearer and more useful for it to be a zero value rather than having both. The UNKNOWN value may be prefixed by the enum name as is typical for avoiding enum value name collisions. Enums which will only be used in a single message should be nested within that message. In this case, the enum should be declared immediately before it is used. The non-zero values of such a nested enum definition should not be prefixed by the name of the enum itself. This generally requires users to write MyState.MYSTATE_ACTIVE in their code, which is unnecessarily verbose. Enums which will be used by multiple messages should be defined at the package level and should be defined at the bottom of the proto file (see AIP-191). Some languages (including C++) hoist enum values into the parent namespace, which can result in conflicts for enums with the same values in the same proto package. To avoid sharing values, APIs should prefix package-level enum values with the name of the enum. Enums should document whether the enum is frozen or they expect to add values in the future. When to use enums Enums can be more accessible and readable than strings or booleans in many cases, but they do add overhead when they change. Therefore, enums should receive new values infrequently. While the definition of \"infrequently\" may change based on individual use cases, a good rule of thumb is no more than once a year. For enums that change frequently, the API should use a string and document the format. Additionally, enums should not be used when there is a competing, widely-adopted standard representation (such as with language codes or media types). Note: If an enumerated value needs to be shared across APIs, an enum may be used, but the assignment between enum values and their corresponding integers must match. Alternatives For enumerated values where the set of allowed values changes frequently, APIs should use a string field instead, and must document the allowed values. String fields with enumerated values should use kebab-case for their values. For enumerated values where there is a competing, widely-adopted standard representation (generally, but not necessarily, a string), that standard representation should be used. This is true even if only a small subset of values are permitted, because using enums in this situation often leads to frustrating lookup tables when trying to use multiple APIs together. Boolean fields may be used in situations where it is clear that no further flexibility will be needed. The default value must be false. Note: When using protocol buffers, it is impossible to distinguish between false and unset. If this is a requirement, an enum may be a better design choice (although google.protobuf.BoolValue is also available). Further reading For states, a special type of enum, see AIP-216. Changelog 2025-10-03: Added prefixing guidance for UNKNOWN value exception.", + 'tags': '', + 'url': '/126', + }, +{ + 'title': "HTTP and gRPC Transcoding", + 'text': "HTTP and gRPC Transcoding APIs that follow resource-oriented design are defined using RPCs, but the resource-oriented design framework allows them to also be presented as APIs that largely follow REST/JSON conventions. This is important in order to help developers use their existing knowledge: over 80% of the public APIs available follow most REST conventions, and developers are accustomed to that pattern. Guidance APIs must provide HTTP definitions for each RPC that they define, except for bi-directional streaming RPCs, which can not be natively supported using HTTP/1.1. When providing a bi-directional streaming method, an API should also offer an alternative method that does not rely on bi-directional streaming. HTTP method and path When using protocol buffers, each RPC must define the HTTP method and path using the google.api.http annotation: rpc CreateBook(CreateBookRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books\" body: \"book\" }; } message CreateBookRequest { // The publisher who will publish this book. // When using HTTP/JSON, this field is automatically populated based // on the URI, because of the `{parent=publishers/*}` syntax. string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The book to create. // When using HTTP/JSON, this field is populated based on the HTTP body, // because of the `body: \"book\"` syntax. Book book = 2 [(google.api.field_behavior) = REQUIRED]; // The user-specified ID for the book. // When using HTTP/JSON, this field is populated based on a query string // argument, such as `?bookId=foo`. This is the fallback for fields that // are not included in either the URI or the body. // Note that clients use camelCase format to communicate the field names // to the service. string book_id = 3; } The first key (post in this example) corresponds to the HTTP method. RPCs may use get, post, patch, or delete. RPCs must use the prescribed HTTP verb for each standard method, as discussed in AIP-131, AIP-132, AIP-133, AIP-134, and AIP-135 RPCs should use the prescribed HTTP verb for custom methods, as discussed in AIP-136. RPCs should not use put or custom. The corresponding value represents the URI. URIs must use the {foo=bar/*} syntax to represent a variable that should be populated in the request proto. When extracting a resource name, the variable must include the entire resource name, not just the ID component. URIs may use nested fields for their variable names. (Additionally, AIP-134 mandates this for Update requests.) URIs must use the * character to represent ID components, which matches all URI-safe characters except for /. URIs may use ** as the final segment of a URI if matching / is required. The body key defines which single top-level field in the request will be sent as the HTTP body. If the body is *, then this indicates that the request object itself is the HTTP body. The request body is encoded as JSON as defined by protocol buffers\u0027 canonical JSON encoding. RPCs must not define a body at all for RPCs that use the GET or DELETE HTTP verbs. RPCs must use the prescribed body for Create (AIP-133) and Update (AIP-134) requests. RPCs should use the prescribed body for custom methods (AIP-136). The body must not contain a nested field (or use the . character), The body must not be the same as a URI parameter. The body must not be a repeated field. Fields should not use the json_name annotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons. Note: Bi-directional streaming RPCs should not include a google.api.http annotation at all. If feasible, the service should provide non-streaming equivalent RPCs. Multiple URI bindings Occasionally, an RPC needs to correspond to more than one URI: rpc CreateBook(CreateBookRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books\" body: \"book\" additional_bindings: { post: \"/v1/{parent=authors/*}/books\" body: \"book\" } additional_bindings: { post: \"/v1/books\" body: \"book\" } }; } RPCs may define any number of additional bindings. The structure is identical to the google.api.http annotation (in fact, it is a recursive reference). RPCs must not define an additional binding within an additional binding. The body clause must be identical in the top-level annotation and each additional binding. Changelog 2022-08-18: Added the comment that query string parameter names are in camelCase. 2021-01-06: Added clarification around body and nested fields. 2019-09-23: Added a statement about request body encoding, and guidance discouraging json_name.", + 'tags': '', + 'url': '/127', + }, +{ + 'title': "Declarative-friendly interfaces", + 'text': "Declarative-friendly interfaces Many services need to interact with common DevOps tools, particularly those that create and manage network-addressable resources (such as virtual machines, load balancers, database instances, and so on). These tools revolve around the principle of \"configuration as code\": the user specifies the complete intended landscape, and tooling is responsible for making whatever changes are necessary to achieve the user\u0027s specification. These tools are declarative: rather than specifying specific actions to take, they specify the desired outcome, with the actions being derived based on the differences between the current landscape and the intended one. Furthermore, there are numerous popular DevOps tools, with more being introduced each year. Integrating hundreds of resource types with multiple tools requires uniformity, so that integration can be automated. Guidance Resources Resources that are declarative-friendly must use only strongly-consistent standard methods for managing resource lifecycle, which allows tools to support these resources generically, as well as conforming to other declarative-friendly guidance (see further reading). Declarative-friendly resources should designate that they follow the declarative-friendly style: message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" style: DECLARATIVE_FRIENDLY }; // Name and other fields... } Reconciliation If a resource takes time (more than a few seconds) for updates to be realized, the resource should include a bool reconciling field to disclose that changes are in flight. This field must be output only. A resource must set the reconciling field to true if the current state of the resource does not match the user\u0027s intended state, and the system is working to reconcile them. This is regardless of whether the root cause of going into reconciliation was user or system action. Note: Services responding to a GET request must return the resource\u0027s current state (not the intended state). Further reading A significant amount of guidance is more strict for declarative-friendly interfaces, due to the focus on automation on top of these resources. This list is a comprehensive reference to declarative-friendly guidance in other AIPs: Resources should not employ custom methods: see AIP-136. Resources must use the Update method for repeated fields: see AIP-144. Resources must include certain standard fields: see AIP-148. Resources must have an etag field: see AIP-154. Resources should provide change validation: see AIP-163. Resources should not implement soft-delete. If the id cannot be re-used, the resource must implement soft-delete and the undelete RPC: see AIP-164 Annotations See AIP-148 annotations. Changelog 2023-07-13: Move annotations from AIP-148. 2023-06-17: Definition of plane was removed and incorporated into AIP-111. 2023-05-11: Removed must on resource_id, which was upstreamed to a general must.", + 'tags': '', + 'url': '/128', + }, +{ + 'title': "Server-Modified Values and Defaults", + 'text': "Server-Modified Values and Defaults Services often provide default values for resource fields, and occasionally normalize the user input before returning it in the response. The guidance herein describes how services document such behavior for the benefit of consumers. Guidance Single Owner Fields Fields must have a single owner, whether that is the client or the server. Server owned fields must be indicated with the OUTPUT_ONLY field_behavior. All other types of fields must be considered to be owned by the client. The server must respect the value (or lack thereof) for all client owned fields and not modify them. Effective Values There are instances where a service will allocate, generate, or calculate a value if the client chooses not to specify one. For example: a client creates a virtual machine without specifying a static IP address for the virtual machine to be available on. Such a scenario is opting into dynamic IP address allocation. Some examples of these types of fields are ones that are: generated (UUID) allocated (dynamic IP address) assigned (most recent software package version) An attribute with an effective value must be expressed as two fields in the API: a mutable field that can be optionally set by the user and must not be modified by the service an OUTPUT_ONLY field that records the effective value decided on by the service Example: message VirtualMachine { \u2026 string ip_address = 4; string effective_ip_address = 5 [ (google.api.field_behavior) = OUTPUT_ONLY ]; } Naming Effective values must be named by prefixing effective_ to the mutable field\u0027s name. User-Specified Fields For user-specified fields, the value in response from the service must be the same as provided by the create or update request. For string fields this means returning the value unchanged, with one exception: When a string field has a data type annotation, a normalized string that represents the given value may be returned. Normalizations A field that is normalized by the service must be annotated with the google.api.field_info extension. See (AIP-202) for guidance on using this extension The allowed set of normalizations includes the following formats: uuid ipv4 ipv6 email Normalizations on fields must be described using the google.api.field_info annotation. Rationale Server-modified and default values often make it harder to implement declarative clients. These clients are often unable to tell when their desired state matches the current state for these fields, as the rules by which a server may modify and return values are complex, not public, and not repeatable. Rationale for Single Owner Fields When fields do not have a single owner they can cause issues for declarative clients. These clients may attempt to set values for fields that are overwritten by server set values, leading to the client entering an infinite loop to correct the change. Rationale for Naming Consistent naming is important for identifying standard behavior across APIs and fields. Programmatic association between user-specified and effective values depends on consistent naming. Rationale for Normalizations Normalizations are important to allow services to store and return values in a standard way while communicating to clients what changes are semantically identical. Normalizing a value on the service side allows the service to accept a wider range of semantically identical inputs without needing to maintain every value as a raw string. Surfacing the normalization that is being applied to clients allows for client side comparison of sent and retrieved values to check for differences. For example, in a resource that accepts an email address on a particular field a client may specify a given email address in a variety of ways. For the email ada@example.com a client may choose to specify ADA@example.com, aDa@example.com, or AdA@example.com. These are semantically identical and should all be accepted by the service. The service then may choose to normalize the email address for storage and retrieval through downcasing or canonicalization. Importantly, the information surfaced to clients on the normalization of a field will not describe the normalization algorithm itself, but instead the comparison method used to accurately compute if two values should be considered equal. Rationale for Field Value Handling For fields not using an allowed normalization, Declarative clients will not be able to identify which changes are semantically meaningful. When a Declarative client sends a particular value it will ensure that the value is being returned by the service to validate it was set correctly. Changelog 2023-10-31: Update to approved.", + 'tags': '', + 'url': '/129', + }, +{ + 'title': "Methods", + 'text': "Methods An API is composed of one or more methods, which represent a specific operation that a service can perform on behalf of the consumer. Guidance Categories of Methods The following enumerates multiple categories of methods that exist, often grouped up under some object (e.g. collection or resource) that the method operates upon. Category Name Related AIPs Declarative client integration CLI / UI integration SDK integration Standard Methods Standard collection methods: operate on a collection of resources (List or Create). AIP-121, AIP-132, AIP-133 automatable automatable automatable Standard resource methods: fetch or mutate a single resource (Get, Update, Delete). AIP-121, AIP-131, AIP-134, AIP-135 automatable automatable automatable Batch resource methods: fetch or mutate multiple resources in a collection by name. AIP-231, AIP-233, AIP-234, AIP-235 may be used to optimize queries automatable automatable Aggregated list methods: fetch or mutate multiple resources of the same type across multiple collections. AIP-159 not useful nor automatable automatable automatable Custom Fetch Methods Custom collection fetch methods: fetch information across a collection that cannot be expressed via a standard method. AIP-136 handwritten automatable automatable Custom resource fetch methods: fetch information for a single resource that cannot be expressed via a standard method. AIP-136 handwritten automatable automatable Custom Mutation Methods Backing up a resource: storing a copy of a resource at a particular point in time. AIP-162 unused or handwritten automatable automatable Restoring a resource: setting a resource to a version from a particular point in time. AIP-162 unused or handwritten automatable automatable Renaming a resource: modify the resource\u0027s name or id while preserving configuration and data. AIP-136 unused or handwritten automatable automatable Custom collection mutation methods: perform an imperative operation referencing a collection that may mutate one or more resources within that collection in fashion that cannot be easily achieved by standard methods (e.g. state transitions). AIP-136 unused or handwritten automatable automatable Custom resource mutation methods: perform an imperative operation on a resource that may mutate it in a way a standard method cannot (e.g. state transitions). AIP-136 unused or handwritten automatable automatable Misc Custom Methods Stateless Methods: a method that has no permanent effect on any data within the API (e.g. translating text) AIP-136 unused or handwritten automatable automatable None of the above Streaming methods: methods that communicate via client, server, or bi-directional streams. handwritten handwritten automatable Choosing a method category While designing a method, API authors should choose from the defined categories in the following order: Standard methods (on collections and resources) Standard batch or aggregate methods Custom methods (on collections, resources, or stateless) Streaming methods Rationale Resource-oriented standard and custom methods are recommended first, as they can be expressed in the widest variety of clients (Declarative clients, CLIs, UIs, and so on), and offer the most uniform experience that allows users to apply their knowledge of one API to another. If a standard method is unsuitable, then custom methods (that are mounted to a resource or collection) offer a lesser, but still valuable level of consistency, helping the user reason about the scope of the action and the object whose configuration is read to inform that action. Although mutative custom methods are not uniform enough to have a automated integration with exclusively resource-oriented clients such as Declarative clients, they are still a pattern that can easily recognized by CLIs, UIs, and SDKs. If one cannot express their APIs in a resource-oriented fashion at all, then the operation falls in a category where the lack of uniformity makes it difficult for any client aside from SDKs to model the operation. This category is preferred last due to the fact that a user cannot rely on their knowledge of similar APIs, as well as the issue that integration with many clients will likely have to be hand-written. Changelog 2023-09-05: Update to approved.", + 'tags': '', + 'url': '/130', + }, +{ + 'title': "Standard methods: Get", + 'text': "Standard methods: Get In REST APIs, it is customary to make a GET request to a resource\u0027s URI (for example, /v1/publishers/{publisher}/books/{book}) in order to retrieve that resource. Resource-oriented design (AIP-121) honors this pattern through the Get method. These RPCs accept the URI representing that resource and return the resource. Guidance APIs must provide a get method for resources. The purpose of the get method is to return data from a single resource. Get methods are specified using the following pattern: rpc GetBook(GetBookRequest) returns (Book) { option (google.api.http) = { get: \"/v1/{name=publishers/*/books/*}\" }; option (google.api.method_signature) = \"name\"; } The RPC\u0027s name must begin with the word Get. The remainder of the RPC name should be the singular form of the resource\u0027s message name. The request message must match the RPC name, with a Request suffix. The response message must be the resource itself. (There is no GetBookResponse.) The response should usually include the fully-populated resource unless there is a reason to return a partial response (see AIP-157). The HTTP verb must be GET. The URI should contain a single variable field corresponding to the resource name. This field should be called name. The URI should have a variable corresponding to this field. The name field should be the only variable in the URI path. All remaining parameters should map to URI query parameters. There must not be a body key in the google.api.http annotation. There should be exactly one google.api.method_signature annotation, with a value of \"name\". Request message Get methods implement a common request message pattern: message GetBookRequest { // The name of the book to retrieve. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; } A resource name field must be included. It should be called name. The field should be annotated as required. The field must identify the resource type that it references. The comment for the name field should document the resource pattern. The request message must not contain any other required fields, and should not contain other optional fields except those described in another AIP. Note: The name field in the request object corresponds to the name variable in the google.api.http annotation on the RPC. This causes the name field in the request to be populated based on the value in the URL when the REST/JSON interface is used. Errors See errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors. Changelog 2023-03-17: Align with AIP-122 and make Get a must. 2022-11-04: Aggregated error guidance to AIP-193. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-06-08: Added guidance on returning the full resource. 2019-10-18: Added guidance on annotations. 2019-08-12: Added guidance for error cases. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership. 2019-05-29: Added an explicit prohibition on arbitrary fields in standard methods.", + 'tags': '', + 'url': '/131', + }, +{ + 'title': "Standard methods: List", + 'text': "Standard methods: List In many APIs, it is customary to make a GET request to a collection\u0027s URI (for example, /v1/publishers/1/books) in order to retrieve a list of resources, each of which lives within that collection. Resource-oriented design (AIP-121) honors this pattern through the List method. These RPCs accept the parent collection (and potentially some other parameters), and return a list of responses matching that input. Guidance APIs must provide a List method for resources unless the resource is a singleton. The purpose of the List method is to return data from a finite collection (generally singular unless the operation supports reading across collections). List methods are specified using the following pattern: rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) { option (google.api.http) = { get: \"/v1/{parent=publishers/*}/books\" }; option (google.api.method_signature) = \"parent\"; } The RPC\u0027s name must begin with the word List. The remainder of the RPC name should be the plural form of the resource being listed. The request and response messages must match the RPC name, with Request and Response suffixes. The HTTP verb must be GET. The collection whose resources are being listed should map to the URI path. The collection\u0027s parent resource should be called parent, and should be the only variable in the URI path. All remaining parameters should map to URI query parameters. The collection identifier (books in the above example) must be a literal string. The body key in the google.api.http annotation must be omitted. If the resource being listed is not a top-level resource, there should be exactly one google.api.method_signature annotation, with a value of \"parent\". If the resource being listed is a top-level resource, there should be either no google.api.method_signature annotation, or exactly one google.api.method_signature annotation, with a value of \"\". Request message List methods implement a common request message pattern: message ListBooksRequest { // The parent, which owns this collection of books. // Format: publishers/{publisher} string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The maximum number of books to return. The service may return fewer than // this value. // If unspecified, at most 50 books will be returned. // The maximum value is 1000; values above 1000 will be coerced to 1000. int32 page_size = 2; // A page token, received from a previous `ListBooks` call. // Provide this to retrieve the subsequent page. // // When paginating, all other parameters provided to `ListBooks` must match // the call that provided the page token. string page_token = 3; } A parent field must be included unless the resource being listed is a top-level resource. It should be called parent. The field should be annotated as required. The field must identify the resource type of the resource being listed. The page_size and page_token fields, which support pagination, must be specified on all list request messages. For more information, see AIP-158. The comment above the page_size field should document the maximum allowed value, as well as the default value if the field is omitted (or set to 0). If preferred, the API may state that the server will use a sensible default. This default may change over time. If a user provides a value greater than the maximum allowed value, the API should coerce the value to the maximum allowed. If a user provides a negative or other invalid value, the API must send an INVALID_ARGUMENT error. The page_token field must be included on all list request messages. The request message may include fields for common design patterns relevant to list methods, such as string filter and string order_by. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. Note: List methods should return the same results for any user that has permission to make a successful List request on the collection. Search methods are more relaxed on this. Response message List methods implement a common response message pattern: message ListBooksResponse { // The books from the specified publisher. repeated Book books = 1; // A token, which can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. string next_page_token = 2; } The response message must include one repeated field corresponding to the resources being returned, and should not include any other repeated fields unless described in another AIP (for example, AIP-217). The response should usually include fully-populated resources unless there is a reason to return a partial response (see AIP-157). The next_page_token field, which supports pagination, must be included on all list response messages. It must be set if there are subsequent pages, and must not be set if the response represents the final page. For more information, see AIP-158. The message may include a int32 total_size (or int64 total_size) field with the number of items in the collection. The value may be an estimate (the field should clearly document this if so). If filtering is used, the total_size field should reflect the size of the collection after the filter is applied. Ordering List methods may allow clients to specify sorting order; if they do, the request message should contain a string order_by field. Values should be a comma separated list of fields. For example: \"foo,bar\". The default sorting order is ascending. To specify descending order for a field, users append a \" desc\" suffix; for example: \"foo desc, bar\". Redundant space characters in the syntax are insignificant. \"foo, bar desc\", \" foo , bar desc \", and \"foo,bar desc\" are all equivalent. Subfields are specified with a . character, such as foo.bar or address.street. The resulting list order should be based on the field type\u0027s natural comparator e.g. numerics ordered numerically, strings ordered lexicographically, etc. However, APIs may choose to use a different ordering; if so, it must be documented in the order_by definition. Furthermore, well-known types, like Timestamp and Duration are compared as their representative type; Timestamp is compared as time e.g. before or after, Duration is compared as a quantity e.g. more or less. Note: Only include ordering if there is an established need to do so. It is always possible to add ordering later, but removing it is a breaking change. Filtering List methods may allow clients to specify filters; if they do, the request message should contain a string filter field. Filtering is described in more detail in AIP-160. Note: Only include filtering if there is an established need to do so. It is always possible to add filtering later, but removing it is a breaking change. Soft-deleted resources Some APIs need to \"soft delete\" resources, marking them as deleted or pending deletion (and optionally purging them later). APIs that do this should not include deleted resources by default in list requests. APIs with soft deletion of a resource should include a bool show_deleted field in the list request that, if set, will cause soft-deleted resources to be included. Errors See errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors. Further reading For details on pagination, see AIP-158. For listing across multiple parent collections, see AIP-159. Changelog 2025-02-25: Require documentation for ordering not matching field type with clarification on ordering of well-known types. 2023-03-22: Fix guidance wording to mention AIP-159. 2023-03-17: Align with AIP-122 and make Get a must. 2022-11-04: Aggregated error guidance to AIP-193. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-09-02: Add link to the filtering AIP. 2020-08-14: Added error guidance for permission denied cases. 2020-06-08: Added guidance on returning the full resource. 2020-05-19: Removed requirement to document ordering behavior. 2020-04-15: Added guidance on List permissions. 2019-10-18: Added guidance on annotations. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership. 2019-07-30: Added guidance about documenting the ordering behavior. 2019-05-29: Added an explicit prohibition on arbitrary fields in standard methods.", + 'tags': '', + 'url': '/132', + }, +{ + 'title': "Standard methods: Create", + 'text': "Standard methods: Create In REST APIs, it is customary to make a POST request to a collection\u0027s URI (for example, /v1/publishers/{publisher}/books) in order to create a new resource within that collection. Resource-oriented design (AIP-121) honors this pattern through the Create method. These RPCs accept the parent collection and the resource to create (and potentially some other parameters), and return the created resource. Guidance APIs should generally provide a create method for resources unless it is not valuable for users to do so. The purpose of the create method is to create a new resource in an already-existing collection. Create methods are specified using the following pattern: rpc CreateBook(CreateBookRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books\" body: \"book\" }; option (google.api.method_signature) = \"parent,book\"; } The RPC\u0027s name must begin with the word Create. The remainder of the RPC name should be the singular form of the resource being created. The request message must match the RPC name, with a Request suffix. The response message must be the resource itself. There is no CreateBookResponse. The response should include the fully-populated resource, and must include any fields that were provided unless they are input only (see AIP-203) or there is a reason to return a partial response (see AIP-157). If the create RPC is long-running, the response message must be a google.longrunning.Operation which resolves to the resource itself. The HTTP verb must be POST. The collection where the resource is being added should map to the URI path. The collection\u0027s parent resource should be called parent, and should be the only variable in the URI path. The collection identifier (books in the above example) must be a literal string. There must be a body key in the google.api.http annotation, and it must map to the resource field in the request message. All remaining fields should map to URI query parameters. There should be exactly one google.api.method_signature annotation, with a value of \"parent,{resource},{resource}_id\", or \"\"parent,{resource}\" if the resource ID is not required. If the API is operating on the management plane, the operation should have strong consistency: the completion of a create operation must mean that all user-settable values and the existence of the resource have reached a steady-state and reading resource state returns a consistent response. Request message Create methods implement a common request message pattern: message CreateBookRequest { // The parent resource where this book will be created. // Format: publishers/{publisher} string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The ID to use for the book, which will become the final component of // the book\u0027s resource name. // // This value should be 4-63 characters, and valid characters // are /[a-z][0-9]-/. string book_id = 2 [(google.api.field_behavior) = REQUIRED]; // The book to create. Book book = 3 [(google.api.field_behavior) = REQUIRED]; } A parent field must be included unless the resource being created is a top-level resource. It should be called parent. The field should be annotated as required. The field must identify the resource type of the resource being created. A {resource}_id field must be included for management plane resources, and should be included for data plane resources. The resource field must be included and must map to the POST body. The request message must not contain any other required fields and should not contain other optional fields except those described in this or another AIP. Long-running create Some resources take longer to create a resource than is reasonable for a regular API request. In this situation, the API should use a long-running operation (AIP-151) instead: rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books\" body: \"book\" }; option (google.longrunning.operation_info) = { response_type: \"Book\" metadata_type: \"OperationMetadata\" }; } The response type must be set to the resource (what the return type would be if the RPC was not long-running). Both the response_type and metadata_type fields must be specified. Important: Declarative-friendly resources (AIP-128) should use long-running operations. The service may return an LRO that is already set to done if the request is effectively immediate. User-specified IDs An API must allow a user to specify the ID component of a resource (the last segment of the resource name) on creation if the API is operating on the management plane. On the data plane, an API should allow a user to specify the ID. Exceptional cases should have the following behavior: The data plane resource allows identical records without a need to disambiguate between the two (e.g. rows in a table with no primary key). The data plane resource will not be exposed in Declarative clients. An API may allow the {resource}_id field have the field_behavior OPTIONAL, and generate a system-generated ID if one is not specified. For example: // Using user-specified IDs. publishers/lacroix/books/les-miserables // Using system-generated IDs. publishers/012345678-abcd-cdef/books/12341234-5678-abcd The {resource}_id field must exist on the request message, not the resource itself. The field may be required or optional. If it is required, it should include the corresponding annotation. The name field on the resource must be ignored. There should be exactly one google.api.method_signature annotation on the RPC, with a value of \"parent,{resource},{resource}_id\" if the resource being created is not a top-level resource, or with a value of \"{resource},{resource}_id\" if the resource being created is a top-level resource. The documentation should explain what the acceptable format is, and the format should follow the guidance for resource name formatting in AIP-122. If a user tries to create a resource with an ID that would result in a duplicate resource name, the service must error with ALREADY_EXISTS. However, if the user making the call does not have permission to see the duplicate resource, the service must error with PERMISSION_DENIED instead. Note: For REST APIs, the user-specified ID field, {resource}_id, is provided as a query parameters on the request URI. Errors See errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors. Further reading For ensuring idempotency in Create methods, see AIP-155. For naming resources involving Unicode, see AIP-210. Rationale Requiring user-specified ids Declarative clients use the resource ID as a way to identify a resource for applying updates and for conflict resolution. The lack of a user-specified ID means a client is unable to find the resource unless they store the identifier locally, and can result in re-creating the resource. This in turn has a downstream effect on all resources that reference it, forcing them to update to the ID of the newly-created resource. Having a user-specified ID also means the client can precalculate the resource name and use it in references from other resources. Changelog 2025-10-03: Allow use of partial responses via AIP-157. 2023-10-20: Clarify that {resource}_id is only required for management plane resources. 2023-08-24: Adding consistency requirement. 2023-05-11: Changing guidance around resource_id to a must. 2022-11-04: Referencing aggregated error guidance in AIP-193, similar to other CRUDL AIPs. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-10-06: Added declarative-friendly guidance. 2020-08-14: Updated error guidance to use permission denied over forbidden. 2020-06-08: Added guidance on returning the full resource. 2019-11-22: Added clarification on what error to use if a duplicate name is sent. 2019-10-18: Added guidance on annotations. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership. 2019-06-10: Added guidance for long-running create. 2019-05-29: Added an explicit prohibition on arbitrary fields in standard methods.", + 'tags': '', + 'url': '/133', + }, +{ + 'title': "Standard methods: Update", + 'text': "Standard methods: Update In REST APIs, it is customary to make a PATCH or PUT request to a resource\u0027s URI (for example, /v1/publishers/{publisher}/books/{book}) in order to update that resource. Resource-oriented design (AIP-121) honors this pattern through the Update method (which mirrors the REST PATCH behavior). These RPCs accept the URI representing that resource and return the resource. Guidance APIs should generally provide an update method for resources unless it is not valuable for users to do so. The purpose of the update method is to make changes to the resources without causing side effects. Update methods are specified using the following pattern: rpc UpdateBook(UpdateBookRequest) returns (Book) { option (google.api.http) = { patch: \"/v1/{book.name=publishers/*/books/*}\" body: \"book\" }; option (google.api.method_signature) = \"book,update_mask\"; } The RPC\u0027s name must begin with the word Update. The remainder of the RPC name should be the singular form of the resource\u0027s message name. The request message must match the RPC name, with a Request suffix. The response message must be the resource itself. (There is no UpdateBookResponse.) The response should include the fully-populated resource, and must include any fields that were sent and included in the update mask unless they are input only (see AIP-203) or there is a reason to return a partial response (see AIP-157). If the update RPC is long-running, the response message must be a google.longrunning.Operation which resolves to the resource itself. The method should support partial resource update, and the HTTP verb should be PATCH. If the method will only ever support full resource replacement, then the HTTP verb may be PUT. However, this is strongly discouraged because it becomes a backwards-incompatible change to add fields to the resource. The resource\u0027s name field should map to the URI path. The {resource}.name field should be the only variable in the URI path. There must be a body key in the google.api.http annotation, and it must map to the resource field in the request message. All remaining fields should map to URI query parameters. There should be exactly one google.api.method_signature annotation, with a value of \"{resource},update_mask\". If the API is operating on the management plane, the operation should have strong consistency: the completion of an update operation must mean that all user-settable values and the existence of the resource have reached a steady-state and reading resource state returns a consistent response. Note: Unlike the other four standard methods, the URI path here references a nested field (book.name) in the example. If the resource field has a word separator, snake_case is used. Request message Update methods implement a common request message pattern: message UpdateBookRequest { // The book to update. // // The book\u0027s `name` field is used to identify the book to update. // Format: publishers/{publisher}/books/{book} Book book = 1 [(google.api.field_behavior) = REQUIRED]; // The list of fields to update. google.protobuf.FieldMask update_mask = 2; } The request message must contain a field for the resource. The field must map to the PATCH body. The field should be annotated as required. A name field must be included in the resource message. It should be called name. The field must identify the resource type of the resource being updated. If partial resource update is supported, a field mask must be included. It must be of type google.protobuf.FieldMask, and it must be called update_mask. The fields used in the field mask correspond to the resource being updated (not the request message). The field must be optional, and the service must treat an omitted field mask as an implied field mask equivalent to all fields that are populated (have a non-empty value). Update masks must support a special value *, meaning full replacement (the equivalent of PUT). API producers need to be conscious of how adding new, mutable fields to a resource will be handled when consumers use * without knowledge of said new, mutable fields. Likewise consumers need to use * only when the risks of doing so are acceptable. In general, it is safest to explicitly specify the fields to update rather than use *. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. Side effects In general, update methods are intended to update the data within the resource. Update methods should not trigger other side effects. Instead, side effects should be triggered by custom methods. In particular, this entails that state fields must not be directly writable in update methods. PATCH and PUT TL;DR: Google APIs generally use the PATCH HTTP verb only, and do not support PUT requests. We standardize on PATCH because Google updates stable APIs in place with backwards-compatible improvements. It is often necessary to add a new field to an existing resource, but this becomes a breaking change when using PUT. To illustrate this, consider a PUT request to a Book resource: PUT /v1/publishers/123/books/456 {\"title\": \"Mary Poppins\", \"author\": \"P.L. Travers\"} Next consider that the resource is later augmented with a new field (here we add rating): message Book { string title = 1; string author = 2; // Subsequently added to v1 in place... int32 rating = 3; } If a rating is set on a book and the existing PUT request was executed, it would wipe out the book\u0027s rating. In essence, a PUT request unintentionally wiped out data because the previous version did not know about it. Long-running update Some resources take longer to update a resource than is reasonable for a regular API request. In this situation, the API should use a long-running operation (AIP-151) instead: rpc UpdateBook(UpdateBookRequest) returns (google.longrunning.Operation) { option (google.api.http) = { patch: \"/v1/{book.name=publishers/*/books/*}\" body: \"book\" }; option (google.longrunning.operation_info) = { response_type: \"Book\" metadata_type: \"OperationMetadata\" }; } The response type must be set to the resource (what the return type would be if the RPC was not long-running). Both the response_type and metadata_type fields must be specified. Note: Declarative-friendly resources (AIP-128) should use long-running update. Create or update If the service uses client-assigned resource names, Update methods may expose a bool allow_missing field, which will cause the method to succeed in the event that the user attempts to update a resource that is not present (and will create the resource in the process): message UpdateBookRequest { // The book to update. // // The book\u0027s `name` field is used to identify the book to be updated. // Format: publishers/{publisher}/books/{book} Book book = 1 [(google.api.field_behavior) = REQUIRED]; // The list of fields to be updated. google.protobuf.FieldMask update_mask = 2; // If set to true, and the book is not found, a new book will be created. // In this situation, `update_mask` is ignored. bool allow_missing = 3; } More specifically, the allow_missing flag triggers the following behavior: If the method call is on a resource that does not exist, the resource is created. All fields are applied regardless of any provided field mask. However, if any required fields are missing or fields have invalid values, an INVALID_ARGUMENT error is returned. If the method call is on a resource that already exists, and all fields match, the existing resource is returned unchanged. If the method call is on a resource that already exists, only fields declared in the field mask are updated. The user must have the update permissions to call Update even with allow_missing set to true. For customers that want to prevent users from creating resources using the update method, IAM conditions should be used. Etags An API may sometimes need to allow users to send update requests which are guaranteed to be made against the most current data (a common use case for this is to detect and avoid race conditions). Resources which need to enable this do so by including a string etag field, which contains an opaque, server-computed value representing the content of the resource. In this situation, the resource should contain a string etag field: message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; // The resource name of the book. // Format: publishers/{publisher}/books/{book} string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The title of the book. // Example: \"Mary Poppins\" string title = 2; // The author of the book. // Example: \"P.L. Travers\" string author = 3; // The etag for this book. // If this is provided on update, it must match the server\u0027s etag. string etag = 4; } The etag field may be either required or optional. If it is set, then the request must succeed if and only if the provided etag matches the server-computed value, and must fail with an ABORTED error otherwise. The update_mask field in the request does not affect the behavior of the etag field, as it is not a field being updated. Expensive fields APIs sometimes encounter situations where some fields on a resource are expensive or impossible to reliably return. This can happen in a few situations: A resource may have some fields that are very expensive to compute, and that are generally not useful to the customer on update requests. A single resource sometimes represents an amalgamation of data from multiple underlying (and eventually consistent) data sources. In these situations, it is impossible to return authoritative information on the fields that were not changed. In this situation, an API may return back only the fields that were updated, and omit the rest, and should document this behavior if they do so. Errors See errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors. In addition, if the user does have proper permission, but the requested resource does not exist, the service must error with NOT_FOUND (HTTP 404) unless allow_missing is set to true. Changelog 2025-10-03: Allow use of partial responses via AIP-157. 2024-12-03: Add caveats to usage of full replacement update_mask. 2024-03-14: Make update_mask optional field_behaviour guidance a must. 2023-08-26: Adding consistency requirement. 2023-07-17: Make update_mask name guidance a must. 2022-11-04: Aggregated error guidance to AIP-193. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2021-11-04: Changed the permission check if allow_missing is set. 2021-07-08: Added error guidance for resource not found case. 2021-03-05: Changed the etag error from FAILED_PRECONDITION (which becomes HTTP 400) to ABORTED (409). 2020-10-06: Added guidance for declarative-friendly resources. 2020-10-06: Added guidance for allow_missing. 2020-08-14: Added error guidance for permission denied cases. 2020-06-08: Added guidance on returning the full resource. 2019-10-18: Added guidance on annotations. 2019-09-10: Added a link to the long-running operations AIP (AIP-151). 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership. 2019-06-10: Added guidance for long-running update. 2019-05-29: Added an explicit prohibition on arbitrary fields in standard methods.", + 'tags': '', + 'url': '/134', + }, +{ + 'title': "Standard methods: Delete", + 'text': "Standard methods: Delete In REST APIs, it is customary to make a DELETE request to a resource\u0027s URI (for example, /v1/publishers/{publisher}/books/{book}) in order to delete that resource. Resource-oriented design (AIP-121) honors this pattern through the Delete method. These RPCs accept the URI representing that resource and usually return an empty response. Guidance APIs should generally provide a delete method for resources unless it is not valuable for users to do so. Delete methods are specified using the following pattern: rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: \"/v1/{name=publishers/*/books/*}\" }; option (google.api.method_signature) = \"name\"; } The RPC\u0027s name must begin with the word Delete. The remainder of the RPC name should be the singular form of the resource\u0027s message name. The request message must match the RPC name, with a Request suffix. The response message should be google.protobuf.Empty. If the resource is soft deleted, the response message should be the resource itself. If the delete RPC is long-running, the response message must be a google.longrunning.Operation which resolves to the correct response. The HTTP verb must be DELETE. The request message field receiving the resource name should map to the URI path. This field should be called name. The name field should be the only variable in the URI path. All remaining parameters should map to URI query parameters. There must not be a body key in the google.api.http annotation. There should be exactly one google.api.method_signature annotation, with a value of \"name\". If an etag or force field are used, they may be included in the signature. If the API is operating on the Management Plane, the operation should have strong consistency: the completion of a delete operation must mean that the existence of the resource has reached a steady-state and reading resource state returns a consistent response. The API must fail with a FAILED_PRECONDITION error if child resources are present. See guidance on Cascading Delete if forcing deletion of parent and child resources is necessary. If the only child resource type is a Singleton, deletion must be allowed, because the lifecycle of a Singleton is tied to that of its parent resource. This applies even if there are multiple different Singleton resource types for the same parent resource. The Delete method should succeed if and only if a resource was present and was successfully deleted. If the resource did not exist, the method should send a NOT_FOUND error. Request message Delete methods implement a common request message pattern: message DeleteBookRequest { // The name of the book to delete. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; } A name field must be included. It should be called name. The field should be annotated as required. The field must identify the resource type that it references. The comment for the field should document the resource pattern. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. Soft delete Note: This material was moved into its own document to provide a more comprehensive treatment: AIP-164. Long-running delete Some resources take longer to delete a resource than is reasonable for a regular API request. In this situation, the API should use a long-running operation instead: rpc DeleteBook(DeleteBookRequest) returns (google.longrunning.Operation) { option (google.api.http) = { delete: \"/v1/{name=publishers/*/books/*}\" }; option (google.longrunning.operation_info) = { response_type: \"google.protobuf.Empty\" metadata_type: \"OperationMetadata\" }; } The response type must be set to the appropriate return type if the RPC was not long-running: google.protobuf.Empty for most Delete RPCs, or the resource itself for soft delete (AIP-164). Both the response_type and metadata_type fields must be specified (even if they are google.protobuf.Empty). Cascading delete Sometimes, it may be necessary for users to be able to delete a resource as well as all applicable child resources. However, since deletion is usually permanent, it is also important that users not do so accidentally, as reconstructing wiped-out child resources may be quite difficult. If an API allows deletion of a resource that may have child resources, the API should provide a bool force field on the request, which the user sets to explicitly opt in to a cascading delete. message DeletePublisherRequest { // The name of the publisher to delete. // Format: publishers/{publisher} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Publisher\" }]; // If set to true, any books from this publisher will also be deleted. // (Otherwise, the request will only work if the publisher has no books.) bool force = 2; } The API must fail with a FAILED_PRECONDITION error if the force field is false (or unset) and child resources are present. Protected delete Sometimes, it may be necessary for users to ensure that no changes have been made to a resource that is being deleted. If a resource provides an etag, the delete request may accept the etag (as either required or optional): message DeleteBookRequest { // The name of the book to delete. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; // Optional. The etag of the book. // If this is provided, it must match the server\u0027s etag. string etag = 2; } If the etag is provided and does not match the server-computed etag, the request must fail with a ABORTED error code. Note: Declarative-friendly resources (AIP-128) must provide the etag field for Delete requests. Delete if existing If the service uses client-assigned resource names, Delete methods may expose a bool allow_missing field, which will cause the method to succeed in the event that the user attempts to delete a resource that is not present (in which case the request is a no-op): message DeleteBookRequest { // The book to delete. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference).type = \"library.googleapis.com/Book\" ]; // If set to true, and the book is not found, the request will succeed // but no action will be taken on the server bool allow_missing = 2; } More specifically, the allow_missing flag triggers the following behavior: If the method call is on a resource that does not exist, the request is a no-op. The etag field is ignored. If the method call is on a resource that already exists, the resource is deleted (subject to other checks). Note: Declarative-friendly resources (AIP-128) should expose the bool allow_missing field. Errors If the user does not have permission to access the resource, regardless of whether or not it exists, the service must error with PERMISSION_DENIED (HTTP 403). Permission must be checked prior to checking if the resource exists. If the user does have proper permission, but the requested resource does not exist, the service must error with NOT_FOUND (HTTP 404) unless allow_missing is set to true. Further reading For soft delete and undelete, see AIP-164. For bulk deleting large numbers of resources based on a filter, see AIP-165. Changelog 2024-06-11: Add deletion behavior for parent resource deletion requests without a force field. 2023-08-24: Adding consistency requirement. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2022-02-02: Changed eTag error from FAILED_PRECONDITION to ABORTED making it consistent with change to AIP-154 \u0026 AIP-134 on 2021-03-05. 2020-10-06: Added guidance for declarative-friendly resources. 2020-10-06: Added guidance for allowing no-op delete for missing resources. 2020-10-06: Moved soft delete and undelete guidance into a new AIP-164. 2020-06-08: Added guidance for Get of soft-deleted resources. 2020-02-03: Added guidance for error cases. 2019-10-18: Added guidance on annotations. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership. 2019-06-10: Added guidance for long-running delete. 2019-05-29: Added an explicit prohibition on arbitrary fields in standard methods.", + 'tags': '', + 'url': '/135', + }, +{ + 'title': "Custom methods", + 'text': "Custom methods Resource-oriented design (AIP-121) uses custom methods to provide a means to express arbitrary actions that are difficult to model using only the standard methods. Custom methods are important because they provide a means for an API\u0027s vocabulary to adhere to user intent. Guidance Custom methods should only be used for functionality that can not be easily expressed via standard methods; prefer standard methods if possible, due to their consistent semantics. (Of course, this only applies if the functionality in question actually conforms to the normal semantics; it is not a good idea to contort things to endeavor to make the standard methods \"sort of work\".) While custom methods vary widely in how they are designed, many principles apply consistently: // Archives the given book. rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*}:archive\" body: \"*\" }; } Note: The pattern above shows a custom method that operates on a specific resource. Custom methods can be associated with resources, collections, or services. The bullets below apply in all three cases. The name of the method should be a verb followed by a noun. The name must not contain prepositions (\"for\", \"with\", etc.). The verb in the name should not contain any of the standard method verbs (Get, List, Create, Update, Delete). The name must not include the term Async. Instead, if the intention is to differentiate between immediate and long-running RPCs, the suffix LongRunning may be used for this purpose. For example, to create a long-running book creation RPC (if the standard CreateBook method was designed before long-running aspects were considered), a custom CreateBookLongRunning method could be introduced. The HTTP method must be GET or POST: GET must be used for methods retrieving data or resource state. POST must be used if the method has side effects or mutates resources or data. The HTTP URI must use a : character followed by the custom verb (:archive in the above example), and the verb in the URI must match the verb in the name of the RPC. If word separation is required, camelCase must be used. The body clause in the google.api.http annotation should be \"*\". See HTTP and gRPC Transcoding for more information. Custom methods should take a request message matching the RPC name, with a Request suffix. Custom methods should return a response message matching the RPC name, with a Response suffix. When operating on a specific resource, a custom method may return the resource itself. Resource-based custom methods Custom methods must operate on a resource if the API can be modeled as such: // Archives the given book. rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*}:archive\" body: \"*\" }; } The parameter for the resource\u0027s name must be called name, and be the only variable in the URI path. Collection-based custom methods While most custom methods operate on a single resource, some custom methods may operate on a collection instead: // Sorts the books from this publisher. rpc SortBooks(SortBooksRequest) returns (SortBooksResponse) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:sort\" body: \"*\" }; } If the collection\u0027s resource has a parent, that resource must be called parent and be the only variable in the URI path. The collection key (books in the above example) must be literal. Stateless methods Some custom methods are not attached to resources at all. These methods are generally stateless: they accept a request and return a response, and have no permanent effect on data within the API. // Translates the provided text from one language to another. rpc TranslateText(TranslateTextRequest) returns (TranslateTextResponse) { option (google.api.http) = { post: \"/v1/{project=projects/*}:translateText\" body: \"*\" }; } If the method runs in a particular scope (such as a project, as in the above example), the field name in the request message should be the name of the scope resource. If word separators are necessary, snake_case must be used. The URI should place both the verb and noun after the : separator (avoid a \"faux collection key\" in the URI in this case, as there is no collection). For example, :translateText is preferable to text:translate. Stateless methods must use POST if they involve billing. Declarative-friendly resources Declarative-friendly resources usually should not employ custom methods (except specific declarative-friendly custom methods discussed in other AIPs), because declarative-friendly tools are unable to automatically determine what to do with them. An exception to this is for rarely-used, fundamentally imperative operations, such as a Move or Rename operation, for which there would not be an expectation of declarative support. Rationale HTTP path Similar to standard methods, a custom method that operates on a resource or collection needs a name or parent parameter to indicate the resource that it operates on. This convention allows clients to map custom methods to the appropriate resource. HTTP methods Allowing both GET and POST HTTP verbs allows a clear distinction for which methods do not mutate data, and which ones do. Methods that only read data have first-class concepts in some clients (DataSources in Terraform) and clearly indicate to a user which methods can be called without risk of runtime impact. Disallowing prepositions Generally, method names with prepositions indicate that a new method is being used where a field should instead be added to an existing method, or the method should use a distinct verb. For example, if a CreateBook message already exists and you are considering adding CreateBookFromDictation, consider a TranscribeBook method instead. Similarly, if there is desire for a property-specific look-up method, instead of GetBookByAuthor consider a SearchBooks with an author field as a search dimension. This helps prevent an explosion of hyper-focused methods that bloat API and client surfaces, and add complexity to both managing and consuming the API. RPC name The term \"async\" is commonly used in programming languages to indicate whether a specific method call is synchronous or asynchronous, including for making RPCs. That sync/async aspect is at a different abstraction level to whether the RPC itself is intended to start a long-running operation. Using \"async\" within the RPC name itself causes confusion, and can even cause issues for client libraries which generate both synchronous and asynchronous methods to call the RPC in some languages. Changelog 2025-05-12: Extend disallowing prepositions rationale. 2025-01-09: Add original rationale for disallowing prepositions in names. 2023-11-16: Included link to AIP-127 \"HTTP and gRPC Transcoding\" for guidance on body definition. 2023-05-16: Added prohibition of the term \"async\" within RPC names. 2023-05-09: Adding guidance for POST and GET, require parent instead of the resource singular. 2023-03-02: Explicitly discourage use of standard method verbs. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-10-06: Added declarative-friendly guidance. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/136', + }, +{ + 'title': "Field names", + 'text': "Field names Naming fields in a way that is intuitive to users can often be one of the most challenging aspects of designing an API. This is true for many reasons; often a field name that seems entirely intuitive to the author can baffle a reader. Additionally, users rarely use only one API; they use many APIs together. As a result, a single company using the same name to mean different things (or different names to mean the same thing) can often cause unnecessary confusion, because users can no longer take what they\u0027ve already learned from one API and apply that to another. In short, APIs are easiest to understand when field names are simple, intuitive, and consistent with one another. Guidance Field names should be in correct American English. Field names should clearly and precisely communicate the concept being presented and avoid overly general names that are ambiguous. That said, field names should avoid including unnecessary words. In particular, avoid including adjectives that always apply and add little cognitive value. For example, a proxy_settings field might be as helpful as shared_proxy_settings if there is no unshared variant. Important: Field names often appear in generated client surfaces. Ensure they are appropriately descriptive and of suitable length. Case Field definitions in protobuf files must use lower_snake_case names. These names are mapped to an appropriate naming convention in JSON and in generated code. Additionally, each word in the field must not begin with a number, because it creates ambiguity when converting between snake case and camel case. Similarly, fields must not contain leading, trailing, or adjacent underscores. Uniformity APIs should endeavor to use the same name for the same concept and different names for different concepts wherever possible. This includes names across multiple APIs, in particular if those APIs are likely to be used together. Repeated fields Repeated fields must use the proper plural form, such as books or authors. On the other hand, non-repeated fields should use the singular form such as book or author. This implies that resource names should use the singular form as well, since the field name should follow the resource name (e.g., use repeated Book books, not Books books = 1). Prepositions Field names should not include prepositions (such as \"with\", \"for\", \"at\", \"by\", etc). For example: error_reason (not reason_for_error) author (not written_by) It is easier for field names to match more often when following this convention. Additionally, prepositions in field names may also indicate a design concern, such as an overly-restrictive field or a sub-optimal data type. This is particularly true regarding \"with\": a field named book_with_publisher likely indicates that the book resource may be improperly structured and worth redesigning. Note: The word \"per\" is an exception to this rule. See AIP-141 for guidance in the case where \"per\" is used as part of a unit (e.g. \"miles per hour\"). Abbreviations For well known name abbreviations among software developers, such as \"config\" and \"spec\", the abbreviations should be used in API definitions instead of the full spelling. This will make the source code easy to read and write. Examples: config (not configuration) id (not identifier) info (not information) spec (not specification) stats (not statistics) Furthermore, well known abbreviations for units should be used in field names. See AIP-141 for more guidance on fields that represent quantities. Examples: distance_km (not distance_kilometers) width_px (not width_pixels) Adjectives For uniformity, field names that contain both a noun and an adjective should place the adjective before the noun. For example: collected_items (not items_collected) imported_objects (not objects_imported) Verbs Field names must not be named to reflect an intent or action. They must not be verbs. Rather, because the field defines the desired value for mutations, e.g. Create and Update, and the current value for reads, e.g. Get and List, the name must be a noun. It defines what is so, not what to do. collected_items (not collect_items) disabled (not disable) In contrast, method names, whether standard or custom, change facets of resources and are named as verbs. Booleans Boolean fields should omit the prefix \"is\". For example: disabled (not is_disabled) required (not is_required) Note: Field names that would otherwise be reserved words are an exception to this rule. For example, is_new (not new). String vs. bytes When using bytes, the contents of the field are base64-encoded when using JSON on the wire. Services should use bytes when there is a need to send binary contents over the wire, and should not ask the user to manually base64-encode a field into a string field. The one exception is when the API is designed to handle data that is meant to be base64-encoded at rest and the double base64-encoding as a result of using bytes is undesirable - in this case, services may use a string. URIs Field names representing arbitrary URIs should use uri. In particular, note that URLs are URIs but not all URIs are URLs. Field names may use a prefix in front of uri as appropriate. Field names that can only represent a URL should use url. message Book { string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // A URL pointing to an image of the book. string image_url = 2; // A URI identifying the book. // This could be an ISBN or a URL. string uri = 3; } Note: APIs that have previously used uri for URL fields may continue to do so to avoid unnecessary API changes and to preserve local consistency. Reserved words Field names should avoid using names that are likely to conflict with keywords in common programming languages, such as new, class, function, import, etc. Reserved keywords can cause hardship for developers using the API in that language. Conflicts Messages should not include a field with the same name as the enclosing message (ignoring case transformations). This causes conflicts when generating code in some languages. Display names Many resources have a human-readable name, often used for display in UI. This field should be called display_name, and should not have a uniqueness requirement. If an entity has an official, formal name (such as a company name or the title of a book), an API may use title as the field name instead. The title field should not have a uniqueness requirement. Further reading For naming resource fields, see AIP-122. For naming fields representing quantities, see AIP-141. For naming fields representing time, see AIP-142. Rationale URI vs URL The guidance itself mentions that all URLs are URIs, but not all URIs are URLs. The goal of aligning on URI is to enable a more generalizable field, that can handle a variety of use cases, as well as drive standardization across APIs, creating a more coherent surface. At the same time, the requirement being a should allows for more specific terms when it truly merits it. Changelog 2025-10-23: Call out AIP-141 unit abbreviations as preferred. 2025-03-10: Add rationale for URI guidance. 2024-12-20: Copy over abbreviations guidance from old design site. 2024-08-26: Codify exception to string and base64 guidance 2024-05-18: Documented the effect of field names on client surfaces. 2023-04-25: Field names must not be expressed as verbs. 2021-07-12: Normalized display name guidance to \"should\". 2021-04-07: Added base64 and bytes guidance. 2021-03-05: Added prohibition on leading, trailing, or adjacent underscores. 2020-06-10: Added prohibition on starting any word with a number. 2020-05-29: Added guidance around URIs. 2020-03-24: Added guidance around conflicting field and message names. 2020-01-30: Added guidance around display_name and title.", + 'tags': '', + 'url': '/140', + }, +{ + 'title': "Quantities", + 'text': "Quantities Many services need to represent a discrete quantity of items (number of bytes, number of miles, number of nodes, etc.). Guidance Quantities with a clear unit of measurement (such as bytes, miles, and so on) must include the unit of measurement as the suffix. When appropriate, units should use generally accepted abbreviations, and abbreviations should not be pluralized (for example, distance_km rather than distance_kilometers). // A representation of a non-stop air route. message Route { // The airport where the route begins. string origin = 1; // The destination airport. string destination = 2; // The distance between the origin and destination airports. // This value is also used to determine the credited frequent flyer miles. int32 distance_miles = 3; } If the quantity is a number of items (for example, the number of nodes in a cluster), then the field should use the suffix _count (not the prefix num_): // A cluster of individual nodes. message Cluster { // The number of nodes in the cluster. int32 node_count = 1; } Note: Fields must not use unsigned integer types, because many programming languages and systems do not support them well. Compound units Quantities with compound units of measurement may use separating underscores between units as needed for clarity. Unabbreviated units must be separated. Abbreviated units should not be separated unless otherwise ambiguous. Compound units should be in plural form, with all component units in singular form except for the final component unit, which should be in plural form unless abbreviated. energy_kwh (not energy_kw_h) energy_kw_fortnights (not energy_kwfortnight or energy_kw_fortnight) Note: Metric prefixes must not be separated from their base unit. Inverse units Quantities with units of measurement that are or include inverse units should indicate all inverse units as a compound unit after a compound of any non-inverse units, separated by the word \"per\". The inverse compound unit should be in singular form. speed_miles_per_hour (not speed_mph) speed_meters_per_second (not speed_meters_per_seconds or speed_meter_per_second) event_count_per_hour (not events_per_hour, event_counts_per_hour, or hourly_events) price_per_kwh (using google.type.Money) Note: This guidance does not apply in cases where generally accepted derived units with special names and symbols exist for inverse quantities. For example, the derived unit \u0027hertz\u0027 should be used when appropriate for reciprocal time. Specialized messages It is sometimes useful to create a message that represents a particular quantity. This is particularly valuable in two situations: Grouping two or more individual quantities together. Example: google.protobuf.Duration Representing a common concept where the unit of measurement may itself vary. Example: google.type.Money APIs may create messages to represent quantities when appropriate. When using these messages as fields, APIs should use the name of the message as the suffix for the field name if it makes intuitive sense to do so. Changelog 2025-07-09: Added guidance for compound units. 2025-07-09: Clarified guidance to not pluralize abbreviated units. 2025-07-09: Clarified guidance to use per_ prefix to represent inverse units. 2019-09-13: Added the prohibition on uint and fixed types.", + 'tags': '', + 'url': '/141', + }, +{ + 'title': "Time and duration", + 'text': "Time and duration Many services need to represent the concepts surrounding time. Representing time can be challenging due to the intricacies of calendars and time zones, as well as the fact that common exchange formats (such as JSON) lack a native concept of time. Guidance Fields representing time should use the common, generally used components (such as google.protobuf.Timestamp or google.type.Date) for representing time or duration types. These types are common components, and using them consistently allows infrastructure and tooling to provide a better experience when interacting with time values. Timestamps Fields that represent an absolute point in time (independent of any time zone or calendar) should use the google.protobuf.Timestamp type, (which uses UNIX timestamps under the hood and hold nanosecond precision). These fields should have names ending in _time, such as create_time or update_time. For repeated fields, the names should end in _times instead. Many timestamp fields refer to an activity (for example, create_time refers to when the applicable resource was created). For these, the field should be named with the {imperative}_time form. For example, if a book is being published, the field storing the time when this happens would use the imperative form of the verb \"to publish\" (\"publish\") resulting in a field called publish_time. Fields should not be named using the past tense (such as published_time, created_time or last_updated_time). Durations Fields that represent a span between two points in time (independent of any time zone or calendar) should use the google.protobuf.Duration type. To illustrate the distinction between timestamps and durations, consider a flight record: // A representation of a (very incomplete) flight log. message FlightRecord { // The absolute point in time when the plane took off. google.protobuf.Timestamp takeoff_time = 1; // The length (duration) of the flight, from takeoff to landing. google.protobuf.Duration flight_duration = 2; } Note: Observant readers may notice that the timestamp and duration messages have the same structure (int64 seconds and int32 nanos). However, the distinction between these is important, because they have different semantic meaning. Additionally, tooling is able to base behavior off of which message is used. For example, a Python-based tool could convert timestamps to datetime objects and durations to timedelta objects. Relative time segments In some cases, it may be necessary to represent a time segment inside a stream. In these cases, the google.protobuf.Duration type should be used, and the field name should end with _offset. To ensure that the meaning is clear, the field must have a comment noting the point that the offset is relative to. To illustrate this, consider a resource representing a segment of an audio stream: message AudioSegment { // The duration relative to the start of the stream representing the // beginning of the segment. google.protobuf.Duration start_offset = 1; // The total length of the segment. google.protobuf.Duration segment_duration = 2; } Civil dates and times Fields that represent a calendar date or wall-clock time should use the appropriate common components: Civil date: google.type.Date Wall-clock time: google.type.TimeOfDay Fields representing civil dates should have names ending in _date, while fields representing civil times or datetimes should have names ending in _time. Note: Both the Date and TimeOfDay components are timezone-na\u00efve. Fields that require timezone-awareness should use DateTime (see below). Civil timestamps Fields that represent a civil timestamp (date and time, optionally with a time zone) should use the google.type.DateTime component, and the field name should end in _time. Compatibility Occasionally, APIs are unable to use the common structures for legacy or compatibility reasons. For example, an API may conform to a separate specification that mandates that timestamps be integers or ISO-8601 strings. In these situations, fields may use other types. If possible, the following naming conventions apply: For integers, include the meaning (examples: time, duration, delay, latency) and the unit of measurement (valid values: seconds, millis, micros, nanos) as a final suffix. For example, send_time_millis. For strings, include the meaning (examples: time, duration, delay, latency) but no unit suffix. In all cases, clearly document the expected format, and the rationale for its use.", + 'tags': '', + 'url': '/142', + }, +{ + 'title': "Standardized codes", + 'text': "Standardized codes Many common concepts, such as spoken languages, countries, currency, and so on, have common codes (usually formalized by the International Organization for Standardization) that are used in data communication and processing. These codes address the issue that there are often different ways to express the same concept in written language (for example, \"United States\" and \"USA\", or \"Espa\u00f1ol\" and \"Spanish\"). Guidance For concepts where a standardized code exists and is in common use, fields representing these concepts should use the standardized code for both input and output. // A message representing a book. message Book { // Other fields... // The IETF BCP-47 language code representing the language in which // the book was originally written. // https://en.wikipedia.org/wiki/IETF_language_tag string language_code = 99; } Fields representing standardized concepts must use the appropriate data type for the standard code (usually string). Fields representing standardized concepts should not use enums, even if they only allow a small subset of possible values. Using enums in this situation often leads to frustrating lookup tables when using multiple APIs together. Fields representing standardized concepts must indicate which standard they follow, preferably with a link (either to the standard itself, the Wikipedia description, or something similar). The field name should end in _code or _type unless the concept has an obviously clearer suffix. When accepting values provided by users, validation should be case-insensitive unless this would introduce ambiguity (for example, accept both en-gb and en-GB). When providing values to users, APIs should use the canonical case (in the example above, en-GB). Content types Fields representing a content or media type must use IANA media types. For legacy reasons, the field should be called mime_type. Countries and regions Fields representing individual countries or nations must use the Unicode CLDR region codes (list), such as US or CH, and the field must be called region_code. Important: Please read the rationale for this requirement. Currency Fields representing currency must use ISO-4217 currency codes, such as USD or CHF, and the field must be called currency_code. Note: For representing an amount of money in a particular currency, rather than the currency code itself, use google.type.Money. Language Fields representing spoken languages must use IETF BCP-47 language codes (list), such as en-US or de-CH, and the field must be called language_code. Time zones Fields representing a time zone should use the IANA TZ codes, and the field must be called time_zone. Fields also may represent a UTC offset rather than a time zone (note that these are subtly different). In this case, the field must use the ISO-8601 format to represent this, and the field must be named utc_offset. Rationale Country/region field naming The use of region_code instead of country_code is critical to being able to convey regions that are distinct from any country and to avoid any political disputes associated with said region regarding their sovereignty or affiliation. Google and many other companies are supporters of Unicode CLDR and standardize their product internationalization efforts on Unicode CLDR, and APIs are no different here. Furthermore, many of the values supported by Unicode CLDR are not countries on their own, so using a more generic name is actually more compatible with the specification. Changelog 2024-12-03: Strengthen rationale of country/region field naming 2024-11-12: Change country/region code list to CLDR list from IANA list 2020-05-12: Replaced country_code guidance with region_code, correcting an original error.", + 'tags': '', + 'url': '/143', + }, +{ + 'title': "Repeated fields", + 'text': "Repeated fields Representing lists of data in an API is trickier than it often appears. Users often need to modify lists in place, and longer data series within a single resource pose a challenge for pagination. Guidance Resources may use repeated fields where appropriate. message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; string name = 1 [(google.api.field_behavior) = IDENTIFIER]; repeated string authors = 2; } Repeated fields must use a plural field name. If the English singular and plural words are identical (\"moose\", \"info\"), the dictionary word must be used rather than attempting to coin a new plural form. Repeated fields should have an enforced upper bound that will not cause a single resource payload to become too large. A good rule of thumb is 100 elements. If repeated data has the chance of being too large, the API should use a sub-resource instead. Repeated fields must not represent the body of another resource inline. Instead, the message should provide the resource names of the associated resources. Scalars and messages Repeated fields should use a scalar type (such as string) if they are certain that additional data will not be needed in the future, as using a message type adds significant cognitive overhead and leads to more complicated code. However, if additional data is likely to be needed in the future, repeated fields should use a message instead of a scalar proactively, to avoid parallel repeated fields. Update strategies A resource may use two strategies to enable updating a repeated field: direct update using the standard Update method, or custom Add and Remove methods. A standard Update method has one key limitation: the user is only able to update the entire list. Field masks are unable to address individual entries in a repeated field. This means that the user must read the resource, make modifications to the repeated field value as needed, and send it back. This is fine for many situations, particularly when the repeated field is expected to have a small size (fewer than 10 or so) and race conditions are not an issue, or can be guarded against with ETags. Note: Declarative-friendly resources must use the standard Update method, and not introduce Add and Remove methods. If declarative tools need to reason about particular relationships while ignoring others, consider using a subresource instead. If atomic modifications are required, the API should define custom methods using the verbs Add and Remove: Note: If both of these strategies are too restrictive, consider using a subresource instead. rpc AddAuthor(AddAuthorRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{book=publishers/*/books/*}:addAuthor\" body: \"*\" }; } rpc RemoveAuthor(RemoveAuthorRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{book=publishers/*/books/*}:removeAuthor\" body: \"*\" }; } The data being added or removed should be a primitive (usually a string). For more complex data structures with a primary key, the API should use a map with the Update method instead. The RPC\u0027s name must begin with the word Add or Remove. The remainder of the RPC name should be the singular form of the field being added. The request message must match the RPC name, with a Request suffix. The response message should be the resource itself, unless there is useful context to provide in the response, in which case the response message must match the RPC name, with a Response suffix. When the response is the resource itself, it should include the fully-populated resource. The HTTP verb must be POST, as is usual for custom methods. The HTTP URI must end with :add* or :remove*, where * is the snake-case singular name of the field being added or removed. The request message field receiving the resource name should map to the URI path. The HTTP variable should be the name of the resource (such as book) rather than name or parent. That variable should be the only variable in the URI path. The body clause in the google.api.http annotation should be \"*\". If the data being added in an Add RPC is already present, the method must error with ALREADY_EXISTS. If the data being removed in a Remove RPC is not present, the method must error with NOT_FOUND. Request Message message AddAuthorRequest { // The name of the book to add an author to. string book = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference).type = \"library.googleapis.com/Book\" ]; string author = 2 [(google.api.field_behavior) = REQUIRED]; } message RemoveAuthorRequest { // The name of the book to remove an author from. string book = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference).type = \"library.googleapis.com/Book\" ]; string author = 2 [(google.api.field_behavior) = REQUIRED]; } A resource field must be included. It should be the name of the resource (such as book) rather than name or parent. The field should be annotated as required. The field should identify the resource type that it references. A field for the value being added or removed must be included. It should be the singular name of the field. The field should be annotated as required. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. Changelog 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-10-17: Recommended returning the resource itself in Add and Remove RPCs over separate response types. 2020-10-17: Added guidance for Add and Remove RPCs and requests.", + 'tags': '', + 'url': '/144', + }, +{ + 'title': "Ranges", + 'text': "Ranges Services often need to represent ranges of discrete or continuous values. These have wide differences in meaning, and come in many types: integers, floats, and timestamps, just to name a few, and the expected meaning of a range can vary in subtle ways depending on the type of range being discussed. Guidance A resource or message representing a range should ordinarily use two separate fields of the same type, with prefixes start_ and end_: // A representation of a chapter in a book. message Chapter { string title = 1; // The page where this chapter begins. int32 start_page = 2; // The page where the next chapter or section begins. int32 end_page = 3; } Inclusive or exclusive ranges Fields representing ranges should use inclusive start values and exclusive end values (half-closed intervals) in most situations; in interval notation: [start_xxx, end_xxx). Exclusive end values are preferable for the following reasons: It conforms to user expectations, particularly for continuous values such as timestamps, and avoids the need to express imprecise \"limit values\" (e.g. 2012-04-20T23:59:59). It is consistent with most common programming languages, including C++, Java, Python, and Go. It is easier to reason about abutting ranges: [0, x), [x, y), [y, z), where values are chainable from one range to the next. Timestamp intervals The following section describes the use of the google.type.Interval type, found amongst the common protos that are described in AIP-213. This type represents a range between two timestamps, with an inclusive start value and exclusive end value. Ranges between two timestamps which conform to the expectations of the Interval message should use this rather than having separate start and end fields. This allows client code to be written against the Interval message (such as checking whether a given timestamp occurs within the interval) and reused across multiple intervals in the same API, or even across multiple APIs. APIs may use start and end timestamp fields instead. In particular, if a message within an API is inherently describing an interval with extra information about that interval, the additional level of nesting introduced by using the Interval message may be undesirable. Exceptions In some cases, there is significant colloquial precedent for inclusive start and end values (closed intervals), to the point that using an exclusive end value would be confusing even for people accustomed to them. For example, when discussing dates (not to be confused with timestamps), most people use inclusive end: a conference with dates \"April 21-23\" is expected to run for three days: April 21, April 22, and April 23. This is also true for days of the week: a business that is open \"Monday through Friday\" is open, not closed, on Fridays. In this situation, the prefixes first and last should be used instead: // A representation of a chapter in a book. message Chapter { string title = 1; // The first page of the chapter. int32 first_page = 2; // The last page of the chapter. int32 last_page = 3; } Fields representing ranges with significant colloquial precedent for inclusive start and end values should use inclusive end values with first_ and last_ prefixes for those ranges only. The service should still use exclusive end values for other ranges where this does not apply, and must clearly document each range as inclusive or exclusive.", + 'tags': '', + 'url': '/145', + }, +{ + 'title': "Generic fields", + 'text': "Generic fields Most fields in any API, whether in a request, a resource, or a custom response, have a specific type or schema. This schema is part of the contract that developers write their code against. However, occasionally it is appropriate to have a generic or polymorphic field of some kind that can conform to multiple schemata, or even be entirely free-form. Guidance While generic fields are generally rare, a service may introduce generic field where necessary. There are several approaches to this depending on how generic the field needs to be; in general, services should attempt to introduce the \"least generic\" approach that is able to satisfy the use case. Oneof A oneof may be used to introduce a type union: the user or service is able to specify one of the fields inside the oneof. Additionally, a oneof may be used with the same type (usually strings) to represent a semantic difference between the options. Because the individual fields in the oneof have different keys, a developer can programmatically determine which (if any) of the fields is populated. A oneof preserves the largest degree of type safety and semantic meaning for each option, and services should generally prefer them over other generic or polymorphic options when feasible. However, the oneof construct is ill-suited when there is a large (or unlimited) number of potential options, or when there is a large resource structure that would require a long series of \"cascading oneofs\". Note: Adding additional possible fields to an existing oneof is a non-breaking change, but moving existing fields into or out of a oneof is breaking (it creates a backwards-incompatible change in Go protobuf stubs). Maps Maps may be used in situations where many values of the same type are needed, but the keys are unknown or user-determined. Maps are usually not appropriate for generic fields because the map values all share a type, but occasionally they are useful. In particular, a map can sometimes be suited to a situation where many objects of the same type are needed, with different behavior based on the names of their keys (for example, using keys as environment names). Struct The google.protobuf.Struct object may be used to represent arbitrary nested JSON. Keys can be strings, and values can be floats, strings, booleans, arrays, or additional nested structs, allowing for an arbitrarily nested structure that can be represented as JSON (and is automatically represented as JSON when using REST/JSON). A Struct is most useful when the service does not know the schema in advance, or when a service needs to store and retrieve arbitrary but structured user data. Using a Struct is convenient for users in this case because they can easily get JSON objects that can be natively manipulated in their environment of choice. If a service needs to reason about the schema of a Struct, it should use JSONSchema for this purpose. Because JSONSchema is itself JSON, a valid JSONSchema document can itself be stored in a Struct. Any The google.protobuf.Any object can be used to send an arbitrary serialized protocol buffer and a type definition. However, this introduces complexity, because an Any becomes useless for any task other than blind data propagation if the consumer does not have access to the proto. Additionally, even if the consumer does have the proto, the consumer has to ensure the type is registered and then deserialize manually, which is an often-unfamiliar process. Because of this, Any should not be used unless other options are infeasible.", + 'tags': '', + 'url': '/146', + }, +{ + 'title': "Sensitive fields", + 'text': "Sensitive fields Sometimes APIs need to collect sensitive information such as private encryption keys meant to be stored by the underlying service but not intended to be read after writing due to the sensitive nature of the data. For this type of data, extra consideration is required for the representation of the sensitive data in API requests and responses. Guidance If the sensitive information is required for the resource as a whole to exist, the data should be accepted as an input-only field with no corresponding output field. Because the sensitive data must be present for the resource to exist, users of the API may assume that existence of the resource implies storage of the sensitive data. For example: message SelfManagedKeypair { string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The public key data in PEM-encoded form. bytes public_key = 2; // The private key data in PEM-encoded form. bytes private_key = 3 [ (google.api.field_behavior) = INPUT_ONLY]; } If the sensitive information is optional within the containing resource, an output-only boolean field with a postfix of _set should be used to indicate whether or not the sensitive information is present. For example: message Integration { string name = 1 [(google.api.field_behavior) = IDENTIFIER]; string uri = 2; // A secret to be passed in the `Authorization` header of the webhook. string shared_secret = 3 [ (google.api.field_behavior) = INPUT_ONLY]; // True if a `shared_secret` has been set for this Integration. bool shared_secret_set = 4 [ (google.api.field_behavior) = OUTPUT_ONLY]; } If it is important to be able to identify the sensitive information without allowing it to be read back entirely, a field of the same type with an obfuscated_ prefix may be used instead of the boolean _set field to provide contextual information about the sensitive information. The specific nature of the obfuscation is outside the scope of this AIP. For example: message AccountRecoverySettings { // An email to use for account recovery. string email = 1 [ (google.api.field_behavior) = INPUT_ONLY]; // An obfuscated representation of the recovery email. For example, // `ada@example.com` might be represented as `a**@e*****e.com`. string obfuscated_email = 2 [ (google.api.field_behavior) = OUTPUT_ONLY]; }", + 'tags': '', + 'url': '/147', + }, +{ + 'title': "Standard fields", + 'text': "Standard fields Certain concepts are common throughout any corpus of APIs. In these situations, it is useful to have a standard field name and behavior that is used consistently to communicate that concept. Guidance Standard fields should be used to describe their corresponding concept, and should not be used for any other purpose. Resource names and IDs name Every resource must have a string name field, used for the resource name (AIP-122), which should be the first field in the resource. Note: The _name suffix should not be used to describe other types of names unless otherwise covered in this AIP. parent The string parent field refers to the resource name of the parent of a collection, and should be used in most List (AIP-132) and Create (AIP-133) requests. Other names display_name The string display_name field must be a mutable, user-settable field where the user can provide a human-readable name to be used in user interfaces. Declarative-friendly resources should include this field. Display names should not have uniqueness requirements, and should be limited to \u003c= 63 characters. title The string title field should be the official name of an entity, such as a company\u0027s name. This is a more formal variant of string display_name. given_name The string given_name field must refer to a human or animal\u0027s given name. Resources must not use first_name for this concept, because the given name is not placed first in many cultures. family_name The string family_name field must refer to a human or animal\u0027s family name. Resources must not use last_name for this concept, because the family name is not placed last in many cultures. Timestamps create_time The output only google.protobuf.Timestamp create_time field must represent the timestamp when the resource was created. This may be either the time creation was initiated or the time it was completed. Declarative-friendly resources should include this field. update_time The output only google.protobuf.Timestamp update_time field must represent the timestamp when the resource was most recently updated. Any change to the resource made by users must refresh this value; changes to a resource made internally by the service may refresh this value. Declarative-friendly resources should include this field. delete_time The output only google.protobuf.Timestamp delete_time field must represent the timestamp that a resource was soft deleted. This may correspond to either the time when the user requested deletion, or when the service successfully soft deleted the resource. If a resource is not soft deleted, the delete_time field must be empty. Resources that support soft delete (AIP-164) should provide this field. expire_time The google.protobuf.Timestamp expire_time field should represent the time that a given resource or resource attribute is no longer useful or valid (e.g. a rotating security key). It may be used for similar forms of expiration as described in AIP-214. Services may provide an expire_time value that is inexact, but the resource must not expire before that time. purge_time The google.protobuf.Timestamp purge_time field should represent the time when a soft deleted resource will be purged from the system (see AIP-164). It may be used for similar forms of expiration as described in AIP-214. Resources that support soft delete should include this field. Services may provide a purge_time value that is inexact, but the resource must not be purged from the system before that time. Annotations To store small amounts of arbitrary data, a map\u003cstring, string\u003e annotations field may be added. The annotations field must use the Kubernetes limits to maintain wire compatibility, and should require dot-namespaced annotation keys to prevent tools from trampling over one another. Examples of information that might be valuable to store in annotations include: For CI/CD, an identifier of the pipeline run or version control identifier used to propagate. Note: Annotations are distinct from various forms of labels. Labels can be used by server-side policies, such as IAM conditions. Annotations exist to allow client tools to store their own state information without requiring a database. Well known string fields IP address A field that represents an IP address must comply with the following: use type string use the name ip_address or end with the suffix _ip_address e.g. resolved_ip_address specify the IP address version format via one of the supported formats IPV4, IPV6, or if it can be either, IPV4_OR_IPV6 (see AIP-202) uid The output only string uid field refers to a system-assigned unique identifier for a resource. When provided, this field must be a UUID4 and must specify this format via the UUID4 format extension (see AIP-202). Declarative-friendly resources should include this field. Further reading For standardized codes, see AIP-143. For the etag field, see AIP-154. For the request_id field, see AIP-155. For the filter field, see AIP-160. For fields related to resource revisions, see AIP-162. For the validate_only field, see AIP-163. For fields related to soft delete and undelete, see AIP-164. Rationale Well known string fields Some fields represent very well defined concepts or artifacts that sometimes also have strict governance of their semantics. For such fields, presenting an equally standardized API surface is important. This enables development of improved API consumer tools and documentation, as well as a more unified user experience across the platform. History Before 2023-07, purge_time for soft-deleted resources was also called expire_time. purge_time was introduced to reduce user confusion. Changelog 2023-10-05: Introduce well known string fields with IP Address and uid. 2023-08-14: Introduce the term annotations from AIP-128. 2023-07-13: Introduce the term purge_time. 2021-04-06: Require output only field behavior for uid and delete_time fields.", + 'tags': '', + 'url': '/148', + }, +{ + 'title': "Unset field values", + 'text': "Unset field values In many messages, many fields are optional: the user is not required to provide them, or for output fields, the service might not populate the field. In most cases, there is no meaningful difference between setting it to a default value (such as 0) as opposed to not setting it at all; however, occasionally this distinction is meaningful. Guidance Services defined in protocol buffers should use the optional keyword for primitives if and only if it is necessary to distinguish setting the field to its default value (0, false, or empty string) from not setting it at all: // A representation of a book in a library. message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; // The name of the book. string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The rating for the book, from 0 to 5. // 0 is distinct from no rating. optional int32 rating = 2; } Important: Services should not need to distinguish between the default value and unset most of the time; if an alternative design does not require such a distinction, it is usually preferred. In practice, this means optional should only ever be used for integers and floats. Important: Tracking field presence is not the same as documenting API field behavior as defined in AIP-203. For example, a field labeled with optional for presence tracking may also be annotated as google.api.field_behavior = REQUIRED if the field must be set. If you only want to document the server perceived behavior of a field, read AIP-203. Backwards compatibility It is a backwards incompatible change to add or remove the optional qualifier to an existing field. This is because the compiled src API is changed (in some languages). For example, in Golang, adding optional changes the field type of primitives to be the pointer variant of their original type, e.g. a field formerly of type string becomes *string, etc. Accordingly, this change requires that both clients and servers update their usage of the changed field in unison, which is risky and error prone. Additional information is documented by Protobuf. Rationale field behavior and optional The field behavior annotation and optional label are not mutually exclusive, because they address different problems. The former, google.api.field_behavior, focuses on communicating the server\u0027s perception of a field within the API e.g. if it is required or not, if it is immutable, etc. The latter, proto3\u0027s optional, is a wire format and code generation option that is strictly for toggling field presence tracking. While it might be confusing for a field to be simultaneously annotated with google.api.field_behavior = REQUIRED and labeled as optional, they are unrelated in practice and can reasonably be used together. Changelog 2024-06-05: Add backwards compatibility considerations 2023-06-20: Differentiate from field behavior documentation", + 'tags': '', + 'url': '/149', + }, +{ + 'title': "Long-running operations", + 'text': "Long-running operations Occasionally, an API may need to expose a method that takes a significant amount of time to complete. In these situations, it is often a poor user experience to simply block while the task runs; rather, it is better to return some kind of promise to the user and allow the user to check back in later. The long-running operations pattern is roughly analogous to a Python Future, or a Node.js Promise. Essentially, the user is given a token that can be used to track progress and retrieve the result. Guidance Individual API methods that might take a significant amount of time to complete should return a google.longrunning.Operation object instead of the ultimate response message. // Create a book. rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books\" body: \"book\" }; option (google.longrunning.operation_info) = { response_type: \"Book\" metadata_type: \"OperationMetadata\" }; } The response type must be google.longrunning.Operation. The Operation proto definition must not be copied into individual APIs. The response must not be a streaming response. The method must include a google.longrunning.operation_info annotation, which must define both response and metadata types. The response and metadata types must be defined in the file where the RPC appears, or a file imported by that file. If the response and metadata types are defined in another package, the fully-qualified message name must be used. The response type should not be google.protobuf.Empty (except for Delete methods), unless it is certain that response data will never be needed. If response data might be added in the future, define an empty message for the RPC response and use that. The metadata type is used to provide information such as progress, partial failures, and similar information on each GetOperation call. The metadata type should not be google.protobuf.Empty, unless it is certain that metadata will never be needed. If metadata might be added in the future, define an empty message for the RPC metadata and use that. APIs with messages that return Operation must implement the Operations service. Individual APIs must not define their own interfaces for long-running operations to avoid non-uniformity. If an RPC supports a validate-only mode, the response to a validation request must be one of the following: A successful response with an Operation which is already complete, with the done field set to true, and a valid (but potentially empty) response message in the response field, wrapped in a google.protobuf.Any message. The name field may be empty, to avoid the service having to maintain state for successful validation. An immediate error response (typically \"bad request\") An Operation with the done field set to false, to indicate long-running validation. In this case, the name field must be set, to allow clients to poll the long-running validation operation until it has completed. Successful validation must eventually be represented by an operation with done=true and a valid (but potentially empty) wrapped response message in the response field. Unsuccessful validation must eventually be represented by an operation with done=true and the error details provided in the error field. Note: User expectations can vary on what is considered \"a significant amount of time\" depending on what work is being done. A good rule of thumb is 10 seconds. Standard methods APIs may return an Operation from the Create, Update, or Delete standard methods if appropriate. In this case, the response type in the operation_info annotation must be the standard and expected response type for that standard method. When creating or deleting a resource with a long-running operation, the resource should be included in List and Get calls; however, the resource should indicate that it is not usable, generally with a state enum. Parallel operations A resource may accept multiple operations that will work on it in parallel, but is not obligated to do so: Resources that accept multiple parallel operations may place them in a queue rather than work on the operations simultaneously. Resources that do not permit multiple operations in parallel (denying any new operation until the one that is in progress finishes) must return ABORTED if a user attempts a parallel operation, and include an error message explaining the situation. Resources with declarative-friendly APIs may allow subsequent updates to preempt existing operations. In this case, the latest update begins processing and previous operations are marked as ABORTED with an error message explaining the situation. Expiration APIs may allow their operation resources to expire after sufficient time has elapsed after the operation completed. Note: A good rule of thumb for operation expiry is 30 days. Errors Errors that prevent a long-running operation from starting must return an error response (AIP-193), similar to any other method. Operations that fail during their execution phase must return an error response (AIP-193), placed in the Operation.error google.rpc.Status field. Non-terminal errors that occur over the course of an operation may be placed in the metadata message and the field(s) must be AIP-193 compliant google.rpc.Status. Backwards compatibility Changing either the response_type or metadata_type of a long-running operation is a breaking change. Rationale Validate-only behavior The guidance for validate-only responses comes from a tension between clients, which benefit from \"fully formed\" operations that can be treated uniformly, and servers, which don\u0027t wish to maintain additional state for trivial operations. It seems counterintuitive that just validating a request should generate more state, but a full operation response that can be fetched later would either require that or \"special\" singleton operation IDs. The guidance provided is a compromise: by returning a \"done\" operation, clients can use existing logic to check that the operation has completed successfully (and therefore doesn\u0027t need to be fetched for an updated status) but server don\u0027t need to maintain any additional state. Changelog 2025-02-04: Clarified error propagation behavior for failures that occur during long-running operations. 2024-04-23: Provided pattern for validation on RPCs returning long-running operations. 2022-05-31: Added compatibility section. 2020-08-24: Clarified that responses are not streaming responses. 2020-06-24: Added guidance for parallel operations. 2020-03-20: Clarified that both response_type and metadata_type are required. 2019-11-22: Added a short explanation of what metadata_type is for. 2019-09-23: Added guidance on errors. 2019-08-23: Added guidance about fully-qualified message names when the message name is in another package. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/151', + }, +{ + 'title': "Jobs", + 'text': "Jobs Occasionally, APIs may need to expose a task that takes significant time to complete, and where a transient long-running operation is not appropriate. For example, a task could need to run repeatedly, or have separate permissions for configuring the task as opposed to running it. Guidance An API may define a Job resource to represent a particular task with distinct setup, configuration, and execution: message WriteBookJob { option (google.api.resource) = { type: \"library.googleapis.com/WriteBookJob\" pattern: \"publishers/{publisher}/writeBookJobs/{write_book_job}\" }; // Name and other fields... } The name of the resource must end with the word \"Job\". The prefix should be a valid RPC name, with a verb and a noun. The service should define all five of the standard methods (AIP-131, AIP-132, AIP-133, AIP-134, AIP-135), and use them as the primary way to configure the job. Run method The service should define a Run custom method that executes the job immediately: rpc RunWriteBookJob(RunWriteBookJobRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{name=publishers/*/writeBookJobs/*}:run\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"RunWriteBookJobResponse\" metadata_type: \"RunWriteBookJobMetadata\" }; } The RPC\u0027s name must begin with the word Run. The remainder of the RPC name should be the singular form of the job resource being run. The request message must match the RPC name, with a Request suffix. The method should return a long-running operation, which must resolve to a response message that includes the result of running the job. The response message name must match the RPC name, with a Response suffix. The method may use any metadata message it wishes. The HTTP verb must be POST, as is usual for custom methods. The body clause in the google.api.http annotation should be \"*\". The URI path should contain a single name variable corresponding to the name of the job resource being run. The URI path must end with :run. Errors that prevent execution of the job from starting must return an error response (AIP-193), similar to any other method. Errors that occur over the course of the job execution may be placed in the metadata message. The errors themselves must still be represented with a google.rpc.Status object. Run request message Run methods implement a common request message pattern: message RunWriteBookJobRequest { // The name of the job to run. string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/WriteBookJob\" }]; } A singular string name field must be included. The field should be annotated as required. The field should identify the resource type that it references. Executions and results Ordinarily, the API should provide results to the user as the final response of the Run method. However, this is sometimes insufficient; for example, a job that runs on a recurring schedule in the background can not deliver results to the user in this way. The service may store resources representing individual executions along with their result as a sub-collection of resources under the job, which allows the user to list past job executions. A service that does this should define the Get, List, and Delete methods for the execution resources: message WriteBookJobExecution { option (google.api.resource) = { type: \"library.googleapis.com/WriteBookJobExecution\" pattern: \"publishers/{publisher}/writeBookJobs/{write_book_job}/executions/{execution}\" }; // Name and other information about the execution, such as metadata, the // result, error information, etc. } In this case, the operation returned by job\u0027s Run method should refer to the child resource. Changelog 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-11-02: Expanded guidance on HTTP, field behavior, and resource reference annotations and request format.", + 'tags': '', + 'url': '/152', + }, +{ + 'title': "Import and export", + 'text': "Import and export Many users want to be able to load data into an API, or get their existing data out of an API. This is particularly important for enterprise users, who are often concerned about vendor lock-in. Guidance APIs may support import and export operations, which may create multiple new resources, or they may populate data into a single resource. Multiple resources Services may support importing and exporting multiple resources into or out of an API, and should implement a common pattern to do so: rpc ImportBooks(ImportBooksRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:import\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"ImportBooksResponse\" metadata_type: \"ImportBooksMetadata\" }; } rpc ExportBooks(ExportBooksRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:export\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"ExportBooksResponse\" metadata_type: \"ExportBooksMetadata\" }; } The method must return a long-running operation (see AIP-151) unless the service can guarantee that it will never need more than a few seconds to complete. The HTTP verb must be POST, and the body must be \"*\". A parent field should be included as part of the URI. If importing into or exporting from multiple resources is required, the API should keep the parent field and allow the user to use the - character to indicate multiple parents (see AIP-159). On import, if the user provides a specific parent, the API must reject any imported resources that would be added to a different parent. The URI suffix should be :import or :export. Data for a single resource Services may support importing and exporting data into or out of a single resource, and should implement a common pattern to do so: rpc ImportPages(ImportPagesRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{book=publishers/*/books/*}:importPages\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"ImportPagesResponse\" metadata_type: \"ImportPagesMetadata\" }; } rpc ExportPages(ExportPagesRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{book=publishers/*/books/*}:exportPages\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"ExportPagesResponse\" metadata_type: \"ExportPagesMetadata\" }; } The method must return a long-running operation (see AIP-151) unless the service can guarantee that it will never need more than a few seconds to complete. The HTTP verb must be POST, and the body must be \"*\". A field representing the resource that data is being imported into should be included as part of the URI. The field should be named after the resource (and should not be called name). The URI suffix should include both the verb and a noun for the data itself, such as :importPages or :exportPages. Request object Imports and exports often require two fundamentally different types of configuration: Configuration specific to the source or destination. Configuration regarding the imported or exported data itself. Source or destination configuration should be grouped into a single message and placed inside a oneof: message ImportBooksRequest { string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; oneof source { AuthorSource author_source = 2; TranslatorSource translator_source = 3; } string isbn_prefix = 4; } message ExportBooksRequest { string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; oneof destination { PrinterDestination printer_destination = 2; TranslatorDestination translator_destination = 3; } string filter = 4; } The source configuration messages must be placed within a oneof source (for import) or oneof destination (for export), even if there is only one. (This maintains flexibility to add more later.) Configuration related to the data itself (and therefore common across all sources) must be placed at the top-level of the request message. Note: The configuration for import and export may be different from one another. (For example, it would be sensible to import from a file but export to a directory.) Inline sources APIs may also permit import and export \"inline\", where the contents to be imported or exported are provided in the request or response. message InlineSource { repeated Book books = 1; } The source or destination should be named InlineSource or InlineDestination. The message should include a repeated field representing the resource. However, if the resource structure is complex, the API may use a separate inline representation. In this situation, the same format must be used for both import and export. Partial failures While partial failures are normally discouraged, import and export RPCs should include partial failure information in the metadata object. Each individual error should be a google.rpc.Status object describing the error. For more on errors, see AIP-193.", + 'tags': '', + 'url': '/153', + }, +{ + 'title': "Resource freshness validation", + 'text': "Resource freshness validation APIs often need to validate that a client and server agree on the current state of a resource before taking some kind of action on that resource. For example, two processes updating the same resource in parallel could create a race condition, where the latter process \"stomps over\" the effort of the former one. ETags provide a way to deal with this, by allowing the server to send a checksum based on the current content of a resource; when the client sends that checksum back, the server can ensure that the checksums match before acting on the request. Guidance A resource may include an etag field on any resource where it is important to ensure that the client has an up to date resource before acting on certain requests: // A representation of a book. message Book { // Other fields... // This checksum is computed by the server based on the value of other // fields, and may be sent on update and delete requests to ensure the // client has an up-to-date value before proceeding. string etag = 99; } The etag field must be a string, and must be named etag. The etag field on the resource should not be given any behavior annotations. The etag field must be provided by the server on output, and values should conform to RFC 7232. If a user sends back an etag which matches the current etag value, the service must permit the request (unless there is some other reason for failure). If a user sends back an etag which does not match the current etag value, the service must send an ABORTED error response (unless another error takes precedence, such as PERMISSION_DENIED if the user is not authorized). If the user does not send an etag value at all, the service should permit the request. However, services with strong consistency or parallelism requirements may require users to send etags all the time and reject the request with an INVALID_ARGUMENT error in this case. Note: ETag values should include quotes as described in RFC 7232. For example, a valid etag is \"foo\", not foo. Declarative-friendly resources A resource that is declarative-friendly (AIP-128) must include an etag field. Etags on request methods In some situations, the etag needs to belong on a request message rather than the resource itself. For example, an Update standard method can \"piggyback\" off the etag field on the resource, but the Delete standard method can not: message DeleteBookRequest { // The name of the book. string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; // The current etag of the book. // If an etag is provided and does not match the current etag of the book, // deletion will be blocked and an ABORTED error will be returned. string etag = 2 [(google.api.field_behavior) = OPTIONAL]; } On a request message, the etag field should be given a behavior annotation - either REQUIRED or OPTIONAL. See AIP-203 for more information. An etag field may also be used on custom methods, similar to the example above. Strong and weak etags ETags can be either \"strongly validated\" or \"weakly validated\": A strongly validated etag means that two resources bearing the same etag are byte-for-byte identical. A weakly validated etag means that two resources bearing the same etag are equivalent, but may differ in ways that the service does not consider to be important. Resources may use either strong or weak etags, as it sees fit, but should document the behavior. Additionally, weak etags must have a W/ prefix as mandated by RFC 7232. Further reading For how to retry on errors in client libraries, see AIP-194. Changelog 2021-04-01: Updated an additional reference to FAILED_PRECONDITION to ABORTED. 2021-03-05: Changed the etag error from FAILED_PRECONDITION (which becomes HTTP 400) to ABORTED (409). 2020-10-06: Added declarative-friendly resource requirement. 2020-09-02: Clarified that other errors may take precedence over FAILED_PRECONDITION for etag mismatches. 2020-09-02: Add guidance for etags on request messages. 2019-09-23: Changed the title to \"resource freshness validation\".", + 'tags': '', + 'url': '/154', + }, +{ + 'title': "Request identification", + 'text': "Request identification It is sometimes useful for an API to have a unique, customer-provided identifier for particular requests. This can be useful for several purposes, such as de-duplicating requests from parallel processes, ensuring the safety of retries, or auditing. The most important purpose for request IDs is to provide idempotency guarantees: allowing the same request to be issued more than once without subsequent calls having any effect. In the event of a network failure, the client can retry the request, and the server can detect duplication and ensure that the request is only processed once. Guidance APIs may add a string request_id parameter to request messages (including those of standard methods) in order to uniquely identify particular requests. message CreateBookRequest { // The parent resource where this book will be created. // Format: publishers/{publisher} string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The ID to use for the book, which will become the final component of // the book\u0027s resource name. // // This value should be 4-63 characters, and valid characters // are /[a-z][0-9]-/. string book_id = 2 [(google.api.field_behavior) = REQUIRED]; // The book to create. Book book = 3 [(google.api.field_behavior) = REQUIRED]; // A unique identifier for this request. Restricted to 36 ASCII characters. // A random UUID is recommended. // This request is only idempotent if a `request_id` is provided. string request_id = 4 [(google.api.field_info).format = UUID4]; } Providing a request ID must guarantee idempotency. If a duplicate request is detected, the server should return the response for the previously successful request, because the client most likely did not receive the previous response. APIs may choose any reasonable timeframe for honoring request IDs. The request_id field must be provided on the request message to which it applies (and it must not be a field on resources themselves). Request IDs should be optional. Request IDs should be able to be UUIDs, and may allow UUIDs to be the only valid format. The format restrictions for request IDs must be documented. Request IDs that are UUIDs must be annotated with the google.api.FieldInfo.Format value UUID4 using the extension (google.api.field_info).format = UUID4. See AIP-202 for more. Stale success responses In some unusual situations, it may not be possible to return an identical success response. For example, a duplicate request to create a resource may arrive after the resource has not only been created, but subsequently updated; because the service has no other need to retain the historical data, it is no longer feasible to return an identical success response. In this situation, the method may return the current state of the resource instead. In other words, it is permissible to substitute the historical success response with a similar response that reflects more current data. Further reading For which codes to retry, see AIP-194. For how to retry errors in client libraries, see AIP-4221. Rationale Using UUIDs for request identification When a value is required to be unique, leaving the format open-ended can lead to API consumers incorrectly providing a duplicate identifier. As such, standardizing on a universally unique identifier drastically reduces the chance for collisions when done correctly. Changelog 2024-01-08: Add book_id to request message. 2023-10-02: Add UUID format extension guidance. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/155', + }, +{ + 'title': "Singleton resources", + 'text': "Singleton resources APIs sometimes need to represent a resource where exactly one instance of the resource always exists within any given parent. A common use case for this is for a config object. Guidance An API may define singleton resources. A singleton resource must always exist by virtue of the existence of its parent, with one and exactly one per parent. For example: message Config { option (google.api.resource) = { type: \"api.googleapis.com/Config\" pattern: \"users/{user}/config\" singular: \"config\" plural: \"configs\" }; // additional fields including name } The Config singleton would have the following RPCs: rpc GetConfig(GetConfigRequest) returns (Config) { option (google.api.http) = { get: \"/v1/{name=users/*/config}\" }; } rpc UpdateConfig(UpdateConfigRequest) returns (Config) { option (google.api.http) = { patch: \"/v1/{config.name=users/*/config}\" body: \"config\" }; } Singleton resources must not have a user-provided or system-generated ID; their resource name includes the name of their parent followed by one static-segment. Example: users/1234/config Singleton resources are always singular. Example: users/1234/thing Singleton resource definitions must provide both the singular and plural fields (see above example). Singleton resources may parent other resources. Singleton resources must not define the Create or Delete standard methods. The singleton is implicitly created or deleted when its parent is created or deleted. Singleton resources should define the Get and Update methods, and may define custom methods as appropriate. However, singleton resources must not define the Update method if all fields on the resource are output only. Singleton resources may define the List method, but must implement it according to AIP-159. See the example below. The trailing segment in the path pattern that typically represents the collection should be the plural form of the Singleton resource e.g. /v1/{parent=users/*}/configs. If a parent resource ID is provided instead of the hyphen - as per AIP-159, then the service should return a collection of one Singleton resource corresponding to the specified parent resource. rpc ListConfigs(ListConfigsRequest) returns (ListConfigsResponse) { option (google.api.http) = { get: \"/v1/{parent=users/*}/configs\" }; } message ListConfigsRequest { // To list all configs, use `-` as the user id. // Formats: // * `users/-` // * `users/{user}` // // Note: Specifying an actual user id will return a collection of one config. // Use GetConfig instead. string parent = 1 [ (google.api.resource_reference).child_type = \"api.googleapis.com/Config\"]; // other standard pagination fields... } Rationale Support for Standard List While Singleton resources are not directly part of a collection themselves, they can be viewed as part of their parent\u0027s collection. The one-to-one relationship of parent-to-singleton means that for every one parent there is one singleton instance, naturally enabling some collection-based methods when combined with the pattern of Reading Across Collections. The Singleton can present as a collection to the API consumer as it is indirectly one based on its parent. Furthermore, presenting the Singleton resource as a pseudo-collection in such methods enables future expansion to a real collection, should a Singleton be found lacking. Including plural definition While a Singleton is by definition singular, there are certain cases where a Singleton resource may appear in a plural form e.g., if the service supports Standard List (as defined here). As such, it is better to forward declare the plural form of the Singleton resource type than to not have it when needed. Changelog 2024-04-15: Singletons must specify singular and plural in resource. 2023-08-10: Add Standard List support. 2023-07-26: Clarified that read-only singletons should not have Update. 2021-11-02: Added an example message and state parent eligibility. 2021-01-14: Changed example from settings to config for clarity.", + 'tags': '', + 'url': '/156', + }, +{ + 'title': "Partial responses", + 'text': "Partial responses Sometimes, a resource can be either large or expensive to compute, and the API needs to give the user control over which fields it sends back. Guidance APIs may support partial responses in one of two ways: Field masks parameter Field masks (google.protobuf.FieldMask) can be used for granting the user fine-grained control over what fields are returned. An API should support the mask in a side channel. For example, the parameter can be specified either using an HTTP query parameter, an HTTP header, or a gRPC metadata entry. Google Cloud APIs specify field masks as a system parameter. Field masks should not be specified in the request. The value of the field mask parameter must be a google.protobuf.FieldMask. The field mask parameter must be optional: An explicit value of \"*\" should be supported, and must return all fields. If the field mask parameter is omitted, it must default to \"*\", unless otherwise documented. An API may allow read masks with non-terminal repeated fields (unlike update masks), but is not obligated to do so. Note: Changing the default value of the field mask parameter is a breaking change. View enumeration Alternatively, an API may support partial responses with view enums. View enums are useful for situations where an API only wants to expose a small number of permutations to the user: enum BookView { // The default / unset value. // The API will default to the BASIC view. BOOK_VIEW_UNSPECIFIED = 0; // Include basic metadata about the book, but not the full contents. // This is the default value (for both ListBooks and GetBook). BOOK_VIEW_BASIC = 1; // Include everything. BOOK_VIEW_FULL = 2; } The enum should be specified as a view field on the request message. The enum should be named something ending in -View The enum should at minimum have values named BASIC and FULL (although it may have values other than these). The UNSPECIFIED value must be valid (not an error), and the API must document what the unspecified value will do. For List RPCs, the effective default value should be BASIC. For the following RPC types, the effective default value should be either BASIC or FULL: Get Create Update Soft Delete Custom Method The enum should be defined at the top level of the proto file (as it is likely to be needed in multiple requests, e.g. both Get and List). See AIP-126 for more guidance on top-level enumerations. APIs may add fields to a given view over time. APIs must not remove a field from a given view (this is a breaking change). Note: If a service requires (or might require) multiple views with overlapping but distinct values, there is a potential for a namespace conflict. In this situation, the service should nest the view enum within the individual resource. Note: Having a partial response be the default of standard methods can degrade the effectiveness of declarative clients. Providing a mechanism to request the full resource be populated in the response, like this View pattern, is preferred if partial responses are deemed necessary. Read masks as a request field Warning: Read mask as a single, explicit field on the request message is DEPRECATED for Google APIs. The system parameter must be used instead. The following guidance is for the benefit of existing legacy Google and external non-Google usage. An API may support read masks as a single field on the request message: google.protobuf.FieldMask read_mask. The read mask must be a google.protobuf.FieldMask and should be named read_mask. The field mask should be optional: An explicit value of \"*\" should be supported, and must return all fields. If the field mask parameter is not provided, all fields must be returned. An API may allow read masks with non-terminal repeated fields (unlike update masks), but is not obligated to do so. Rationale Deprecating read_mask in request messages As mentioned, Google API infrastructure implements a service-wide response field filtering mechanism, so there is no need for individual API methods to specify a read_mask in their request schema. Doing so is both redundant and a potential point of conflict for the client or service. Changelog 2025-10-03: Added default view guidance for other RPC types, and declarative client warning. 2025-06-16: Reinstate read mask guidance as historical/external reference. 2023-05-09: Fix top-level enum example and link to AIP-126. 2022-03-14: Updated guidance on default value and how to specify a read mask. 2021-10-06: Updated the guidance with system parameters. 2021-03-04: Added guidance for conflicting view enums.", + 'tags': '', + 'url': '/157', + }, +{ + 'title': "Pagination", + 'text': "Pagination APIs often need to provide collections of data, most commonly in the List standard method. However, collections can often be arbitrarily sized, and also often grow over time, increasing lookup time as well as the size of the responses being sent over the wire. Therefore, it is important that collections be paginated. Guidance RPCs returning collections of data must provide pagination at the outset, as it is a backwards-incompatible change to add pagination to an existing method. // The request structure for listing books. message ListBooksRequest { // The parent, which owns this collection of books. // Format: publishers/{publisher} string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The maximum number of books to return. The service may return fewer than // this value. // If unspecified, at most 50 books will be returned. // The maximum value is 1000; values above 1000 will be coerced to 1000. int32 page_size = 2; // A page token, received from a previous `ListBooks` call. // Provide this to retrieve the subsequent page. // // When paginating, all other parameters provided to `ListBooks` must match // the call that provided the page token. string page_token = 3; } // The response structure from listing books. message ListBooksResponse { // The books from the specified publisher. repeated Book books = 1; // A token that can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. string next_page_token = 2; } Request messages for collections should define an int32 page_size field, allowing users to specify the maximum number of results to return. The page_size field must not be required. If the user does not specify page_size (or specifies 0), the API chooses an appropriate default, which the API should document. The API must not return an error. If the user specifies page_size greater than the maximum permitted by the API, the API should coerce down to the maximum permitted page size. If the user specifies a negative value for page_size, the API must send an INVALID_ARGUMENT error. The API may return fewer results than the number requested (including zero results), even if not at the end of the collection. Request messages for collections should define a string page_token field, allowing users to advance to the next page in the collection. The page_token field must not be required. If the user changes the page_size in a request for subsequent pages, the service must honor the new page size. The user is expected to keep all other arguments to the RPC the same; if any arguments are different, the API should send an INVALID_ARGUMENT error. The response must not be a streaming response. Response messages for collections should define a string next_page_token field, providing the user with a page token that may be used to retrieve the next page. The field containing pagination results should be the first field in the message and have a field number of 1. It should be a repeated field containing a list of resources constituting a single page of results. If the end of the collection has been reached, the next_page_token field must be empty. This is the only way to communicate \"end-of-collection\" to users. If the end of the collection has not been reached (or if the API can not determine in time), the API must provide a next_page_token. Response messages for collections may provide an int32 total_size field, providing the user with the total number of items in the list. This total may be an estimate (but the API should explicitly document that). Skipping results The request definition for a paginated operation may define an int32 skip field to allow the user to skip results. The skip value must refer to the number of individual resources to skip, not the number of pages. For example: A request with no page token and a skip value of 30 returns a single page of results starting with the 31st result. A request with a page token corresponding to the 51st result (because the first 50 results were returned on the first page) and a skip value of 30 returns a single page of results starting with the 81st result. If a skip value is provided that cannot be fulfilled e.g. due to latency of querying a massive data set, the response must be 200 OK with an empty result set. If it is known to put the cursor beyond the total size of the collection, the response must not include a next_page_token. Opacity Page tokens provided by APIs must be opaque (but URL-safe) strings, and must not be user-parseable. This is because if users are able to deconstruct these, they will do so. This effectively makes the implementation details of your API\u0027s pagination become part of the API surface, and it becomes impossible to update those details without breaking users. Warning: Base-64 encoding an otherwise-transparent page token is not a sufficient obfuscation mechanism. For page tokens which do not need to be stored in a database, and which do not contain sensitive data, an API may obfuscate the page token by defining an internal protocol buffer message with any data needed, and send the serialized proto, base-64 encoded. Page tokens must be limited to providing an indication of where to continue the pagination process only. They must not provide any form of authorization to the underlying resources, and authorization must be performed on the request as with any other regardless of the presence of a page token. Expiring page tokens Many APIs store page tokens in a database internally. In this situation, APIs may expire page tokens a reasonable time after they have been sent, in order not to needlessly store large amounts of data that is unlikely to be used. It is not necessary to document this behavior. Note: While a reasonable time may vary between APIs, a good rule of thumb is three days. Backwards compatibility Adding pagination to an existing RPC is a backwards-incompatible change. This may seem strange; adding fields to proto messages is generally backwards compatible. However, this change is behaviorally incompatible. Consider a user whose collection has 75 resources, and who has already written and deployed code. If the API later adds pagination fields, and sets the default to 50, then that user\u0027s code breaks; it was getting all resources, and now is only getting the first 50 (and does not know to advance pagination). Even if the API set a higher default limit, such as 100, the user\u0027s collection could grow, and then the code would break. Additionally, client libraries implement automatic pagination, typically representing paginated RPCs using different method signatures to unpaginated ones. This means that adding pagination to a previously-unpaginated method causes a breaking change in those libraries. For this reason, it is important to always add pagination to RPCs returning collections up front; they are consistently important, and they can not be added later without causing problems for existing users. Warning: This also entails that, in addition to presenting the pagination fields, they must be actually implemented with a non-infinite default value. Implementing an in-memory version (which might fetch everything then paginate) is reasonable for initially-small collections. Rationale Degraded skip response Large collections, complex queries, and globally distributed data can all contribute to a paginated method being unable to quickly or confidently fulfill a given skip request. Backend queries can timeout, data collation can take time, and the end user experience need not suffer as a result. In such cases, the pagination interface can be leveraged to keep the client engaged by providing a next_page_token, while the service collects an appropriate result. When the service has definitively determined that the requested skip exceeds the available results, the pagination interface is again applied and next_page_token is omitted to signal the end of results. Changelog 2025-07-08: Clarify degraded skip response guidance 2020-05-24: Clarified that adding pagination breaks client libraries. 2020-05-13: Added guidance for skipping results. 2020-08-24: Clarified that responses are not streaming responses. 2020-06-24: Clarified that page size is always optional for users. 2019-02-12: Added guidance on the field being paginated over. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership. 2019-07-19: Update the opacity requirement from \"should\" to \"must\".", + 'tags': '', + 'url': '/158', + }, +{ + 'title': "Reading across collections", + 'text': "Reading across collections Sometimes, it is useful for a user to be able to retrieve resources across multiple collections, or retrieve a single resource without needing to know what collection it is in. Guidance APIs may support reading resources across multiple collections by allowing users to specify a - (the hyphen or dash character) as a wildcard character in a standard List method: GET /v1/publishers/-/books?filter=... The URI pattern must still be specified with * and permit the collection to be specified; a URI pattern must not hard-code the - character. The method must explicitly document that this behavior is supported. The resources provided in the response must use the canonical name of the resource, with the actual parent collection identifiers (instead of -). Services may support reading across collections on List requests regardless of whether the identifiers of the child resources are guaranteed to be unique. However, services must not support reading across collections on Get requests if the child resources might have a collision. Cross-parent requests should not support order_by. If they do, the field must document that it is best effort. This is because cross-parent requests introduce ambiguity around ordering, especially if there is difficulty reaching a parent (see AIP-217). Important: If listing across multiple collections introduces the possibility of partial failures due to unreachable parents (such as when listing across locations), the method must indicate this following the guidance in AIP-217. Unique resource lookup Sometimes, a resource within a sub-collection has an identifier that is unique across parent collections. In this case, it may be useful to allow a Get method to retrieve that resource without knowing which parent collection contains it. In such cases, APIs may allow users to specify the wildcard collection ID - (the hyphen or dash character) to represent any parent collection: GET https://example.googleapis.com/v1/publishers/-/books/{book} The URI pattern must still be specified with * and permit the collection to be specified; a URI pattern must not hard-code the - character. The method must explicitly document that this behavior is supported. The resource name in the response must use the canonical name of the resource, with actual parent collection identifiers (instead of -). For example, the request above returns a resource with a name like publishers/123/books/456, not publishers/-/books/456. The resource ID must be unique within parent collections. Further reading For partial failures due to unreachable resources, see AIP-217. Changelog 2019-08-26: Added a reference to guidance for unreachable resources. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/159', + }, +{ + 'title': "Filtering", + 'text': "Filtering Often, when listing resources (using a list method as defined in AIP-132 or something reasonably similar), it is desirable to filter over the collection and only return results that the user is interested in. It is tempting to define a structure to handle the precise filtering needs for each API. However, filtering requirements evolve frequently, and therefore it is prudent to use a string field with a structured syntax accessible to a non-technical audience. This allows updates to be able to be made transparently, without waiting for UI or client updates. Note: Because list filters are intended for a potentially non-technical audience, they sometimes borrow from patterns of colloquial speech rather than common patterns found in code. Guidance APIs may provide filtering to users on List methods (or similar methods to query a collection, such as Search). If they choose to do so, they should follow the common specification for filters discussed here. The syntax is formally defined in the EBNF grammar. When employing filtering, a request message should have exactly one filtering field, string filter. Filtering of related objects is handled through traversal or functions. Note: List Filters have fuzzy matching characteristics with support for result ranking and scoring. For developers interested in deterministic evaluation of list filters, see CEL. Literals A bare literal value (examples: \"42\", \"Hugo\") is a value to be matched against. Literals appearing alone (with no specified field) should usually be matched anywhere it may appear in an object\u0027s field values. However, a service may choose to only consider certain fields; if so, it must document which fields it considers. A service may include new fields over time, but should do so judiciously and consider impact on existing users. Note: Literals separated by whitespace are considered to have a fuzzy variant of AND. Therefore, Victor Hugo is roughly equivalent to Victor AND Hugo. Logical Operators Filtering implementations should provide the binary operators: Operator Example Meaning AND a AND b True if a and b are true. OR a OR b OR c True if any of a, b, c are true. Note: To match common patterns of speech, the OR operator has higher precedence than AND, unlike what is found in most programming languages. The expression a AND b OR c evaluates: a AND (b OR c). API documentation and examples should encourage the use of explicit parentheses to avoid confusion, but should not require explicit parentheses. Negation Operators Filtering implementations should provide the unary operators NOT and -. These are used interchangeably, and a service that supports negation must support both formats. Operator Example Meaning NOT NOT a True if a is not true. - -a True if a is not true. Comparison Operators Filtering implementations should provide the binary comparison operators =, !=, \u003c, \u003e, \u003c=, and \u003e= for string, numeric, timestamp, and duration fields (but should not provide them for booleans or enums). Operator Example Meaning = a = true True if a is true. != a != 42 True unless a equals 42. \u003c a \u003c 42 True if a is a numeric value below 42. \u003e a \u003e \"foo\" True if a is lexically ordered after \"foo\". \u003c= a \u003c= \"foo\" True if a is \"foo\" or lexically before it. \u003e= a \u003e= 42 True if a is a numeric value of 42 or higher. Note: Unlike in most programming languages, field names must appear on the left-hand side of a comparison operator; the right-hand side only accepts literals and logical operators. Because filters are accepted as query strings, type conversion takes place to translate the string to the appropriate strongly-typed value: Enums expect the enum\u0027s string representation (case-sensitive). Booleans expect true and false literal values. Numbers expect the standard integer or float representations. For floats, exponents are supported (e.g. 2.997e9). Durations expect a numeric representation followed by an s suffix (for seconds). Examples: 20s, 1.2s. Timestamps expect an RFC-3339 formatted string (e.g. 2012-04-21T11:30:00-04:00). UTC offsets are supported. Warning: The identifiers true, false, and null only carry intrinsic meaning when used in the context of a typed field reference. Additionally, when comparing strings for equality, services should support wildcards using the * character; for example, a = \"*.foo\" is true if a ends with \".foo\". Traversal operator Filtering implementations should provide the . operator, which indicates traversal through a message, map, or struct. Example Meaning a.b = true True if a has a boolean b field that is true. a.b \u003e 42 True if a has a numeric b field that is above 42. a.b.c = \"foo\" True if a.b has a string c field that is \"foo\". Traversal must be written using the field names from the resource. If a service wishes to support \"implicit fields\" of some kind, they must do so through well-documented functions. A service may specify a subset of fields that are supported for traversal. If a user attempts to traverse to a field that is not defined on the message, the service should return an error with INVALID_ARGUMENT. A service may permit traversal to undefined keys on maps and structs, and should document how it behaves in this situation. When evaluating an expression involving a traversal, if any non-primitive field in the chain is not set on the entry being evaluated, the entry should be skipped i.e. not match the filter expression. This applies even when the comparison is a !=, which would imply matching on empty values. In the examples above, if resource field a is not set on the resource instance, that instance is skipped as a non-match. Important: The . operator must not be used to traverse through a repeated field or list, except for specific use with the : operator. Has Operator Filtering implementations must provide the : operator, which means \"has\". It is usable with collections (repeated fields or maps) as well as messages, and behaves slightly differently in each case. Repeated fields query to see if the repeated structure contains a matching element: Example Meaning r:42 True if r contains 42. r.foo:42 True if r contains an element e such that e.foo = 42. Important: Filters can not query a specific element on a repeated field for a value. For example, e.0.foo = 42 and e[0].foo = 42 are not valid filters. Maps, structs, messages can query either for the presence of a field in the map or a specific value: Example Meaning m:foo True if m contains the key \"foo\". m.foo:* True if m contains the key \"foo\". m.foo:42 True if m.foo is 42. There are two slight distinctions when parsing messages: When traversing messages, a field is only considered to be present if it has a non-default value. When traversing messages, field names are snake case, although implementations may choose to support automatic conversion between camel case and snake case. For all aforementioned types, simply checking for the presence of a top-level resource field is possible with the * value: Example Meaning r:* True if repeated field r is present. p:* True if map field p is present. m:* True if message field m is present. Note: For map and repeated fields, there is no semantic difference between an unset field and \"set with empty value\" - they both resolve to \"not present\". Functions The filtering language supports a function call syntax in order to support API-specific extensions. An API may define a function using the call(arg...) syntax, and must document any specific functions it supports. Limitations A service may specify further structure or limitations for filter queries, above what is defined here. For example, a service may support the logical operators but only permit a certain number of them (to avoid \"queries of death\" or other performance concerns). Further structure or limitations must be clearly documented, and must not violate requirements set forth in this document. Validation If a non-compliant or schematically invalid filter string is specified, the API should error with INVALID_ARGUMENT. Wherever validation is relaxed for filter, the API must document the difference. Schematic validation refers, but is not limited to, the following: Fields referenced in the filter must exist on the filtered schema Field values provided in the filter must align to the type of the field For example, for a field int32 age a filter like \"age=hello\" is invalid Field values for bounded data types e.g. enum provided in the filter must be a valid value in the set Field values for standardized types e.g. Timestamp must conform to the documented standard (see Comparison Operators for a list of such types) Changelog 2025-10-03: Clarify top-level field has operator behavior. 2025-01-07: Clarify behavior for unset field in traversal operator chain. 2024-12-11: Move non-compliant filter guidance to Validation section.", + 'tags': '', + 'url': '/160', + }, +{ + 'title': "Field masks", + 'text': "Field masks Often, when updating resources (using an update method as defined in AIP-134 or something reasonably similar), it is desirable to specify exactly which fields are being updated, so that the service can ignore the rest, even if the user sends new values. It is tempting to define a mask format to handle the precise needs for each API. However, masking requirements evolve, and therefore it is prudent to use a structured syntax. This allows updates to be able to be made transparently, without waiting for UI or client updates. Guidance These masks of field names are called \"field masks\". Fields representing a field mask must use the google.protobuf.FieldMask type. Field masks are most common on Update requests (AIP-134). Field masks must always be relative to the resource: Warning: Read masks as a single field on the request message, for example: google.protobuf.FieldMask read_mask are DEPRECATED. Instead, see AIP-157. message UpdateBookRequest { // The book to update. // // The book\u0027s `name` field is used to identify the book to update. // Format: publishers/{publisher}/books/{book} Book book = 1 [(google.api.field_behavior) = REQUIRED]; // The list of fields to update. // Fields are specified relative to the book // (e.g. `title`, `rating`; *not* `book.title` or `book.rating`). google.protobuf.FieldMask update_mask = 2; } Read-write consistency Read and write behavior for field masks must be self-consistent if a mask is present: If a user updates a resource with a given mask, and then reads the same resource with the same mask, the exact same data must be returned. Exception: Output only fields. Similarly, reading a resource with a given mask and then updating the resource with the returned data and the same mask must be a no-op. Note: This implies that any mask that is valid for either read or write must be valid for both. Specifying specific fields Field masks must permit the specification of specific fields in a defined struct, using the . character for traversal. Because field masks are always relative to the resource, direct fields on the resource require no traversal (examples: title, rating). Traversal is used when resources contain messages (example: author.given_name). Note: A user must be able to specify either a field as a whole, or one of its subfields: author and author.given_name are both valid. Map fields Field masks may permit the specification of specific fields in a map, if and only if the map\u0027s keys are either strings or integers, using the . character for traversal. Field masks should support string keys that contain characters that are problematic for the field mask syntax, using the backtick character. message Book { // The name of the book. // Format: publishers/{publisher}/books/{book} string name = 1; // Reviews for the back cover. The key is the author of the review, // and the value is the text of the review. // // Valid field masks: reviews, reviews.smith, reviews.`John Smith` map\u003cstring, string\u003e reviews = 2; } Wildcards Field masks may permit the use of the * character on a repeated field or map to indicate the specification of particular sub-fields in the collection: message Book { option (google.api.resource) = { type: \"library.googleapis.com/Book\" pattern: \"publishers/{publisher}/books/{book}\" }; // The name of the book. // Format: publishers/{publisher}/books/{book} string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The author or authors of the book. // Valid field masks: authors, authors.*.given_name, authors.*.family_name // Invalid field masks: authors.0, authors.0.given_name repeated Author authors = 2; } message Author { // The author\u0027s given name. string given_name = 1; // The author\u0027s family name. string family_name = 2; } Note: Field masks must not permit accessing a particular element of a repeated field by index, and must return an INVALID_ARGUMENT error if this is attempted. Output only fields If a user includes an output only field in an update mask indirectly (by using a wildcard or specifying an overall message that includes an output-only subfield), the service must ignore any output only fields provided as input, even if they are cleared or modified. If a user directly specifies an output only field in an update mask, the service must ignore the output only fields provided as input, even if they are cleared or modified, to permit the same field mask to be used for input and output. Invalid field mask entries When reading data, field masks may ignore entries that point to a value that can not exist (either a field that does not exist, or a map key that the service considers invalid). When writing data, field masks should return an INVALID_ARGUMENT error if an entry points to a value that can not exist; however, the service may permit deletions. Changelog 2023-10-18: Update guidance for presence of output only fields in update mask. 2023-07-17: Move update_mask guidance to AIP-134.", + 'tags': '', + 'url': '/161', + }, +{ + 'title': "Resource Revisions", + 'text': "Resource Revisions Some APIs need to have resources with a revision history, where users can reason about the state of the resource over time. There are several reasons for this: Users may want to be able to roll back to a previous revision, or diff against a previous revision. An API may create data which is derived in some way from a resource at a given point in time. In these cases, it may be desirable to snapshot the resource for reference later. Note: We use the word revision to refer to a historical reference for a particular resource, and intentionally avoid the term version, which refers to the version of an API as a whole. Guidance APIs may store a revision history for a resource. Examples of when it is useful include: When it is valuable to expose older versions of a resource via an API. This can avoid the overhead of the customers having to write their own API to store and enable retrieval of revisions. Other resources depend on different revisions of a resource. There is a need to represent the change of a resource over time. APIs implementing resources with a revision history should abstract resource revisions as nested collection of the resource. Sometimes, the revisions collection can be a top level collection, exceptions include: If resource revisions are meant to have longer lifespan than the parent resource. In other words, resource revisions exist after resource deletion. message BookRevision { // The name of the book revision. string name = 1; // The snapshot of the book Book snapshot = 2 [(google.api.field_behavior) = OUTPUT_ONLY]; // The timestamp that the revision was created. google.protobuf.Timestamp create_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY]; // Other revision IDs that share the same snapshot. repeated string alternate_ids = 4 [(google.api.field_behavior) = OUTPUT_ONLY]; } The message must be annotated as a resource (AIP-123). The message name must be named {ResourceType}Revision. The resource revision must contain a field with a message type of the parent resource, with a field name of snapshot. The value of snapshot must be the configuration of the parent at the point in time the revision was created. The resource revision must contain a create_time field (see AIP-142). The resource revision may contain a repeated field alternate_ids, which would contain a list of resource IDs that the revision is also known by (e.g. latest) Creating Revisions Depending on the resource, different APIs may have different strategies for Create a new revision any time that there is a change to the parent resource Create a new revision when important system state changes Create a new revision when specifically requested APIs may use any of these strategies. APIs must document their revision creation strategy. Resource names for revisions When referring to specific revision of a resource, the subcollection name must be named revisions. Resource revisions have names with the format {resource_name}/revisions/{revision_id}. For example: publishers/123/books/les-miserables/revisions/c7cfa2a8 Server-specified Aliases Services may reserve specific IDs to be aliases (e.g. latest). These are read-only and managed by the service. GET /v1/publishers/{publisher}/books/{book}/revisions/{revision_id} If a latest ID exists, it must represent the most recently created revision. The content of publishers/{publisher}/books/{book}/revisions/latest and publishers/{publisher}/books/{book} can differ, as the latest revision may be different from the current state of the resource. User-Specified Aliases APIs may provide a mechanism for users to assign an alias ID to an existing revision with a custom method \"alias\": rpc AliasBookRevision(AliasBookRevisionRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*/revisions/*}:alias\" body: \"*\" }; } message AliasBookRevisionRequest { string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/BookRevision\" }]; // The ID of the revision to alias to, e.g. `CURRENT` or a semantic // version. string alias_id = 2 [(google.api.field_behavior) = REQUIRED]; } The request message must have a name field: The field must be annotated as required. The field must identify the resource type that it references. The request message must have a alias_id field: The field must be annotated as required. If the user calls the method with an existing alias_id, the request must succeed and the alias will be updated to refer to the provided revision. This allows users to write code against a specific alias (e.g. published) and the revision can change with no code change. Rollback A common use case for a resource with a revision history is the ability to roll back to a given revision. APIs should handle this with a Rollback custom method: rpc RollbackBook(RollbackBookRequest) returns (BookRevision) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*/revisions/*}:rollback\" body: \"*\" }; } The method must use the POST HTTP verb. The method should return a resource revision. message RollbackBookRequest { // The revision that the book should be rolled back to. string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/BookRevision\" }]; } The request message must have a name field, referring to the resource revision whose configuration the resource should be rolled back to. The field must be annotated as required. The field must identify the resource type that it references. Child resources Resources with a revision history may have child resources. If they do, there are two potential variants: Child resources where each child resource is a child of the parent resource as a whole. Child resources where each child resource is a child of a single revision of the parent resource. APIs should not include multiple levels of resources with revisions, as this quickly becomes difficult to reason about. Standard methods Any standard methods must implement the corresponding AIPs (AIP-131, AIP-132, AIP-133, AIP-134, AIP-135), with the following additional behaviors: List methods: By default, revisions in the list response must be ordered in reverse chronological order. User can supply order_by to override the default behavior. If the revision supports aliasing, a delete method with the resource name of the alias (e.g. revisions/1.0.2) must remove the alias instead of deleting the resource. As revisions are nested under the resource, also see cascading delete. Rationale Abstract revisions as nested collection Revisions being resources under nested collection make revisions a first class citizen. Revisions can offer standard get, list, and delete methods. It retains the flexibility of extending new fields to revision in addition to the resource message. Tagging to Aliases Previously, a concept of tag existed. This concept was redundant with that of an alias, and the terms were consolidated to reduce complexity in the AIPs. Output only resource configuration Although it was an option to have the revision take in the resource configuration as part of the create method, doing so would have allowed users to submit resource configuration for a revision that the resource was never in. OUTPUT_ONLY and requiring that a created revision represents the resource at current point in time eliminates that issue. History Switching from a collection extension to a subcollection In 2023-09, revisions are abstracted as a nested resource collection. Prior to this, revisions are more like extension of an existing resource by using @ symbol. List and delete revisions were custom methods on the resource collection. A single Get method was used to retrieve either the resource revision, or the resource. Its primary advantage was allowing a resource reference to seamlessly refer to a resource, or its revision. It also had several disadvantages: List revisions is a custom method (:listRevisions) on the resource collection Delete revision is a custom method on the resource collection Not visible in API discovery doc Resource ID cannot use @ The guidance was modified ultimately to enable revisions to behave like a resource, which reduces the users cognitive load and allows resource-oriented clients to easily list, get, create, and update revisions. Using resource ID instead of tag In the previous design, revisions had a separate identifer for a revision known as a tag, that would live in a revision. Tags were effectively a shadow resource ID, requiring methods to create, get and filter revisions based on the value of the tag. By consolidating the concept of a tag into the revision ID, the user no longer needs to be familiar with a second set of retrieval and identifier methods. Changelog 2023-09-01: AIP was updated to be a sub-collection. 2021-04-27: Added guidance on returning the resource from Delete Revision.", + 'tags': '', + 'url': '/162', + }, +{ + 'title': "Change validation", + 'text': "Change validation Occasionally, a user wants to validate an intended change to see what the result will be before actually making the change. For example, a request to provision new servers in a fleet will have an impact on the overall fleet size and cost, and could potentially have unexpected downstream effects. Guidance APIs may provide an option to validate, but not actually execute, a request, and provide the same response (status code, headers, and response body) that it would have provided if the request was actually executed. To provide this option, the method should include a bool validate_only field in the request message: message ReviewBookRequest { string name = 1 [(google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; int32 rating = 2; string comment = 3; // If set, validate the request and preview the review, but do not actually // post it. bool validate_only = 4; } The API must perform permission checks and any other validation that would be performed on a \"live\" request; a request using validate_only must fail if it determines that the actual request would fail. Note: It may occasionally be infeasible to provide the full output. For example, if creating a resource would create an auto-generated ID, it does not make sense to do this on validation. APIs should omit such fields on validation requests in this situation. Declarative-friendly resources A resource that is declarative-friendly (AIP-128) must include a validate_only field on methods that mutate the resource. Changelog 2020-10-06: Added declarative-friendly resource requirement.", + 'tags': '', + 'url': '/163', + }, +{ + 'title': "Soft delete", + 'text': "Soft delete There are several reasons why a client could desire soft delete and undelete functionality, but one over-arching reason stands out: recovery from mistakes. A service that supports undelete makes it possible for users to recover resources that were deleted by accident. Guidance APIs may support the ability to \"undelete\", to allow for situations where users mistakenly delete resources and need the ability to recover. If a resource needs to support undelete, the Delete method must simply mark the resource as having been deleted, but not completely remove it from the system. If the method behaves this way, it should return the updated resource instead of google.protobuf.Empty. Resources that support soft delete should have both a delete_time and purge_time field as described in AIP-148. Additionally, resources should include a DELETED state value if the resource includes a state field (AIP-216). Undelete A resource that supports soft delete should provide an Undelete method: rpc UndeleteBook(UndeleteBookRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*}:undelete\" body: \"*\" }; } The HTTP verb must be POST. The body clause must be \"*\". The response message must be the resource itself. There is no UndeleteBookResponse. The response should include the fully-populated resource unless it is infeasible to do so. If the undelete RPC is long-running, the response message must be a google.longrunning.Operation which resolves to the resource itself. Undelete request message Undelete methods implement a common request message pattern: message UndeleteBookRequest { // The name of the deleted book. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference).type = \"library.googleapis.com/Book\"]; } A name field must be included. It should be called name. The field should be annotated as required. The field should identify the resource type that it references. The comment for the field should document the resource pattern. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. Long-running undelete Some resources take longer to undelete a resource than is reasonable for a regular API request. In this situation, the API should use a long-running operation (AIP-151) instead: rpc UndeleteBook(UndeleteBookRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*}:undelete\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"Book\" metadata_type: \"OperationMetadata\" }; } The response type must be set to the resource (what the return type would be if the RPC was not long-running). Both the response_type and metadata_type fields must be specified. Expunge Resources that support soft delete may provide an Expunge custom method to allow users to trigger immediate permanent deletion of a resource. This method can operate on resources that are currently in a CREATING, READY or SOFT_DELETED state (e.g., delete_time is set). // Permanently deletes a soft-deleted Book. rpc ExpungeBook(ExpungeBookRequest) returns (google.protobuf.Empty) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*}:expunge\" body: \"*\" }; option (google.api.method_signature) = \"name\"; } The URI must use a custom method with the :expunge suffix. The HTTP verb must be POST and the body clause must be \"*\". The response message must be google.protobuf.Empty or a google.longrunning.Operation. Long-running expunge If the expunge process takes significant time, the method may be a google.longrunning.Operation (AIP-151) instead: // Permanently deletes a soft-deleted Book. rpc ExpungeBook(ExpungeBookRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*}:expunge\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"google.protobuf.Empty\" metadata_type: \"OperationMetadata\" }; option (google.api.method_signature) = \"name\"; } Expunge request message Expunge methods implement a common request message pattern: message ExpungeBookRequest { // The name of the soft-deleted book to expunge. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference).type = \"library.googleapis.com/Book\" ]; } The request message must refer to the resource to be expunged by name. There should not be any other request fields. List and Get Soft-deleted resources should not be returned in List (AIP-132) responses by default (unless bool show_deleted is true). Get (AIP-131) requests for soft-deleted resources should return the resource (rather than a NOT_FOUND error). APIs that soft delete resources may choose a reasonable strategy for purging those resources, including automatic purging after a reasonable time (such as 30 days), allowing users to set an expiry time (AIP-214), or retaining the resources indefinitely. Regardless of what strategy is selected, the API should document when soft deleted resources will be completely removed. Declarative-friendly resources Soft-deletable resources have a poorer experience than hard-deleted resources in declarative clients: since an ID on a soft-deleted resource is not re-usable unless a custom method (undelete) is called, an imperative client must be introduced or hand-written code is required to incorporate the usage of the custom method. Errors If the user does not have permission to access the resource, regardless of whether or not it exists, the service must error with PERMISSION_DENIED (HTTP 403). Permission must be checked prior to checking if the resource exists. If the user does have proper permission, but the requested resource does not exist (either it was never created or already expunged), the service must error with NOT_FOUND (HTTP 404). If the user calling a soft Delete has proper permission, but the requested resource is already deleted, the service must succeed if allow_missing is true, and should error with NOT_FOUND (HTTP 404) if allow_missing is false. If the user calling Undelete has proper permission, but the requested resource is not deleted, the service must respond with ALREADY_EXISTS (HTTP 409). If the user calling Expunge requests a resource that does not exist (was never created or already expunged), the method must return NOT_FOUND (HTTP 404). If the resource exists but is not in a ready or soft-deleted state, the method must return FAILED_PRECONDITION (HTTP 400). Standard permission errors (PERMISSION_DENIED) apply. Services must require an explicit expunge permission that is separate from standard delete permissions (e.g., \u003cservice\u003e.\u003cresource\u003e.expunge). Further reading For the Delete standard method, see AIP-135. For long-running operations, see AIP-151. For resource freshness validation (etag), see AIP-154. For change validation (validate_only), see AIP-163. Changelog 2026-04-28: Added guidance for the Expunge custom method. 2024-09-24: Included missing requirement for delete_time. 2023-07-13: Renamed overloaded expire_time to purge_time. 2021-07-12: Added error behavior when soft deleting a deleted resource. 2021-07-12: Clarified that ALREADY_EXISTS errors apply to Undelete. 2021-07-12: Changed the expire_time field to \"should\" for consistency with AIP-148. 2020-09-23: Soft delete material in AIP-135 migrated to this AIP.", + 'tags': '', + 'url': '/164', + }, +{ + 'title': "Criteria-based delete", + 'text': "Criteria-based delete Occasionally, an API may need to provide a mechanism to delete a large number of resources based on some set of filter parameters, rather than requiring the individual resource name of the resources to be deleted. This is a rare case, reserved for situations where users need to delete thousands or more resources at once, in which case the normal Batch Delete pattern (AIP-235) becomes unwieldy and inconvenient. Guidance Important: Most APIs should use only Delete (AIP-135) or Batch Delete (AIP-235) for deleting resources, and should not implement deleting based on criteria. This is because deleting is generally irreversible and this type of operation makes it easy for a user to accidentally lose significant amounts of data. An API may implement a Purge method to permit deleting a large number of resources based on a filter string; however, this should only be done if the Batch Delete (AIP-235) pattern is insufficient to accomplish the desired goal: rpc PurgeBooks(PurgeBooksRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:purge\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"PurgeBooksResponse\" metadata_type: \"PurgeBooksMetadata\" }; } The RPC\u0027s name must begin with the word Purge. The remainder of the RPC name should be the plural form of the resource being purged. The request message must match the RPC name, with a Request suffix. The response type must be a google.longrunning.Operation (see AIP-151) that resolves to a message whose name matches the RPC name, with a Response suffix. The HTTP verb must be POST, and the body must be \"*\". The URI path should represent the collection for the resource. The parent field should be included in the URI. If the API wishes to support deletion across multiple parents, it should accept the - character consistent with AIP-159. Request message Purge methods implement a common request message pattern: message PurgeBooksRequest { // The publisher to purge books from. // To purge books across publishers, send \"publishers/-\". string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // A filter matching the books to be purged. string filter = 2 [(google.api.field_behavior) = REQUIRED]; // Actually perform the purge. // If `force` is set to false, the method will return a sample of // resource names that would be deleted. bool force = 3; } A singular string parent field should be included, unless the resource is top-level. The field should be annotated as required. The field should identify the resource type that it references. A singular string filter field must be included and must follow the same semantics as in List methods (AIP-160). It should be annotated as required. A wildcard value of \"*\" may be supported for deleting everything. A singular bool force field must be included. If it is not set, the API must return a count of the resources that would be deleted as well as a sample of those resources, without actually performing the deletion. Response message Purge methods implement a common response message pattern: message PurgeBooksResponse { // The number of books that this request deleted (or, if `force` is false, // the number of books that will be deleted). int32 purge_count = 1; // A sample of the resource names of books that will be deleted. // Only populated if `force` is set to false. repeated string purge_sample = 2 [(google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; } A singular int32 purge_count field should be included, and provide the number of resources that were deleted (or would be deleted). This count may be an estimate similar to total_size in AIP-158 (but the service should document this if so). A repeated string purge_sample field should be included: If force is false, it should provide a sample of resource names that will be deleted. If force is true, this field should not be populated. The sample should be a sufficient size to catch clearly obvious mistakes: A good rule of thumb is 100. The API should document the size, and should document that it is a maximum (it is possible to send fewer). The sample may be random or may be deterministic (such as the first matched resource names). The API should document which approach is used. The field should identify the resource type that it references. Note: Even if purge_count and purge_sample are not included, the force field must still be included in the request. Changelog 2025-07-23: Explicitly state filter wildcard may be supported. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-10-29: Expanded guidance on HTTP, field behavior, and resource reference annotations.", + 'tags': '', + 'url': '/165', + }, +{ + 'title': "Backwards compatibility", + 'text': "Backwards compatibility APIs are fundamentally contracts with users, and users often write code against APIs that is then launched into a production service with the expectation that it continues to work (unless the API has a stability level that indicates otherwise). Therefore, it is important to understand what constitutes a backwards compatible change and what constitutes a backwards incompatible change. Guidance Existing client code must not be broken by a service updating to a new minor or patch release. Old clients must be able to work against newer servers (with the same major version number). Important: It is not always clear whether a change is compatible or not. The guidance here should be treated as indicative, rather than as a comprehensive list of every possible change. There are three distinct types of compatibility to consider: Source compatibility: Code written against a previous version must compile against a newer version, and successfully run with a newer version of the client library. Wire compatibility: Code written against a previous version must be able to communicate correctly with a newer server. In other words, not only are inputs and outputs compatible, but the serialization and deserialization expectations continue to match. Semantic compatibility: Code written against a previous version must continue to receive what most reasonable developers would expect. (This can be tricky in practice, however, and sometimes determining what users will expect can involve a judgment call.) Note: In general, the specific guidance here assumes use of protocol buffers and JSON as transport formats. Other transport formats may have slightly different rules. Note: This guidance assumes that APIs are intended to be called from a range of consumers, written in multiple languages and with no control over how and when consumers update. Any API which has a more limited scope (for example, an API which is only called by client code written by the same team as the API producer, or deployed in a way which can enforce updates) should carefully consider its own compatibility requirements. Adding components In general, new components (interfaces, methods, messages, fields, enums, or enum values) may be added to existing APIs in the same major version. However, keep the following guidelines in mind when doing this: Code written against the previous surface (and thus is unaware of the new components) must continue to be treated the same way as before. New required fields must not be added to existing request messages or resources. Any field being populated by clients must have a default behavior matching the behavior before the field was introduced. This can be tricky to do in some cases. For example, adding pagination after the fact where previously all items were returned (i.e. page_size is infinite, which is not advised). If the default for the new page_size field is less than what was previously returned, older clients will incorrectly assume all results were returned. Any field previously populated by the server must continue to be populated, even if it introduces redundancy. For enum values specifically, be aware that it is possible that user code does not handle new values gracefully. Enum values may be freely added to enums which are only used in request messages. Enums that are used in response messages or resources and which are expected to receive new values should document this. Enum values still may be added in this situation; however, appropriate caution should be used. Note: It is possible when adding a component closely related to an existing component (for example, string foo_value when string foo already exists) to enter a situation where generated code will conflict. Service owners should be aware of subtleties in the tooling they or their users are likely to use (and tool authors should endeavor to avoid such subtleties if possible). Removing or renaming components Existing components (interfaces, methods, messages, fields, enums, or enum values) must not be removed from existing APIs in the same major version. Removing a component is a backwards incompatible change. Important: Renaming a component is semantically equivalent to \"remove and add\". In cases where these sorts of changes are desirable, a service may add the new component, but must not remove the existing one. In situations where this can allow users to specify conflicting values for the same semantic idea, the behavior must be clearly specified. Moving components between files Existing components must not be moved between files. Moving a component from one proto file to another within the same package is wire compatible, however, the code generated for languages like C++ or Python will result in breaking change since import and #include will no longer point to the correct code location. Moving into oneofs Existing fields must not be moved into or out of a oneof. This is a backwards-incompatible change in the Go protobuf stubs. Changing the type of fields Existing fields and messages must not have their type changed, even if the new type is wire-compatible, because type changes alter generated code in a breaking way. Changing string length APIs should avoid increasing the upper bound for the size or limit (if accepted as input) of string fields. APIs should treat expected size upper bound increases as incompatible changes (see Changing resource names as an example). APIs may pad out values with filler characters if reserving a consistent size is necessary, but this must be documented if done. Changing resource names A resource must not change its name. Unlike most breaking changes, this affects major versions as well: in order for a client to expect to use v2.0 access a resource that was created in v1.0 or vice versa, the same resource name must be used in both versions. More subtly, the set of valid resource names should not change either, for the following reasons: If resource name formats become more restrictive, a request that would previously have succeeded will now fail. If resource name formats become less restrictive than previously documented, then code making assumptions based on the previous documentation could break. Users are very likely to store resource names elsewhere, in ways that may be sensitive to the set of permitted characters and the length of the name. Alternatively, users might perform their own resource name validation to follow the documentation. For example, Amazon gave customers a lot of warning and had a migration period when they started allowing longer EC2 resource IDs. Semantic changes Code will often depend on API behavior and semantics, even when such behavior is not explicitly supported or documented. Therefore, APIs must not change visible behavior or semantics in ways that are likely to break reasonable user code, as such changes will be seen as breaking by those users. Note: This does involve some level of judgment; it is not always clear whether a proposed change is likely to break users, and an expansive reading of this guidance could ostensibly prevent any change (which is not the intent). Changing value format or construction APIs must not change the expected format or algorithm used to construct the value of an existing field - even if the field is OUTPUT_ONLY and populated by the API service - within an API version. Doing so requires a new API version. For example, changing the format of a field ip_address conforming to IPv4 format to instead contain IPv6 values is a breaking change. Default values must not change Default values are the values set by servers for resources when they are not specified by the client. This section only applies to static default values within fields on resources and does not apply to dynamic defaults such as the default IP address of a resource. Changing the default value is considered breaking and must not be done. The default behavior for a resource is determined by its default values, and this must not change across minor versions. For example: message Book { // google.api.resource and other annotations and fields // The genre of the book // If this is not set when the book is created, the field will be given a value of FICTION. enum Genre { UNSPECIFIED = 0; FICTION = 1; NONFICTION = 2; } } Changing to: message Book { // google.api.resource and other annotations and fields // The genre of the book // If this is not set when the book is created, the field will be given a value of NONFICTION. enum Genre { UNSPECIFIED = 0; FICTION = 1; NONFICTION = 2; } } would constitute a breaking change. Serializing defaults APIs must not change the way a field with a default value is serialized. For example if a field does not appear in the response if the value is equal to the default, the serialization must not change to include the field with the default. Clients may depend on the presence or absence of a field in a resource as semantically meaningful, so a change to how serialization is done for absent values must not occur in a minor version. Consider the following proto, where the default value of wheels is 2: // A representation of an automobile message Automobile { // google.api.resource and other annotations and fields // The number of wheels on the automobile. // The default value is 2, when no value is sent by the client. int wheels = 2; } First the proto serializes to JSON when the value of wheels is 2 as follows: { \"name\": \"my-car\" } Then, the API service changes the serialization to include wheel even if the value is equal to the default value, 2 as follows: { \"name\": \"my-car\", \"wheels\": 2 } This constitutes a change that is not backwards compatible within a major version. Further reading For compatibility around field behavior, see AIP-203. For compatibility around pagination, see AIP-158. For compatibility around long-running operations, see AIP-151. For understanding stability levels and expectations, see AIP-181. For compatibility with client library resource name parsing, see AIP-4231 For compatibility with client library method signatures, see AIP-4232 For compatibility around field presence changes, see AIP-149. For compatibility around resource types, see AIP-123. Rationale Risk of string length changes End users may store resource properties, like the name, in a dedicated database column with a limited length. If the service starts returning values for the name that are twice the originally documented/observed length, this may unexpectedly break the customer\u0027s database. Furthermore, string properties that appear in URLs (including query parameters) are especially likely to have client-side limits, making them more sensitive to length changes. Risk of changing value format or construction Customers often depend on the format or algorithmic construction of a field for client-side parsing, hashing, or database table construction. Changing it in an existing field could break that client-side consumption. Changelog 2025-10-21: Added guidance for string length changes, changing formats, and an example for carefully adding components. 2024-08-07: Added reference to resource type compatibility. 2024-06-05: Added reference to field presence compatibility. 2023-07-26: Added reference to field behavior compatibility. 2023-07-26: Added note on APIs which have limited clients. 2022-08-11: Added \"Moving components between files\" section. 2022-06-01: Added more links to other AIPs with compatibility concerns 2019-12-16: Clarified that moving existing fields into oneofs is breaking.", + 'tags': '', + 'url': '/180', + }, +{ + 'title': "Stability levels", + 'text': "Stability levels While different organizations (both inside Google and outside) have different product life cycles, AIPs refer to the stability of an API component using the following terms. Note: These stability levels roughly correspond to the product launch stages (alpha, beta, GA) in Google Cloud, but are not identical. GCP imposes its own additional expectations and commitments on top of what is outlined here. Alpha An alpha component undergoes rapid iteration with a known set of users who must be tolerant of change. The number of users should be a curated, manageable set, such that it is feasible to communicate with all of them individually. Breaking changes must be both allowed and expected in alpha components, and users must have no expectation of stability. Beta A beta component must be considered complete and ready to be declared stable, subject to public testing. Beta components should be exposed to an unknown and potentially large set of users. In other words, beta components should not be behind an allowlist; instead, they should be available to the public. Because users of beta components tend to have a lower tolerance of change, beta components should be as stable as possible; however, the beta component must be permitted to change over time. These changes should be minimal but may include backwards-incompatible changes to beta components. Backwards-incompatible changes must be made only after a reasonable deprecation period to provide users with an opportunity to migrate their code. This deprecation period must be defined at the time of being marked beta. Beta components should be time-boxed and promoted to stable if no issues are found in the specified timeframe, which should be specified at the time of being marked beta. A reasonable time period may vary, but a good rule of thumb is 90 days. Stable A stable component must be fully-supported over the lifetime of the major API version. Because users expect such stability from components marked stable, there must be no breaking changes to these components, subject to the caveats described below. Major versions When breaking changes become necessary, the API producer should create the next major version of the API, and start a deprecation clock on the existing version. Turn-down of any version containing stable components must have a formal process defined at the time of being marked stable. This process must specify a deprecation period for users which provides them with reasonable advance warning. Isolated changes On very rare occasions, it could be preferable to make a small, isolated breaking change, if this will only cause inconvenience to a small subset of users. (Creating a new major version is an inconvenience to all users.) In this case, the API producer may deprecate the component, but must continue to support the component for the normal turndown period for a stable component. Important: Making an in-place breaking change in a stable API is considered an extreme course of action, and should be treated with equal or greater gravity as creating a new major version. For example, at Google, this requires the approval of the API Governance team. Emergency changes In certain exceptional cases, such as security concerns or regulatory requirements, any API component may be changed in a breaking manner regardless of its stability level, and a deprecation is not promised in these situations.", + 'tags': '', + 'url': '/181', + }, +{ + 'title': "External software dependencies", + 'text': "External software dependencies Some services have a particular type of dependency on external software: they allow users to create resources that run on or expose the external software in some way. For example: A database admin service can allow users to create databases running on a particular version of a particular database engine (for example, PostgreSQL 13.4). A virtual machine service can allow users to create VMs running a particular operating system (for example, Ubuntu 20.04). An application or function platform service can allow users to write code that runs against a particular version of a programming language (for example, Node.js 16.6). Services that provide external software to users in this way will eventually need to address the fact that all of these types of software have release lifecycles, and the versions they currently expose will eventually reach end-of-life. Guidance Services that expose external software dependencies should allow users to create resources using any currently-supported LTS (long-term support) version of the supported software, and may allow users to create resources using non-LTS versions. Services should not indefinitely allow users to create new resources using versions that have reached end-of-life, although they may have a transition period between when the software version reaches end-of-life and when support for creating new resources with that version is removed. Note: Restricting or removing the ability to create resources using end-of-life versions of software is not considered a breaking change for the service for the purpose of AIP-181, even though it actually is one. However, because the change can break existing users\u0027 workflows, services must notify users who are using resources approaching end-of-life. If possible, services should allow previously-created resources to remain, and may warn users of the risks associated with continuing to use end-of-life software. Services should not proactively remove resources using end-of-life software, or impose other restrictions on existing resources, unless critical security concerns require the service to do so. Continued support If supporting a version that has reached end-of-life is necessary for business reasons (usually because the end-of-life software still has significant adoption), the service may choose to officially support the end-of-life version, but must take on the responsibility of patching and maintaining the software if it does so.", + 'tags': '', + 'url': '/182', + }, +{ + 'title': "API Versioning", + 'text': "API Versioning This topic describes the versioning strategies used by Google APIs. In general, these strategies apply to all Google-managed services. Guidance All Google API interfaces must provide a major version number, which is encoded at the end of the protobuf package, and included as the first part of the URI path for REST APIs. In the event an API needs to make an incompatible change, consult AIP-180 and AIP-181 for necessary steps based on the stability level of the surface in question. Note: The use of the term \"major version number\" above is taken from semantic versioning. However, unlike in traditional semantic versioning, Google APIs must not expose minor or patch version numbers. For example, Google APIs use v1, not v1.0, v1.1, or v1.4.2. From a user\u0027s perspective, major versions are updated in place with minor/patch equivalent changes, and users receive new functionality without migration. A new major version of an API must not depend on a previous major version of the same API. An API surface must not depend on other APIs, except for in the cases outlined in AIP-213 and AIP-215. Different versions of the same API must be able to work at the same time within a single client application for a reasonable transition period. This time period allows the client to transition smoothly to the newer version. An older version must go through a reasonable, well-communicated deprecation period before being shut down. For releases which have alpha or beta stability, APIs must append the stability level after the major version number in the protobuf package and URI path using one of these strategies: Channel-based versioning (recommended) Release-based versioning Visibility-based versioning Channel-based versioning A stability channel is a long-lived release at a given stability level that receives in-place updates. There is no more than one channel per stability level for a major version. Under this strategy, there are up to three channels available: alpha, beta, and stable. The alpha and beta channel must have their stability level appended to the version, but the stable channel must not have the stability level appended. For example, v1 is an acceptable version for the stable channel, but v1beta or v1alpha are not. Similarly, v1beta or v1alpha are acceptable versions for the respective beta and alpha channel, but v1 is not acceptable for either. Each of these channels receives new features and updates \"in-place\". The beta channel\u0027s functionality must be a superset of the stable channel\u0027s functionality, and the alpha channel\u0027s functionality must be a superset of the beta channel\u0027s functionality. Deprecating API functionality API elements (fields, messages, RPCs) may be marked deprecated in any channel to indicate that they should no longer be used: // Represents a scroll. Books are preferred over scrolls. message Scroll { option deprecated = true; // ... } Deprecated API functionality must not graduate from alpha to beta, nor beta to stable. In other words, functionality must not arrive \"pre-deprecated\" in any channel. The beta channel\u0027s functionality may be removed after it has been deprecated for a sufficient period; we recommend 180 days. For functionality that exists only in the alpha channel, deprecation is optional, and functionality may be removed without notice. If functionality is deprecated in an API\u0027s alpha channel before removal, the API should apply the same annotation, and may use any timeframe it wishes. Release-based versioning Important: This pattern is not commonly used for new services. There are existing services that follow it, but Channel-based Versioning is the preferred mechanism. An individual release is an alpha or beta release that is expected to be available for a limited time period before its functionality is incorporated into the stable channel, after which the individual release will be shut down. When using release-based versioning strategy, an API may have any number of individual releases at each stability level. Note: Both the channel-based and release-based strategies update the stable version in-place. There is a single stable channel, rather than individual stable releases, even when using the release-based strategy. Alpha and beta releases must have their stability level appended to the version, followed by an incrementing release number. For example, v1beta1 or v1alpha5. APIs should document the chronological order of these versions in their documentation (such as comments). Each alpha or beta release may be updated in place with backwards-compatible changes. For beta releases, backwards-incompatible updates should be made by incrementing the release number and publishing a new release with the change. For example, if the current version is v1beta1, then v1beta2 is released next. Alpha and beta releases should be shut down after their functionality reaches the stable channel. An alpha release may be shut down at any time, while a beta release should allow users a reasonable transition period; we recommend 180 days. Visibility-based versioning API visibility is an advanced feature provided by Google API infrastructure. It allows API producers to expose multiple external API views from one internal API surface, and each view is associated with an API visibility label, such as: import \"google/api/visibility.proto\"; message Resource { string name = 1; // Preview. Do not use this feature for production. string display_name = 2 [(google.api.field_visibility).restriction = \"PREVIEW\"]; } A visibility label is a case-sensitive string that can be used to tag any API element. By convention, visibility labels should always use UPPER case. An implicit PUBLIC label is applied to all API elements unless an explicit visibility label is applied as in the example above. Each visibility label is an allow-list. API producers need to grant visibility labels to API consumers for them to use API features associated with the labels. In other words, an API visibility label is like an ACL\u0027ed API version. Multiple visibility labels may be applied to an element by using a comma-separated string (e.g. \"PREVIEW,TRUSTED_TESTER\"). When multiple visibility labels are used, then the client needs only one of the visibility labels (logical OR). By default, the visibility labels granted to the API consumer are used to verify incoming requests. However, a client can send requests with an explicit visibility label as follows: GET /v1/projects/my-project/topics HTTP/1.1 Host: pubsub.googleapis.com Authorization: Bearer y29.... X-Goog-Visibilities: PREVIEW A single API request can specify at most one visibility label. API producers can use API visibility for API versioning, such as INTERNAL and PREVIEW. A new API feature starts with the INTERNAL label, then moves to the PREVIEW label. When the feature is stable and becomes generally available, all API visibility labels are removed from the API definition. In general, API visibility is easier to implement than API versioning for incremental changes, but it depends on sophisticated API infrastructure support. Google Cloud APIs often use API visibility for Preview features.", + 'tags': '', + 'url': '/185', + }, +{ + 'title': "Naming conventions", + 'text': "Naming conventions This topic describes the naming conventions used in Google APIs. In general, these conventions apply to all Google-managed services. Guidance In order to provide consistent developer experience across many APIs and over a long period of time, all names used by an API should be: straightforward intuitive consistent This includes names of interfaces, resources, collections, methods, and messages. Since English is a second language for many developers, one goal of these naming conventions is to make every API name understandable to the majority of developers. It does this by encouraging the use of a simple, consistent, and small vocabulary when naming methods and resources. Names used in APIs should be in correct American English. For example, license (instead of licence), color (instead of colour). Commonly accepted short forms or abbreviations of long words may be used for brevity. For example, API is preferred over Application Programming Interface. Unless otherwise specified, definitions must use UpperCamelCase names, as defined by Google Java Style. Use intuitive, familiar terminology where possible. For example, when describing removing (and destroying) a resource, delete is preferred over erase. Use the same name or term for the same concept, including for concepts shared across APIs. Avoid name overloading. Use different names for different concepts. Avoid overly general names that are ambiguous within the context of the API and the larger ecosystem of Google APIs. They can lead to misunderstanding of API concepts. Rather, choose specific names that accurately describe the API concept. This is particularly important for names that define first-order API elements, such as resources. There is no definitive list of names to avoid, as every name must be evaluated in the context of other names. Instance, info, and service are examples of names that have been problematic in the past. Names chosen should describe the API concept clearly (for example: instance of what?) and distinguish it from other relevant concepts (for example: does \"alert\" mean the rule, the signal, or the notification?). Carefully consider use of names that may conflict with keywords in common programming languages. Such names may be used but will likely trigger additional scrutiny during API review. Use them judiciously and sparingly. Interface names To avoid confusion with Service Names such as pubsub.googleapis.com, the term interface name refers to the name used when defining a service in a .proto file: // Library is the interface name. service Library { rpc ListBooks(...) returns (...); rpc ... } You can think of the service name as a reference to the actual implementation of a set of APIs, while the interface name refers to the abstract definition of an API. An interface name should use an intuitive noun such as Calendar or BlobStore. The name should not conflict with any well-established concepts in programming languages and their runtime libraries (for example, File). In the rare case where an interface name would conflict with another name within the API, a suffix (for example Api or Service) should be used to disambiguate. Method names A service may, in its IDL specification, define one or more API methods that correspond to methods on collections and resources. The method names should follow the naming convention of VerbNoun in UpperCamelCase, where the noun is typically the resource type. Standard methods, and their Batch variants, define their naming guidance in the following documents: Method Standard Batch Get AIP-131 AIP-231 List AIP-132 N/A Create AIP-133 AIP-233 Update AIP-134 AIP-234 Delete AIP-135 AIP-235 All other methods are considered Custom Methods and adhere to AIP-136 naming guidance. Message names Message names should be short and concise. Avoid unnecessary or redundant words. Adjectives can often be omitted if there is no corresponding message without the adjective. For example, the Shared in SharedProxySettings is unnecessary if there are no unshared proxy settings. Message names should not include prepositions (e.g. \"With\", \"For\"). Generally, message names with prepositions are better represented with optional fields on the message. Request and response messages For request and response message names, see AIP-136 for custom methods and the appropriate AIP for standard methods. Further reading For proto and language package naming, see AIP-191. For collection ID naming conventions, see AIP-122. For Enum names, see AIP-126. For field names, see AIP-140. For repeated field names, see AIP-140. For fields representing times and durations, see AIP-142. For fields representing dates and times of day, see AIP-142. For fields representing a quantity, see AIP-141. For the canonical List method filter field, see AIP-132. For the canonical List response message, see AIP-132. For well known abbreviations, see AIP-140.", + 'tags': '', + 'url': '/190', + }, +{ + 'title': "File and directory structure", + 'text': "File and directory structure A consistent file and directory structure, while making minimal difference technically, makes API surface definitions easier for users and reviewers to read. Guidance Note: The following guidance applies to APIs defined in protocol buffers, such as those used throughout Google. While the spirit of this guidance applies to APIs defined using other specification languages or formats, some of the particular recommendations might be irrelevant. Syntax APIs defined in protocol buffers must use proto3 syntax. Single package APIs defined in protocol buffers must define each individual API in a single package, which must end in a version component. For example: syntax = \"proto3\"; package google.cloud.translation.v3; Google APIs must reside in a directory that matches the protocol buffer package directive. For example, the package above dictates that the directory be google/cloud/translation/v3. File names It is often useful to divide API definitions into multiple files. File names must use snake_case. APIs should have an obvious \"entry\" file, generally named after the API itself. An API with a small number of discrete services (Google Cloud Pub/Sub\u0027s Publisher and Subscriber is a good example) may have a separate entry file per service. APIs with only one file should use a filename corresponding to the name of the API. API service definitions and associated RPC request and response message definitions should be defined in the same file. Bear in mind that the file names often become module names in client libraries, and customers use them in import or use statements. Therefore, choosing a descriptive and language keyword-free filename does matter. For example, a file called import.proto may be problematic in Python. Note: The version must not be used as a filename, because this creates bizarre imports in client libraries. Filenames such as v3.proto or v1beta1.proto are prohibited. File layout Individual files should place higher level and more important definitions before lower level and less important definitions. In a proto file, components should be in the following order, and each of these should be separated by a blank line: Copyright and license notice (if applicable). The proto syntax statement. The proto package statement. Any import statements, in alphabetical order. Any file-level option statements. Any service definitions. Methods should be grouped by the resource they impact, and standard methods should precede custom methods. Resource message definitions. A parent resource must be defined before its child resources. The RPC request and response message definitions, in the same order of the corresponding methods. Each request message must precede its corresponding response message (if any). Any remaining message definitions. Any top-level enum definitions. Packaging annotations Protocol buffers ships with annotations to declare the package or namespace (depending on the vocabulary of the target language) of the generated files. For example, setting go_package or csharp_namespace will override the inferred package name. When defining APIs, the following rules apply: Java The java_package annotation must be set. The correct value is usually the proto package with the appropriate TLD prefixed. Example: com.google.example.v1. The java_multiple_files annotation must be set to true. The java_outer_classname annotation must be set, and should be set to the name of the proto filename, in PascalCase, with Proto appended. Example: LibraryProto. Other languages Package or namespace directives for other languages must be set either in every file in the proto package, or none of them. If they are set, the values must be identical in every file. If any part of the protobuf package is a compound name (such as accessapproval), C#, Ruby and PHP options must be specified in order to take account of the word breaks using PascalCase (UpperCamelCase). Example: option csharp_namespace = \"Google.Cloud.AccessApproval.V1\"; option php_namespace = \"Google\\\\Cloud\\\\AccessApproval\\\\V1\"; option ruby_package = \"Google::Cloud::AccessApproval::V1\"; The go_package value depends directly on how the Go code is managed i.e. if the module name is based on the VCS provider or using a remote import path, but often has a consistent structure. The module may differ based on product area e.g. google.cloud.accessapproval.v1 would be in module cloud.google.com/go/accessapproval. The package import path should be derived from the proto package. An API version in the proto package should be prefixed with api e.g. the proto package segment v1 becomes apiv1. The terminal import path segment should be based on the product name found within the proto package and must be suffixed with pb e.g. accessapproval becomes accessapprovalpb. This value should be left to the team owning the generated code to decide on. All packaging annotations should be specified in alphabetical order of name. Refer to the Protobuf documentation for more about language package options. Important: While languages other than Java have sensible defaults for APIs which don\u0027t include compound names, be aware that adding this annotation (with a value not equivalent to the default) constitutes a breaking change in that language. When releasing protos, be sure that omissions are intentional. Rationale Java packaging options Set the option, java_multiple_files, to true to get a cleaner file structure. Doing so instructs protoc to create one output file per Protobuf type, which allows for more fine-grained imports. The option, java_outer_classname, is required in combination with java_multiple_files. It instructs protoc to wrap each compiled Protobuf type in a Java class whose name is the value of the option. This prevents potential naming collisions between generated types. Go packaging option The Go packaging option needs to be decided by the team that owns the generated code, because it is directly tied to the source code management practices of the team. Allowing every proto package to decide on their own Go package creates inconsistencies and friction in management of the code. Within that owning team, having a consistent structure in the Go package naming is critical to a consistent end user experience. Changelog 2024-06-13: Added guidance for Go packaging annotation. 2024-06-05: Added rationale for Java packaging options. 2023-02-24: Added guidance on protobuf syntax. 2022-10-18: Added guidance on Ruby/PHP/C# options. 2019-11-18: Added guidance on the packaging annotations.", + 'tags': '', + 'url': '/191', + }, +{ + 'title': "Documentation", + 'text': "Documentation Documentation is one of the most critical aspects of API design. Users of your API are unable to dig into the implementation to understand the API better; often, the API surface definition and its corresponding documentation will be the only things a user has. Therefore, it is important that documentation be as clear, complete, and unambiguous as possible. Guidance In APIs defined in protocol buffers, public comments must be included over every component (service, method, message, field, enum, and enum value) using the protocol buffers comment format. This is important even in cases where the comment is terse and uninteresting, as numerous tools read these comments and use them. Services, in particular, should have descriptive comments that explain what the service is and what users are able to do with it. Note: Many readers will not be native English speakers. Comments should avoid jargon, slang, complex metaphors, pop culture references, or anything else that will not easily translate. Additionally, many readers will have different backgrounds and viewpoints; if writing examples involving people, comments should use people who are non-controversial and no longer alive. Style Comments should be in grammatically correct American English. However, the first sentence of each comment should omit the subject and be in the third-person present tense: // Creates a book under the given publisher. rpc CreateBook(CreateBookRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books\" body: \"book\" }; } Descriptions Descriptions of messages and fields should be brief but complete. Sometimes comments are necessarily perfunctory because there is little to be said; however, before jumping to that conclusion, consider whether some of the following questions are relevant: What is it? How do you use it? What does it do if it succeeds? What does it do if it fails? Is it idempotent? What are the units? (Examples: meters, degrees, pixels) What are the side effects? What are common errors that may break it? What is the expected input format? What range of values does it accept? (Examples: [0.0, 1.0), [1, 10]) Is the range inclusive or exclusive? For strings, what is the minimum and maximum length, and what characters are allowed? If a value is above the maximum length, do you truncate or send an error? Is it always present? (Example: \"Container for voting information. Present only when voting information is recorded.\") Does it have a default setting? (Example: \"If page_size is omitted, the default is 50.\") Formatting Any formatting in comments must be in CommonMark. Headings and tables must not be used, as these cause problems for several tools, and are unsuitable for client library reference documentation. Comments should use code font for field or method names and for literals (such as true). Raw HTML must not be used. \"ASCII art\" attempts to present a diagram within the protos must not be used. The Markdown within the protos is consumed by a large number of renderers, and any ASCII art is very unlikely to be well-presented by all of them. If a diagram is useful in order to understand the API, include a link to a documentation page containing the diagram as an image. Cross-references A comment can \"link\" to another component (service, method, message, field, enum, or enum value) as a Markdown reference link. The reference must be one of the following forms: The fully-qualified name of the element e.g. [Book][google.example.v1.Book] A scope-relative reference qualified e.g. [Sci-Fi genre][Genre.GENRE_SCI_FI] An implied reference e.g. [Book][] which equates to [Book][Book] These references are resolved as per name resolution rules. Containing fields names must not be used in references. They will not resolve. The original definition must be referenced instead. For example, [author][Book.author.family_name] where author is a field of Book, will not resolve, but [author][Author.family_name] will. External links Comments may link to external pages to provide background information beyond what is described in the public comments themselves. External links must use absolute (rather than relative) URLs, including the protocol (usually https), and should not assume the documentation is located on any particular host. For example: [Spanner Documentation](https://cloud.google.com/spanner/docs) Trademarked names When referring to the proper, trademarked names of companies or products in comments, acronyms should not be used, unless the acronym is such dominant colloquial use that avoiding it would obscure the reference (example: IBM). Comments should spell and capitalize trademarked names consistent with the trademark owner\u0027s current branding. Deprecations To deprecate a component (service, method, message, field, enum, or enum value), the deprecated option must be set to true, and the first line of the respective comment must start with \"Deprecated: \" and provide alternative solutions for developers. If there is no alternative solution, a deprecation reason must be given. Internal comments Comments may be explicitly marked as internal by wrapping internal content in (-- and --). Non-public links, internal implementation notes (such as TODO and FIXME directives), and other such material must be marked as internal. Note: Comments should use only leading comments (not trailing comments or detached comments). In particular, comments must not use both a leading and trailing comment to describe any component, because this is a common source of inadvertent omissions of the internal content annotation. Changelog 2024-10-29: Include cross-reference resolution rules. 2023-08-11: Expand deprecated comment requirement to all components. 2021-04-20: Added guidance for deprecated services and RPCs. 2020-04-01: Added guidance requiring absolute URLs for external links. 2020-02-14: Added guidance around the use of trademarked names. 2019-09-23: Added guidance about not using both leading and trailing comments. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/192', + }, +{ + 'title': "Errors", + 'text': "Errors Effective error communication is an important part of designing simple and intuitive APIs. Services returning standardized error responses enable API clients to construct centralized common error handling logic. This common logic simplifies API client applications and eliminates the need for cumbersome custom error handling code. Guidance Services must return a google.rpc.Status message when an API error occurs, and must use the canonical error codes defined in google.rpc.Code. More information about the particular codes is available in the gRPC status code documentation. Error messages should help a reasonably technical user understand and resolve the issue, and should not assume that the user is an expert in your particular API. Additionally, error messages must not assume that the user will know anything about its underlying implementation. Error messages should be brief but actionable. Any extra information should be provided in the details field. If even more information is necessary, you should provide a link where a reader can get more information or ask questions to help resolve the issue. It is also important to set the right tone when writing messages. The following sections describe the fields of google.rpc.Status. Status.message The message field is a developer-facing, human-readable \"debug message\" which should be in English. (Localized messages are expressed using a LocalizedMessage within the details field. See LocalizedMessage for more details.) Any dynamic aspects of the message must be included as metadata within the ErrorInfo that appears in details. The message is considered a problem description. It is intended for developers to understand the problem and is more detailed than ErrorInfo.reason, discussed later. Messages should use simple descriptive language that is easy to understand (without technical jargon) to clearly state the problem that results in an error, and offer an actionable resolution to it. For pre-existing (brownfield) APIs which have previously returned errors without machine-readable identifiers, the value of message must remain the same for any given error. For more information, see Changing Error Messages. Status.code The code field is the status code, which must be the numeric value of one of the elements of the google.rpc.Code enum. For example, the value 5 is the numeric value of the NOT_FOUND enum element. Status.details The details field allows messages with additional error information to be included in the error response, each packed in a google.protobuf.Any message. Google defines a set of standard detail payloads for error details, which cover most common needs for API errors. Services should use these standard detail payloads when feasible. Each type of detail payload must be included at most once. For example, there must not be more than one BadRequest message in the details, but there may be a BadRequest and a PreconditionFailure. All error responses must include an ErrorInfo within details. This provides machine-readable identifiers so that users can write code against specific aspects of the error. The following sections describe the most common standard detail payloads. ErrorInfo The ErrorInfo message is the primary way to send a machine-readable identifier. Contextual information should be included in metadata in ErrorInfo and must be included if it appears within an error message. The reason field is a short snake_case description of the cause of the error. Error reasons are unique within a particular domain of errors. The reason must be at most 63 characters and match a regular expression of [A-Z][A-Z0-9_]+[A-Z0-9]. (This is UPPER_SNAKE_CASE, without leading or trailing underscores, and without leading digits.) The reason should be terse, but meaningful enough for a human reader to understand what the reason refers to. Good examples: CPU_AVAILABILITY NO_STOCK CHECKED_OUT AVAILABILITY_ERROR Bad examples: THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE (overly verbose) ERROR (too general) The domain field is the logical grouping to which the reason belongs. The domain must be a globally unique value, and is typically the name of the service that generated the error, e.g. pubsub.googleapis.com. The (reason, domain) pair form a machine-readable way of identifying a particular error. Services must use the same (reason, domain) pair for the same error, and must not use the same (reason, domain) pair for logically different errors. The decision about whether two errors are \"the same\" or not is not always clear, but should generally be considered in terms of the expected action a client might take to resolve them. The metadata field is a map of key/value pairs providing additional dynamic information as context. Each key within metadata must be at most 64 characters long, and conform to the regular expression [a-z][a-zA-Z0-9-_]+. Any request-specific information which contributes to the Status.message or LocalizedMessage.message messages must be represented within metadata. This practice is critical so that machine actors do not need to parse error messages to extract information. For example consider the following message: An \u003ce2-medium\u003e VM instance with \u003clocal-ssd=3,nvidia-t4=2\u003e is currently unavailable in the \u003cus-east1-a\u003e zone. Consider trying your request in the \u003cus-central1-f,us-central1-c\u003e zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation. The ErrorInfo.metadata map for the same error could be: \"zone\": \"us-east1-a\" \"vmType\": \"e2-medium\" \"attachment\": \"local-ssd=3,nvidia-t4=2\" \"zonesWithCapacity\": \"us-central1-f,us-central1-c\" Additional contextual information that does not appear in an error message may also be included in metadata to allow programmatic use by the client. The metadata included for any given (reason,domain) pair can evolve over time: New keys may be included All keys that have been included must continue to be included (but may have empty values) In other words, once a user has observed a given key for a (reason, domain) pair, the service must allow them to rely on it continuing to be present in the future. The set of keys provided in each (reason, domain) pair is independent from other pairs, but services should aim for consistent key naming. For example, two error reasons within the same domain should not use metadata keys of vmType and virtualMachineType. LocalizedMessage google.rpc.LocalizedMessage is used to provide an error message which should be localized to a user-specified locale where possible. If the Status.message field has a sub-optimal value which cannot be changed due to the constraints in the Changing Error Messages section, LocalizedMessage may be used to provide a better error message even when no user-specified locale is available. Regardless of how the locale for the message was determined, both the locale and message fields must be populated. The locale field specifies the locale of the message, following IETF bcp47 (Tags for Identifying Languages). Example values: \"en-US\", \"fr-CH\", \"es-MX\". The message field contains the localized text itself. This should include a brief description of the error and a call to action to resolve the error. The message should include contextual information to make the message as specific as possible. Any contextual information in the message must be included in ErrorInfo.metadata. See ErrorInfo for more details of how contextual information may be included in a message and the corresponding metadata. The LocalizedMessage payload should contain the complete resolution to the error. If more information is needed than can reasonably fit in this payload, then additional resolution information must be provided in a Help payload. See the Help section for guidance. Help When other textual error messages (in Status.message or LocalizedMessage.message) don\u0027t provide the user sufficient context or actionable next steps, or if there are multiple points of failure that need to be considered in troubleshooting, a link to supplemental troubleshooting documentation must be provided in the Help payload. Provide this information in addition to a clear problem definition and actionable resolution, not as an alternative to them. The linked documentation must clearly relate to the error. If a single page contains information about multiple errors, the ErrorInfo.reason value must be used to narrow down the relevant information. The description field is a textual description of the linked information. This must be suitable to display to a user as text for a hyperlink. This must be plain text (not HTML, Markdown etc). Example description value: \"Troubleshooting documentation for STOCKOUT errors\" The url field is the URL to link to. This must be an absolute URL, including scheme. Example url value: \"https://cloud.google.com/compute/docs/resource-error\" For publicly-documented services, even those with access controls on actual usage, the linked content must be accessible without authentication. For privately-documented services, the linked content may require authentication. Error messages Textual error messages can be present in both Status.message and LocalizedMessage.message fields. Messages should be succinct but actionable, with request-specific information (such as a resource name or region) providing precise details where appropriate. Any request-specific details must be present in ErrorInfo.metadata. Changing error messages Changing the content of Status.message over time must be done carefully, to avoid breaking clients who have previously had to rely on the message for all information. See the rationale section for more details. For a given RPC: If the RPC has always returned ErrorInfo with machine-readable information, the content of Status.message may change over time. (For example, the API producer may provide a clearer explanation, or more request-specific information.) Otherwise, the content of Status.message must be stable, providing the same text with the same request-specific information. Instead of changing Status.message, the API should include a LocalizedMessage within Status.details. Even if an RPC has always returned ErrorInfo, the API may keep the existing Status.message stable and add a LocalizedMessage within Status.details. The content of LocalizedMessage.details may change over time. Partial errors APIs should not support partial errors. Partial errors add significant complexity for users, because they usually sidestep the use of error codes, or move those error codes into the response message, where the user must write specialized error handling logic to address the problem. However, occasionally partial errors are necessary, particularly in bulk operations where it would be hostile to users to fail an entire large request because of a problem with a single entry. Methods that require partial errors should use long-running operations, and the method should put partial failure information in the metadata message. The errors themselves must still be represented with a google.rpc.Status object. Permission Denied If the user does not have permission to access the resource or parent, regardless of whether or not it exists, the service must error with PERMISSION_DENIED (HTTP 403). Permission must be checked prior to checking if the resource or parent exists. If the user does have proper permission, but the requested resource or parent does not exist, the service must error with NOT_FOUND (HTTP 404). HTTP/1.1+JSON representation When clients use HTTP/1.1 as per AIP-127, the error information is returned in the body of the response, as a JSON object. For backward compatibility reasons, this does not map precisely to google.rpc.Status, but contains the same core information. The schema is defined in the following proto: message Error { message Status { // The HTTP status code that corresponds to `google.rpc.Status.code`. int32 code = 1; // This corresponds to `google.rpc.Status.message`. string message = 2; // This is the enum version for `google.rpc.Status.code`. google.rpc.Code status = 4; // This corresponds to `google.rpc.Status.details`. repeated google.protobuf.Any details = 5; } Status error = 1; } The most important difference is that the code field in the JSON is an HTTP status code, not the direct value of google.rpc.Status.code. For example, a google.rpc.Status message with a code value of 5 would be mapped to an object including the following code-related fields (as well as the message, details etc): { \"error\": { \"code\": 404, // The HTTP status code for \"not found\" \"status\": \"NOT_FOUND\" // The name in google.rpc.Code for value 5 } } The following JSON shows a fully populated HTTP/1.1+JSON representation of an error response. { \"error\": { \"code\": 429, \"message\": \"The zone \u0027us-east1-a\u0027 does not have enough resources available to fulfill the request. Try a different zone, or try again later.\", \"status\": \"RESOURCE_EXHAUSTED\", \"details\": [ { \"@type\": \"type.googleapis.com/google.rpc.ErrorInfo\", \"reason\": \"RESOURCE_AVAILABILITY\", \"domain\": \"compute.googleapis.com\", \"metadata\": { \"zone\": \"us-east1-a\", \"vmType\": \"e2-medium\", \"attachment\": \"local-ssd=3,nvidia-t4=2\", \"zonesWithCapacity\": \"us-central1-f,us-central1-c\" } }, { \"@type\": \"type.googleapis.com/google.rpc.LocalizedMessage\", \"locale\": \"en-US\", \"message\": \"An \u003ce2-medium\u003e VM instance with \u003clocal-ssd=3,nvidia-t4=2\u003e is currently unavailable in the \u003cus-east1-a\u003e zone. Consider trying your request in the \u003cus-central1-f,us-central1-c\u003e zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation.\" }, { \"@type\": \"type.googleapis.com/google.rpc.Help\", \"links\": [ { \"description\": \"Additional information on this error\", \"url\": \"https://cloud.google.com/compute/docs/resource-error\" } ] } ] } } Rationale Requiring ErrorInfo ErrorInfo is required because it further identifies an error. With only approximately twenty available values for Status.status, it is difficult to disambiguate one error from another across an entire API Service. Also, error messages often contain dynamic segments that express variable information, so there needs to be machine-readable component of every error response that enables clients to use such information programmatically. Including LocalizedMessage LocalizedMessage was selected as the location to present alternate error messages. While LocalizedMessage may use a locale specified in the request, a service may provide a LocalizedMessage even without a user-specified locale, typically to provide a better error message in situations where Status.message cannot be changed. Where the locale is not specified by the user, it should be en-US (US English). A service may include LocalizedMessage even when the same message is provided in Status.message and when localization into a user-specified locale is not supported. Reasons for this include: An intention to support user-specified localization in the near future, allowing clients to consistently use LocalizedMessage and not change their error-reporting code when the functionality is introduced. Consistency across all RPCs within a service: if some RPCs include LocalizedMessage and some only use Status.message for error messages, clients have to be aware of which RPCs will do what, or implement a fall-back mechanism. Providing LocalizedMessage on all RPCs allows simple and consistent client code to be written. Updating Status.message If a client has ever observed an error with Status.message populated (which it always will be) but without ErrorInfo, the developer of that client may well have had to resort to parsing Status.message in order to find out information beyond just what Status.code conveys. That information may be found by matching specific text (e.g. \"Connection closed with unknown cause\") or by parsing the message to find out metadata values (e.g. a region with insufficient resources). At that point, Status.message is implicitly part of the API contract, so must not be updated - that would be a breaking change. This is one reason for introducing LocalizedMessage into the Status.details. RPCs which have always included ErrorInfo are in a better position: the contract is then more about the stability of ErrorInfo for any given error. The reason and domain need to be consistent over time, and the metadata provided for any given (reason,domain) can only be expanded. It\u0027s still possible that clients could be parsing Status.message instead of using ErrorInfo, but they will always have had a more robust option available to them. Further reading For which error codes to retry, see AIP-194. For how to retry errors in client libraries, see AIP-4221. Changelog 2024-10-18: Rewrite/restructure for clarity. 2024-01-10: Incorporate guidance for writing effective messages. 2023-05-17: Change the recommended language for Status.message to be the service\u0027s native language rather than English. 2023-05-17: Specify requirements for changing error messages. 2023-05-10: Require ErrorInfo for all error responses. 2023-05-04: Require uniqueness by message type for error details. 2022-11-04: Added guidance around PERMISSION_DENIED errors previously found in other AIPs. 2022-08-12: Reworded/Simplified intro to add clarity to the intent. 2020-01-22: Added a reference to the ErrorInfo message. 2019-10-14: Added guidance restricting error message mutability to if there is a machine-readable identifier present. 2019-09-23: Added guidance about error message strings being able to change.", + 'tags': '', + 'url': '/193', + }, +{ + 'title': "Automatic retry configuration", + 'text': "Automatic retry configuration RPCs sometimes fail. When one does, the client performing the RPC needs to know whether it is safe to retry the operation. When status codes are used consistently across multiple APIs, clients can respond to failures appropriately. Guidance Clients should automatically retry requests for which repeated runs would not cause unintended state changes, which are non-transactional, and which are unary. Clients should not automatically retry transactional requests; instead these requests should have application-level retry logic that retries the entire transaction block from the start. Clients should not automatically retry requests in which repeated runs would cause unintended state changes. Note: This AIP does not cover client streaming or bi-directional streaming. Note: For client side retry behavior in the client libraries: see AIP-4221. Retryable codes For methods listed as retryable above, clients should retry the following error codes: UNAVAILABLE: This code generally results from network hiccups, and is generally transient. It is retryable under the expectation that the connection will become available (soon). Non-retryable codes The following codes should not be automatically retried for any request: OK: The request succeeded. CANCELLED: An application can cancel a request, which must be honored. DEADLINE_EXCEEDED: An application can set a deadline, which must be honored. INVALID_ARGUMENT: Retrying a request with an invalid argument will never succeed. DATA_LOSS: This is an unrecoverable error and must immediately be surfaced to the application. Generally non-retryable codes: The following codes generally should not be automatically retried for any request: RESOURCE_EXHAUSTED: This code may be a signal that quota is exhausted. Retries therefore may not be expected to work for several hours; meanwhile the retries may have billing implications. If RESOURCE_EXHAUSTED is used for other reasons than quota and the expected time for the resource to become available is much shorter, it may be retryable. INTERNAL: This code generally means that some internal part of the system has failed, and usually means a bug should be filed against the system. These should immediately be surfaced to the application. UNKNOWN: Unlike INTERNAL, this code is reserved for truly unknown-to-the-system errors, and therefore may not be safe to retry. These should immediately be surfaced to the application. ABORTED: This code typically means that the request failed due to a sequencer check failure or transaction abort. These should not be retried for an individual request; they should be retried at a level higher (the entire transaction, for example). Some codes may be automatically retried if a system is designed without synchronization or signaling between various components. For example, client might retry NOT_FOUND on a read operation, which is designed to hang forever until the resource is created. However, these types of systems are generally discouraged. Therefore, the following codes should not be automatically retried for any request: NOT_FOUND: A client should not retry until a resource is created. ALREADY_EXISTS: A client should not retry until a resource is deleted. PERMISSION_DENIED: A client should not retry until it has permission. UNAUTHORIZED: A client should not retry until it is authorized. UNAUTHENTICATED: A client should not retry until it is authenticated. FAILED_PRECONDITION: A client should not retry until system state changes. OUT_OF_RANGE: A client should not retry until the range is extended. UNIMPLEMENTED: A client should not retry until the RPC is implemented. Further reading For parallel or retried request disambiguation, see AIP-154.", + 'tags': '', + 'url': '/194', + }, +{ + 'title': "Precedent", + 'text': "Precedent Many times, APIs are written in ways that do not match new guidance that is added to these standards after those APIs have already been released. Additionally, sometimes it can make sense to intentionally violate standards for particular reasons, such as maintaining consistency with established systems, meeting stringent performance requirements, or other practical concerns. Finally, as carefully as everyone reviews APIs before they are released, sometimes mistakes can slip through. Since it often is not feasible to fix past mistakes or make the standards serve every use case, APIs may be stuck with these exceptions for quite some time. Further, since new APIs often base their designs (names, types, structures, etc) on existing APIs, it is possible that a standards violation in one API could spill over into other APIs, even if original reason for the exception is not applicable to the other APIs. As a result of this problem, it is important to \"stop the bleeding\" of these standards exceptions into new APIs, and additionally document the reasons for each exception so that historical wisdom is not lost. Guidance If an API violates the AIP standards for any reason, there must be an internal comment linking to this document using its descriptive link (aip.dev/not-precedent) to ensure others do not copy the violations or cite the errors as precedent of a \"previously approved API\". The comment should also include an explanation of what violates standards and why it is necessary. For example: message DailyMaintenanceWindow { // Time within the maintenance window to start the maintenance operations. // It must use the format \"HH MM\", where HH : [00-23] and MM : [00-59] GMT. // (-- aip.dev/not-precedent: This was designed for consistency with crontab, // and preceded the AIP standards. // Ordinarily, this type should be `google.type.TimeOfDay`. --) string start_time = 2; // Output only. Duration of the time window, automatically chosen to be // smallest possible in the given scenario. // (-- aip.dev/not-precedent: This preceded the AIP standards. // Ordinarily, this type should be `google.protobuf.Duration`. --) string duration = 3; } Important: APIs should only be considered to be precedent-setting if they are in beta or GA. Local consistency If an API violates a standard throughout, it would be jarring and frustrating to users to break the existing pattern only for the sake of adhering to the global standard. For example, if all of an API\u0027s resources use creation_time (instead of the standard field create_time described in AIP-142), a new resource in that API should continue to follow the local pattern. However, others who might otherwise copy that API should be made aware that this is contra-standard and not something to cite as precedent when launching new APIs. // ... message Book { // (-- aip.dev/not-precedent: This field was present before there was a // standard field. // Ordinarily, it should be spelled `create_time`. --) google.protobuf.Timestamp creation_time = 1; } // ... message Author { // (-- aip.dev/not-precedent: `Book` had `creation_time` before there was // a standard field, so we match that here for consistency. Ordinarily, // this would be spelled `create_time`. --) google.protobuf.Timestamp creation_time = 1; } Pre-existing functionality Standards violations are sometimes overlooked before launching, resulting in APIs that become stable and therefore can not easily be modified. Additionally, a stable API may pre-date a standards requirement. In these scenarios, it is difficult to make the API fit the standard. However, the API should still cite that the functionality is contra-standard so that other APIs do not copy the mistake and cite the existing API as a reason why their design should be approved. Adherence to external spec Occasionally, APIs must violate standards because specific requests are implementations of an external specification (for example, OAuth), and their specification may be at odds with AIP guidelines. In this case, it is likely to be appropriate to follow the external specification. Adherence to existing systems Similar to the example of an external specification above, it may be proper for an API to violate AIP guidelines to fit in with an existing system in some way. This is a fundamentally similar case where it is wise to meet the customer where they are. A potential example of this might be integration with or similarity to a partner API. Expediency Sometimes there are users who need an API surface by a very hard deadline or money walks away. Since most APIs serve a business purpose, there will be times when an API could be better but cannot get it that way and into users\u0027 hands before the deadline. In those cases, API review councils may grant exceptions to ship APIs that violate guidelines due to time and business constraints. Technical concerns Internal systems sometimes have very specific implementation needs (e.g., they rely on operation transforms that speak UTF-16, not UTF-8) and adhering to AIP guidelines would require extra work that does not add significant value to API consumers. Future systems which are likely to expose an API at some point should bear this in mind to avoid building underlying infrastructure which makes it difficult to follow AIP guidelines. Changelog 2020-03-27: Reworded much of this AIP to follow AIP-8, and remove first and second person. No semantic changes. 2019-05-04: Changed to a public link (aip.dev/not-precedent), and changed references to \"the style guide\" to use the more generic term \"standards\" (to account for a general shift to AIPs).", + 'tags': '', + 'url': '/200', + }, +{ + 'title': "Fields", + 'text': "Fields The google.api.FieldInfo type, through its accompanying extension google.api.field_info, enriches a field\u0027s schema beyond the basic name and type information. Guidance Decorating a field with google.api.field_info is only necessary when explicitly stated in this AIP or another that leverages google.api.FieldInfo information. As such, the guidance herein applies to those scenarios as well. Format Fields with a primitive type can still have a specific format. To convey that type format, the FieldInfo.Format enumeration is used via the (google.api.field_info).format extension field. The following guidance conveys the meaning of and requirements for use of each FieldInfo.Format value. UUID4 The UUID4 format represents a UUID version 4 value as governed by RFC 4122. It must only be used on a field of type string. Such a value may be normalized by the service to entirely lowercase letters. For example, the value F47AC10B-58CC-0372-8567-0E02B2C3D479 would be normalized to f47ac10b-58cc-0372-8567-0e02b2c3d479. As such, equivalence comparison must not be done via primitive text comparison. Instead, an RFC 4122 compliant implementation must be used. IPv4 The IPV4 format represents an IP v4 address as governed by RFC 791. It must only be used on a field of type string. Such a value may be condensed by the service, with leading zeros in each octet stripped. For example, 001.022.233.040 would be condensed to 1.22.233.40. As such, equivalence comparison must not be done via primitive text comparison. Instead, an RFC 791 compliant implementation must be used. IPv6 The IPV6 format represents an IP v6 address as governed by RFC 4291. It must only be used on a field of type string. Such a value may be normalized by the service to entirely lowercase letters with zeros compressed, following RFC 5952. For example, the value 2001:0DB8:0::0 would be normalized to 2001:db8::. As such, equivalence comparison must not be done via primitive text comparison. Instead, an RFC 4291 compliant implementation must be used. IPv4 or IPv6 The IPV4_OR_IPV6 value indicates that the field can be either an IP v4 or v6 address, as described in the IPv4 and IPv6 sections. Format Compatibility Adding a format specifier to an existing, unspecified field is not backwards compatible, unless the field in question has always conformed to the format being specified. Changing an existing format specifier to a different one in all cases is not backwards compatible. Extending Format Any new FieldInfo.Format value must be governed by an IETF-approved RFC or a Google-approved AIP. Rationale Why add a format specifier? The format of a primitive-typed field can be critical to its usability. Some programming languages may convey a specific type format as a standalone type, as Java does with UUID. Most have specific structural requirements that are validated by the service, so conveying the format to the user ahead of time is critical to their experience. Why discourage primitive equality comparisons? The text representations of the supported formats have many nuances and transforming the value into a canonical representation is non-trivial. As such, aligning implementations between each consumer and each service without any issue is infeasible. Why document value normalizations? While primitive comparison is not recommended for any of the supported formats, uniform normalization of values is important to set consumer expectations, and create a user-friendly surface. Why require an RFC or AIP for new formats? Those formats which are sufficiently standardized to merit an RFC or AIP are stable enough and widely enough known to be incorporated as a supported value and see usage in Google APIs. Requiring such extra guidance means that governing the format specification is not the responsibility of the FieldInfo.Format enumeration itself.", + 'tags': '', + 'url': '/202', + }, +{ + 'title': "Field behavior documentation", + 'text': "Field behavior documentation When defining fields in protocol buffers, it is customary to explain to users certain aspects of the field\u0027s behavior (such as whether it is required or optional). Additionally, it can be useful for other tools to understand this behavior (for example, to optimize client library signatures). Guidance APIs use the google.api.field_behavior annotation to describe well-understood field behavior, such as a field being required or immutable. // The audio data to be recognized. RecognitionAudio audio = 2 [(google.api.field_behavior) = REQUIRED]; APIs must apply the google.api.field_behavior annotation on every field on a message or sub-message used in a request. An exception to this is the AIP-154 etag field on a resource message, which should not have any google.api.field_behavior assigned. The annotation must include any google.api.FieldBehavior values that accurately describe the behavior of the field. FIELD_BEHAVIOR_UNSPECIFIED must not be used. APIs must at minimum use one of REQUIRED, OPTIONAL, or OUTPUT_ONLY. Warning: Although field_behavior does not impact proto-level behavior, many clients (e.g. CLIs and SDKs) rely on them to generate code. Thoroughly review and consider which values are relevant when adding a new field. Fields with no annotation are interpreted as OPTIONAL for backwards-compatility. Nontheless, this annotation must not be omitted. Note: The vocabulary given in this document is for descriptive purposes only, and does not itself add any validation. The purpose is to consistently document this behavior for clients. field behavior of nested messages google.api.field_behavior annotations on a nested message are independent of the annotations of the parent. For example, a nested message can have a field behavior of REQUIRED while the parent field can be OPTIONAL: message Title { string text = 1 [(google.api.field_behavior) = REQUIRED]; } message Slide { Title title = 1 [(google.api.field_behavior) = OPTIONAL]; } In the case above, if a title is specified, the text field is required. Vocabulary Identifier The use of IDENTIFIER indicates that a field within a resource message is used to identify the resource. It must be attached to the name field and must not be attached to any other field (see fields representing resource names). The IDENTIFIER value conveys that the field is not accepted as input (i.e. OUTPUT_ONLY) in the context of a create method, while also being considered IMMUTABLE and accepted as input for mutation methods that accept the resource as the primary input e.g. Standard Update. This annotation must not be applied to references to other resources within a message. Immutable The use of IMMUTABLE indicates that a field on a resource cannot be changed after its creation. This can apply to either fields that are input or outputs, required or optional. When a service receives an immutable field in an update request (or similar), even if included in the update mask, the service should ignore the field if the value matches, but should error with INVALID_ARGUMENT if a change is requested. Potential use cases for immutable fields (this is not an exhaustive list) are: Attributes of resources that are not modifiable for the lifetime of the application (e.g. a disk type). Note: Fields which are \"conditionally immutable\" must not be given the immutable annotation. Input only The use of INPUT_ONLY indicates that the field is provided in requests and that the corresponding field will not be included in output. Additionally, a field should only be described as input only if it is a field in a resource message or a field of a message included within a resource message. Notably, fields in request messages (a message which only ever acts as an argument to an RPC, with a name usually ending in Request) should not be described as input only because this is already implied. Potential use cases for input only fields (this is not an exhaustive list) are: The ttl field as described in AIP-214. Warning: Input only fields are rare and should be considered carefully before use. Optional The use of OPTIONAL indicates that a field is not required. A field may be described as optional if it is a field on a request message (a message that is an argument to an RPC, usually ending in Request), or a field on a submessage. Output only The use of OUTPUT_ONLY indicates that the field is provided in responses, but that including the field in a message in a request does nothing (the server must clear out any value in this field and must not throw an error as a result of the presence of a value in this field on input). Similarly, services must ignore the presence of output only fields in update field masks (see: AIP-161). Additionally, a field should only be described as output only if it is a field in a resource message, or a field of a message farther down the tree. Notably, fields in response messages (a message which only ever acts as a return value to an RPC, usually ending in Response) should not be described as output only because this is already implied. Output only fields may be set to empty values if appropriate to the API. Potential use cases for output only fields (this is not an exhaustive list) are: Create or update timestamps. Derived or structured information based on original user input. Properties of a resource assigned by the service which can not be altered. Required The use of REQUIRED indicates that the field must be present (and set to a non-empty value) on the request or resource. A field should only be described as required if either: It is a field on a resource that a user provides somewhere as input. In this case, the resource is only valid if a \"truthy\" value is stored. When creating the resource, a value must be provided for the field on the create request. When updating the resource, the user may omit the field provided that the field is also absent from the field mask, indicating no change to the field (otherwise it must be provided). It is a field on a request message (a message that is an argument to an RPC, with a name usually ending in Request). In this case, a value must be provided as part of the request, and failure to do so must cause an error (usually INVALID_ARGUMENT). We define the term \"truthy\" above as follows: For primitives, values other than 0, 0.0, empty string/bytes, and false For repeated fields maps, values with at least one entry For messages, any message with at least one \"truthy\" field. Fields should not be described as required in order to signify: A field which will always be present in a response. A field which is conditionally required in some situations. A field on any message (including messages that are resources) which is never used as user input. Note: In most cases, empty values (such as false for booleans, 0 for integers, or the unspecified value for enums) are indistinguishable from unset values, and therefore setting a required field to a falsy value yields an error. A corollary to this is that a required boolean must be set to true. Unordered List The use of UNORDERED_LIST on a repeated field of a resource indicates that the service does not guarantee the order of the items in the list. A field should be described as an unordered list if the service does not guarantee that the order of the elements in the list will match the order that the user sent, including a situation where the service will sort the list on the user\u0027s behalf. A resource with an unordered list may return the list in a stable order, or may return the list in a randomized, unstable order. Backwards compatibility Adding or changing google.api.field_behavior values can represent a semantic change in the API that is perceived as incompatible for existing clients. The following are examples of backwards incompatible changes with google.api.field_behavior: Adding REQUIRED to an existing field previously considered OPTIONAL (implicitly or otherwise) Adding a new field annotated as REQUIRED to an existing request message Adding OUTPUT_ONLY to an existing field previously accepted as input Adding INPUT_ONLY to an existing field previously emitted as output Adding IMMUTABLE to an existing field previously considered mutable Removing OUTPUT_ONLY from an existing field previously ignored as input Removing IDENTIFIER from an existing field. There are some changes that are backwards compatible, which are as follows: Adding OPTIONAL to an existing field Adding IDENTIFIER to an existing name field Changing from REQUIRED to OPTIONAL on an existing field Changing from OUTPUT_ONLY and/or IMMUTABLE to IDENTIFIER on an existing field Removing REQUIRED from an existing field Removing INPUT_ONLY from an existing field previously excluded in responses Removing IMMUTABLE from an existing field previously considered immutable Rationale Identifier field behavior Resource names, the primary identifiers for any compliant resource, are never fully constructed by the user on create. Such fields are typically assigned OUTPUT_ONLY field behavior. They are, however, also often consumed as the primary identifier in scenarios where the resource itself is the primary request payload. Such fields could not be considered OUTPUT_ONLY. Furthermore, in mutation requests, like Standard Update, the resource name as the primary identifier cannot be changed in place. Such fields are typically assigned IMMUTABLE field behavior. These conflicting and context-dependent field behaviors meant that a new value was necessary to single out and convey the behavior of the resource name field. Required set of annotations A field used in a request message must be either an input or an output. In the case of an output, the OUTPUT_ONLY annotation is sufficient. In the case of an input, a field is either required or optional, and therefore should have at least the REQUIRED or OPTIONAL annotation, respectively. Only providing INPUT_ONLY does not convey the necessity of the field, so specifying either REQUIRED or OPTIONAL is still necessary. Requiring field behavior By including the field behavior annotation for each field, the overall behavior that the resource exhibits is more clearly defined. Clearly defined field behavior improves programmatic clients and user understanding. Requiring the annotation also forces the API author to explicitly consider the behavior when initially authoring of the API. Modifying field behavior after initial authoring can result in backwards-incompatible changes in clients. For example, making an optional field required results in backwards-incompatible changes in the method signature of an RPC or a resource in a Declarative client. See the Backwards compatibility section for more detailed compatibility guidance. History In 2023-05 field_behavior was made mandatory. Prior to this change, the annotation was often omitted. Its values are relied upon to produce high quality clients. Furthermore, adding or changing some of the field_behavior values after the fact within a major version can be backwards-incompatible. See the Backwards compatibility section for more detailed compatibility guidance. The benefits of requiring field_behavior at the time that the API is authored surpass the costs to clients and API users of not doing so. Changelog 2023-09-14: Clarify that nested behavior and parent behavior are independent. 2023-08-25: Add guidance on IDENTIFIER. 2023-07-20: Describe compatibility guidance with new section. 2023-05-24: Clarify that IMMUTABLE does not imply input nor required. 2023-05-10: Added guidance to require the annotation. 2020-12-15: Added guidance for UNORDERED_LIST. 2020-05-27: Clarify behavior when receiving an immutable field in an update. 2019-12-05: Added guidance on output only fields in field masks. 2019-06-18: Use the machine-readable annotation, not comments.", + 'tags': '', + 'url': '/203', + }, +{ + 'title': "Beta-blocking changes", + 'text': "Beta-blocking changes APIs often release an Alpha version of their API in order to get early feedback from customers. This API is provisional and can change many times before the important feedback is incorporated and the API is made stable for Beta. Since the purpose of Alpha is to gather feedback, the API does not need to be perfect yet, and it\u0027s not strictly necessary for API authors to address every usability concern or address every point in the API standards. Often, API authors and API reviewers will not agree on the best design, and the best way to find out is by having users try out the API. However, once the feedback has been collected and the API is going to be promoted to Beta, usability concerns and style issues do need to be addressed. In order to ensure that these issues are not forgotten, they should be explicitly documented in the API. Guidance If an API has usability concerns or violates API standards, and the present design should receive additional scrutiny before being carried through to the Beta version, there must be an internal comment linking to this document using its descriptive link (aip.dev/beta-blocker) to ensure that the design is corrected before the API is released to Beta. The comment must also indicate what kind of change should be made for Beta. For example: message InputConfig { // Parameters for input. // (-- aip.dev/beta-blocker: Convert well-known parameters into explicit // fields before the Beta launch. --) map\u003cstring, string\u003e parameters = 1; } If an exception to API standards does need to be carried through to Beta and GA, see AIP-200.", + 'tags': '', + 'url': '/205', + }, +{ + 'title': "Unicode", + 'text': "Unicode APIs should be consistent on how they explain, limit, and bill for string values and their encodings. This ranges from little ambiguities (like fields \"limited to 1024 characters\") all the way to billing confusion (are names and values of properties in Datastore billed based on characters or bytes?). In general, if we talk about limits measured in bytes, we are discriminating against non-ASCII text since it takes up more space. On the other hand, if we talk about \"characters\", we are ambiguous about whether those are Unicode \"code points\", \"code units\" for a particular encoding (e.g. UTF-8 or UTF-16), \"graphemes\", or \"grapheme clusters\". Unicode primer Character encoding tends to be an area we often gloss over, so a quick primer: Strings are just bytes that represent numbers according to some encoding format. When we talk about characters, we sometimes mean Unicode code points, which are numbers in the Unicode spec (up to 21 bits). Other times we might mean graphemes or grapheme clusters, which may have multiple numeric representations and may be represented by more than one code point. For example, \u00e1 may be represented as a composition of U+0061 + U+0301 (the a + the accent combining mark) or as a single code point, U+00E1. Protocol buffers uses UTF-8 (\"Unicode Transformation Format\") which is a variable-length encoding scheme using up to 4 code units (8-bit bytes) per code point. Guidance Character definition TL;DR: In our APIs, \"characters\" means \"Unicode code points\". In API documentation (e.g., API reference documents, blog posts, marketing documentation, billing explanations, etc), \"character\" must be defined as a Unicode code point. Length units TL;DR: Set size limits in \"characters\" (as defined above). All string field length limits defined in API comments must be measured and enforced in characters as defined above. This means that there is an underlying maximum limit of (4 * characters) bytes, though this limit will only be hit when using exclusively characters that consist of 4 UTF-8 code units (32 bits). If you use a database system (e.g. Spanner) which allows you to define a limit in characters, it is safe to assume that this byte-defined requirement is handled by the underlying storage system. Billing units APIs may use either code points or bytes (using the UTF-8 encoding) as the unit for billing or quota measurement (e.g., Cloud Translation chooses to use characters). If an API does not define this, the assumption is that the unit of billing is characters (e.g., $0.01 per character, not $0.01 per byte). Unique identifiers TL;DR: Unique identifiers should limit to ASCII, generally only letters, numbers, hyphens, and underscores, and should not start with a number. Strings used as unique identifiers should limit inputs to ASCII characters, typically letters, numbers, hyphens, and underscores ([a-zA-Z][a-zA-Z0-9_-]*). This ensures that there are never accidental collisions due to normalization. If an API decides to allow all valid Unicode characters in unique identifiers, the API must reject any inputs that are not in Normalization Form C. Generally, unique identifiers should not start with a number as that prefix is reserved for Google-generated identifiers and gives us an easy way to check whether we generated a unique numeric ID for or whether the ID was chosen by a user. Unique identifiers should use a maximum length of 64 characters, though this limit may be expanded as necessary. 64 characters should be sufficient for most purposes as even UUIDs only require 36 characters. Note: See AIP-122 for recommendations about resource ID segments. Normalization TL;DR: Unicode values should be stored in Normalization Form C. Values should always be normalized into Normalization Form C. Unique identifiers must always be stored in Normalization Form C (see the next section). Imagine we\u0027re dealing with Spanish input \"estar\u00e9\" (the accented part will be bolded throughout). This text has what we might visualize as 6 \"characters\" (in this case, they are grapheme clusters). It has two possible Unicode representations: Using 6 code points: U+0065 U+0073 U+0074 U+0061 U+0072 U+00E9 Using 7 code points: U+0065 U+0073 U+0074 U+0061 U+0072 U+0065 U+0301 Further, when encoding to UTF-8, these code points have two different serialized representations: Using 7 code-units (7 bytes): 0x65 0x73 0x74 0x61 0x72 0xC3 0xA9 Using 8 code-units (8 bytes): 0x65 0x73 0x74 0x61 0x72 0x65 0xCC 0x81 To avoid this discrepancy in size (both code units and code points), use Normalization Form C which provides a canonical representation for strings. Uniqueness TL;DR: Unicode values must be normalized to Normalization Form C before checking uniqueness. For the purposes of unique identification (e.g., name, id, or parent), the value must be normalized into Normalization Form C (which happens to be the most compact). Otherwise we may have what is essentially \"the same string\" used to identify two entirely different resources. In our example above, there are two ways of representing what is essentially the same text. This raises the question about whether the two representations should be treated as equivalent or not. In other words, if someone were to use both of those byte sequences in a string field that acts as a unique identifier, would it violate a uniqueness constraint? The W3C recommends using Normalization Form C for all content moving across the internet. It is the most compact normalized form on Unicode text, and avoids most interoperability problems. If we were to treat two Unicode byte sequences as different when they have the same representation in NFC, we\u0027d be required to reply to possible \"Get\" requests with content that is not in normalized form. Since that is definitely unacceptable, we must treat the two as identical by transforming any incoming string data into Normalized Form C or rejecting identifiers not in the normalized form. There is some debate about whether we should view strings as sequences of code points represented as bytes (leading to uniqueness determined based on the byte-representation of said string) or to interpret strings as a higher level abstraction having many different possible byte-representations. The stance taken here is that we already have a field type for handling that: bytes. Fields of type string already express an opinion of the validity of an input (it must be valid UTF-8). As a result, treating two inputs that have identical normalized forms as different due to their underlying byte representation seems to go against the original intent of the string type. This distinction typically doesn\u0027t matter for strings that are opaque to our services (e.g., description or display_name), however when we rely on strings to uniquely identify resources, we are forced to take a stance. Put differently, our goal is to allow someone with text in any encoding (ASCII, UTF-16, UTF-32, etc) to interact with our APIs without a lot of \"gotchas\". References Unicode normalization forms Datastore pricing \"name and value of each property\" doesn\u0027t clarify this. Natural Language pricing uses charges based on UTF-8 code points rather than code units. Text matching and normalization", + 'tags': '', + 'url': '/210', + }, +{ + 'title': "Authorization checks", + 'text': "Authorization checks The majority of operations, whether reads or writes, require authorization: permission to do the thing the user is asking to do. Additionally, it is important to be careful how much information is provided to unauthorized users, since leaking information can be a security concern. Guidance Services must check authorization before validating any request, to ensure both a secure API surface and a consistent user experience. An operation may require multiple permissions or preconditions in order to grant authorization. If a request can not pass the authorization check for any reason, the service must error with PERMISSION_DENIED, and the corresponding error message should look like: \"Permission \u0027{p}\u0027 denied on resource \u0027{r}\u0027 (or it might not exist).\" This avoids leaking resource existence. If it is not possible to determine authorization for a resource because the resource does not exist, the service should check authorization to read children on the parent resource, and return NOT_FOUND if the authorization check passes. Multiple operations A service could encounter a situation where it has two different operations with two different permissions, either of which would reveal the existence of a resource if called, but a user only has permission to call one of them. In this situation, the service should still only check for authorization applicable to the operation being called, and should not try to \"help out\" by checking for related authorization that would provide permission to reveal existence, because such algorithms are complicated to implement correctly and prone to accidental leaks. For example, posit a scenario where: A resource exists within a given collection that a user is unable to read. The user does have the ability to create other resources, and the collection uses user-specified IDs (meaning that a failure because of a duplicate ID would reveal existence). In this situation, the get or create methods should still only check their permissions when determining what error to return, and not one another\u0027s. Rationale RFC 7231 \u00a76.5.3 states that services are permitted to use 404 Not Found in lieu of 403 Forbidden in situations where the service does not want to divulge existence, whereas this AIP argues for the use of PERMISSION_DENIED (which corresponds to 403 Forbidden in HTTP) instead. We take this position for the following reasons: The practice of \"getting 404 Not Found until you have enough permission to get 403 Forbidden\" is counter-intuitive and increases the difficulty of troubleshooting. A service could ameliorate this by sending information about missing permissions while still using the 404 Not Found status code, but this constitutes a mixed message. While 403 Forbidden is essentially always an error requiring manual action, 404 Not Found is often a valid response that the application can handle (e.g. \"get or create\"); overloading it for permission errors deprives applications of this benefit. RFC 7231 \u00a76.5.4 states that 404 Not Found results are cacheable, but permission errors are not generally cacheable. Sending explicit cache controls on a conditional basis could ameliorate this, but would defeat the purpose. The guidance here is more consistent with most other real-world authorization systems. Changelog 2021-05-11: Added a more detailed \"Rationale\" section.", + 'tags': '', + 'url': '/211', + }, +{ + 'title': "Common components", + 'text': "Common components As specified in AIP-215, APIs must be self-contained except for the use of \"common component\" packages which are intended for use by multiple APIs. There are two kinds of common component packages: Organization-specific common components, covering organization-specific concepts such as a \"viewport\" in Maps. Global common components which are generic (i.e. not domain-specific), such as \"timestamp\" or \"postal address\". Where it is safe to share a single representation across multiple APIs, common components can make it easier for clients to interact with those APIs. Concept-specific client code can be written once, and messages can be used from the response of one API in the request of another without clunky copying, for example. This benefit comes with significant restrictions and limitations, however, and should not be attempted lightly. Note that even if the domain of a component is common, the requirements of a component may be organization-specific. For example, some organizations may have particular requirements of how financial values are represented, leading to multiple finance-oriented organization-specific common components - because any global common component would either not meet the organization-specific requirements, or be too complex for general use. Guidance Organization-wide common component packages must end with .type, e.g. google.geo.type or google.shopping.type. Organizations must consult the API design team before creating a new organization-wide common component package. Organization-wide common component packages must be published in the googleapis repository. Organizations creating and publishing a new organization-wide common component package must update this AIP to include it in the list below. Organizations must not define generic components in organization-specific common component packages, instead preferring global common components. Common components must not be \"moved\" (that is, deleted from one common component package and added to a different one) from an organization-specific common component package to a global common component package or vice versa. A common component may be copied from an organization-specific common component package to a global common component package (without deleting the original component) if it is found to be more widely-applicable than originally expected. Fields should not be added to existing messages. Values should not be added to existing enums. Fields must not be removed from existing messages. Values must not be removed from existing enums. While documentation may be clarified, it should not change the meanings of existing values, including the validity of any given message or set of messages. New proto messages and enums may be added to common component packages. API teams should allow sufficient time for propagation to clients before using the new messages and enums in their APIs. Fields may take some time for any changes to propagate through publication to client libraries and other surfaces. API teams should consult widely within their organization, and ideally with the API design team, before adding a new message or enum, due to the limitations listed above. Existing global common components The global common components, which public-facing protos for an API may safely import, are as follows: google.api.* (but not subpackages of google.api) google.longrunning.Operation google.protobuf.* google.rpc.* google.type.* Note that some common components may have internal-only fields. APIs should generally only rely on fields which have been released into open source. Google APIs may also import google.iam.v1.*, which provides the IAM messages used throughout Google. Note: Many APIs also import components from other packages for internal-only use (e.g. to apply visibility labels or provide instructions to internal infrastructure). This is acceptable provided that the public components do not contain such references. Protobuf types The google.protobuf package is somewhat special in that it is shipped with protocol buffers itself, rather than with API tooling. (For most API designers, this should be an implementation detail). This package includes a small library of types useful for representing common programming language constructs: google.protobuf.Duration: Durations, with nanosecond-level precision. The protobuf runtime provides helper functions to convert to and from language-native duration objects where applicable (such as Python\u0027s timedelta). google.protobuf.Struct: JSON-like structures (a dictionary of primitives, lists, and other dictionaries). The protobuf runtime provides helper functions in most languages to convert struct objects to and from JSON. google.protobuf.Timestamp: Timestamps, with nanosecond-level precision. The protobuf runtime provides helper functions in most languages to convert to and from language-native timestamp objects (such as Python\u0027s datetime). API Types The google.type package provides a \"standard library\" of types useful for representing common concepts in APIs. While types are added from time to time and the definitive list is always the code, several types deserve note: google.type.Color: RGB or RGBA colors. google.type.Date: Calendar dates, with no time or time zone component. google.type.DayOfWeek: The day of the week, with no other date, time, or time zone component. google.type.LatLng: Geographic coordinates. google.type.Money: Currency. google.type.PostalAddress: Postal addresses in most countries. google.type.TimeOfDay: Wall-clock time, with no date or time zone component. Adding to common protos Occasionally, it may be useful to add protos to these packages or to add to the list of commonly-available protos. In order to do this, open an issue on the AIP repository in GitHub, noting the guidelines above. Existing organization-specific common component packages The following organization-specific common component packages exist and conform with the above guidance: google.apps.script.type Common component package for Google Apps Script. google.geo.type Common component package for Google Maps and the Geo organization. google.actions.type Common component package for Actions on Google APIs. Non-conformant common component packages The following common component packages exist, but do not conform with the above guidance, and do not form a precedent for further such packages. google.cloud.common: This does not conform to the requirement for the package name to end in .type. (This would otherwise be acceptable, and this package should be considered as the Cloud common component package.) google.logging.type: This appears to be API-specific, although it\u0027s used from multiple APIs; some aspects should probably be global or in a Cloud common component package. google.cloud.workflows.type: API-specific types. google.cloud.oslogin.common: API-specific types, and a non-conformant name. google.identity.accesscontextmanager.type: API-specific types. google.networking.trafficdirector.type: API-specific types. Rationale Common components are effectively unversioned: APIs evolve independently of each other, both in terms of definition and implementation. A change such as adding a field is backward-compatible and predictable in specific APIs, and the API team can ensure that the server implementation is available before the API definition is published. By contrast, a change in a common component would effectively be universally available even if most API implementations did not take it into account. Adding a new message or enum is backward-compatible, as it does not affect existing APIs that may import other messages or enums from the same common component package. Consultation with the API design team is required for global common components and suggested for organization-specific common components as the border between \"generic\" and \"organization-specific\" is a gray area; some generic concepts have organization-specific use cases which surface through the components. Changelog 2023-06-27: Restructured AIPs 215 and 213 for clarity, and introduced the concept of organization-wide common protos more formally. 2018-08-17: Initial AIP written.", + 'tags': '', + 'url': '/213', + }, +{ + 'title': "Resource expiration", + 'text': "Resource expiration Customers often want to provide the time that a given resource or resource attribute is no longer useful or valid (e.g. a rotating security key). Currently we recommend that customers do this by specifying an exact \"expiration time\" into a google.protobuf.Timestamp expire_time field; however, this adds additional strain on the user when they want to specify a relative time offset until expiration rather than a specific time until expiration. Furthermore, the world understands the concept of a \"time-to-live\", often abbreviated to TTL, but the typical format of this field (an integer, measured in seconds) results in a sub-par experience when using an auto-generated client library. Guidance APIs wishing to convey an expiration must rely on a google.protobuf.Timestamp field called expire_time. APIs wishing to allow a relative expiration time must define a oneof called expiration (or {something}_expiration) containing both the expire_time field and a separate google.protobuf.Duration field called ttl, the latter marked as input only. APIs must always return the expiration time in the expire_time field and leave the ttl field blank when retrieving the resource. APIs that rely on the specific semantics of a \"time to live\" (e.g., DNS which must represent the TTL as an integer) may use an int64 ttl field (and should provide an aip.dev/not-precedent comment in this case). Example message ExpiringResource { // google.api.resource and other annotations and fields oneof expiration { // Timestamp in UTC of when this resource is considered expired. // This is *always* provided on output, and is calculated using // the value of [ttl][] if set when created. google.protobuf.Timestamp expire_time = 2; // Input only. The TTL for this resource. google.protobuf.Duration ttl = 3 [(google.api.field_behavior) = INPUT_ONLY]; } } Rationale Alternatives considered A new standard field called ttl We considered allowing a standard field called ttl as an alternative way of defining the expiration, however doing so would require that API services continually update the field, like a clock counting down. This could potentially cause problems with the read-modify-write lifecycle where a resource is being processed for some time, and effectively has its life extended as a result of that processing time. Always use expire_time This is the current state of the world with a few exceptions. In this scenario, we could potentially push the computation of now + ttl = expire_time into client libraries; however, this leads to a somewhat frustrating experience in the command-line and using REST/JSON. Leaving things as they are is typically the default, but it seems many customers want the ability to define relative expiration times as it is quite a bit easier and removes questions of time zones, stale clocks, and other silly mistakes.", + 'tags': '', + 'url': '/214', + }, +{ + 'title': "API-specific protos", + 'text': "API-specific protos APIs are mostly defined in terms of protos which are API-specific, with occasional dependencies on common components. Keeping APIs isolated from each other avoids versioning problems and client library packaging problems. Guidance All protos specific to an API must be within a package with a major version (e.g., google.library.v1). References to resources in other APIs must be expressed in terms of resource names (AIP-122), rather than using the resource messages. When two versions of an API use effectively the same (API-specific) proto that proto must be duplicated in each version. (In other words, APIs must not create their own \"API-specific common component\" packages.) Organization-specific common components may be placed in a common package, as described in AIP-213, but must not be used by any API outside that organization. Global common components (also described in AIP-213) may be freely used by any API. Rationale When one API depends on protos defined by another API, this introduces uncertainty in terms of customer-expected behavior and client library dependency management. Suppose google.cloud.library.v1 depends on the protos (rather than abstract resources) in google.cloud.movies.v2. Any change to google.cloud.movies.v2 can cause problems. For example: If a field is added to a message in google.cloud.movies.v2, should customers using google.cloud.library.v1 expect to see it? If so, how soon after the field has been added? What about other API changes? If the whole major version google.cloud.movies.v2 is deprecated (typically after v3 has been released), does that mean google.cloud.library.v1 has to change to use google.cloud.movies.v3, and if so, does that require a new major version for the library API as well? How should client library versioning reflect changes to dependent APIs? Keeping APIs isolated from each other, with a limited set of common components which are maintained in a highly disciplined way, reduces a lot of the issues with dependencies. API-specific common components shared across versions add complexity for client library generation and packaging, and are inflexible in terms of versioning. When protos are duplicated because they start off the same in multiple versions, they can still diverge over time as they are isolated from each other. Changelog 2023-06-27: Restructured AIPs 215 and 213 for clarity. 2023-05-11: Changed \"PA\" to \"organization\". 2018-10-01: Initial AIP written.", + 'tags': '', + 'url': '/215', + }, +{ + 'title': "States", + 'text': "States Many API resources carry a concept of \"state\": ordinarily, the resource\u0027s place in its life cycle. For example, a virtual machine may be being provisioned, available for use, being spun down, or potentially be in one of several other situations. A job or query may be preparing to run, be actively running, have completed, and so on. Guidance Resources needing to communicate their state should use an enum, which should be called State (or, if more specificity is required, end in the word State). This enum should be nested within the message it describes when only used as a field within that message. Important: We use the term State, and not Status (which is reserved for the HTTP and gRPC statuses). Enum values Ideally, Google APIs use the same terminology throughout when expressing the same semantic concepts. There are usually many words available to express a given state, but our customers often use multiple APIs together, and it is easier for them when our terms are consistent. At a high level: Resources that are available for use are ACTIVE (preferred over terms such as \"ready\" or \"available\"). Resources that have completed a (usually terminal) requested action use past participles (usually ending in -ED), such as SUCCEEDED (not \"successful\"), FAILED (not \"failure\"), DELETED, SUSPENDED, and so on. Resources that are currently undergoing a state change use present participles (usually ending in -ING), such as RUNNING, CREATING, DELETING, and so on. In this case, it is expected that the state is temporary and will resolve to another state on its own, with no further user action. Note: Remember to only add states that are useful to customers. Exposing a large number of states simply because they exist in your internal system is unnecessary and adds confusion for customers. Each state must come with a use case for why it is necessary. Output only The field referencing the State enum in a resource should behave and be documented as \"Output only\", in accordance with AIP-203. APIs should not allow a State enum to be directly updated through an \"update\" method (or directly set through the \"create\" method), and should instead use custom state transition methods. This is because update methods are generally not expected to have side effects, and also because updating state directly implies that it is possible to set the state to any available value, whereas states generally reflect a resource\u0027s progression through a lifecycle. State transition methods State transition methods are a special type of custom method that are responsible for transitioning a state field from one enum value to another. As part of the transition, other fields may also change, e.g. an update_time field. The method definition should look like the following: // Publishes a book. // The `state` of the book after publishing is `PUBLISHED`. // `PublishBook` can be called on Books in the state `DRAFT`; Books in a // different state (including `PUBLISHED`) returns an error. rpc PublishBook(PublishBookRequest) returns (Book) { option (google.api.http) = { post: \"/v1/{name=publishers/*/books/*}:publish\" body: \"*\" }; } The name of the method should be a verb followed by the singular form of the resource\u0027s message name. The request message must match the RPC name, with a Request suffix. The response message should be the resource itself. If the RPC is long-running, the response message should be a google.longrunning.Operation which resolves to the resource itself. The HTTP verb must be POST. The HTTP URI must use a : character followed by the custom verb (:publish in the above example), and the verb in the URI must match the verb in the name of the RPC. If word separation is required, camelCase must be used. The body clause in the google.api.http annotation must be \"*\". The request message field receiving the resource name should map to the URI path. This field should be called name. The name field should be the only variable in the URI path. All remaining parameters should map to URI query parameters. If the state transition is not allowed, the service must error with FAILED_PRECONDITION (HTTP 400). The request message should look like this: message PublishBookRequest { // The name of the book to publish. // Format: publishers/{publisher}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; } A resource name field must be included. It should be called name. The comment for the field should document the resource pattern. Other fields may be included. Additional Guidance Default value The zero value of each state enum should adhere to the following convention: enum State { // The default value. This value is used if the state is omitted. STATE_UNSPECIFIED = 0; // Other values... } Resources should not provide an unspecified state to users, and this value should not actually be used. Value uniqueness Multiple top-level enums within the same package must not share the same values. This is because the C++ protoc code generator flattens top-level enum values into a single namespace. State enums should live inside the resource definition. Prefixes Using a STATE_ prefix on every enum value is unnecessary. State enum values should not be prefixed with the enum name, except for the default value STATE_UNSPECIFIED. Breaking changes TL;DR: Clearly communicate to users that state enums may receive new values in the future, and be conscientious about adding states to an existing enum. Even though adding states to an existing states enum can break existing user code, adding states is not considered a breaking change. Consider a state with only two values: ACTIVE and DELETED. A user may add code that checks if state == ACTIVE, and in the else cases simply assumes the resource is deleted. If the API later adds a new state for another purpose, that code will break. We ultimately can not control this behavior, but API documentation should actively encourage users to code against state enums with the expectation that they may receive new values in the future. APIs may add new states to an existing State enum when appropriate, and adding a new state is not considered a breaking change. When to avoid states Sometimes, a State enum may not be what is best for your API, particularly in situations where a state has a very small number of potential values, or when states are not mutually exclusive. Consider the example of a state with only ACTIVE and DELETED, as discussed above. In this situation, the API may be better off exposing a google.protobuf.Timestamp delete_time, and instructing users to rely on whether it is set to determine deletion. Common states The following is a list of states in common use. APIs should consider prior art when determining state names, and should value local consistency above global consistency in the case of conflicting precedent. Resting states \"Resting states\" are lifecycle states that, absent user action, are expected to remain indefinitely. However, the user can initiate an action to move a resource in a resting state into certain other states (resting or active). ACCEPTED ACTIVE CANCELLED DELETED FAILED SUCCEEDED SUSPENDED VERIFIED Active states \"Active states\" are lifecycle states that typically resolve on their own into a single expected resting state. Note: Remember only to expose states that are useful to customers. Active states are valuable only if the resource will be in that state for a sufficient period of time. If state changes are immediate, active states are not necessary. CREATING (usually becomes ACTIVE) DELETING (usually becomes DELETED) PENDING (usually becomes RUNNING) REPAIRING (usually becomes ACTIVE) RUNNING (usually becomes SUCCEEDED) SUSPENDING (usually becomes SUSPENDED) Further reading For information on enums generally, see AIP-126. Changelog 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-10-20: Added guidance on prefixing enum values with enum name. 2020-09-02: Clarified that states are not directly set on create either. 2019-12-05: Changed guidance on state transition methods, downgrading must to should on the response type. 2019-08-16: Added guidance for state transition methods. 2019-07-18: Added explicit guidance on the unspecified value.", + 'tags': '', + 'url': '/216', + }, +{ + 'title': "Unreachable resources", + 'text': "Unreachable resources Occasionally, a user may ask for a list of resources, and some set of resources in the list are temporarily unavailable. The most typical use case is while supporting Reading Across Collections. For example, a user may ask to list resources across multiple parent locations, but one of those locations is temporarily unreachable. In this situation, it is still desirable to provide the user with all the available resources, while indicating that something is missing. Guidance If a method to retrieve data is capable of partially failing due to one or more resources being temporarily unreachable, the response message must include a field to indicate this: message ListBooksResponse { // The books matching the request. repeated Book books = 1; // The next page token, if there are more books matching the // request. string next_page_token = 2; // Unreachable resources. repeated string unreachable = 3 [ (google.api.field_behavior) = UNORDERED_LIST ]; } The field must be a repeated string, and should be named unreachable. The field must contain the resource names of the resources that are unreachable or those that impede reaching the requested collection, such as the parent resource of the collection that could not be reached. For example, if an entire location is unreachable, preventing access to the localized collection of resources requested, the location resource is included. The field must contain service-relative resource names, and must not contain full resource names, resource URIs, or simple resource IDs. See AIP-122 for definitions. For example, if a Book resource is unreachable, the service-relative resource name \"shelves/scifi1/books/starwars4\" is included in unreachable, as opposed to the full resource name \"//library.googleapis.com/shelves/scifi1/books/starwars4\", the parent-relative resource \"books/starwars4\", the resource ID \"starwars4\", or the resource URI. The response must not provide any other information about the issue(s) that made the listed resources unreachable. For example, the response cannot contain an extra field with error reasons for each unreachable entry. The service must provide a way for the user to make a more specific request and receive an error with additional information e.g. via a Standard Get or a Standard List targeted at the unreachable collection parent. The service must also allow the user to repeat the original call with more restrictive parameters. The resource names that appear in unreachable may be heterogeneous. The unreachable field definition should document what potential resources could be provided in this field, and note that it might expand later. For example, if both an entire location and a specific resource in a different location are unreachable, the unreachable location\u0027s name e.g. \"projects/example123/locations/us-east1\" and the unreachable resource\u0027s name e.g. \"projects/example123/locations/europe-west2/instances/example456\" will both appear in unreachable. The unreachable field must not have semantically meaningful ordering or structure within the list. Put differently, unreachable must be an unordered list. As such, the unreachable field must be annotated with UNORDERED_LIST field behavior (see AIP-203). Important: If a single unreachable location or resource prevents returning any data by definition (for example, a list request for a single publisher where that publisher is unreachable), the service must fail the entire request with an error. Pagination While preparing a page of results to fulfill a page fetch RPC e.g. an AIP-132 Standard List call, if the service encounters any unreachable resources or collections they must do the following: Include the resource name for the unreachable resource in the unreachable response field. The resource name must be the most appropriately scoped for the unreachable resource or collection. For example, if a specific zone within a region is unreachable, the unreachable resource name would be a zonal Location e.g. projects/example/locations/us-west1-a, but if an entire region is unreachable, the resource name would be a regional Location e.g. projects/example/locations/us-west1. The resource name must be included, regardless of restrictive paging parameters e.g. order_by, when it is identified as unreachable. Populate results that were previously considered unreachable on a following page if their availability is restored and the paging parameters allow for their inclusion. Determining inclusion eligibility based on paging parameters also includes any documented default ordering behavior in the absence of user-specified ordering in the request. For example, if region projects/example/locations/us-west1 was unavailable in the first page of an ordered paging call, and including its resources would violate the ordering, those out-of-order resources are not included in the following page. Similarly, if the same exact request is made, and resources previously considered unreachable are available again, they must be populated, within the constraints of the paging parameters. Limit the number of unreachable resource names returned in a given response if, even after up-scoping the unreachable resource name, the number of unreachable resource names exceeds a documented maximum. This maximum must be documented in the unreachable field comments directly. This is independent of the page_size set by the caller. Retaining previous behavior Services may continue with previously implemented unreachable pagination behavior where changing it would induce an incompatible change as per AIP-180, but must document said behavior on the unreachable field(s) directly. Adopting partial success In order for an existing API that has a default behavior differing from the aforementioned guidance i.e. the API call returns an error status instead of a partial result, to adopt the unreachable pattern the API must do the following: The default behavior must be retained to avoid incompatible behavioral changes For example, if the default behavior is to return an error if any location is unreachable, that default behavior must be retained. The request message must have a bool return_partial_success field The response message must have the standard repeated string unreachable field The two aforementioned fields must be added simultaneously When the bool return_partial_success field is set to true in a request, the API must behave as described in the aforementioned guidance with regards to populating the repeated string unreachable response field. message ListBooksRequest { // Standard List request fields... // Setting this field to `true` will opt the request into returning the // resources that are reachable, and into including the names of those that // were unreachable in the [ListBooksResponse.unreachable] field. This can // only be `true` when reading across collections e.g. when `parent` is set to // `\"projects/example/locations/-\"`. bool return_partial_success = 4; } message ListBooksResponse { // Standard List Response fields... // Unreachable resources. Populated when the request opts into // `return_partial_success` and reading across collections e.g. when // attempting to list all resources across all supported locations. repeated string unreachable = 3 [ (google.api.field_behavior) = UNORDERED_LIST ]; } Partial success granularity If the bool return_partial_success field is set to true in a request that is scoped beyond the supported granualirty of the API\u0027s ability to reasonably report unreachable resources, the API should return an INVALID_ARGUMENT error with details explaining the issue. For example, if the API only supports return_partial_success when Reading Across Collections, it returns an INVALID_ARGUMENT error when given a request scoped to a specific parent resource collection. The supported granularity must be documented on the return_partial_success field. Rationale Using service-relative resource names In general, relative resource names, as defined in AIP-122, are the best practice for referring to resources by name within a service and in other services when that other service is obvious. The full resource name format is strictly less consumable (e.g., requires extra parsing client side), and over-specified for the uses of unreachable. Resource URIs are not transport agnostic, as they are unusable in standard methods for gRPC users, and simple resource IDs do not provide enough information about exactly which resource was unreachable in a heterogenous list of resources. Minimizing extra error details in response The context in which an unreachable resource is discovered may be sensitive and the state of the system fluid between calls. As such, it is preferred to defer to the service by making a more specific RPC to get more details about a specific resource or parent. This allows the parent to handle all necessary RPC checks and system state resolution on at time of request, rather than by shoehorning potentially privileged or stale information into the broader list call it was unreachable for. Unordered unreachable contents It is important for broad API consistency that the contents of unreachable not have a specific or order semantic structure. If each API baked a specific ordering into a standard field, no single implementation, client or server side, would be correct. Per page unreachable resources Populating unreachable resources on a per page basis allows end users to identify immediately when a page is incomplete, rather than after paging through all results. Paging to completion is not guaranteed, so it is important to communicate as soon as possible when there are unreachable resource missing from a given page. Furthermore, it allows users to identify when there is a potential issue that they need to account for in subsequent calls. Finally, retaining unreachable resources until the end of paging results requires services to retain the state for what should be indepedent and fully isolated API calls. Using request field to opt-in Introducing a new request field as means of opting into the partial success behavior is the best way to communicate user intent while keeping the default behavior backwards compatible. The alternative, changing the default behavior with the introduction of the unreachable response field, presents a backwards incompatible change. Users that previously expected failure when any resource was unreachable, assume the successful response means all resources are accounted for in the response. Introducing fields simultaneously Introducing the request and response fields simultaneously is to prevent an invalid intermediate state that is presented by only adding one or the other. If only unreachable is added, then it could be assumed that it being empty means all resources were returned when that may not be true. If only return_partial_success is added, then the user wouldn\u0027t have a means of knowing which resources were unreachable. Partial success granularity limitations At a certain level of request scope granularity, an API is simply unable to enumerate the resources that are unreachable. For example, global-only APIs may be unable to provide granularity at a localized collection level. In such a case, preemptively returning an error when return_partial_success=true protects the user from the risks of the alternative - expecting unreachable resources if there was an issue, but not getting any, thus falsely assuming everything was retrieved. This aligns with guidance herein that suggests failing requests that cannot be fulfilled preemptively. History Pagination guidance The original guidance for how to populate the unreachable field revolved around consuming the contents as if they were the paged results. This meant that paged resources and unreachable resources couldn\u0027t be returned in the same response i.e. page, and users needed to completely page through all results in order to see if any were unreachable. See the Rationale section for the reasoning around the changes. Further reading For listing across collections, see AIP-159. Changelog 2024-07-29: Reformat guidance, add explicit resource name format 2024-07-26: Change pagination guidance. requirement. 2024-07-19: Add guidance for brownfield adoption of partial success.", + 'tags': '', + 'url': '/217', + }, +{ + 'title': "Batch methods: Get", + 'text': "Batch methods: Get Some APIs need to allow users to get a specific set of resources at a consistent time point (e.g. using a read transaction). A batch get method provides this functionality. Guidance APIs may support Batch Get using the following pattern: rpc BatchGetBooks(BatchGetBooksRequest) returns (BatchGetBooksResponse) { option (google.api.http) = { get: \"/v1/{parent=publishers/*}/books:batchGet\" }; } The RPC\u0027s name must begin with BatchGet. The remainder of the RPC name should be the plural form of the resource being retrieved. The request and response messages must match the RPC name, with Request and Response suffixes. The HTTP verb must be GET. The HTTP URI must end with :batchGet. The URI path should represent the collection for the resource, matching the collection used for simple CRUD operations. If the operation spans parents, a dash (-) may be accepted as a wildcard. There must not be a body key in the google.api.http annotation. The operation must be atomic: it must fail for all resources or succeed for all resources (no partial success). For situations requiring partial failures, List (AIP-132) methods should be used. If the operation covers multiple locations and at least one location is down, the operation must fail. Request message The request for a batch get method should be specified with the following pattern: message BatchGetBooksRequest { // The parent resource shared by all books being retrieved. // Format: publishers/{publisher} // If this is set, the parent of all of the books specified in `names` // must match this field. string parent = 1 [ (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The names of the books to retrieve. // A maximum of 1000 books can be retrieved in a batch. // Format: publishers/{publisher}/books/{book} repeated string names = 2 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; } A parent field should be included, unless the resource being retrieved is a top-level resource, to facilitate inclusion in the URI as well to permit a single permissions check. If a caller sets this field, and the parent collection in the name of any resource being retrieved does not match, the request must fail. This field should be required if only 1 parent per request is allowed. The field should identify the resource type that it references. The comment for the field should document the resource pattern. The request message must include a repeated field which accepts the resource names specifying the resources to retrieve. The field should be named names. If no resource names are provided, the API should error with INVALID_ARGUMENT. The field should be required. The field should identify the resource type that it references. The comment for the field should document the resource pattern. Other fields besides name may be \"hoisted\" from the standard Get request. There is no way to allow for these fields to accept different values for different resources; if this is needed, use the alternative request message form. Batch get should not support pagination because transactionality across API calls would be extremely difficult to implement or enforce, and the request defines the exact scope of the response anyway. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. The comment above the names field should document the maximum number of requests allowed. Response message The response for a batch get method should be specified with the following pattern: message BatchGetBooksResponse { // Books requested. repeated Book books = 1; } The response message must include one repeated field corresponding to the resources being retrieved. The order of books in the response must be the same as the names in the request. Nested request objects If the standard Get request message contains a field besides the resource name that needs to be different between different resources being requested, the batch message may alternatively hold a repeated field of the standard Get request message. This is generally discouraged unless your use case really requires it. The request for a batch get method using this approach should be specified with the following pattern: message BatchGetBooksRequest { // The parent resource shared by all books being retrieved. // Format: publishers/{publisher} // If this is set, the parent field in the GetBookRequest messages // must either be empty or match this field. string parent = 1 [ (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The requests specifying the books to retrieve. // A maximum of 1000 books can be retrieved in a batch. repeated GetBookRequest requests = 2 [(google.api.field_behavior) = REQUIRED]; } A parent field should be included. If a caller sets this field, and the parent collection in the name of any resource being retrieved does not match, the request must fail. This field should be required if only 1 parent per request is allowed. The field should identify the resource type that it references. The comment for the field should document the resource pattern. The request message must include a repeated field which accepts the request messages specifying the resources to retrieve, as specified for standard Get methods. The field should be named requests. The field should be required. Other fields may be \"hoisted\" from the standard Get request, which means that the field can be set at either the batch level or child request level. Similar to parent, if both the batch level and child request level are set for the same field, the values must match. Batch get should not support pagination because transactionality across API calls would be extremely difficult to implement or enforce, and the request defines the exact scope of the response anyway. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. The comment above the requests field should document the maximum number of requests allowed. Changelog 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-09-16: Suggested annotating parent, names, and requests fields. 2020-08-27: Removed parent recommendations for top-level resources. 2020-03-24: Clarified behavior if no resource names are sent. 2019-09-11: Changed the primary recommendation to specify a repeated string instead of a repeated standard Get request message. Moved the original recommendation into its own section. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/231', + }, +{ + 'title': "Batch methods: Create", + 'text': "Batch methods: Create Some APIs need to allow users to create multiple resources in a single transaction. A batch create method provides this functionality. Guidance APIs may support Batch Create using the following two patterns: Returning the response synchronously rpc BatchCreateBooks(BatchCreateBooksRequest) returns (BatchCreateBooksResponse) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:batchCreate\" body: \"*\" }; } Returning an Operation which resolves to the response asynchronously rpc BatchCreateBooks(BatchCreateBooksRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:batchCreate\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"BatchCreateBooksResponse\" metadata_type: \"BatchCreateBooksOperationMetadata\" }; } The RPC\u0027s name must begin with BatchCreate. The remainder of the RPC name should be the plural form of the resource being created. The request and response messages must match the RPC name, with Request and Response suffixes. If the batch method returns an google.longrunning.Operation, both the response_type and metadata_type fields must be specified. The HTTP verb must be POST. The HTTP URI must end with :batchCreate. The URI path should represent the collection for the resource, matching the collection used for simple CRUD operations. If the operation spans parents, a dash (-) may be accepted as a wildcard. The body clause in the google.api.http annotation should be \"*\". Atomic vs. Partial Success The batch create method may support atomic (all resources created or none are) or partial success behavior. To make a choice, consider the following factors: Complexity of Ensuring Atomicity: Operations that are simple passthrough database transactions should use an atomic operation, while operations that manage complex resources should use partial success operations. End-User Experience: Consider the perspective of the API consumer. Would atomic behavior be preferable for the given use case, even if it means that a large batch could fail due to issues with a single or a few entries? Synchronous batch create must be atomic. Asynchronous batch create may support atomic or partial success. If supporting partial success, see Operation metadata message requirements. Request message The request for a batch create method should be specified with the following pattern: message BatchCreateBooksRequest { // The parent resource shared by all books being created. // Format: publishers/{publisher} // If this is set, the parent field in the CreateBookRequest messages // must either be empty or match this field. string parent = 1 [ (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The request message specifying the resources to create. // A maximum of 1000 books can be created in a batch. repeated CreateBookRequest requests = 2 [(google.api.field_behavior) = REQUIRED]; } A parent field should be included, unless the resource being created is a top-level resource. If a caller sets this field, and the parent field of any child request message does not match, the request must fail. The parent field of child request messages can be omitted if the parent field in this request is set. This field should be required if only 1 parent per request is allowed. The field should identify the resource type that it references. The comment for the field should document the resource pattern. The request message must include a repeated field which accepts the request messages specifying the resources to create, as specified for standard Create methods. The field should be named requests. The field should be required. Other fields may be \"hoisted\" from the standard Create request, which means that the field can be set at either the batch level or child request level. Similar to parent, if both the batch level and child request level are set for the same field, the values must match. Fields which must be unique cannot be hoisted (e.g. Customer-provided id fields). The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. The comment above the requests field should document the maximum number of requests allowed. Response message The response for a batch create method should be specified with the following pattern: message BatchCreateBooksResponse { // Books created. repeated Book books = 1; } The response message must include one repeated field corresponding to the resources that were created. Operation metadata message The metadata_type message must either match the RPC name with OperationMetadata suffix, or be named with Batch prefix and OperationMetadata suffix if the type is shared by multiple Batch methods. If batch create method supports partial success, the metadata message must include a map\u003cint32, google.rpc.Status\u003e failed_requests field to communicate the partial failures. The key in this map is the index of the request in the requests field in the batch request. The value in each map entry must mirror the error(s) that would normally be returned by the singular Standard Create method. If a failed request can eventually succeed due to server side retries, such transient errors must not be communicated using failed_requests. When all requests in the batch fail, Operation.error must be set with code = google.rpc.Code.Aborted and message = \"None of the requests succeeded, refer to the BatchCreateBooksOperationMetadata.failed_requests for individual error details\" The metadata message may include other fields to communicate the operation progress. Adopting Partial Success In order for an existing Batch API to adopt the partial success pattern, the API must do the following: The default behavior must be retained to avoid incompatible behavioral changes. If the API returns an Operation: The request message must have a bool return_partial_success field. The Operation metadata_type must include a map\u003cint32, google.rpc.Status\u003e failed_requests field. When the bool return_partial_success field is set to true in a request, the API should allow partial success behavior, otherwise it should continue with atomic behavior as default. If the API returns a direct response synchronously: Since the existing clients will treat a success response as an atomic operation, the existing version of the API must not adopt the partial success pattern. A new version must be created instead that returns an Operation and follows the partial success pattern described in this AIP. Rationale Restricting synchronous batch methods to be atomic The restriction that synchronous batch methods must be atomic is a result of the following considerations. The previous iteration of this AIP recommended batch methods must be atomic. There is no clear way to convey partial failure in a sync response status code because an OK implies it all worked. Therefore, adding a new field to the response to indicate partial failure would be a breaking change because the existing clients would interpret an OK response as all resources created. On the other hand, as described in AIP-193, Operations are more capable of presenting partial states. The response status code for an Operation does not convey anything about the outcome of the underlying operation and a client has to check the response body to determine if the operation was successful. Communicating partial failures The AIP recommends using a map\u003cint32, google.rpc.Status\u003e failed_requests field to communicate partial failures, where the key is the index of the failed request in the original batch request. The other options considered were: A repeated google.rpc.Status field. This was rejected because it is not clear which entry corresponds to which request. A map\u003cstring, google.rpc.Status\u003e field, where the key is the request id of the failed request. This was rejected because: Client will need to maintain a map of request_id -\u003e request in order to use the partial success response. Populating a request id for the purpose of communicating errors could conflict with AIP-155 if the service can not guarantee idempotency for an individual request across multiple batch requests. A repeated FailedRequest field, where FailedRequest contains the individual create request and the google.rpc.Status. This was rejected because echoing the request payload back in response is discouraged due to additional challenges around user data sensitivity. Changelog 2025-03-06: Added detailed guidance for partial success behavior, and decision framework for choosing between atomic and partial success 2023-04-18: Changed the recommendation to allow returning partial successes. 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-09-16: Suggested annotating parent and requests fields. 2020-08-27: Removed parent recommendations for top-level resources. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/233', + }, +{ + 'title': "Batch methods: Update", + 'text': "Batch methods: Update Some APIs need to allow users to modify a set of resources in a single transaction. A batch update method provides this functionality. Guidance APIs may support Batch Update using the following two patterns: Returning the response synchronously rpc BatchUpdateBooks(BatchUpdateBooksRequest) returns (BatchUpdateBooksResponse) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:batchUpdate\" body: \"*\" }; } Returning an Operation which resolves to the response asynchronously rpc BatchUpdateBooks(BatchUpdateBooksRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:batchUpdate\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"BatchUpdateBooksResponse\" metadata_type: \"BatchUpdateBooksOperationMetadata\" }; } The RPC\u0027s name must begin with BatchUpdate. The remainder of the RPC name should be the plural form of the resource being updated. The request and response messages must match the RPC name, with Request and Response suffixes. If the batch method returns an google.longrunning.Operation, both the response_type and metadata_type fields must be specified. The HTTP verb must be POST. The HTTP URI must end with :batchUpdate. The URI path should represent the collection for the resource, matching the collection used for simple CRUD operations. If the operation spans parents, a dash (-) may be accepted as a wildcard. The body clause in the google.api.http annotation should be \"*\". Atomic vs. Partial Success The batch update method may support atomic (all resources updated or none are) or partial success behavior. To make a choice, consider the following factors: Complexity of Ensuring Atomicity: Operations that are simple passthrough database transactions should use an atomic operation, while operations that manage complex resources should use partial success operations. End-User Experience: Consider the perspective of the API consumer. Would atomic behavior be preferable for the given use case, even if it means that a large batch could fail due to issues with a single or a few entries? Synchronous batch update must be atomic. Asynchronous batch update may support atomic or partial success. If supporting partial success, see Operation metadata message requirements. Request message The request for a batch update method should be specified with the following pattern: message BatchUpdateBooksRequest { // The parent resource shared by all books being updated. // Format: publishers/{publisher} // If this is set, the parent field in the UpdateBookRequest messages // must either be empty or match this field. string parent = 1 [ (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The request message specifying the resources to update. // A maximum of 1000 books can be modified in a batch. repeated UpdateBookRequest requests = 2 [(google.api.field_behavior) = REQUIRED]; } A parent field should be included, unless the resource being updated is a top-level resource. If a caller sets this field, and the parent collection in the name of any resource being updated does not match, the request must fail. This field should be required if only 1 parent per request is allowed. The field should identify the resource type that it references. The comment for the field should document the resource pattern. The request message must include a repeated field which accepts the request messages specifying the resources to update, as specified for standard Update methods. The field should be named requests. The field should be required. Other fields may be \"hoisted\" from the standard Update request, which means that the field can be set at either the batch level or child request level. Similar to parent, if both the batch level and child request level are set for the same field, the values must match. The update_mask field is a good candidate for hoisting. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. The comment above the requests field should document the maximum number of requests allowed. Response message The response for a batch update method should be specified with the following pattern: message BatchUpdateBooksResponse { // Books updated. repeated Book books = 1; } The response message must include one repeated field corresponding to the resources that were updated. Operation metadata message The metadata_type message must either match the RPC name with OperationMetadata suffix, or be named with Batch prefix and OperationMetadata suffix if the type is shared by multiple Batch methods. If batch update method supports partial success, the metadata message must include a map\u003cint32, google.rpc.Status\u003e failed_requests field to communicate the partial failures. The key in this map is the index of the request in the requests field in the batch request. The value in each map entry must mirror the error(s) that would normally be returned by the singular Standard Update method. If a failed request can eventually succeed due to server side retries, such transient errors must not be communicated using failed_requests. When all requests in the batch fail, Operation.error must be set with code = google.rpc.Code.Aborted and message = \"None of the requests succeeded, refer to the BatchUpdateBooksOperationMetadata.failed_requests for individual error details\" The metadata message may include other fields to communicate the operation progress. Adopting Partial Success In order for an existing Batch API to adopt the partial success pattern, the API must do the following: The default behavior must be retained to avoid incompatible behavioral changes. If the API returns an Operation: The request message must have a bool return_partial_success field. The Operation metadata_type must include a map\u003cint32, google.rpc.Status\u003e failed_requests field. When the bool return_partial_success field is set to true in a request, the API should allow partial success behavior, otherwise it should continue with atomic behavior as default. If the API returns a direct response synchronously: Since the existing clients will treat a success response as an atomic operation, the existing version of the API must not adopt the partial success pattern. A new version must be created instead that returns an Operation and follows the partial success pattern described in this AIP. Rationale Restricting synchronous batch methods to be atomic The restriction that synchronous batch methods must be atomic is a result of the following considerations. The previous iteration of this AIP recommended batch methods must be atomic. There is no clear way to convey partial failure in a sync response status code because an OK implies it all worked. Therefore, adding a new field to the response to indicate partial failure would be a breaking change because the existing clients would interpret an OK response as all resources updated. On the other hand, as described in AIP-193, Operations are more capable of presenting partial states. The response status code for an Operation does not convey anything about the outcome of the underlying operation and a client has to check the response body to determine if the operation was successful. Communicating partial failures The AIP recommends using a map\u003cint32, google.rpc.Status\u003e failed_requests field to communicate partial failures, where the key is the index of the failed request in the original batch request. The other options considered were: A repeated google.rpc.Status field. This was rejected because it is not clear which entry corresponds to which request. A map\u003cstring, google.rpc.Status\u003e field, where the key is the request id of the failed request. This was rejected because: Client will need to maintain a map of request_id -\u003e request in order to use the partial success response. Populating a request id for the purpose of communicating errors could conflict with AIP-155 if the service can not guarantee idempotency for an individual request across multiple batch requests. A repeated FailedRequest field, where FailedRequest contains the individual update request and the google.rpc.Status. This was rejected because echoing the request payload back in response is discouraged due to additional challenges around user data sensitivity. Changelog 2025-03-06: Changed recommendation to allow partial success, along with detailed guidance 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-09-16: Suggested annotating parent and requests fields. 2020-08-27: Removed parent recommendations for top-level resources. 2019-09-11: Fixed the wording about which child field the parent field should match. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/234', + }, +{ + 'title': "Batch methods: Delete", + 'text': "Batch methods: Delete Some APIs need to allow users to delete a set of resources in a single transaction. A batch delete method provides this functionality. Guidance APIs may support Batch Delete using the following two patterns: Returning the response synchronously rpc BatchDeleteBooks(BatchDeleteBooksRequest) returns (google.protobuf.Empty) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:batchDelete\" body: \"*\" }; } Returning an Operation which resolves to the response asynchronously rpc BatchDeleteBooks(BatchDeleteBooksRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{parent=publishers/*}/books:batchDelete\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"google.protobuf.Empty\" metadata_type: \"BatchDeleteBooksOperationMetadata\" }; } The RPC\u0027s name must begin with BatchDelete. The remainder of the RPC name should be the plural form of the resource being deleted. The request message must match the RPC name, with a Request suffix. The response message should be google.protobuf.Empty. If the resource is soft deleted, the response message should be a response message containing the updated resources. If the batch method returns an google.longrunning.Operation, both the response_type and metadata_type fields must be specified. If the resource is soft deleted, the response_type should be a response message containing the updated resources. The HTTP verb must be POST (not DELETE). The HTTP URI must end with :batchDelete. The URI path should represent the collection for the resource, matching the collection used for simple CRUD operations. If the operation spans parents, a dash (-) may be accepted as a wildcard. The body clause in the google.api.http annotation should be \"*\". Atomic vs. Partial Success The batch delete method may support atomic (all resources deleted or none are) or partial success behavior. To make a choice, consider the following factors: Complexity of Ensuring Atomicity: Operations that are simple passthrough database transactions should use an atomic operation, while operations that manage complex resources should use partial success operations. End-User Experience: Consider the perspective of the API consumer. Would atomic behavior be preferable for the given use case, even if it means that a large batch could fail due to issues with a single or a few entries? Synchronous batch delete must be atomic. Asynchronous batch delete may support atomic or partial success. If supporting partial success, see Operation metadata message requirements. Request message The request for a batch delete method should be specified with the following pattern: message BatchDeleteBooksRequest { // The parent resource shared by all books being deleted. // Format: publishers/{publisher} // If this is set, the parent of all of the books specified in `names` // must match this field. string parent = 1 [ (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The names of the books to delete. // A maximum of 1000 books can be deleted in a batch. // format: publishers/{publisher}/books/{book} repeated string names = 2 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; } A parent field should be included, unless the resource being deleted is a top-level resource. If a caller sets this field, and the parent collection in the name of any resource being deleted does not match, the request must fail. This field should be required if only 1 parent per request is allowed. The field should identify the resource type that it references. The comment for the field should document the resource pattern. The request message must include a repeated field which accepts the resource names specifying the resources to delete. The field should be named names. The field should be required. The field should identify the resource type that it references. The comment for the field should document the resource pattern. Other fields besides name may be \"hoisted\" from the standard Delete request. There is no way to allow for these fields to accept different values for different resources; if this is needed, use the alternative request message form. The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. The comment above the names field should document the maximum number of requests allowed. Filter-based matching must not be supported. Request message containing standard delete request messages If the standard Delete request message contains a field besides the resource name that needs to be different between different resources being requested, the batch message may alternatively hold a repeated field of the standard Delete request message. This is generally discouraged unless your use case really requires it. The request for a batch delete method should be specified with the following pattern: message BatchDeleteBooksRequest { // The parent resource shared by all books being deleted. // Format: publishers/{publisher} // If this is set, the parent of all of the books specified in the // DeleteBookRequest messages must match this field. string parent = 1 [ (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The requests specifying the books to delete. // A maximum of 1000 books can be deleted in a batch. repeated DeleteBookRequest requests = 2 [(google.api.field_behavior) = REQUIRED]; } A parent field should be included. If a caller sets this field, and the parent collection in the name of any resource being deleted does not match, the request must fail. This field should be required if only 1 parent per request is allowed. The field should identify the resource type that it references. The comment for the field should document the resource pattern. The request message must include a repeated field which accepts the request messages specifying the resources to delete, as specified for standard Delete methods. The field should be named requests. The field should be required. Other fields may be \"hoisted\" from the standard Delete request, which means that the field can be set at either the batch level or child request level. Similar to parent, if both the batch level and child request level are set for the same field, the values must match. Fields which must be unique cannot be hoisted (e.g. etag). The request message must not contain any other required fields, and should not contain other optional fields except those described in this or another AIP. The comment above the requests field should document the maximum number of requests allowed. Filter-based matching must not be supported unless it is infeasible to support critical use cases without it, because it makes it too easy for users to accidentally delete important data. If it is unavoidable, see AIP-165. Response message (soft-delete only) In the case where a response message is necessary because the resource is soft-deleted, the response should be specified with the following pattern: message BatchDeleteBooksResponse { // Books deleted. repeated Book books = 1; } The response message must include one repeated field corresponding to the resources that were soft-deleted. Operation metadata message The metadata_type message must either match the RPC name with OperationMetadata suffix, or be named with Batch prefix and OperationMetadata suffix if the type is shared by multiple Batch methods. If batch delete method supports partial success, the metadata message must include a map\u003cint32, google.rpc.Status\u003e failed_requests field to communicate the partial failures. The key in this map is the index of the request in the requests field in the batch request. The value in each map entry must mirror the error(s) that would normally be returned by the singular Standard Delete method. If a failed request can eventually succeed due to server side retries, such transient errors must not be communicated using failed_requests. When all requests in the batch fail, Operation.error must be set with code = google.rpc.Code.Aborted and message = \"None of the requests succeeded, refer to the BatchDeleteBooksOperationMetadata.failed_requests for individual error details\" The metadata message may include other fields to communicate the operation progress. Adopting Partial Success In order for an existing Batch API to adopt the partial success pattern, the API must do the following: The default behavior must be retained to avoid incompatible behavioral changes. If the API returns an Operation: The request message must have a bool return_partial_success field. The Operation metadata_type must include a map\u003cint32, google.rpc.Status\u003e failed_requests field. When the bool return_partial_success field is set to true in a request, the API should allow partial success behavior, otherwise it should continue with atomic behavior as default. If the API returns a direct response synchronously: Since the existing clients will treat a success response as an atomic operation, the existing version of the API must not adopt the partial success pattern. A new version must be created instead that returns an Operation and follows the partial success pattern described in this AIP. Rationale Restricting synchronous batch methods to be atomic The restriction that synchronous batch methods must be atomic is a result of the following considerations. The previous iteration of this AIP recommended batch methods must be atomic. There is no clear way to convey partial failure in a sync response status code because an OK implies it all worked. Therefore, adding a new field to the response to indicate partial failure would be a breaking change because the existing clients would interpret an OK response as all resources created. On the other hand, as described in AIP-193, Operations are more capable of presenting partial states. The response status code for an Operation does not convey anything about the outcome of the underlying operation and a client has to check the response body to determine if the operation was successful. Communicating partial failures The AIP recommends using a map\u003cint32, google.rpc.Status\u003e failed_requests field to communicate partial failures, where the key is the index of the failed request in the original batch request. The other options considered were: A repeated google.rpc.Status field. This was rejected because it is not clear which entry corresponds to which request. A map\u003cstring, google.rpc.Status\u003e field, where the key is the request id of the failed request. This was rejected because: Client will need to maintain a map of request_id -\u003e request in order to use the partial success response. Populating a request id for the purpose of communicating errors could conflict with AIP-155 if the service can not guarantee idempotency for an individual request across multiple batch requests. A repeated FailedRequest field, where FailedRequest contains the individual create request and the google.rpc.Status. This was rejected because echoing the request payload back in response is discouraged due to additional challenges around user data sensitivity. Changelog 2025-03-06: Changed recommendation to allow partial success, along with detailed guidance 2022-06-02: Changed suffix descriptions to eliminate superfluous \"-\". 2020-09-16: Suggested annotating parent, names, and requests fields. 2020-08-27: Removed parent recommendations for top-level resources. 2020-03-27: Added reference to AIP-165 for criteria-based deletion. 2019-10-11: Changed the primary recommendation to specify a repeated string instead of a repeated standard Delete message. Moved the original recommendation into its own section. 2019-09-11: Fixed the wording about which child field the parent field should match. 2019-08-01: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/235', + }, +{ + 'title': "Policy preview", + 'text': "Policy preview A policy is a resource that provides rules that admit or deny access to other resources. Generally, the outcome of a policy can be evaluated to a specific set of outcomes. Changes to policies without proper validation may have unintended consequences that can severely impact a customer\u2019s overall infrastructure setup. To safely update resources, it is beneficial to test these changes via policy rollout APIs. Preview is a rollout safety mechanism for policy resources, which gives the customer the ability to validate the effect of their proposed changes against production traffic prior to the changes going live. The result of the policy evaluation against traffic is logged in order to give the customer the data required to test the correctness of the change. Firewall policies exemplify a case that is suitable for previewing. A new configuration can be evaluated against traffic to observe which IPs would be allowed or denied. This gives the customer the data to guide a decision on whether to promote the proposed changes to live. The expected flow for previewing a policy is as follows: The user creates an experiment containing a new policy configuration intended to replace the live policy. The user uses the \"startPreview\" method to start generating logs which compare the live and experiment policy evaluations against live traffic. The user inspects the logs to determine whether the experiment has the intended result. The user uses the \"commit\" method to promote the experiment to live. Guidance Non-goals This proposal is for a safety mechanism for policy rollouts only. Safe rollouts for non-policy resources are not in scope. Experiments A new configuration of a policy to be previewed is stored as a nested collection under the policy. These nested collections are known as experiments. A hypothetical policy resource called, Policy, is used throughout. It has the following resource name pattern: projects/{project}/locations/{location}/policies/{policy} The experimental versions of the resource used for previewing or other safe rollout practices are represented as a nested collection under Policy using a new resource type. The resource type must follow the naming convention RegularResourceTypeExperiment. The following pattern is used for the experiment collection: projects/{project}/locations/{location}/policies/{policy}/experiments/{experiment} A proto used to represent an experiment must contain the following: 1. The required top-level fields for a resource, like `name` and `etag` 2. The policy message that is being tested itself 3. The field, `preview_metadata`, which contains metadata specific to previewing the experiment of a specific resource type. message PolicyExperiment { // google.api.resource, name, and other annotations and fields // The policy experiment. This Policy will be used to preview the effects of // the change but will not affect live traffic. Policy policy = 2; // The metadata associated with this policy experiment. PolicyPreviewMetadata preview_metadata = 3 [(google.api.field_behavior) = OUTPUT_ONLY]; // Allows clients to store small amounts of arbitrary data. map\u003cstring, string\u003e annotations = 4; } The experiment proto must have a top-level field with the same type as the live policy. It must be named as the live resource type. For example, if the experiment is for FirewallPolicy, then this field must be named firewall_policy. The name inside the embedded policy message must be the name of the live policy. When the user is ready to promote an experiment, they must copy the policy message into the live policy and delete the experiment. This can be done manually or via a \"commit\" custom method. A product may support multiple experiments concurrently being previewed for a single live policy. Each experiment must generate logs having each entry preceded by log_prefix so that the user can compare the results of the experiment with the behavior of the live policy. The number of experimental configurations for a given live policy may be capped at a certain number and the cap must be documented. Cascading deletes must occur: if the live policy is deleted, all experiments must also be deleted. map\u003cstring,string\u003e annotations must allow clients to store small amounts of arbitrary data. Metadata preview_metadata tracks all metadata of previewing the experiment. The messages must follow the convention: RegularResourceTypePreviewMetadata. This is so the proto can be defined uniquely for each resource type in the same service with experiments. message PolicyPreviewMetadata { // Possible values of the state of previewing the experiment. enum State { // Default value. This value is unused. STATE_UNDEFINED = 0; // The experiment is actively previewing. ACTIVE = 1; // The previewing of the experiment has been stopped. SUSPENDED = 2; } // The state of previewing the experiment. State state = 1; // An identifying string common to all logs generated when previewing the // experiment. Searching all logs for this string will isolate the results. string log_prefix = 2; // The most recent time at which this experiment started previewing. google.protobuf.Timestamp start_time = 3; // The most recent time at which this experiment stopped previewing. google.protobuf.Timestamp stop_time = 4; } PolicyPreviewMetadata must have the fields defined in the proto above. It may have additional fields if the service or resource requires it. When an experiment is first previewed, preview_metadata must be absent. It is present on the experiment once the \"startPreview\" method is used. All preview_metadata fields must be output only. state changes between ACTIVE and SUSPENDED when previewing is started or stopped. This happens when the \"startPreview\" or \"stopPreview custom methods are invoked, respectively. The first time the \"startPreview\" custom method is used, the system must create preview_metadata and do the following: It must set the state to ACTIVE It must populate start_time with the current time. start_time must be updated every time state is changed to ACTIVE. It must set a system generated log_prefix string, which is a predefined constant hard coded by the system developers. The same value is used for previewing experiments for the given resource type. For example, \"FirewallPolicyPreviewLog\" for FirewallPolicy. When the \"stopPreview\" custom method is used, the system must do the following: It must set the state to SUSPENDED It must populate the stop_time with the current time. Methods create The resource must be created using long-running Create and google.longrunning.operation_info.response_type must be PolicyExperiment. Creating a new experiment to preview must support the following use cases: Preview a new policy. Preview an update to an already live policy. Preview a deletion of a current policy. For the update and delete use cases, the policy field in the experiment must have the full payload of the live policy copied into it, including the name. The user must set the rules to the new intended state to preview an update. The user must set set the rules to represent a no-op to preview a delete. To preview a new policy, the system must do the following: If the system does not support a nested collection without a live policy, the user must create a live policy and set the rules to represent a no-op. For example, the rules of a no-op policy may be empty. An experiment is created as a child of the no-op policy. If the system supports previewing multiple experiments for a live policy, calling \"create\" more than once must create multiple experiments. update The resource must be updated using long-running Update and google.longrunning.operation_info.response_type must be PolicyExperiment. The name inside policy must not change but the other fields can in order to change the experiment being previewed because this policy is intended to replace the live policy, and the name of the live policy must not change. The system must set the state to SUSPENDED if the state was ACTIVE at the time of an update. This is so the user can easily distinguish between different versions of the experiment being previewed. get The standard method, Get, must be included for PolicyExperiment resource types. list The standard method, List, must be included for PolicyExperiment resource types. Filtering on PolicyPreviewMetadata indicates which experiments are actively previewed. For example, the following filter string returns a List response with experiments being previewed: preview_metadata.state = ACTIVE. delete The resource must be deleted using long-running Delete and google.longrunning.operation_info.response_type must be PolicyExperiment. startPreview // Starts previewing a PolicyExperiment. This triggers the system to start // generating logs to evaluate the PolicyExperiment. rpc StartPreviewPolicyExperiment(StartPreviewPolicyExperimentRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{name=policies/*/experiments/*}:startPreview\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"PolicyExperiment\" metadata_type: \"StartPreviewPolicyExperimentMetadata\" }; } // The request message for the startPreview custom method. message StartPreviewPolicyExperimentRequest { // The name of the PolicyExperiment. string name = 1; } This custom method is required. google.longrunning.Operation.metadata_type must follow guidance on Long-running operations This method must trigger the system to start generating logs to preview the experiment. Whenever the method is called successfully, the system must set the following values in the PolicyPreviewMetadata: log_prefix to the predefined constant. start_time to the current time state to ACTIVE. If the method is called on an experiment with the rules representing a no-op, then the system must preview the deletion of the live policy. stopPreview // Stops previewing a PolicyExperiment. This triggers the system to stop // generating logs to evaluate the PolicyExperiment. rpc StopPreviewPolicyExperiment(StopPreviewPolicyExperimentRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{name=policies/*/experiments/*}:stopPreview\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"PolicyExperiment\" metadata_type: \"StopPreviewPolicyExperimentMetadata\" }; } // The request message for the stopPreview custom method. message StopPreviewPolicyExperimentRequest { // The name of the PolicyExperiment. string name = 1; } This custom method is required. google.longrunning.Operation.metadata_type must follow guidance on Long-running operations This method must trigger the system to stop generating logs to preview the experiment. Whenever the method is called successfully, the system must set the following values in the PolicyPreviewMetadata: stop_time to the current time state to SUSPENDED commit The resource may expose a new custom method called \"commit\" to promote an experiment. The system copies policy from the experiment into the live policy and then deletes the experiment. Declarative clients may manually copy fields from an experiment into the live policy and then delete the experiment rather than calling \"commit\" if preferable. // Commits a PolicyExperiment. This copies the PolicyExperiment\u0027s policy message // to the live policy then deletes the PolicyExperiment. rpc CommitPolicyExperiment(CommitPolicyExperimentRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: \"/v1/{name=policies/*/experiments/*}:commit\" body: \"*\" }; option (google.longrunning.operation_info) = { response_type: \"google.protobuf.Empty\" metadata_type: \"CommitPolicyExperimentMetadata\" }; } // The request message for the commit custom method. message CommitPolicyExperimentRequest { string name = 1; string etag = 2; string parent_etag = 3; } google.longrunning.Operation.metadata_type must follow guidance on Long-running operations The method must atomically copy policy from the experiment into the live policy, and then delete the experiment. If any experiment fails \"commit\", previewing it must not stop, and the live policy must not be updated. The method can be called on an experiment in any state. The etag must match that of the experiment in order for commit to be successful. This is so the user does not commit an unintended version of the experiment. If no etag is provided, the API must not succeed to prevent the user from unintentionally committing a different version of the experiment as intended. A parent_etag may be provided to guarantee that the experiment overwrites a specific version of the live policy. The method is not idempotent and calling it twice on the same experiment must return a 404 NOT_FOUND as the experiment is deleted as part of the first call. Changes to live policy API methods delete A delete of the live policy must delete all experiments. To maintain the experiments while negating the effect of the live policy, the live policy must be changed to a no-op policy instead of using this method. Logging Logging is crucial for the user to evaluate whether an experiment should be promoted to live. Logs must contain the results of the evaluated experiment, the etag associated with that experiment alongside that of the live policy, and be preceded by the value of log_prefix. - The etag fields help the user identify which configurations of the live and experiment are evaluated in the log. - log_prefix helps the user separate logs specifically generated for previewing the experiment from other use cases. Overall, these logs help the user make a decision about whether to promote the experiment to live. Changelog 2023-04-27: Methods for start and stop renamed. State to enum. Annotations added. 2023-03-30: Initial AIP written.", + 'tags': '', + 'url': '/236', + }, +{ + 'title': "Project identifiers", + 'text': "Project identifiers Historically, Google had two kinds of projects: API projects and App Engine projects. API projects used project numbers (e.g. 12345) as identifiers, and App Engine projects used project IDs (e.g. happy-armadillo-789) as identifiers. Later, Google converged API projects and App Engine projects, so now each project has both unique and immutable identifiers. The two types of identifiers are used differently in different contexts, and create a lot of complexity for application development. One critical issue is that applications cannot reliably join data from different services, because different services use different project identifiers. Guidance TL;DR: The project number is the canonical identifier, and the project ID is an alias; however, unlike normal aliases, it should be returned if it is what the user sent. Additionally, third-party services are unable to accept project IDs. The rationale for this is: Each resource should always have one canonical identifier. Because Google\u0027s privacy policy restricts the use of project IDs, both internally and with partners, only the project number can be the canonical identifier. However, even though the project number is the canonical identifier, a policy of returning it even if the user sent a project ID has proven to be unfriendly to both humans and declarative tools. Google APIs Externally-facing Google APIs should accept both project IDs and project numbers for incoming API requests. However, even though the project number is the canonical identifier as described in AIP-122, services should return whichever ID the user sent. The reason for this is because automatic translation between user-friendly project IDs and user-unfriendly project numbers has proven to cause real-world difficulty for users, and also for declarative tools (see AIP-128 for more on declarative-friendliness). Two additional points: Error responses must return the originally-provided value without modification. Error responses must not perform any translation between project IDs and project numbers. If a service receives a resource name for a resource that the service does not own, it should not perform any translation between project IDs and project numbers for those resource names. Internal Google services Internal Google services must use project numbers for internal data storage and for output. Project identifiers are widely used as storage keys, which often appear in logs and metrics. Project IDs are user-settable and thus considered PII and user data, but project numbers are not. Therefore, when an internal service calls an external Google APIs, it should use project numbers for making API requests. Resource References Project identifiers also appear in resource names. These resource names are used both to identify the resource itself and can refer to other resources (example). When project identifiers are provided, the response should include the identifier as it occurred in the request: if the project ID was provided it should be returned, and if the project number was provided, that is what should be in the response. For example, consider a Book resource, message Book { option (google.api.resource) = { type: \"pubsub.googleapis.com/Book\" pattern: \"projects/{project}/books/{book}\" }; // The resource name of the Book. string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // A reference to another resource, a Shelf. string shelf = 2 [(google.api.resource_reference) = { type: \"library.googleapis.com/Shelf\" }]; // Other fields... } with the following book submitted from a previous create request (represented as JSON in this example), { \"name\": \"projects/my-project/books/les-miserables\", \"shelf\": \"projects/12345/shelves/top-shelf\" } and a GetBookRequest, message GetBookRequest { // The name of the Book to retrieve. // Format: projects/{project}/books/{book} string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: \"library.googleapis.com/Book\" }]; } and if the value of name on such a request is, projects/my-project/books/les-miserables then the value of the field, name, returned for the Book, should match: the project ID and not the number should be returned. But, the value for the field, shelf should use the project number, as the create request had submitted a shelf with the project number in the resource name. In other words, the following values should be returned: book: projects/my-project/books/les-miserables shelf: projects/12345/shelves/top-shelf This guidance is to ensure that there is a minimal difference between user input and output. Third-party services Third-party services that are integrated with Google Cloud Platform must only store or provide project numbers. Google\u0027s privacy policy prohibits sharing project IDs with third-party services, or providing a service for third-party services to translate between project IDs and project numbers at runtime. Project identifier format Services must use project resource names as defined by the Resource Manager API to refer to projects, such as projects/123456. This allows the same API to work with other resources similar to projects, such as organizations and folders. Changelog 2022-10-19: Clarified guidance for project identifiers in resource references. 2021-07-29: Reversed previous guidance on returning project IDs; this AIP now advocates returning what the user sent. 2019-08-11: Add an exception for resources that a service does not own. 2019-06-19: Clarify how error messages should be treated 2019-06-10: Minor language and organization tweaks", + 'tags': '', + 'url': '/cloud/2510', + }, +{ + 'title': "Parameter-dependent arguments", + 'text': "Parameter-dependent arguments When designing CLI commands, a common scenario is that a command corresponding to some conceptual action may take different, largely non-overlapping arguments depending on the value of a particular parameter. For instance, suppose we\u0027re designing a new gcloud surface for managing images, and we need a command that formats an image as JPEG, GIF, or PNG. Regardless of the image format, the command will need arguments for the source and destination files, but otherwise depending on the format, an entirely different set of options will apply. JPEG, for example, might take arguments for smoothing, subsampling, and DCT method, which are only relevant for JPEG images. GIF, on the other hand, might take arguments for controlling animated gifs e.g. whether to loop forever, and a delay time in between frames. Finally, PNG might take arguments for color type and bits per channel. Guidance When the parameter-specific arguments are numerous relative to the other arguments, create a command group for the action, with separate subcommands named after each of the parameter values. In the example above, we would thus create a gcloud images format command group, with subcommands called jpeg, gif, and png. These subcommands can then take their own format-specific flags. Example usage: $ gcloud images format jpeg --help $ gcloud images format jpeg --source-file=foo --destination-file=bar \\ --dct-method=integer --smoothing=0.1 --subsampling=4:4:4 $ gcloud images format png --source-file=foo --destination-file=bar \\ --color-type=0 --bits-per-channel=16 $ gcloud images format gif --source-file=foo --destination-file=bar \\ --loop-forever --frame-delay=1ms It\u0027s possible that over time more and more arguments are added that are common to all parameters. In that case, it may make sense to instead use a single command that takes an argument for the parameter. This can be done without breaking backward compatibility by making the parameter a positional argument. In the example above, this would involve changing format from a command group to a command, and having it take a positional image format argument which can be one of: jpeg, gif, or png. Note that all the example commands above would still function identically (except for the first one, but since it only affects help text it\u0027s not considered a breaking change.) Alternatives considered There are several other possibilities for the design of such a command, outlined below: Single command with an explicit flag corresponding to the parameter In the example, this would involve a --type flag to specify the image format: $ gcloud images format --source-file=source --destination-file=dest \\ --type=JPEG --dct-method=integer --smoothing=0.1 --subsampling=4:4:4 $ gcloud images format --source-file=source --destination-file=dest \\ --type=GIF --loop-forever --frame-delay=1ms $ gcloud images format --source-file=source --destination-file=dest \\ --type=PNG --color-type=0 --bits-per-channel=16 Conceptually it makes the most sense to just have a single format command. However, this approach has several drawbacks: Unnecessary help text. The user will see all of the format-specific options, most of which will be irrelevant since they apply to different formats. In graphical image editing programs such as Photoshop or GIMP, the UI can selectively show these format-specific options once the user chooses the desired format from a dropdown. On the CLI, however, we have no such capability because the help text is statically generated. Additional logic needed for validation. Since some arguments will be invalid depending on the format, the command author needs to ensure specifying invalid combinations returns an appropriate error. While this can be accomplished with appropriately nested mutex groups, the nesting has the potential to become overly deep and complex. Multiple commands named after the action hyphenated with the parameter value In the example, this would look like: $ gcloud images format-jpeg ... $ gcloud images format-gif ... $ gcloud images format-png ... This is similar to the recommended design in that each parameter value gets its own command. However, there are disadvantages: Backward compatibility. If in the future it becomes desirable to make the parameter value an argument to a single command, this would necessitate a breaking change. It\u0027s less elegant from a command tree layout perspective. Grouping the parameter-specific commands into a command group allows for a natural decomposition of the command space, in keeping with gcloud\u0027s CLI design philosophy, and allows for progressive disclosure in the help text and in autocompletion.", + 'tags': '', + 'url': '/cloud/2602', + }, +{ + 'title': "List command arguments", + 'text': "List command arguments Some list requests take argument(s) for the parent collection in which to list resources. For example, suppose an API has book resources belonging to publisher resources, and consider a request to list books belonging to a publisher: message ListBooksRequest { // The parent, which owns this collection of books. // Format: publishers/{publisher} string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { child_type: \"library.googleapis.com/Book\" }]; // The maximum number of items to return. int32 page_size = 2; // The next_page_token value returned from a previous List request, if any. string page_token = 3; } For the corresponding gcloud list command, we have the choice between gcloud publishers books list PUBLISHER (positional) and gcloud publishers books list --publisher=PUBLISHER (flag). Guidance All list command arguments should be flags, not positionals. In gcloud\u0027s resource model, command groups generally correspond to resources, and the positional arguments for commands in a group are reserved for those resources. In the case of a list command that takes an argument, the argument will refer to the parent resource and not the command group\u0027s resource; therefore, it should be a flag instead of a positional. In the example above, the list command takes an argument for a publisher. Commands in the books command group should reserve positional arguments for book resources. Thus, the publisher argument for the list command should be a flag: gcloud publishers books list --publisher=PUBLISHER Changelog 2020-09-23: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/cloud/2603', + }, +{ + 'title': "Numeric arguments", + 'text': "Numeric arguments Some API fields refer to either a percentage or a fixed number. For example, in GCE a group can be created with a configurable limit for either the percentage or number of instances in the group that can undergo maintenance simultaneously: message ConcurrencyControl { enum LimitType { INVALID = 0; PERCENT = 1; FIXED = 2; } optional int32 concurrency_limit = 1; optional LimitType limit_type = 2; } Guidance Flag layout In gcloud, such API fields should correspond to a mutually exclusive group consisting of two flags: one for specifying a number, and the other for specifying a percentage. The API field in the example above would thus correspond to the following surface specification in gcloud: - group: mutex: true arguments: - name: concurrency-limit help_text: | Maximum number of instances in the group that can undergo maintenance simultaneously. - name: concurrency-limit-percent help_text: | Integer from 0 to 100 representing the maximum percentage of instances in the group that can undergo maintenance simultaneously. Flag naming Any flag taking a percentage should end with -percent (not -percentage). Flag type Any flag taking a percentage should take an integer from 0 to 100. If more precision is required, it is acceptable to take a float from 0 to 100. Alternatives considered One flag, where percentage is specified if the flag value ends with \u0027%\u0027, and number is assumed otherwise In other words, to specify 10% one would use --concurrency-limit=10%, and to specify 10 instances one would use --concurrency-limit=10. This would be a cleaner design since it naturally maps a single concept (the limit) to a single flag (--concurrency-limit), avoiding the need for additional flags that clutter the help text. However, the main reason not to prefer this approach is that it significantly increases the risk of user error. For instance, suppose a group currently contains 20 instances with a concurrency limit of 10%, and a user wishes to update the limit to 20%. If the user issues a describe command (or performs a GET request) to see the existing limit, the API response will contain something like: concurrencyControl: concurrencyLimit: 10 limitType: PERCENT It\u0027s easy for the user to gloss over limitType and just assume that --concurrency-limit=20 will update the limit to 20%. However, in reality this would set the limit to 20 instances (100% of the group), potentially leading to catastrophic consequences. The recommend approach avoids this ambiguity at the expense of some elegance, but we deem this tradeoff necessary. One flag, where percentage is specified if the flag value ends with \u0027%\u0027, and number is specified if the flag value ends with \u0027n\u0027 In other words, to specify 10% one would use --concurrency-limit=10%, and to specify 10 instances one would use --concurrency-limit=10n. It would be an error to provide a value that doesn\u0027t end in \u0027%\u0027 or \u0027n\u0027. While this avoids the potential for a user to confuse percentages and numbers, requiring \u0027n\u0027 at the end of a number is inelegant UX. A number should obviously resemble a number, and the choice of \u0027n\u0027 is also rather arbitrary. Exceptions This CIP does not apply for API fields like timestamps, where we allow the user to enter either absolute times or durations in the same flag. This is because absolute times and durations have natural formats that differ, and thus there\u0027s no potential for a user to confuse the two. In general if this is the case, one flag that accepts both formats should be preferred for the sake of UX simplicity.", + 'tags': '', + 'url': '/cloud/2604', + }, +{ + 'title': "Application Default Credentials", + 'text': "Application Default Credentials Google auth libraries use a strategy called Application Default Credentials (ADC) to detect and select credentials based on environment or context. With ADC, developers should be able to run the code in different environments and the supporting systems fetch the appropriate credentials based on each environment in an effortless manner. Auth libraries following the standards in these AIPs are known as \"Google Unified Auth Clients\", or GUAC for short. The resulting libraries are colloquially called GUACs. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance Credential Types This section outlines the supported credential types of the ADC. Gcloud Credential: A credential provided by the Gcloud tool that identifies a human user that needs to authenticate to access Google APIs. The auth libraries must support this credential type. Service Account Key: A credential that identifies a non-human user that needs to authenticate to access Google APIs. The auth libraries must support this credential type. OAuth Client ID: A credential that identifies the client application which allows human users to sign-in through 3-legged OAuth flow, which grants the permissions to the application to access Google APIs on behalf of the human user. The auth libraries may support this credential type. External Account Credential: A configuration file identifying external non-Google credentials that can be exchanged for Google access tokens to access Google APIs. The auth libraries must support this credential type. Environment Variables The auth libraries must support the following environment variables to allow developers to provide authentication configuration for their application: GOOGLE_APPLICATION_CREDENTIALS: The specified value will be used as the full path for ADC to locate the credentials file. The credentials file should be one of the following types: Gcloud credentials Service account key External account credentials The credentials may be the OAuth Client ID if it is supported by the auth library. Credentials file path specified at the program level (e.g. via client options) must have priority over the value of this environment variable. GOOGLE_API_USE_CLIENT_CERTIFICATE: The specified value must be either true or false. The client certificate must be ignored if this variable is set to false. The default value is false if the value is unset. GOOGLE_API_USE_CLIENT_CERTIFICATE=[true|false] GOOGLE_CLOUD_QUOTA_PROJECT: The quota project id to be set on the credential. The value from the environment variable will override any quota project that is present in the credential detected by the ADC mechanism. Inputs \u0026 Outputs From the input/output perspective, the inputs of ADC should be the credentials as well as the underlying environment such as environment variables or metadata service that provides these credentials. For example, the GOOGLE_APPLICATION_CREDENTIALS environment variable can provide the default credential JSON as the input here, or the well-known path that gCloud uses to store the default user credential JSON. The output is the access token that application can use to access the Google APIs. This access token may be a bearer token, a certificate-bound token, or an identity-bound token depending on the chosen authentication flow. Expected Behavior This section outlines the expected behavior of the ADC. Auth libraries must implement these concepts in order to be considered complete. digraph d_front_back { rankdir=TB; ranksep=0.3; node [ style=\"filled,solid\" shape=box fontname=\"Roboto\" ]; check_env_var [ label=\"1. Check Environment Variables\" ]; load_credentials [ label=\"2. Load Credentials\" ]; check_metadata [ label=\"3. Check workload credentials\" ]; auth_flows [ label=\"4. Determine Auth Flows\" ]; execute [ label=\"5. Execute Auth Flows\" ]; post_processing [ label=\"6. Post Processing\" ]; check_env_var -\u003e load_credentials -\u003e check_metadata -\u003e auth_flows -\u003e execute -\u003e post_processing; load_credentials -\u003e auth_flows; check_metadata -\u003e post_processing; } Check environment variables Check GOOGLE_APPLICATION_CREDENTIALS If set, go to step (2.2) If not set, go to step (2) Load credentials Check gcloud default credentials through its default path If found go to step (2.2) Otherwise go to step (3) Check the provided credential type If the credential is gcloud credentials, go to step (4) If the credential is a service account key JSON, go to step (4) If the credential is an external account JSON, go to step (4) If the credential is unknown type, return an error saying that [END] Credentials not found [END] Check workload credentials (on GCE, GKE, GAE and Serverless) If true, If identity binding is enabled, by meeting the requirements in mTLS Token Binding, use the mTLS Token Binding flow to fetch an identity-bound access token. Go to step(6). If there is an issue when obtaining bound access tokens, return an error indicating that [END] If identity binding is not enabled, use the virtual machine flow to fetch an auth token associated with the current environment If target audience is provided by the developer, get an identity token. Go to step(6). Otherwise, get an access token. Go to step(6). If false, go to step (2.3) Determine auth flows If the credential is gcloud credential go to step (5.3) If target audience or scope is provided by the developer go to step (5.1) If the credential is an external account go to step (5.4) Otherwise, go to step (5.2) Execute auth flows Use 2LO flow to exchange for an auth token If target audience is provided by the developer, get an identity token. Go to step(6). Otherwise, get an access token. Go to step(6). If client certificate is presented, the exchanged token will be a certificate bind token. Go to step(6). Use self-signed JWT flow to create an access token locally. If certificate is presented, embed the certificate into the JWT. Use the regular self-signed JWT flow for an access token. Go to step(6). Use user identity flow to exchange for an access token. Go to step(6). Use external account flow to exchange for an access token. Go to step(6). Post Processing Update Quota Project If a quota project is provided explicitly while initiating ADC, override the quota project in the credential with the explicit value. [END] Else if the GOOGLE_CLOUD_QUOTA_PROJECT environment variable is set, override the quota project in the credential with this value. [END] Changelog 2019-08-13: Add a link to virtual machine flow (AIP 4115). 2019-08-18: Remove STS support from ADC. 2021-01-20: Add identity token flow (AIP 4116). 2021-06-29: Guidance for GOOGLE_API_KEY temporarily removed until consensus can be established. 2021-12-10: Add external account credentials (AIP 4117). 2023-01-23: Add Quota Project Environment variable.", + 'tags': '', + 'url': '/auth/4110', + }, +{ + 'title': "Self-signed JWT", + 'text': "Self-signed JWT Self-signed JWT (JSON Web Token) for Google APIs was introduced in 2014 to provide a more efficient auth stack for Cloud APIs being accessed via service accounts by bypassing the intermediate step of exchanging client assertions for OAuth tokens. A self-signed JWT is a spec-conforming JWT that is locally signed by the service account private key. Since many Cloud APIs accept self-signed JWT in place of traditional access tokens, it is now considered a standard authentication method. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance This section describes the general guidance of supporting self-signed JWT as a means of authentication. Application Default Credentials Supporting self-signed JWT is considered a part of application default credentials. To understand the overall flow, please read AIP-4110. Scope vs. Audience In the past, the self-signed JWT was only applicable with audience. Recently, the usage of the \"scope\" claim in self-signed JWTs is now allowed in the Google Cloud auth ecosystem, which makes the self-signed JWT usable with both audience and scope. However, caller must not specify scope and audience at the same time to prevent potential conflicts. Opt-in Strategy Currently, this scope support for JWT is gated behind a configurable boolean option UseJWTAccessWithScope(the actual naming may vary depending on the programming language), as the feature is not supported for all Cloud API service backends. The default value of this boolean is false, and to use scope with self-signed JWT, caller must specify this option as true. Otherwise the OAuth exchange flow should be used instead when scope is provided. The API clients should try to automatically determine this option with the appropriate value based on the APIs, so this complexity is not exposed to the upper-layer developer. Default Authentication Method For Service Account Keys Considering its better efficiency and reliability comparing with OAuth flow (bypassing the exchanging step), ADC should use self-signed JWT as the default authentication flow when service account key is provided as the source credential. In other words, ADC should choose the OAuth flow over the self-signed JWT flow only if scope is provided and JWT is not enabled via UseJWTAccessWithScope. Expected Behavior To support self-signed JWT, the auth libraries must follow the steps below: 1. Load the service account ID JSON file. Please note that the self-signed JWT only supports service account ID credential type. 2. Using any standard JWT library, such as one found at jwt.io, create a JWT with a header and payload like the following examples: (1) Example of using audience: { \"alg\": \"RS256\", \"typ\": \"JWT\", \"kid\": \"abcdef1234567890\" } { \"iss\": \"123456-compute@developer.gserviceaccount.com\", \"sub\": \"123456-compute@developer.gserviceaccount.com\", \"aud\": \"https://pubsub.googleapis.com/\", \"iat\": 1511900000, \"exp\": 1511903600 } (2) Example of using scope: { \"alg\": \"RS256\", \"typ\": \"JWT\", \"kid\": \"abcdef1234567890\" } { \"iss\": \"123456-compute@developer.gserviceaccount.com\", \"sub\": \"123456-compute@developer.gserviceaccount.com\", \"scope\": \"https://www.googleapis.com/auth/cloud-platform\", \"iat\": 1511900000, \"exp\": 1511903600 } For the kid field in the header, specify the service account\u0027s private key ID. You can find this value in the private_key_id field of the service account JSON file. For the iss and sub fields, specify the service account\u0027s email address. You can find this value in the client_email field of the service account JSON file. For the aud field, specify the audience. The default audience value should be https://[SERVICE]/. (e.g. https://pubsub.googleapis.com/) For the scope field, specify the scope. Please note that aud and scope cannot be specified at the same time. For the iat field, specify the current Unix time, and for the exp field, the value must be exactly 3600 seconds later, when the JWT will expire. 3. Sign the JWT with RSA-256 using the private key found in the service account JSON file. Changelog 2019-08-13: Add a section for application default credential. 2021-06-02: Update scope support.", + 'tags': '', + 'url': '/auth/4111', + }, +{ + 'title': "Service Account Keys", + 'text': "Service Account Keys A service account is a special kind of account used by an application or a virtual machine (VM) instance, not a person. Applications use service accounts to make authorized API calls, authorized as either the service account itself, or as Google Workspace or Cloud Identity users through domain-wide delegation. Service accounts are associated with private/public RSA key-pairs that are used for authentication, which is the focus of this AIP. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance This section describes the general guidance of supporting Service Account Key authentication using traditional OAuth flow. For Service Account Key authentication using self-signed JWT flow, please refer to the self-signed JWT AIP. Service Account Key Authentication Using OAuth Under the latest ADC guidance, when Service Account Key is provided as the source credential, we prefer to use the self-signed JWT flow by default, which does not use the OAuth \"scope\" argument. Therefore, the client should choose the OAuth flow over self-signed JWT flow only if the OAuth \"scope\" is explicitly provided to the client. Expected Behavior To support Service Account Key authentication using OAuth flow, the auth libraries must follow the steps below: 1. Load the Service Account ID JSON file from the file path specified by GOOGLE_APPLICATION_CREDENTIALS environment variable, or an explicit credentials file path specified through client options. The JSON file will look like below: { \"type\": \"service_account\", \"project_id\": \"testproject\", \"private_key_id\": \"redacted\", \"private_key\": \"redacted\", \"client_email\": \"testserviceaccount@test.iam.gserviceaccount.com\", \"client_id\": \"113258942105700140798\", \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\", \"token_uri\": \"https://oauth2.googleapis.com/token\", \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\", \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/testserviceaccount%40test.iam.gserviceaccount.com\" } Note: A Service Account ID JSON file can be downloaded from Google Cloud Console. 2. Using any standard JWT library, such as one found at jwt.io, create a JWT with a header and claims set like the following example: { \"alg\": \"RS256\", \"typ\": \"JWT\", \"kid\": \"abcdef1234567890\" } { \"iss\": \"123456-compute@developer.gserviceaccount.com\", \"sub\": \"123456-compute@developer.gserviceaccount.com\", \"scope\": \"https://www.googleapis.com/auth/pubsub\", } For the kid field in the header, specify the service account\u0027s private key ID. You can find this value in the private_key_id field of the service account JSON file. For the iss and sub fields, specify the service account\u0027s email address. You can find this value in the client_email field of the service account JSON file. For the scope field, specify the scope parameter provided by the client. Multiple scopes can be specified using single space (\" \") as delimiter. 3. Sign the JWT with RSA-256 using the private_key found in the service account JSON file. The output will be used as the request payload (a.k.a. assertion) for the 2-legged OAuth flow. 4. Define a parameter \"grant_type\" as \"urn:ietf:params:oauth:grant-type:jwt-bearer\". Define a parameter \"assertion\" as the payload from step 3. 5. Make a POST request to the token_uri endpoint with the parameters from step 4 to obtain an OAuth2 Access Token.", + 'tags': '', + 'url': '/auth/4112', + }, +{ + 'title': "gcloud CLI Integration", + 'text': "gcloud CLI Integration gcloud is the CLI that manages authentication, local configuration, developer workflow, and interactions with the Google Cloud Platform (GCP) APIs. gcloud can generate default credentials by obtaining user access credentials via 3-legged OAuth (3LO) web flow and saving them to well-known locations in JSON format. These credentials are intended to be consumed by applications other than gcloud. Application Default Credentials (ADC) and Google Unified Auth Clients (GUAC) must support the gcloud default credentials. Note: Although the sample code is written in Python, this AIP describes guidance and requirements in a language-neutral way. It uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance This section describes the general guidance of supporting the gcloud default credentials. Credentials Generation gcloud default credentials can be generated via command \u2018gcloud auth application-default login\u2019. $ gcloud auth application-default login The generated credentials are saved to well-known locations which vary as platforms: Linux, Mac: \\$HOME/.config/gcloud/application_default_credentials.json Windows: %APPDATA%/gcloud/application_default_credentials.json Below is an example of the gcloud default credentials, { \"client_id\": \"fake_id.apps.googleusercontent.com\", \"client_secret\": \"fake_secret\", \"quota_project_id\": \"fake_project\", \"refresh_token\": \"fake_token\", \"type\": \"authorized_user\" } All the fields are populated by the login response from the Google authorization backend except for \u2018quota_project_id\u2019 which is retrieved from gcloud\u2019s context. Additionally, the users can override \u2018quota_project_id\u2019 with the \u2018--client-id-file\u2019 flag, $ gcloud auth application-default login --client-id-file=clientid.json Expected Behaviors The auth libraries will use the information in the gcloud default credentials to exchange access tokens with Google authorization backend. The resulting access tokens will be further used by applications to call GCP APIs. The auth libraries and applications must follow the steps below: The auth library loads the gcloud default credentials from the well-known location (see previous section) of the platform on which it runs. The auth library calls Google authorization backend with the refresh token, client ID and client secret in the gcloud default credentials and procures an access token. The URL for acquiring access tokens from Google authorization backend is https://oauth2.googleapis.com/token. Below is an example code with google-auth as the auth library and urllib3 as the http transport. from google.oauth2 import _client as google_auth_client import google.auth.transport.urllib3 as google_auth_urllib3 import urllib3 # Create an http transport for communicating with Google authorization backend. http = urllib3.PoolManager() request = google_auth_urllib3.Request(http) # Build parameters for the access token request. Assume the gcloud default # credentials are deserialized are into a dictionary \u2018gcloud_default\u2019 # in the previous step. token_uri = \u0027https://oauth2.googleapis.com/token\u0027 refresh_token = gcloud_default[\u0027refresh_token\u0027] client_id = gcloud_default[\u0027client_id\u0027] client_secret = gcloud_default[\u0027client_secret\u0027] scopes = [\u0027https://www.googleapis.com/auth/cloud-platform\u0027] # Obtain an access token. access_token, _, _, _ = google_auth_client.refresh_grant( request, token_uri, refresh_token, client_id, client_secret, scopes) The application calls GCP API with the access token obtained from the previous step. \u2018quota_project_id\u2019 in the gcloud default credentials should be added to the \u2018X-Goog-User-Project\u2019 http header so that the associated account will be charged for billing and quota.", + 'tags': '', + 'url': '/auth/4113', + }, +{ + 'title': "Device Certificate Authentication via Mutual TLS", + 'text': "Device Certificate Authentication via Mutual TLS Mutual TLS (a.k.a mTLS) authentication enables authentication of both client and server identities in a TLS handshake and provides the foundation for Device Certificate Authentication for Context Aware Access for GCP enterprise customers. With Device Certificate Authentication, the server takes into account the client certificate in the transport layer when making authorization decisions. The use of a client certificate provides a stronger indication of the access originating from a trusted device. This allows enterprise customers to restrict access from untrusted devices. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance This section describes the general guidance of supporting Device Certificate Authentication (a.k.a. DCA) via mTLS. Application Default Credentials for DCA Users should enable DCA through ADC instead of manual configuration via client options. There are two aspects of ADC for DCA. The first is the automatic procurement of a device certificate. The second is the automatic switching of the service endpoint to the mTLS version of the service endpoint. Clients must support both of these aspects when supporting ADC for DCA. Expected Behavior Client support for DCA must give priority to user overrides specified via client options. The following decision tree should be used: If user specifies both device certificate and endpoint override via client options, use them as is. If user does not specify device certificate, attempt to procure and use a default device certificate. If user does not specify endpoint override, use the default mTLS endpoint if a device certificate is available and the default regular endpoint otherwise. Implications of the above logic: If user specifies a non-mTLS endpoint override but a device certificate is available, pass along the certificate anyway and let the server decide what to do. If user specifies an mTLS endpoint override but device certificate is not available, do not fail-fast, but let server return error when connecting. The above behavior avoids introducing client-side logic that parses whether the endpoint override is an mTLS url, since the url pattern may change at anytime. Obtaining the Default mTLS Endpoint The default mTLS endpoint for a service should be read from the Discovery Document field \"mtlsRootUrl\" instead of generated via regex patterns. Obtaining the Default Device Certificate via SecureConnect The default device certificate should be procured using the EndpointVerification workflow, which fetches the certificate from a platform-specific credential store (ex. KeyChain in macOS) via a native helper. Exporting the certificate via the native helper involves executing a \"cert provider command\" specified in a well-known gcloud metadata file of the following format: { \"version\": 1 \"min_cloud_sdk_version\": \"240.0.0\" \"has_client_cert\": true \"endpoint_verification_error\": \"\" \"cert_provider_command\": \"[absolute_path_to_provider_command] --fetch_client_cert\" } For Linux and macOS platforms, the above metadata file is located at \"~/.secureConnect/context_aware_metadata.json\". The cert provider command will print the certificate to stdout, which will be in the form of an X.509 cert followed immediately by the private key: -----BEGIN CERTIFICATE----- Common Name: Google Endpoint Verification Valid From: November 10, 2019 Valid To: November 10, 2020 Serial Number: 4921083229008411918 (0x444b331faf2dbd0e) ... -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY----- Obtaining the Default Device Certificate via ECP The Enterprise Certificate Proxy (ECP) project is the newly recommended way to procure device certificates. It has two major advantages compared to the legacy SecureConnect mechanism: Allows usage of enterprise certs and private keys stored in native keystores and TPMs instead of relying on self-signed certs. Delegates signing operations to keystores, so private keys never leave the security realm. Please see ECP Public Documentation for details on ECP configuration. Environment Variables There are situations where the ADC for DCA behavior needs to be modified, such as for integration testing, or for failsafe. To accomodate those scenarios, the following environment variables should be supported. GOOGLE_API_USE_MTLS_ENDPOINT: If \"always\", always use mTLS endpoint. If \"never\", always use regular endpoint. If \"auto\", use the default behavior, which is to use the mTLS endpoint if a device certificate is available. The default value of this environment variable will be \"auto\". GOOGLE_API_USE_CLIENT_CERTIFICATE: If \"true\", device certificate authentication will be supported as described in the general guidance. If \"false\", the device certificate must not be used, even if specified by the user. The default value should be \"true\" as of May 3, 2024. Users who wish to disable DCA feature must explicitly set this environment variable to \"false\". Firewall and IP Address Guidance For any given GCP service, its mTLS endpoint has a different IP address compared to the non-mTLS endpoint but is expected to fall within the same IP range. The GCP guidance for IP range management is on a service by service basis. See Compute Engine IP Range Documentation for example. In the unlikely event that an end-user has configured firewall rules based on exact IP addresses instead of an IP range, they may be impacted by the \"auto\" mTLS endpoint upgrade behavior. The best-practice recommendation in this case would be to avoid adding rules that expect exact IP address matches, and instead use range-based IP rules following public GCP documentation. Changelog *2024-11-25: GOOGLE_API_USE_CLIENT_CERTIFICATE should default to \"true\" as of May 3, 2024. *2025-02-20: Add Firewall and IP Address Guidance", + 'tags': '', + 'url': '/auth/4114', + }, +{ + 'title': "Default Credentials For Google Cloud Virtual Environments", + 'text': "Default Credentials For Google Cloud Virtual Environments If the client runs on Google cloud virtual environments such as Google Compute Engine (GCE), Serverless, or Google Kubernetes Engine (GKE), the auth library may leverage Google\u2019s default mutual TLS (mTLS) credentials and obtain bound tokens for the instance. The auth library may use the default mTLS credentials and bound tokens to access Google APIs. mTLS authentication enables authentication of both client and server identities in a TLS handshake. Applications running in Google virtual environments can authenticate to Google APIs using X.509 SPIFFE Verifiable Identity Documents (SVIDs). These SVIDs are X.509 certificates that contain SPIFFE IDs specifying the identity of the certificate owner. Bound tokens are access tokens that are bound to some property of the credentials used to establish the mTLS connection. The advantage of bound tokens is that they can be used over secure channels established via mTLS credentials with the correct binding information, when appropriate access policies have been put in place. Therefore, using bound tokens is more secure than bearer tokens, which can be stolen and adversarially replayed. This AIP describes the flow of: Retrieving a configuration through a metadata server (MDS) endpoint. The configuration specifies how to access Google\u2019s default mTLS credentials. Requesting bound tokens. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance Access Default mTLS Credentials Note: Before trying to use Google\u2019s default mTLS credentials, the client must first check if the remote Google API endpoint supports mTLS. If the remote endpoint does NOT support mTLS, the client should connect to the endpoint using TLS. How to check if an endpoint supports mTLS is out of the scope of this AIP. If the remote endpoint does support mTLS, the client should try to connect using mTLS first before falling back to TLS. How to find the remote API\u2019s mTLS endpoint is out of the scope of this AIP. If users enabled Device Certificate Authentication (DCA), the client should give priority to DCA as mTLS credentials. To leverage Google\u2019s default mTLS credentials, the client should retrieve configurations from MDS. The MDS in all virtual environments (GCE, Serverless, and GKE) exposes an HTTP endpoint that serves a configuration that specifies how to access Google\u0027s default mTLS credentials. This endpoint is called the mTLS configuration endpoint. The URL of the MDS\u0027s mTLS configuration endpoint is: http://metadata.google.internal/computeMetadata/v1/instance/platform-security/auto-mtls-configuration The request to the MDS\u0027s mTLS configuration endpoint should be an HTTP GET request without any parameter or payload. The response from the MDS\u0027s mTLS configuration endpoint should contain the following information: The Secure Session Agent address: the client doesn\u2019t have direct access to mTLS credentials. The Secure Session Agent manages default mTLS credentials. The client can only use mTLS credentials through the Secure Session Agent. The address can be an IP:port address or a file path representing a Unix Domain Socket (UDS). The client must follow the steps below to access Google\u2019s default mTLS credentials. Check if the remote endpoint supports mTLS. If yes, go to step (2). If not, go to step (3). Send a request to the MDS\u0027s mTLS configuration endpoint. If the request is successful and the response contains a Secure Session Agent address, use the address to access Google\u0027s default mTLS credentials, and go to step (4). If the request fails or the response contains an empty address, go to step (3). Fall back to TLS [END]. Configure the TLS library to use the Secure Session Agent (example) for client authentication during the mTLS handshake. Request Bound Tokens To access Google APIs with bound tokens, the client should request tokens from MDS. The MDS in all virtual environments (GCE, Serverless, and GKE) exposes an HTTP endpoint that serves access tokens. This endpoint is called the access token endpoint. The URL of the MDS\u0027s access token endpoint is: http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token The request to the MDS\u0027s access token endpoint should be an HTTP GET request. The request may have a \u201cscopes\u201d URL parameter with a list of comma-separated scopes. The auth library should allow the caller to optionally specify a list of custom scopes, and add the \u201cscopes\u201d parameter to the request when needed. Depending on the runtime environment, the request for custom scopes may be transparently ignored or fulfilled by the server. The response from the MDS\u0027s access token endpoint should contain an access token in the following JSON format: { \"access_token\": \"YOUR_ACCESS_TOKEN\", \"expires_in\": 3599, \"token_type\": \"Bearer\" } The client must follow the steps below to request new access tokens for Google APIs if existing tokens expire. Send an HTTP request to the MDS access token endpoint, retrieve the access token from the response and go to step (2). Attach the token from step (1) to the request to Google APIs. Changelog 2020-12-14: Replace note on scopes with more detailed discussion. 2021-07-13: Clarify GCE equivalent runtimes 2023-02-16: Add mTLS configuration endpoint and unify the token binding flow.", + 'tags': '', + 'url': '/auth/4115', + }, +{ + 'title': "Identity Tokens", + 'text': "Identity Tokens Identity Tokens (or ID Tokens) are JSON Web Tokens (JWT) with additional claims pertaining to the identity of the client or end-user (such as \"email\"). Which additional claims fields are included in the ID token are dependent on the ID token provider. The fetching of ID tokens is used to: request a protected Cloud Run service, which requires a valid ID token in the Authentication header. request an IAP-protected resource, which requires a valid ID token in the Authentication header. The validation of ID tokens should be done by: services receiving an authenticated PubSub push message sent outside of Google Cloud. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance This section describes the general guidance of ID tokens as a means of authentication. ID tokens obtained by Application Default Credentials When a target audience is provided by the developer, ADC should fetch an ID token with the credentials provided. For example, if service account keys are provided, ADC will request an ID token from the OAuth token endpoint. If virtual machine credentials are provided, ADC will request an ID token from the virtual machine server. Expected Behavior for Fetching ID Tokens To support fetching ID Tokens, the auth libraries must follow the steps below: 1. Accept a target audience parameter when Application Default Credentials are requested. If a target audience and scope are both provided to the auth library, an exception must be thrown. 2. Virtual machine credentials return the ID token retrieved from the metadata server\u0027s instance/service-accounts/default/identity endpoint, setting the audience querystring parameter to the provided target audience. 3. Service account Keys use the JWT Bearer grant type, and set the target_audience claim to the provided target audience. This will return a JSON object containing an id_token key. User Identity flows may be used to issue ID tokens, but are not required to. Expected Behavior for Verifying ID Tokens To support verifying ID Tokens, the auth libraries must provide a method to validate a JWT token which can do the following: 1. Validate a JWT with an ES256 signature. 2. Validate JWT aud claim against a user-provided audience. 3. Validate JWT exp claim against the current timestamp.", + 'tags': '', + 'url': '/auth/4116', + }, +{ + 'title': "External Account Credentials (Workload Identity Federation)", + 'text': "External Account Credentials (Workload Identity Federation) Using workload identity federation, your application can access Google Cloud resources from Amazon Web Services (AWS), Microsoft Azure or any identity provider that supports OpenID Connect (OIDC) or SAML 2.0. Traditionally, applications running outside Google Cloud have used service account keys to access Google Cloud resources. Using identity federation, you can allow your workload to impersonate a service account. This lets you access Google Cloud resources directly, eliminating the maintenance and security burden associated with service account keys. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance This section describes the general guidance of supporting non-Google external credentials (AWS, Azure, OIDC and SAML IdPs, etc) as a means of authentication. Prerequisite In order to use workload identity federation to access Google cloud resources from non-Google cloud platforms, the following steps are needed to configure workload identity pools, providers, service account impersonation and generate the JSON configuration file to be used by the auth libraries. Configure Workload Identity Federation from AWS Configure Workload Identity Federation from Microsoft Azure Configure Workload Identity Federation from an OIDC identity provider Configure Workload Identity Federation from a SAML identity provider Configuration File Generation and Usage After workload identity federation is configured, the JSON configuration file should be generated. This sample shows how an AWS configuration file is generated: $ gcloud iam workload-identity-pools create-cred-config \\ projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \\ --service-account=$SERVICE_ACCOUNT_EMAIL \\ --aws \\ --output-file=$FILEPATH.json The following values would need to be replaced: PROJECT_NUMBER: Project number of the project that contains the workload identity pool. POOL_ID: ID of the workload identity pool. PROVIDER_ID: ID of the workload identity pool provider. SERVICE_ACCOUNT_EMAIL: Email address of the service account to impersonate. FILEPATH: File to save configuration to. If you are using AWS IMDSv2, an additional flag --enable-imdsv2 should be added to the gcloud iam workload-identity-pools create-cred-config command: $ gcloud iam workload-identity-pools create-cred-config \\ projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \\ --service-account=$SERVICE_ACCOUNT_EMAIL \\ --aws \\ --enable-imdsv2 \\ --output-file=$FILEPATH.json If you wish to configure the service account access token lifetime, an additional flag --service-account-token-lifetime-seconds should be added to the gcloud iam workload-identity-pools create-cred-config command (this example uses an AWS configuration, but the token lifetime can be configured for all workload identity federation providers): $ gcloud iam workload-identity-pools create-cred-config \\ projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \\ --service-account=$SERVICE_ACCOUNT_EMAIL \\ --aws \\ --service-account-token-lifetime-seconds=$TOKEN_LIFETIME \\ --output-file=$FILEPATH.json The service-account-token-lifetime-seconds flag is optional. If not provided, this defaults to one hour. The minimum allowed value is 600 (10 minutes) and the maximum allowed value is 43200 (12 hours). If a lifetime greater than one hour is required, the service account must be added as an allowed value in an Organization Policy that enforces the constraints/iam.allowServiceAccountCredentialLifetimeExtension constraint. The external identities configuration file can be used with Application Default Credentials. In order to use external identities with Application Default Credentials, the full path to this file should be stored in the GOOGLE_APPLICATION_CREDENTIALS environment variable. export GOOGLE_APPLICATION_CREDENTIALS=/path/to/config.json The library can now automatically choose the right type of client and initialize credentials from the context provided in the configuration file: import google.auth credentials, project = google.auth.default() External account credentials can also be initialized explicitly using the generated configuration file. # Sample for Azure or OIDC/SAML providers. import json from google.auth import identity_pool json_config_info = json.loads(function_to_get_json_config()) credentials = identity_pool.Credentials.from_info(json_config_info) scoped_credentials = credentials.with_scopes( [\u0027https://www.googleapis.com/auth/cloud-platform\u0027]) # Sample for AWS. import json from google.auth import aws json_config_info = json.loads(function_to_get_json_config()) credentials = aws.Credentials.from_info(json_config_info) scoped_credentials = credentials.with_scopes( [\u0027https://www.googleapis.com/auth/cloud-platform\u0027]) Expected Behavior The auth libraries should use the information in the JSON configuration file to retrieve the external credentials and exchange them for Google access tokens using the GCP Security Token Service (via the token exchange endpoint https://sts.googleapis.com/v1/token) and then impersonating a service account by calling the IamCredentials generateAccessToken API to access GCP resources. All external account JSON files must share the following fields: Field Name Required Description type Yes This identifies the new type of credential object. This must be \"external_account\" audience Yes This is the STS audience which contains the resource name for the workload identity pool and the provider identifier in that pool. subject_token_type Yes This is the STS subject token type based on the OAuth 2.0 token exchange spec. service_account_impersonation_url No This is the URL for the service account impersonation request. If this is not available, the STS returned access token should be directly used without impersonation. service_account_impersonation.* No This object defines additional service account impersonation options. Only one field is currently supported: \u201ctoken_lifetime_seconds\": This is the requested access token lifetime, e.g. 2800. token_url Yes This is the STS token exchange endpoint. credential_source.* Yes This object defines the mechanism used to retrieve the external credential from the local environment so that it can be exchanged for a GCP access token via the STS endpoint. The auth libraries and applications must follow the steps below for all types of external account credentials: Check credential_source to determine the necessary logic to retrieve the external credential which should be used to construct the subject token to pass to the STS endpoint. This is covered in detail for every credential configuration below. Construct the STS request, based on rfc8693: STS audience should be constructed using the audience field. grant_type must be urn:ietf:params:oauth:grant-type:token-exchange requested_token_type must be urn:ietf:params:oauth:token-type:access_token subject_token_type is the subject_token_type field as described in the RFC. subject_token is the retrieved external credentials. Check the subsequent sections on how this is retrieved in various environments. scope: the list of space-delimited, case-insensitive OAuth scopes that specify the desired scopes of the requested security token in the context of the service or resource where the token should be used. If service account impersonation is used, the cloud platform or IAM scope should be passed to STS and then the customer provided scopes should be passed in the IamCredentials call to generateAccessToken. The STS token exchange URL should be the token_url (e.g. https://sts.googleapis.com/v1/token). Send the STS token exchange request to get the Google access token and its expiration. If the service_account_impersonation_url is available, trigger service account impersonation flow by POSTing to that endpoint with the previously returned Google access token. If this is not available, end the flow and just use the STS access token for authorization. The list of scopes also need to be provided for this endpoint. The customer provided scopes should be used for this endpoint. In order to access this API, the (Cloud platform https://www.googleapis.com/auth/cloud-platform or IAM scope https://www.googleapis.com/auth/iam) are required in the underlying access token. The service account access token lifetime also needs to be provided for this endpoint. The value in service_account_impersonation.token_lifetime_seconds will be used if it was provided, otherwise it will default to 1 hour. Determining the subject token in AWS External account configuration JSON files should contain the following information in the credential_source object to facilitate retrieval of AWS credentials to be passed as subject tokens to the GCP STS token exchange endpoint. Field Name Required Description environment_id Yes This is the environment identifier, of format aws${version}. A version should be specified to indicate to the auth library whether breaking changes were introduced to the underlying AWS implementation. So if aws1 is supported in the current version of the library but a credential file with aws2 is provided, an error should be thrown instructing the developer to upgrade to a newer version of the library. region_url No This URL should be used to determine the current AWS region needed for the signed request construction when the region environment variables are not present. url No This AWS metadata server URL should be used to retrieve the access key, secret key and security token needed to sign the GetCallerIdentity request. The $ROLE_NAME should be retrieved from calling this endpoint without any parameter and then calling again with the returned role name appended to this URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME regional_cred_verification_url Yes This defines the regional AWS GetCallerIdentity action URL. This URL should be used to determine the AWS account ID and its roles. This should not actually be called by the Auth libraries. It should be called on the STS token server. The region should be substituted by SDK, e.g. sts.eu-west-1.amazonaws.com. imdsv2_session_token_url No Presence of this URL enforces the auth libraries to fetch a Session Token from AWS. This field is required for EC2 instances using IMDSv2. This Session Token would later be used while making calls to the metadata endpoint. The JSON file for AWS configuration files should have the following form: { \"type\": \"external_account\", \"audience\": \"//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID\", \"subject_token_type\": \"urn:ietf:params:aws:token-type:aws4_request\", \"service_account_impersonation_url\": \"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken\", \"token_url\": \"https://sts.googleapis.com/v1/token\", \"credential_source\": { \"environment_id\": \"aws1\", \"region_url\": \"http://169.254.169.254/latest/meta-data/placement/availability-zone\", \"url\": \"http://169.254.169.254/latest/meta-data/iam/security-credentials\", \"regional_cred_verification_url\": \"https://sts.{region}.amazonaws.com?Action=GetCallerIdentity\u0026Version=2011-06-15\", \"imdsv2_session_token_url\": \"http://169.254.169.254/latest/api/token\" } } The auth libraries and applications must follow the steps below: Check credential_source for environment ID. If the environment ID is aws${version}, this should be an AWS native credential. Inspect the version in the environment ID. If this is a newer unexpected error, trigger an error that the auth library needs to be updated to handle this type of credentials. Validate the host for the url, regional_url and imdsv2_session_token_url fields if they are provided. The host should either be 169.254.169.254 or fd00:ec2::254. If imdsv2_session_token_url is available, then fetch session token from imdsv2_session_token_url. Note: only perform this step if you need to communicate with the metadata server to fetch the region and/or the security credentials Check the environment variables in the following order (AWS_REGION and then the AWS_DEFAULT_REGION) to determine the AWS region. If found, skip using the AWS metadata server to determine this value. If the region environment variables are not provided, use the region_url to determine the current AWS region. The API returns the zone name, e.g. us-east-1d. The region should be determined by stripping the last character, e.g. us-east-1. Check the environment variables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and the optional AWS_SESSION_TOKEN for the AWS security credentials. If found, skip using the AWS metadata server to determine these values. If url is available and the security credentials environment variables are not provided: Call url to retrieve the attached AWS IAM role name to the current instance. Call url/$ROLE_NAME to get the access key, secret key and security token needed to sign the GetCallerIdentity request. Construct the AWS signed request (AWS Signature Version 4) using the GetCallerIdentity regional_cred_verification_url (with the region substituted). This should be serialized by formatting it as a url-encoded JSON and passed as the subject_token to STS endpoint. Here is a sample of the JSON format used: { \"url\": \"https://sts.us-east-1.amazonaws.com?Action=GetCallerIdentity\u0026Version=2011-06-15\", \"headers\": [ { \"value\": \"//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID\", \"key\": \"x-goog-cloud-target-resource\" }, { \"value\": \"20200228T225005Z\", \"key\": \"x-amz-date\" }, { \"value\": \"AWS4-HMAC-SHA256 Credential=AKIASOZTBDV4D7ABCDEDF/20200228/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token;x-goog-cloud-target-resource, Signature=abcedefdfedfd\", \"key\": \"Authorization\" }, { \"value\": \"sts.us-east-1.amazonaws.com\", \"key\": \"host\" }, { \"value\": \"IQoJb3JpZ2luX2VjEIz//////////wEaCXVzLWVh...\", \"key\": \"x-amz-security-token\" } ], \"method\": \"POST\", \"body\": \"\" } For the AWS token, STS requires a special header x-goog-cloud-target-resource to recognize that the token is for a specific workload identity provider. Determining the subject token in Microsoft Azure and URL-sourced credentials External account configuration JSON files should contain the following information in the credential_source object to facilitate retrieval of Azure and other URL-sourced credentials to be passed as subject tokens to the GCP STS token exchange endpoint. Field Name Required Description url Yes This defines the local metadata server to retrieve the external credentials from. For Azure, this should be the Azure Instance Metadata Service (IMDS) URL used to retrieve the Azure AD access token. headers No This defines the headers to append to the GET request to credential_source.url. format.type No This indicates the format of the URL response. This can be either \"text\" or \"json\". The default should be \"text\". format.subject_token_field_name No Required for JSON URL responses. This indicates the JSON field name where the subject_token should be stored. The JSON file for URL-sourced configuration files (OIDC / SAML) should have the following form: { \"type\": \"external_account\", \"audience\": \"//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID\", \"subject_token_type\": \"urn:ietf:params:oauth:token-type:jwt\", \"service_account_impersonation_url\": \"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken\", \"token_url\": \"https://sts.googleapis.com/v1/token\", \"credential_source\": { \"url\": \"http://localhost:5000/token\", \"format\": { \"type\": \"json\", \"subject_token_field_name\": \"id_token\" } } } Azure configuration files are a type of OIDC URL-sourced credentials. { \"type\": \"external_account\", \"audience\": \"//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID\", \"subject_token_type\": \"urn:ietf:params:oauth:token-type:jwt\", \"service_account_impersonation_url\": \"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken\", \"token_url\": \"https://sts.googleapis.com/v1/token\", \"credential_source\": { \"headers\": { \"Metadata\": \"True\" }, \"url\": \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01\u0026resource=https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID\", \"format\": { \"type\": \"json\", \"subject_token_field_name\": \"access_token\" } } } The auth libraries and applications must follow the steps below: Check credential_source has a url field and no environment_id, otherwise skip the rest of the steps. An HTTP GET request should be sent to this local url while injecting the headers key/values (if provided in the configuration file) in the request header. The request should respond with the external credentials subject token to be passed to STS token endpoint. Before parsing the token, check the format field. If the format is not available, assume the external credential returned by the URL response is provided in plain text format. If available, check if the type is json If json, check the subject_token_field_name. For Azure, this is set to access_token. Parse the file as JSON and then retrieve the external credential from the field name based on the value of subject_token_field_name. Determining the subject token in file-sourced credentials External account configuration JSON files contain the following information in the credential_source object to facilitate retrieval of file-sourced credentials to be passed as subject tokens to the GCP STS token exchange endpoint. Field Name Required Description file Yes This is the source of the credential. This should be used for a credential locally available. This should take precedence over url when both are provided. format.type No This indicates the format of the file where the token is stored. This can be either \"text\" or \"json\". The default should be \"text\". format.subject_token_field_name No Required for JSON file formats. This indicates the JSON field name where the subject_token should be stored. The JSON file for file-sourced configuration files (OIDC / SAML) should have the following form: { \"type\": \"external_account\", \"audience\": \"//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID\", \"subject_token_type\": \"urn:ietf:params:oauth:token-type:saml2\", \"service_account_impersonation_url\": \"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken\", \"token_url\": \"https://sts.googleapis.com/v1/token\", \"credential_source\": { \"file\": \"/var/run/saml/assertion/token\" } } The auth libraries and applications must follow the steps below: Check credential_source has a file field and no environment_id. If not, this is not a file-sourced credential and the proceeding steps do not apply. Get the external credential from the file location specified by the credential_source.file field. Before parsing the token, check the format field. If the format is not available, assume the external credential is provided in plain text format. If available, check if the type is json If json, check the subject_token_field_name. Parse the file as JSON and then retrieve the external credential from the field name based on the value of subject_token_field_name. Determining the subject token in executable-sourced credentials External account configuration JSON files contain the following information in the credential_source object to facilitate retrieval of executable-sourced credentials to be passed as subject tokens to the GCP STS token exchange endpoint. Field Name Required Description executable Yes Holds the information necessary to run the executable. executable.command Yes Specifies the full command to run to retrieve the subject token. This can include arguments. Must be an absolute path for the program. executable.timeout_millis No Specifies the timeout duration, in milliseconds. Defaults to 30 seconds when not provided. executable.output_file No Specifies the absolute path to the output file where the executable will cache the response. By specifying this path, the auth libraries will first check this location before running the executable. The format of the file should match the JSON format expected by the auth libraries defined below. The JSON file for executable-sourced configuration files (OIDC / SAML) should have the following form: { \"type\": \"external_account\", \"audience\": \"//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID\", \"subject_token_type\": \"urn:ietf:params:oauth:token-type:saml2\", \"token_url\": \"https://sts.googleapis.com/v1/token\", \"service_account_impersonation_url\": \"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL@project.iam.gserviceaccount.com:generateAccessToken\", \"credential_source\": { \"executable\": { \"command\": \"/path/to/executable --arg1=value1 --arg2=value2\", \"timeout_millis\": 5000, \"output_file\": \"/path/to/cached/credentials\" } } } To use executable-sourced credentials, the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable must be set to 1. Additionally, the executable must adhere to the following response format: Successful responses: Field Name Type Description version number The version of the JSON output. Currently only version 1 is supported. success boolean The status of the response. True in this case. token_type string The 3rd party subject token type. Must be urn:ietf:params:oauth:token-type:jwt, urn:ietf:params:oauth:token-type:id_token, or urn:ietf:params:oauth:token-type:saml2. id_token OR saml_response string The 3rd party OIDC token or SAML response. expiration_time number The optional 3rd party subject token expiration time in seconds (unix epoch time). Only required in the response when an output file is specified in the credential configuration. A sample successful executable OIDC response: { \"version\": 1, \"success\": true, \"token_type\": \"urn:ietf:params:oauth:token-type:id_token\", \"id_token\": \"...\", \"expiration_time\": 1620499962 } A sample successful executable SAML response: { \"version\": 1, \"success\": true, \"token_type\": \"urn:ietf:params:oauth:token-type:saml2\", \"saml_response\": \"...\", \"expiration_time\": 1620499962 } Error responses: Field Name Type Description version number The version of the JSON output. Currently only version 1 is supported. success boolean The status of the response. False in this case. code string The error code. message string The error message. A sample executable error response: { \"version\": 1, \"success\": false, \"code\": \"401\", \"message\": \"Caller not authorized.\" } The auth libraries and applications must follow the steps below: Check credential_source has an executable field and no environment_id. If not, this is not a executable-sourced credential and the proceeding steps do not apply. Retrieve the external credential\u0027s executable information from the credential_source.executable field. Check that the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable is set to 1. If not, error out. Before the next step, check if credential_source.executable.output_file was specified in the credential configuration. If present, check if there is an executable response at that location. If the response is valid and unexpired, or there is no response at that location, continue execution. If the response is malformed or invalid, error out. Ensure the following environment variables will be available to the executable: GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE: The audience field from the credential configuration. Must always be present. GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE: The subject token type. Must always be present. GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL: The service account email. Only present when service account impersonation is used. GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE: The output file location from the credential configuration. Only present when specified in the credential configuration. Run the command specified at credential_source.executable.command. Fail in the following scenarios: The executable failed to complete in the timeout duration specified. The executable\u0027s response is invalid, was unsuccessful or expired. The executable finished with a non-zero exit code. Parse the executable response as JSON and then retrieve the external credential from the field name based on the value of token_type. The token_type value must be urn:ietf:params:oauth:token-type:jwt, urn:ietf:params:oauth:token-type:id_token, or urn:ietf:params:oauth:token-type:saml2. If the token_type is urn:ietf:params:oauth:token-type:saml2, the subject token will be parsed from the saml_response field. Otherwise it will be parsed from the id_token field. Changelog 2025-10-17: Corrections in specification and examples for External Account Credentials (AIP 4117). 2021-12-10: Add AIP for External Account Credentials (AIP 4117). 2022-05-18: Document executable-sourced credentials (AIP 4117). 2022-08-31: Document configurable token lifetime (AIP 4117). 2023-09-12: Mark region_url as optional (AIP 4117).", + 'tags': '', + 'url': '/auth/4117', + }, +{ + 'title': "Mutual Authentication Using Workload Credentials", + 'text': "Mutual Authentication Using Workload Credentials Mutual TLS (a.k.a mTLS) authentication enables authentication of both client and server identities in a TLS handshake. With workload credentials, applications running in Google Cloud can authenticate to Google APIs using X.509 SPIFFE Verifiable Identity Documents (SVIDs). These SVIDs are X.509 certificates that contain SPIFFE IDs specifying the identity of the certificate owners. mTLS authentication using X.509 SVIDs occurs when the client uses an X.509 SVID when performing the TLS handshake. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance If users enable token binding, they should do so via ADC. This section describes the general guidance of supporting such authentication. Provisioning Workload Credentials in Google Cloud On Google Cloud, workload credentials should be provisioned using one of the following methods: Set up service security with Envoy. Set up service security with proxyless gRPC. In order for workload credentials to be properly used, the auth libraries must support the automatic switching of the service endpoint to its mTLS counterpart. Using Workload Credentials Users should configure ADC to use workload credentials via the certificate configuration gcloud metadata file. Workload credentials can be added as a \"cert_configs\" type as follows: { \"version\": 1 \"cert_configs\": { \"workload\": { \"cert_path\": \"path/to/cert/file\" \"key_path\": \"path/to/key/file\" \"workload_identity_provider\": \"...\" \"authenticate_as_identity_type\": \"gsa/native\" \"service_account_email\": \"...\" }, \"keychain\": { ... }, \"pkcs11\": { ... }, \"windows\": { ... }, }, \"libs\": { ... } } For Linux and macOS platforms, the above metadata file is located in the well-known gcloud config directory at \"~/.config/gcloud/certificate_config.json\". Note that the default location of this file can be changed using the GOOGLE_API_CERTIFICATE_CONFIG environment variable. The following lists the fields of the \"workload\" certificate info type that are relevant to workload credentials: \"cert_path\": The specified value will be used as the full path to locate the workload certificate file. This file must contain a PEM-encoded X.509 certificate chain (ordered from leaf to root) where the leaf certificate is a valid X.509 SVID. The chain may consist of only the leaf certificate. \"key_path\": The specified value will be used as the full path to locate the workload private key file. This file must contain a PEM-formatted private key associated with the X.509 certificate specified by \u201ccert_path\u201d. The description of the \"workload_identity_provider\", \"authenticate_as_identity_type\" and \"service_account_email\" fields can be found in mTLS Token Binding. To enable mutual authentication to Google APIs using workload credentials, the \"workload\" section and its \"cert_path\" and \"key_path\" values must be present in the \"~/.config/gcloud/certificate_config.json\" configuration file. Expected Behavior Support for mTLS authentication to Google APIs using workload credentials must give priority to user mTLS endpoint override via client options. The auth libraries must follow the steps below: Locate the workload certificate and private key files using the above config file. If one of these files is not present, mTLS using workload credentials may be disabled. The auth libraries must check that the public and private keys in the certificate and key files match before passing them to the TLS library. Occasional mismatches may happen, since during certificate rotation the client library may read the two files while another process is replacing them. In that case, the library must retry reading the certificate and private key files and checking their match status, up to a maximum of four attempts. The library should wait for 5 seconds between attempts. If the certificate and private key files are loaded in memory (as opposed to being read from disk for every mTLS connection), the auth libraries must periodically reload them (at least every 10 minutes or when the certificate expires) to refresh their copies in memory after the infrastructure rotates them. Refreshing the credentials must be done in a background thread and not upon usage. Configure the TLS library to use the found, and matched, certificate and key for client authentication during the TLS handshake. If the user specifies the endpoint override via client options, use it as is and connect to the specified endpoint using mTLS. If the user does not specify the endpoint override, use the default mTLS endpoint if the certificate and key files exist and the default regular endpoint otherwise. Note that mTLS 1.3 must be the only supported version to preserve client identity and certificate confidentiality. One implication of the above logic is that if the user enables mTLS authentication using workload credentials, provides valid certificate and key files, and specifies a non-mTLS endpoint override, the client libraries should use the certificate and key anyway and let the server decide what to do. This avoids introducing client-side logic that parses whether the endpoint override is an mTLS URL, since the URL pattern may change at any time. Obtaining the Default mTLS Endpoint The default mTLS endpoint for a service should be read from the Discovery Document field \"mtlsRootUrl\" instead of generated via regex patterns.", + 'tags': '', + 'url': '/auth/4118', + }, +{ + 'title': "mTLS Token Binding", + 'text': "mTLS Token Binding Token binding allows issuing Google access tokens that are bound to mTLS credentials. The advantage of such mTLS bound tokens is that they are meant to only be used over secure channels established via mTLS credentials they are bound to. Therefore, using bound tokens is more secure than bearer tokens which can be stolen and adversarially replayed. This AIP describes the flow of (1) obtaining access tokens bound to X.509 certificate identities, called identity-bound tokens and (2) how to use them to access Google APIs using the Google auth libraries. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments. Guidance If users enable token binding, they should do so via ADC. This section describes the general guidance of supporting such tokens. Prerequisites Identity-bound access tokens require that the clients have X.509 SPIFFE Verifiable Identity Documents (SVIDs). Mutual Authentication Using Workload Credentials describes how such SVIDs are provisioned in Google Cloud. Additionally, identity-bound access tokens tokens require configuring a workload identity pool and identity provider with Google Cloud\u0027s IAM. The instructions on how to do this are out of scope of this AIP. Using mTLS Token Binding The auth libraries must support the following values in the \"~/.config/gcloud/certificate_config.json\" configuration file. Note that the default location of this file can be changed using the GOOGLE_API_CERTIFICATE_CONFIG environment variable. { \"version\": 1 \"cert_configs\": { \"workload\": { \"cert_path\": \"path/to/cert/file\" \"key_path\": \"path/to/key/file\" \"workload_identity_provider\": \"...\" \"authenticate_as_identity_type\": \"gsa/native\" \"service_account_email\": \"...\" }, \"keychain\": { ... }, \"pkcs11\": { ... }, \"windows\": { ... }, }, \"libs\": { ... } } The following lists the fields relevant to mTLS token binding configuration: \"workload_identity_provider\": The specified value will be used to populate the request to Security Token Service (STS) to request identity-bound access tokens. This value refers to the fully qualified name of the workload identity pool and identity provider configured in IAM. The specified value must be of the following format. \"workload_identity_provider\":\"//iam.googleapis.com/projects/\u003cproject_number\u003e/locations/global/workloadIdentityPools/\u003cpool_identifier\u003e/providers/\u003cprovider_identifier\u003e\" \"authenticate_as_identity_type\": This field specifies what identity is used to authenticate to Google APIs. The value can be set to gsa or native, where gsa is the GCP service account of the workload, e.g., the GCP service account of a GCE VM, and native is the native workload identity, e.g., the GKE pod kubernetes service account. If not specified, the default value is gsa. \"service_account_email\": If set, the specified value will be used to populate the request to the IAM Credentials service to request identity-bound access tokens. This value refers to the service account email to be used for resource access. If not set, the service account email will be determined automatically by querying the following Metadata Service endpoint: http://metadata/computeMetadata/v1/instance/service-accounts/default/email. The value of this field is only relevant if \"authenticate_as_identity_type\" is set to gsa. The description of the \"cert_path\" and \"key_path\" fields can be found in Mutual Authentication Using Workload Credentials. To enable using token binding when communicating with Google APIs the following conditions are required: Mutual Authentication Using Workload Credentials must be enabled. The \"workload_identity_provider\" must be present, \"authenticate_as_identity_type\" may be set and \"service_account_email\" may be set in the \"workload\" section of the \"~/.config/gcloud/certificate_config.json\" configuration file. Expected Behavior To support the usage of identity-bound access tokens, the auth libraries must follow the steps below when sending requests to Google APIs: Connect to the mTLS endpoint of the STS API using the workload credentials provisioned as described in Mutual Authentication Using Workload Credentials. This endpoint must be sts.mtls.googleapis.com. Send an HTTP request to STS\u2019s ExchangeToken method requesting an identity-bound token using the information in the \"workload_identity_provider\" field in the \"~/.config/gcloud/certificate_config.json\" configuration file. The scope of the requested token must be https://www.googleapis.com/auth/iam. Connect to the mTLS endpoint of the IAM Credentials Service API using the workload credentials provisioned as described in Mutual Authentication Using Workload Credentials. This endpoint must be iamcredentials.mtls.googleapis.com. If \"authenticate_as_identity_type\" is set to gsa, send an HTTP request to the IAM Credentials Service\u2019s GenerateAccessToken method requesting an identity bound token asserting the service account email in the \"service_account_email\" field in the \"~/.config/gcloud/certificate_config.json\" configuration file. The scope of this token must be the same scope defined by the user for accessing the requested Google API. Attach the returned token in Step 4 to the request. Note that this request must be sent over an mTLS channel using the same workload credentials in Step 1.", + 'tags': '', + 'url': '/auth/4119', + }, +{ + 'title': "Client library generators", + 'text': "Client library generators API guidelines exist in order to promote simple, intuitive, and consistent APIs. Users familiar with APIs that generally adhere to AIP guidance are able to take what they learn in prior APIs and apply it to new ones. Client libraries provide a mechanism for users to get started with APIs more quickly, by simplifying common concerns (such as auth) and by a language-native way to call API endpoints and receive language-native responses. However, for these libraries to provide the most value, they also must be simple, intuitive, and consistent. Code generators provide a means for producing consistent client libraries at scale. Code generators following the standards in these AIPs are known as \"generated API client generators\", or GAPIC generators for short. The resulting libraries are colloquially called GAPICs. Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments (for example, the use of the term class even though languages such as Go do not have classes). This AIP\u0027s particular use of vocabulary is best understood as an explanation of principles, and precise adherence to exact vocabulary in this AIP is not an expectation. Guidance The general flow of code generation for client libraries and supporting code in most supported languages is outlined below. Note: Exceptions to this pattern are typically due to use of a unique stack e.g. Node.js use of protobuf.js and grpc-node which don\u0027t have code generation, or Python using a protobuf wrapper in proto-plus-python, but the general GAPIC flow remains the same. digraph { node [ style=\"filled,solid\" shape=box fontname=\"Roboto\" ]; splines=ortho; nodesep=0.3; center=true; proto [ label=\"API Protobuf\\nDescriptors\" shape=rectangle fillcolor=aliceblue ]; subgraph cluster_code_generators { rank = same; style = filled; fillcolor = lightgrey; node [ shape=oval ]; protobuf [ label=\"protobuf\\ngenerator\" fillcolor=deepskyblue3 ]; grpc [ label=\"gRPC\\ngenerator\" fillcolor=gold3 ]; gapic [ label=\"GAPIC\\ngenerator\" fillcolor=darkseagreen ]; } proto -\u003e protobuf; proto -\u003e grpc; proto -\u003e gapic; subgraph cluster_generated_code { rank = same; style = filled; fillcolor = lightgrey; node [ shape=rectangle ]; protobuf_output [ label=\"Message \u0026 Enum\\nCode\" fillcolor=deepskyblue3 ]; grpc_output [ label=\"Server \u0026 Client\\nStubs\" fillcolor=gold3 ]; gapic_output [ label=\"Google API\\nClient\" fillcolor=darkseagreen ]; } protobuf -\u003e protobuf_output; grpc -\u003e grpc_output; gapic -\u003e gapic_output; assembly [ label=\"Package\\nassembly\" shape=oval fillcolor=aliceblue ]; protobuf_output -\u003e assembly grpc_output -\u003e assembly gapic_output -\u003e assembly assembled_package [ label=\"Package of\\ngenerated code\" fillcolor=aliceblue ]; assembly -\u003e assembled_package } The following sections focus on the \"GAPIC generator\" in the above diagram. Protobuf plugins The protobuf compiler, protoc, supports a plugin system for code generation. The plugin system allows plugins to be written in and for any language. Code generators must be implemented as protoc plugins. The following rules apply to the implementation of a client library generator as a protoc plugin: The plugin should be written in the language being targeted for generation. protoc expects plugins to be an executable in $PATH, and named protoc-gen-{plugin_name}, corresponding to the --{plugin_name}_out option sent to the protoc executable. As such: the plugin executable should be named protoc-gen-{lang}_gapic the plugin option should follow the convention --{lang}_gapic_out The plugin must not leverage protoc \"insertion points\". Despite the protoc plugin documentation indicating the existence of insertion points, their use is unsupported and discouraged by the Protobuf team. CLI options Code generators should be able to run without any options or flags if at all possible, and be able to generate a valid library from only the protos. If options are required, protoc allows them to be passed as --{plugin_name}_opt, and the string provided here becomes set as the parameter string on the CodeGeneratorRequest. Important: The CodeGeneratorRequest.parameter value is a comma-delimited string of all associated plugin option values that appear at execution time. This means that commas cannot be used to delimit list-like plugin option values. Code generators must not rely on environment variables for configuration. Expected behavior This section outlines the expected behavioral attributes of the output of the client library generator (in other words: the libraries that the generators write). Client libraries must implement these concepts in order to be considered complete. Messages and Enums Client library generators should not generate code for message or enum descriptors which are already generated by the Protobuf-provided code generators. Services and methods Each of the service and rpc directives in the requested protos must be represented in the client library output, unless the language or transport is unable to support it. Note: While how to accomplish this may vary from language to language, in most classical languages it is probably a class for each service, containing methods for each RPC. The classes generated for each service directive must honor the google.api.default_host annotation if it is provided, and use that host as the default hostname. These classes should provide a mechanism for the end user to override the hostname. If the google.api.default_host annotation is not present on the service directive, then the generated class should require a hostname when it is instantiated. Additionally, if the classes generated for each service support using OAuth and service credentials, they must honor the google.api.oauth_scopes annotation (if it is provided), and use these scopes by default. Services that have set the deprecated protobuf option to true should have an equivalent deprecation tag generated in the generated class. If applicable, this tag may include a comment that specifies when the service will be removed, which is typically the next major version update. Similarly, RPCs with this option set to true should have their generated language method(s) marked as deprecated. Finally, service classes must also accept credentials, which are used appropriately when requests are made. (Accepting a custom gRPC channel satisfies this requirement.) Code generators must not generate client stub classes, that would normally be generated by gRPC, in addition to client library classes. Long-running operations An RPC is considered to be a \"long-running\" RPC if (and only if) the RPC\u0027s return type is google.longrunning.Operation. Any API which has one or more RPCs returning an Operation is expected to implement the Operations service. Because the response and metadata fields in Operation are of the type google.protobuf.Any, it is necessary to know what message to use to deserialize them. This is annotated on the RPC using the google.longrunning.operation_info annotation. Note: The values in this struct are strings, not message objects; the code generator uses the string to determine the appropriate message to use. Strings with no period (.) character refer to a message in the same proto package. Code generators should fail with an error if a type is provided in the operation_info annotation which was not imported, or if no response type or metadata type is provided. Code generators should fail with an error if either the response_type or metadata_type keys are omitted. Client libraries must honor the LRO interface; if an RPC has an Operation as its return type, the generated method must intercept it and return an appropriate idiomatic object for resolving the LRO (such as a Future or Promise bound to the underlying Operation object). Streaming Client libraries must implement streaming to the extent that their supporting transports allow. An RPC is considered to be streaming if the stream keyword is present on the argument or response type. This is present in the MethodDescriptorProto message using the client_streaming and server_streaming keys. Changelog 2023-06-22: Added code gen diagram, message/enum guidance, and cleaned up plugin \u0026 option guidance.", + 'tags': '', + 'url': '/client-libraries/4210', + }, +{ + 'title': "Client-side retry", + 'text': "Client-side retry Many APIs have error modes that a client should retry. These error modes vary across APIs, leaving users to hand-write retry logic around client libraries based on available documentation. Client libraries have the opportunity to help by implementing automatic client-side retries of well-known error modes. Guidance Client libraries should provide automatic, client-side retry logic. Client libraries with automatic client-side retry logic should provide a mechanism for users to specify error codes to be retried and delays for those retries. Client libraries for API systems that support remotely-resolved client retry configuration should respect the remotely-resolved configuration. However, user configuration must be honored. Client library generators implementing this feature must accept a retry configuration. This retry configuration may be supplied via a protoc plugin option. In the absence of a given retry configuration, client library generators should not generate a default retry configuration. Retry implementation Client libraries should make client-side retry transparent to the user. The user should not have to opt-in to client-side retry explicitly, but the user must have a way to disable client-side retry altogether. Retry configuration mechanisms Client libraries should surface a mechanism through which users may control the client-side retry configuration, including disabling client-side retry altogether. For example, Go client libraries for gRPC services can supply an option, WithDisableRetry, at client initialization to disable the use of the automatic client-side retry logic. opts := []grpc.DialOption{ grpc.WithDisableRetry(), grpc.WithTransportCredentials(creds), } cc, err := grpc.Dial(\"my.api.net:443\", opts...) if err != nil { // ... } Remotely-resolved client configuration Some API systems have built-in mechanisms for clients to retrieve a remotely-defined configuration that includes client-side retry configuration. For example, gRPC supports the resolution of client configuration that includes configuration for automatic client-side retry. Client libraries should respect the remotely-resolved configuration, except when a user overrides it via the aforementioned client library retry configuration mechanisms. Client library generator retry configuration Client library generators that implement client-side retry must accept a retry configuration. This is to enable API producers to supply a retry configuration that best-suits their service. For example, gRPC client-side retry is configured with a RetryPolicy within a gRPC Service Config. Here is a configuration that applies the RetryPolicy to all methods in the google.example.library.v1.LibraryService service, except for those that are explicitly named which get no RetryPolicy. { \"methodConfig\": [{ \"name\": [{ \"service\": \"google.example.library.v1.LibraryService\" }], \"waitForReady\": true, \"timeout\": \"60s\", \"retryPolicy\": { \"maxAttempts\": 3, \"initialBackoff\": \"1s\", \"maxBackoff\": \"10s\", \"backoffMultiplier\": 2, \"retryableStatusCodes\": [\"UNAVAILABLE\"] } }, { \"name\": [ { \"service\": \"google.example.library.v1.LibraryService\", \"method\": \"CreatePublisher\" }, { \"service\": \"google.example.library.v1.LibraryService\", \"method\": \"DeletePublisher\" }, { \"service\": \"google.example.library.v1.LibraryService\", \"method\": \"CreateBook\" }, { \"service\": \"google.example.library.v1.LibraryService\", \"method\": \"DeleteBook\" }, { \"service\": \"google.example.library.v1.LibraryService\", \"method\": \"UpdateBook\" }, { \"service\": \"google.example.library.v1.LibraryService\", \"method\": \"MoveBook\" } ], \"waitForReady\": true, \"timeout\": \"10s\" }] } The retry configuration may be a protoc plugin option. For example, a generator could accept the file path of the configuration with an option like: --{plugin_name}_opt=\"retry-config=/path/to/config.file\" In the absence of a retry configuration, a generator should not generate a \"default\" retry configuration. This results in a generated client library that does not retry anything unless configured to do so by the user. Further reading For which error codes to retry, see AIP-194. Changelog 2020-09-23: Changed the examples from \"shelves\" to \"publishers\", to present a better example of resource ownership.", + 'tags': '', + 'url': '/client-libraries/4221', + }, +{ + 'title': "Routing headers", + 'text': "Routing headers In some situations, a gRPC API backend is able to route traffic more efficiently if it knows about some values in the request; however, the request payload can not be reasonably deconstructed on the wire to perform that routing. Guidance Code generators must use the annotations to generate client libraries that, on a per-RPC basis, extract routing information from the request payload and add that information to the routing header. There are two annotations that specify how to extract routing information from the request payload: the google.api.routing annotation that specifies how to construct routing headers explicitly the google.api.http annotation that may specify how to construct routing headers implicitly. For any given RPC, if the explicit routing headers annotation is present, the code generators must use it and ignore any routing headers that might be implicitly specified in the google.api.http annotation. If the explicit routing headers annotation is absent, the code generators must parse the google.api.http annotation to see if it specifies routing headers implicitly, and use that specification. Explicit Routing Headers (google.api.routing) For an unary or server-streaming RPC the code generator must look at the routing parameters specified in the google.api.routing annotation, if present. Any given routing parameter specifies a field name and a pattern with exactly one named resource ID path segment. For example: rpc CreateTopic(CreateTopicRequest) { option (google.api.routing) = { routing_parameters { field: \"parent\" path_template: \"{project=projects/*}/**\" } } } The value of the field field must be one of the following: a name of a field in the top-level of the request message a dot-separated path of field names leading to a field in a sub-message of the request message e.g. \"book.author.name\" where book is a message field in the request message, author is a message field in the book message, and name is a string field in the author message The actual field specified in the field field must have the following characteristics: - it is type string - it either has a path-like value format resembling a resource name or contains an unstructured value that would be appropriate as an individual path segment e.g. a project_id. Note: An empty google.api.routing annotation is acceptable. It means that no routing headers should be generated for the RPC, when they otherwise would be e.g. implicitly from the google.api.http annotation. Note: It is acceptable to omit the pattern in the resource ID segment, {parent} for example, is equivalent to {parent=*} and must be parsed, e.g.: routing_parameters { field: \"parent\" path_template: \"projects/{parent}\" } is the same as routing_parameters { field: \"parent\" path_template: \"projects/{parent=*}\" } Note: It is acceptable to omit the path_template field altogether. An omitted path_template is equivalent to a path_template with the same resource ID name as the field and the pattern **, and must be parsed, e.g.: routing_parameters { field: \"parent\" } is the same as routing_parameters { field: \"parent\" path_template: \"{parent=**}\" } Note: An omitted path_template field does not indicate that key-value pairs with empty values can be sent. It\u0027s merely a shorthand. When the user supplies an instance of CreateTopicRequest to the method, the client library must match all the routing parameters in the order specified to the fields of that instance. For each routing parameter, the pattern in the path_template must be matched to the input message field specified by the routing parameter\u0027s field field. In case of a match, the name of the resource ID path segment must be used as a key, and the value of the resource ID path segment match must be used as a value of a key-value pair to be appended to the x-goog-request-params header. Both the key and the value must be URL-encoded per RFC 6570 \u00a73.2.2. This can be done with standard library URL encoding. For example, adding this header to a gRPC request in Ruby: header_params = {} if (pattern_matches(\"{project=projects/*}/**\", request.parent)) header_params[\"project\"] = extract_match_value(\"{project=projects/*}/**\", request.parent) end request_params_header = URI.encode_www_form header_params metadata[:\"x-goog-request-params\"] = request_params_header In cases when multiple routing parameters have the same resource ID path segment name, thus referencing the same header key, the \"last one wins\" rule is used to determine which value to send. The \"last\" here is meant in terms of the order in which they\u0027re specified in the annotation. If some of the routing parameters with the same resource ID segment name have failed to match the field, or if the field was unset, or if the extracted matched value is an empty string, these parameters are not considered when determining which value to send. Example: option (google.api.routing) = { routing_parameters { field: \"parent\" path_template: \"{project=projects/*}/**\" } routing_parameters { field: \"parent\" path_template: \"{project=projects/*/subprojects/*}/**\" } routing_parameters { field: \"billing_project\" path_template: \"{project=**}\" } } In this case if in a given request the billing_project field is set to an non-empty value, its value will be sent with the project key because the routing parameter looking at billing_project field is specified last. If the billing_project field is not set, the parent field will be considered, first trying to send a project with a subproject specified, and then without. Note that if a given request has a parent field with a value e.g. projects/100/subprojects/200/foo, patterns in both first and second routing_parameters will match it, but the second one will \"win\" since it is specified \"last\". If all the routing parameters with the same resource ID segment name have failed to match the field, the key-value pair corresponding to those routing parameters\u0027 resource ID path segment name must not be sent. If none of the routing parameters matched their respective fields, the routing header must not be sent. Much like URL parameters, if there is more than one key-value pair to be sent, the \u0026 character is used as the separator. path_template syntax As seen in the above examples, the path_template can use a variety of symbols that are interpreted by code generators during conversion to regular expressions or non-regular expression matcher implementations. The path_template consists of segments delimited by the segment delimiter. The syntax for path_template is as follows: The only acceptable segment delimiter is /. The last symbol in a path_template may be a delimiter - it will be ignored. A segment must be of one of the following types: *: A single-segment wildcard. Corresponds to 1 or more non-/ symbols. The regex describing it is [^/]+. A Single-segment wildcard typically represents a resource ID. **: A multi-segment wildcard. Corresponds to 0 or more segments. A multi-segment wildcard must only appear as the final segment or make up the entire path_template. In a multi-segment path_template, a multi-segment wildcard must appear immediately following a segment delimiter. This delimiter is consumed while matching so a path_template like foo/** matches all of the following: foo, foo/, foo/bar/baz. In a multi-segment path_template, when used as the last segment the regex describing it is ([:/].*)?. When used as the entire path_template, the regex describing it is .*. Segment delimiters are consumed while matching, including any preceding delimiter. LITERAL: A literal segment. A literal segment can contain any alphanumeric symbol. A literal segment must not contain a symbol reserved in this syntax. Literal segments typically represent a resource collection ID or base path. {}: A variable segment. This matches part of the path as specified by its template. A variable segment can be either of the following: {key}, where key is the name to be used in the key-value pair of the header {key=template}, where the template is the segment(s) (expressed in this path_template syntax) to extract as the value paired with key A variable segment of just {key} defaults to a template of * which matches 1 or more non-/ symbols. While {key=*} is technically valid syntax, the simpler syntax of {key} should be used. A variable segment must not contain other variable segments. This syntax is not recursive. A segment must not represent a complex resource ID as described in AIP-4231. A Generator should emit an error in this case. Implicit Routing Headers (google.api.http) Note: For an RPC annotated with the google.api.routing annotation, the google.api.http annotation must be ignored for the purpose of adding routing headers. If an unary or server-streaming RPC is not annotated with the google.api.routing annotation, code generators must look at URI-based variables declared in the google.api.http annotation and transcribe these into the x-goog-request-params header in unary calls. A URI-based variable is a variable declared as a key in curly braces in the URI string. For example: rpc CreateTopic(CreateTopicRequest) { option (google.api.http).post = \"{parent=projects/*}/topics\"; } Note: It is acceptable to omit the pattern in the resource ID segment, {parent} for example, is equivalent to {parent=*} and must be parsed. In this case, the applicable variable is parent, and it refers to the parent field in CreateTopicRequest. When the user provides an instance of CreateTopicRequest to the method (or once the client library has built it, in the case of method overloads), the client library must extract the key and value, and append them to the x-goog-request-params header. Both the key and the value must be URL-encoded per RFC 6570 \u00a73.2.2. This can be done with standard library URL encoding. For example, adding this header to a gRPC request in Go: md := metadata.Pairs(\"x-goog-request-params\", url.QueryEscape(\"parent\") + \"=\" + url.QueryEscape(req.GetParent())) At runtime, if a field with the same name as the named parameter is unset on the request message, the key-value pair corresponding to that parameter must not be included in the routing header. If none of the parameters must be included in the routing header, the routing header must not be sent. If the google.api.http annotation contains additional_bindings, these patterns must be parsed for additional request parameters. Fields not duplicated in the top-level (or additional_bindings) pattern must be included in request parameters, encoded in the same way. Much like URL parameters, if there is more than one key-value pair, the \u0026 character is used as the separator. Changelog 2023-07-07: Include path_template syntax. 2022-07-13: Updated to include the new google.api.routing annotation. 2020-04-21: Explicitly parse path variables missing a trailing segment. 2019-11-27: Include additional_bindings as a request parameter source. 2019-06-26: Fix wording and example of key-value pair encoding. 2019-06-20: Specify encoding of header parameters.", + 'tags': '', + 'url': '/client-libraries/4222', + }, +{ + 'title': "Client-side payload validation", + 'text': "Client-side payload validation Client-side payload validation is the practice of inspecting the request payload for any misconfigurations (e.g. missing required fields, attempting to update an immutable field) prior to executing a network call with the payload. Typically, documentation communicates the expectations of the service with regards to each request field, including any requirements on presence or format. The google.api.field_behavior annotation defined in AIP-203 is the machine-readable format that services use to document behavior in relation to specific request fields. Guidance Client libraries must not implement client-side payload validation based on the google.api.field_behavior annotation, except to prevent local failures. The reason for this is that the google.api.field_behavior annotation is primarily a machine-readable form of documentation, and not a configuration for payload validation. The annotation conveys how the service already handles the field, and alludes to a service\u0027s own payload validation or expectations. Admittedly, depending on services to implement payload validation means clients will sometimes make network calls that are bound to result in errors. Furthermore, users then depend on services to provide actionable errors, when the client could have provided a language-idiomatic, localized error. However, robust server-side payload validation means that all types of client (first party, third party, curl, etc.) will benefit from the same validation, and that there is no lag between service and clients when the field behavior changes. Local failures Client libraries may implement client-side payload validation based on the google.api.field_behavior annotation only to the extent that it prevents local failures, such as crashes within the client library code itself.", + 'tags': '', + 'url': '/client-libraries/4223', + }, +{ + 'title': "Parsing resource names", + 'text': "Parsing resource names In resource-oriented design (AIP-121), resources represent the primary nouns within APIs, and often have resource names (AIP-122). These resource names convey information about the structure and hierarchy of the resource structure in that API. APIs accept these resource names as parameters when retrieving and modifying resources, and when referencing them in other objects. However, users may struggle to piece together resource names to send, and client libraries have the opportunity to make this easier through the use of helper components. Guidance Client libraries may provide helper classes or functions to make constructing resource names more straightforward. However, client libraries that choose to implement this feature must always accept the plain strings also, for two reasons: An existing API that adds resource descriptor annotations should be able to do so without incurring a breaking change. Resource name patterns occasionally evolve, and users need to be able to send and receive resource names that a statically-compiled client library may not yet acknowledge. Resource messages A resource in an API always has a message that describes the representation of that resource in that API. Client library generators are able to recognize these messages when they are annotated with the google.api.resource annotation: // A representation of a Topic in Pub/Sub. message Topic { option (google.api.resource) = { type: \"pubsub.googleapis.com/Topic\" pattern: \"projects/{project}/topics/{topic}\" }; // name and so on... } The type field provides the unified resource type name. Client libraries should name their helper component based on this value. The universal resource type usually (but not always) ends with a name that matches the name of the message. The pattern field provides the structure of this resource type\u0027s names. The components in braces represent variable substitutions. Client libraries implementing this feature must accept variables based on these names when building resource name strings. Variable substitution names are usually specified in snake_case, but this is not guaranteed. Client libraries should be able to accept any annotation that uses any coherent case system. Patterns are usually slash-separated, but this is not guaranteed. Client libraries should use string interpolation to piece together the resource name. The defining message is expected to contain a field called name, which is the field holding the resource name. APIs are able to override the name field\u0027s name by setting the name_field property on the google.api.resource annotation. Code generators should fail with an error if a message is annotated as a resource and has no name field (either the default of name or the field provided in the name_field property of the annotation). Code generators should also fail with an error if the field is not a string). Multi-pattern resources Occasionally, a resource may have more than one pattern. The common case for this is when a resource can live under more than one parent type. In this situation, the pattern field on the annotation can be specified more than once: message LogEntry { option (google.api.resource) = { type: \"logging.googleapis.com/Log\" pattern: \"projects/{project}/logs/{log}\" pattern: \"organizations/{organization}/logs/{log}\" pattern: \"folders/{folder}/logs/{log}\" pattern: \"billingAccounts/{billing_account}/logs/{log}\" }; // name and so on... } If necessary, client libraries may create a separate helper component for each pattern, and may provide a rollup component. Resources without messages Occasionally, a resource may be implicitly defined by an API service, but not have an explicit message representing that resource. (For example, the Firestore API defines databases as a common ancestor to its resources, but does not define a database message.) In this situation, APIs annotate the resource on the file instead of on a message, using the google.api.resource_definition annotation: option (google.api.resource_definition) = { type: \"firestore.googleapis.com/Database\" pattern: \"projects/{project}/databases/{database}\" }; Client library generators implementing this feature must generate the same utility components that would be generated when encountering a resource message. Referencing other resources APIs often use resource names for referencing fields defined elsewhere. This is particularly common with the request messages for the standard methods, such as Get and Update; however, resources and other structures use resource name strings as references also. Client libraries implementing this feature should also provide their helper components when resources are being referenced. Client libraries are able to recognize these fields when they are annotated with the google.api.resource_reference annotation: message GetTopicRequest { // The name of the topic to retrieve. string name = 1 [(google.api.resource_reference) = { type: \"pubsub.googleapis.com/Topic\" }]; } The resource reference references the unified resource type name. Some methods also refer to the parent of a type, and in situations where there are multiple parents, it is repetitive and error-prone to refer to each individual parent type. In these situations, API producers specify child_type rather than type: message ListLogEntriesRequest { // The collection of log entries to list. string parent = 1 [(google.api.resource_reference) = { child_type: \"logging.googleapis.com/Log\" }]; } In this situation, client library generators implementing this feature must derive the set of parent resources from the child type. Client library generators must fail with an error if both type and child_type are provided. Referencing an arbitrary resource Occasionally, a field may reference an arbitrary resource. In this case, APIs use the special value * in their resource reference. message GetIamPolicyRequest { string resource = 1 [(google.api.resource_reference) = { type: \"*\" }]; } In this situation, client library generators implementing this feature may provide a generic utility class or function to address that resource name. Complex resource ID path segments Warning: Complex resource ID path segments should not generally be used in new APIs. AIP-124 contains advice on handling many-to-many associations. Resource patterns may contain resource ID path segments which contain multiple pattern variables separated by a variable separator: message FeedItemTarget { option (google.api.resource) = { type: \"googleads.googleapis.com/FeedItemTarget\" pattern: \"customers/{customer}/feedItemTargets/{feed}~{feed_item}\" }; // name and other fields... } This is only used when the resource ID is naturally in multiple parts and it is useful for the user to be able to manipulate the separate ID parts. A variable separator is one character long, and must only one of: _, -, ., ~ (underscore, hyphen, period, tilde). A variable separator must not appear before the first pattern variable or after the last pattern variable. Backwards compatibility Client libraries implementing helper components for resources must conform to the following backwards-compatibility expectations: The addition of a google.api.resource annotation on an existing message must be a backwards-compatible change. An existing resource must be able to add new patterns (including the \"*\" wildcard pattern) without breaking changes as long as the following conditions are met: New patterns must always be appended to the list. New patterns must use a distinct sequence of collection identifiers (see AIP-122) compared with all existing patterns within this resource. The identifiers within the pattern variables are final - they must not be changed. These identifiers are used in the surface of generated client libraries. The addition of a google.api.resource_reference annotation on an existing field must be a backwards-compatible change. Changing a google.api.resource_reference from child_type to type must be a backwards-compatible change when the child_type referenced has a single pattern and the newly referenced type is the matching parent resource pattern (see the Referencing other resources section for more info). For references that appear in a request, changing from type to child_type must be a backwards-compatible change when the resource pattern originally referenced via the type is included in the set of possible resource patterns derived through child_type resolution (see the above Multi-pattern resources and Referencing other resources sections for more examples). Note: The ORIGINALLY_SINGLE_PATTERN and FUTURE_MULTI_PATTERN flags are deprecated, and must not be used. Further reading For more on resource names and patterns, see AIP-122. For more on unified resource types, see AIP-123. Changelog 2023-03-25: Include compatibility guidance for type and child_type. 2022-10-28: Pattern variables are considered final 2020-09-14: Disallow simultaneous use of both type and child_type. 2020-05-14: Added complex resource ID path segments. 2020-05-07: Updated backwards compatibility guidance. 2019-09-16: Added guidance for resources without messages.", + 'tags': '', + 'url': '/client-libraries/4231', + }, +{ + 'title': "Method signatures", + 'text': "Method signatures In protocol buffer RPCs, each RPC takes exactly one argument: a message. However, sending a full message structure can be cumbersome in the case of extremely simple requests. Many RPCs provide information about which pieces of the request are important and commonly used. In many languages, functions and methods take multiple positional or keyword arguments. Guidance Some APIs provide annotations to hint how to effectively translate from a single request object to individual arguments, and client libraries may provide overloads based on these hints. However, client libraries implementing this feature must retain the default behavior of accepting the full request object. Put another way, if an API adds this annotation to an already-published API, the resulting library change must be backwards-compatible. Client library generators may also choose to provide this functionality in some cases but not others, as appropriate in the environment. For example, any of the following strategies would be permissible: Providing overloads iff all arguments in the signature are primitives. Providing overloads only for the first of multiple signatures when providing more than one would produce a conflict. Any combination of the above. In all of these situations, the requirement that the request object is always accepted still applies. Furthermore, client library generators may choose to support this functionality for a subset of RPC types, those being: Unary Server Streaming Client Streaming Bi-directional Streaming Method Signatures An RPC with the google.api.method_signature annotation indicates that an overload with a flattened method signature is desired where supported. The string contains comma-separated arguments, in order. If a field\u0027s name contains a period (.) character, this indicates a nested field. An RPC can provide this annotation more than once to specify multiple signatures. Order matters here: In some situations, it may not be possible to generate an overload for every signature provided. In this situation, client library generators must follow a \"first match wins\" strategy (generate an overload for the first signature in the conflict set, and drop the rest). Note: A corollary to this is that it is only guaranteed to be a backwards-compatible change to append method signature annotations. Required Arguments Often, certain fields on the request message are consistently required, as described in AIP-203. While client libraries generally should not perform validation on this (that is the server\u0027s role), client libraries may distinguish required arguments in method signatures from optional ones if appropriate for the language. A field is considered required for this purpose if annotated with the google.api.field_behavior annotation value of REQUIRED: message TranslateTextRequest { // The text to translate. string q = 1 [(google.api.field_behavior) = REQUIRED]; } Note: The annotation for field behavior is attached to the field, not the method. Restrictions If an RPC lists a nested field in google.api.method_signature (for example, \"foo.bar.baz\"), none of the individual component fields may be repeated except for the last one (continuing the example, baz could be repeated but foo or bar could not be). Code generators implementing this feature must error with a descriptive error message if encountering a non-terminal repeated field as a field name. If any fields are required arguments, all required arguments are expected to appear before any optional ones. Code generators implementing this feature should error with a descriptive error message if encountering a required field after an optional one, and must do so if the resulting client library would not be valid. Compatibility Removing, reordering or altering an existing google.api.method_signature entry is a breaking change for client libraries. The associated generated method is either removed entirely or its signature is altered, both of which break user code. Changelog 2020-07-14: Added caveat for supporting some RPC types 2019-09-27: Added a Compatibility section.", + 'tags': '', + 'url': '/client-libraries/4232', + }, +{ + 'title': "Automatic pagination", + 'text': "Automatic pagination Many API responses, particularly to list and search methods, are paginated (AIP-158). Users calling these methods are then required to implement their own pagination logic, which is common boilerplate. Guidance Client libraries may provide automatic resolution of pagination (meaning that it performs requests in the background on an as-needed basis). Pagination can be inferred for an RPC when all of the following conditions are met: The request message contains an int32 page_size field. For APIs that predate AIP-158, a field named max_results and/or typed as google.protobuf.UInt32Value or google.protobuf.Int32Value are permissible alternatives. The request message contains a string page_token field. The response message contains a string next_page_token field. The response message contains one non-primitive repeated field. Client library generators implementing this feature must ensure that it is a backwards-compatible change to add client-side pagination functionality where it was previously absent. Implementing pagination For the client library to implement pagination (as defined by AIP-158), it should use the next_page_token value from the response message to populate the page_token value of an otherwise-identical request message, continuing indefinitely until the next_page_token value is empty. Important: Client libraries that are implementing automatic resolution of pagination should only perform requests for future pages on an as-needed basis, and avoid greedily resolving potentially long and unnecessary result sets. Client libraries that are implementing automatic pagination must still provide access to the individual fields on the response message, in the usual fashion. Note: If the response message has more than one non-primitive repeated field, the first one (in order of appearance in the file and field number) is used. If the first field by order of appearance in the message and the first field by field number do not match, code generators that implement automatic pagination should fail with an error.", + 'tags': '', + 'url': '/client-libraries/4233', + }, +{ + 'title': "Common service client mixins", + 'text': "Common service client mixins Often, APIs can have common features for administering resources that are separated into utility services. These common, utility services are shared among the discrete product services. These common services each have a centrally-defined surface, but individual instances are hosted alongside each product service. Thus, the surfaces of each common service hosted by the product service are \"mixed in\" at runtime. Guidance Client libraries may provide client methods for the common services that its API declares to be mixed-in. Such methods improve the user experience by presenting the mixin methods from a client configured to communicate with the product service that hosts the mixin service. If client libraries support mixin services, they must support the following common services (and may support others): google.cloud.location.Locations google.iam.v1.IAMPolicy google.longrunning.Operations Note: The list of supported mixin services and the mixin services themselves both change infrequently. Any new common service to be supported must be added to the list here and generators must be updated. To be generated into a client library, a mixin service must be declared under apis in a google.api.Service. Furthermore, only the RPCs with google.api.http bindings declared in the http configuration of the same google.api.Service can be generated (more details on these bindings in AIP-127). If a mixin service RPC does not have a google.api.http rule declared in the google.api.Service, it must not be generated. Implementing mixin support Generator configuration Client library generators must accept the file path of a google.api.Service in YAML form. This file is specified via a flag that must be optional. In other words, the flag must not be required for basic client generation that omits the mixin methods. Mixin API client configuration If a mixin API utilizes client library configuration (i.e. annotations, default retry settings, etc.) such as google.api.method_signature or request header injection, generators may support it in the generated mixin methods if the configuration is accessible. Where client library configuration calls for a fully-qualified name, the mixin\u0027s fully-qualified name must be used. That is to say, the host service must not refer to a mixin element as if it was in its own package. For example, configuring google.iam.v1.IAMPolicy.GetIAMPolicy with default retry and timeout settings would be as follows: { \"name\": [{ \"service\": \"google.iam.v1.IAMPolicy\", \"method\": \"GetIAMPolicy\" }], \"timeout\": \"60s\", \"retryPolicy\": { \"initialBackoff\": \"0.1s\", \"maxBackoff\": \"5s\", \"backoffMultiplier\": 1.3, \"retryableStatusCodes\": [\"UNKNOWN\"] } } Generating mixin methods The mixin API RPCs should be generated as methods on the surface of the host API\u0027s service client library, alongside the host service\u0027s RPCs. This presents them as top-level methods on the client, but under-the-hood, the appropriate mixin API stub or request should be invoked. However, generators may choose to present the mixin API RPCs in a different manner if it is more language idiomatic. Note: For gRPC clients, the mixin API gRPC stub must be used in order to properly construct the gRPC request. For example, the generated, Go gRPC stub LocationsClient must be used to invoke RPCs for the google.cloud.location.Locations mixin, as opposed to that of the host service\u0027s gRPC stub. Multiple host service clients If there are multiple services defined by the host API that would result in multiple clients being generated, generators must include the mixin methods on all eligible, generated service clients. Overriding a duplicate RPC Client library generators must not generate a mixin method on any host service client if a host service already defines an RPC with the same name. For example, take the following service definition: service LibraryService { rpc ListBooks(ListBooksRequest) returns (ListBooksResponse); // Other host API RPCs... // Redefinitions of the google.iam.v1.IAMPolicy mixin service. rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest) returns (google.iam.v1.Policy); rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest) returns (google.iam.v1.Policy); rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest) returns (google.iam.v1.TestIamPermissionsResponse); } Should the host API declare the google.iam.v1.IAMPolicy as a mixin service, client library generators must not generate the resulting mixin methods that match the names explicitly declared above for any service client in the host proto package, but they must generate the other methods for this mixin. In this case, the generator may log a warning indicating that a collision was avoided, or silently skip the mixin methods in question.", + 'tags': '', + 'url': '/client-libraries/4234', + }, +{ + 'title': "Automatically populate fields in the request message", + 'text': "Automatically populate fields in the request message For APIs that leverage request idempotency as described via AIP-155, APIs may choose to have the client libraries automatically populate fields such as request_id if they are not already set by the customer. Note: This feature is primarily written for request_id fields within the request message. Nonetheless, this feature must work for a field of any name, as long as the conditions below hold true. Guidance APIs may configure fields in the request message for automatic population. For a field to be automatically populated, all the conditions below must be true: The field must be of type string The field must be at the top-level of the request message The RPC must be a unary RPC (i.e. streaming RPCs are not supported) The field must not be annotated with google.api.field_behavior = REQUIRED. The field must be annotated with google.api.field_info.format = UUID4. The field name must be listed in the google.api.MethodSettings.auto_populated_fields entry in google.api.Publishing.method_settings for the target method. Expected Generator and Client Library Behavior If the aforementioned requirements are met for a given field, client library generators must enable automatic population of said field in the generated client. The field must be automatically populated if and only if one of the following conditions holds: The field supports explicit presence, and has not been set by the user The field doesn\u0027t support explicit presence, and its value is the empty string (i.e. the default value) If a field is specified in the auto_populated_fields, but does not meet the structural requirements, the client library generators must not enable automatic population for that field. Client library generators may emit an error during generation. Client libraries must reuse automatically populated values for retries of the same request. In other words, the automatically populated fields must not be regenerated for each RPC attempt with the same request message.", + 'tags': '', + 'url': '/client-libraries/4235', + }, +{ + 'title': "Version-aware clients", + 'text': "Version-aware clients APIs can annotate API interfaces with google.api.api_version. If google.api.api_version is specified, version-aware clients must include the value of google.api.api_version in the request to the API and in the documentation of the per-API interface clients. Generator and client library behavior If an API interface is annotated with google.api.api_version, client library generators must include either an HTTP query parameter $apiVersion or HTTP header/gRPC metadata key X-Goog-Api-Version, but a request must not contain both. Generated client documentation Generated client documentation for a given API interface must include the value of google.api.api_version, if it exists in the source protos. The comment must include the original API interface name and the exact contents of the annotation. Note: The text does not need to match exactly to the examples below, but it still needs to fulfill the requirements desribed herein. For example, the following API interface definition would produce the following Go client documentation: service LibraryService { option (google.api.api_version) = \"2026-01-01\"; } // The LibraryClient is a client for interacting with the Cloud Library... // // This client uses LibraryService version 2026-01-01. type LibraryClient struct {} Any generated documentation for an entire API service\u0027s client package must include a section that lists the client-interface-version tuples present in the package. For example, the following API interface defintions would produce the following client package documentation section: service LibraryService { option (google.api.api_version) = \"2026-01-01\"; } service BookService { option (google.api.api_version) = \"2026-05-15\"; } service ShelfService { option (google.api.api_version) = \"2026-02-05\"; } ## API Versions * LibraryClient uses LibraryService version 2026-01-01 * BookClient uses BookService version 2026-05-15 * ShelfClient uses ShelfService version 2026-02-05 If all API interfaces share the same API version, this list should be reduced to a single sentence for brevity. For example, if all versions were the same in the definitions above, the generated client package documentation would be as follows: ## API Versions All clients use API version 2026-01-01. Version opacity Clients and generators must treat the value of google.api.api_version as opaque to ensure robust compatibility. This means that the specific format or structure of the version string must not be parsed or interpreted for any purpose beyond identifying the intended API version. Rationale Necessity for Versioning Explicit API versioning using the google.api.api_version annotation is essential for maintaining compatibility between clients and services over time. As services evolve, their schemas and behaviors may change. By specifying the API version, a client communicates its expectations to the API service. This allows the API service to respond in a manner consistent with the client\u0027s intended semantics, preventing errors or unexpected results due to incompatible changes. Importance of Opaque Treatment Treating the google.api.api_version value as opaque is important for ensuring robust compatibility guarantees. By using this identifier opaquely, clients avoid making assumptions about the underlying versioning scheme, which may change independently of the API itself. This flexibility allows API service providers to evolve their versioning strategies without impacting client compatibility. Mutual Exclusivity of Query and Header Both the query parameter and header mechanisms exist to provide flexibility for different client environments. However, allowing both simultaneously could lead to ambiguity if the values differ. To ensure consistent version identification and prevent potential conflicts, only one mechanism should be used at a time. Inclusion in documentation The API version identifies the iteration of the API contract being consumed by the client and thus the end user. The end user needs a means of relating the API version in use by the client to other API artifacts (such as product documentation and other client surfaces) and vice versa. Changelog 2025-12-08: Add documentation generation requirements and reformat.", + 'tags': '', + 'url': '/client-libraries/4236', + }, +{ + 'title': "Docker interface", + 'text': "Docker interface A consequence of using individual generators for API client library generation is that each generator has its own set of dependencies and requirements in order to run. This is reasonable for a user who wishes to generate many libraries for a single environment, but presents challenges for a user wishing to generate a single API for many languages or environments. Users need a way to generate libraries easily and quickly, with minimal ramp-up per language. Guidance Client library generators should ship Docker images providing the generator and exposing a common interface, so that generating the same API in multiple languages usually only requires substituting in the appropriate Docker image. Docker images for Google-authored generators will follow a consistent scheme. CLI usage The expected user command to invoke the code generator in a Docker image (from the proto import root, on a POSIX machine): $ docker run --rm --user $UID \\ --mount type=bind,source=`pwd`/a/b/c/v1/,destination=/in/a/b/c/v1/,readonly \\ --mount type=bind,source=/path/to/dest/,destination=/out/ \\ gcr.io/gapic-images/{GENERATOR} \\ [-- additional options...] Note: Even though each component of this is standard in the Docker ecosystem (other than the destination path issue, which is a result of how protoc handles imports), this is still a rather long command. We can provide a shortcut script to further simplify this, but such a script would be for convenience and not a replacement for this interface. Container composition Containers must include: A current version of protoc, the protocol buffer compiler. Common protos permitted to be used by all APIs (googleapis). The applicable code generator plugin, as well as any dependencies it requires. The code generator plugin itself should be added using an ADD or COPY statement from the host machine at build time and installed locally; it should not pull from a package manager. (This leads to catch-22 situations when cutting releases.) Images may include either a pre-compiled binary of the plugin, or the installed source code, depending on the needs of the applicable ecosystem. Installation of dependencies should use appropriate package managers. The common protos and the protoc compiler are supplied by an independent image (gcr.io/gapic-images/api-common-protos). Both protoc and the common protos can be retrieved from this image into a generator\u0027s image using the COPY --from syntax (see multi-stage builds). This is the preferred approach as it follows Docker conventions, and allows the protos to be versioned independently. Base images TL;DR: Each language probably wants language:x.y-alpine or language:x.y-slim. For example, ruby:2.5-alpine or python:3.7-slim. (Alpine images are smaller but idiosyncratic.) The following guidelines apply to selecting base images (sorted roughly from most important to least important): Images should generally be based off an official image for the latest stable version of the language in which the generator is implemented. Images should be able to install required system dependencies from a well-understood package manager. Images should be ultimately based off of Alpine, Debian, or Ubuntu. This is to ensure we benefit from GCR\u0027s vulnerability scanning. Images should endeavor to be as small as possible, in line with the general expectations of the Docker community: Use the smallest base image you can. Alpine-based images are great if possible, but may not always be reasonable. \"Slim\" Debian images are usually the next best (and probably significantly more feasible in many situations). Mount points protoc must read protos (representing the API to be generated) from disk, and must write the final output (the client library) to disk. Because the user has the API protos on the host machine, and will ultimately need the output to go to said host machine, Docker images should use two mount points. This creates a hole in the abstraction layer: the user must mount the appropriate locations on the host machine to the appropriate locations in the container. The expected locations in the container must be constant, and consistent between all generator container images: /in/: The location of the protos to be generated. This must be the import root. Example: If generating protos for the Language API, the protos in the Docker image must live in /in/google/cloud/language/v1/. /out/: The location to which the client library shall be written. Plugin options Some micro-generators support configuration provided via protoc plugin options. In such cases, the options must be routed from the CLI input to the protoc command. The ultimate protoc invocation could look like the following: protoc --proto_path {path/to/common/protos} --proto_path /in/ \\ --{LANG}_gapic_out /out/ \\ --{LANG}_gapic_opt \"go-gapic-package=GO_PACKAGE_VALUE\" \\ `find /in/ -name *.proto` A resulting invocation of the Docker image would be as follows: $ docker run --rm --user $UID \\ --mount type=bind,source=`pwd`/a/b/c/v1/,destination=/in/a/b/c/v1/,readonly \\ --mount type=bind,source=/path/to/dest/,destination=/out/ \\ gcr.io/gapic-images/{GENERATOR} \\ --go-gapic-package GO_PACKAGE_VALUE Thus shortcut scripts written to wrap the Docker image invocation must pass all options occurring after -- to the underlying docker run command. The internal Docker image must provide the conversion from usual shell syntax to the protoc option syntax. Client library generators that make use of plugin options must accept those options as either flags or key=value pairs. (If a generator receives a string without an = character, that is a flag, and the implied value is true.) If multiple options are provided, they are comma-separated, to conform with the protoc behavior if multiple --opt flags are specified. Additionally, generators should prefix all understood option keys with the target language for that generator (e.g. go-gapic-package, java-gapic-package), and should use kebab-case for keys (in order to match Docker, since protoc is inconsistent). Microgenerators must not error on option keys that they do not recognize, although they may issue a warning. Publishing images Images for Google-created generators should be published in gcr.io/gapic-images, a dedicated project in Google Container Registry. Images should follow the naming scheme: gcr.io/gapic-images/gapic-generator-{lang} CI should be configured to push a new Docker image to the registry when releases are made. When a release is tagged in GitHub (with a version number, such as 1.0.3), the CI service should build an image based on the code at that tag. The resulting image should be tagged with each component of the version number, as well as latest, and the resulting tags pushed the registry. (This is in addition to pushing to a package manager if appropriate, which is outside the scope of this AIP.) This means that a release tag of 1.0.3 in GitHub would result in pushing the following four tags to GCR: gcr.io/gapic-images/gapic-generator-{lang}:1 gcr.io/gapic-images/gapic-generator-{lang}:1.0 gcr.io/gapic-images/gapic-generator-{lang}:1.0.3 gcr.io/gapic-images/gapic-generator-{lang}:latest Note: These rules assumes that releases have ever-increasing version numbers; this process will need to be amended slightly if a generator needs to maintain multiple version streams simultaneously.", + 'tags': '', + 'url': '/client-libraries/4290', + }, +{ + 'title': "Projects and Apps", + 'text': "Projects and Apps Guidance Resource Hierarchy APIs that utilize an App ID as part of a resource name must include a Project identifier in the parent: apps/*/items Must instead be: projects/*/apps/*/items Project identifiers must follow Cloud guidance. As App IDs are globally unique, Firebase APIs should allow the unique resource lookup pattern, allowing a - in place of a Project ID/Number. For example: projects/-/apps/1:111222333444:web:abcdef0123456789/things Referencing App IDs When referencing an App ID in an SDK or API field, method, or parameter, the platform-correct initialism of app_id must be used (as opposed to e.g. app, application_id, or gmp_app_id).", + 'tags': '', + 'url': '/firebase/3201', + }, +{ + 'title': "Firebase CLI", + 'text': "Firebase CLI Guidance Command Naming Commands must be named in lowercase using colons to separate namespaces. The final segment of a command should be an action verb, for example list, deploy, or clone. A \"get\" of a single resource may omit the action for the sake of brevity (e.g. apps:sdkconfig instead of apps:sdkconfig:get). Project Selection The Firebase CLI works with \"project directories\" that can be associated with one or more Firebase projects via the use command. This ambient project selection can be overridden by passing the -P or --project flag. All Firebase CLI commands must determine the intended project for a command based on common project selection, except when a command involves multiple projects (e.g. a command that clones configuration from one project to another). JSON Output All Firebase CLI commands support machine-readable output via the --json flag. If a command correlates to a single API call, the unmodified response of that API call should be provided as the JSON response (with wrapped CLI metadata). If a command does not directly correlate to an API call, the output should include all information a user might reasonably need for programmatic interpretation of the command. Output must be formatted in snake-case and generally conform to all standard Google API guidance (e.g. field names). Arguments and Flags Required inputs for a command must be represented as arguments (e.g. database:get /path) unless doing so would be confusing to the user. For instance, appdistribution:distribute requires as input both a file to distribute and an App ID, so --app \u003cappId\u003e as a required flag is more clear than two unrelated arguments with no clear hierarchy. Flags must be named using kebab case (e.g. --example-flag) and may provide a single-letter alias that does not conflict with defined global flags. Common Flags --app \u003cappId\u003e - used to refer to a specific app within a Firebase project. --force - used to indicate that a command should proceed without additional prompting regarding potentially destructive actions. For example, deploying Cloud Functions with --force will automatically delete functions, while without the user is prompted. -o, --output \u003cpath\u003e - this flag may be used to allow convenient output of a serialized response to a local file. If the output is JSON, it must output equivalent JSON to --json without wrapped CLI metadata. If the command fetches a deployable resource, it must fetch it in a deploy-compatible format. The string path may be optional if a clear default path exists. If a file already exists at the path, a confirmation prompt must be displayed unless a --force flag is also provided. Common Command Types List Commands Commands that return a list of like resources must use a :list suffix (e.g. projects:list). List commands must not require manual pagination (e.g. a --page-token flag) and will generally fetch all results (via multiple API calls if necessary). List commands may include a --limit \u003cint\u003e flag when a natural ordering exists, such as a reverse chronological list of releases. A --limit 0 flag indicates that all results should be fetched and returned. The JSON output of a list command must be a concatenated array of all fetched resources in their original wire format. Clone Commands If a command\u0027s purpose is to copy information from one resource to another, it must be suffixed with :clone and must take a from and to argument: firebase example:clone \u003cfromProject\u003e \u003ctoProject\u003e To avoid confusion and accidental misuse, clone commands must explicitly require both arguments and must not rely on project selection to populate either. If a clone operation is destructive (replaces existing state), the command should prompt the user for confirmation before proceeding. If a prompt is added, the command must allow a --force flag to bypass the prompt. Deployment Behavior that takes local state (e.g. a rules file) and applies it to the live operation of a Firebase project must integrate with the deploy command. Scoped Deployments If a service has multiple deployable resources, it may allow specifying which resources are deployed through colon namespacing, for example: firebase deploy --only functions:func1,functions:func2,hosting:site3 Colon namespacing may be used to identify one of many like resources (as with functions above) or to identify specific resource type (e.g. firestore:indexes vs. firestore:rules). If the service integrates with deploy targets, the targets must be addressable via colon namespacing.", + 'tags': '', + 'url': '/firebase/3260', + }, +{ + 'title': "JavaScript APIs", + 'text': "JavaScript APIs Guidance Changelog", + 'tags': '', + 'url': '/firebase/3270', + }, +{ + 'title': "Android APIs", + 'text': "Android APIs Guidance Changelog", + 'tags': '', + 'url': '/firebase/3271', + }, +{ + 'title': "iOS APIs", + 'text': "iOS APIs Guidance Changelog", + 'tags': '', + 'url': '/firebase/3272', + }, +{ + 'title': "C++ APIs", + 'text': "C++ APIs Guidance Changelog", + 'tags': '', + 'url': '/firebase/3273', + }, +{ + 'title': ".NET APIs", + 'text': ".NET APIs Guidance Changelog", + 'tags': '', + 'url': '/firebase/3274', + }, +{ + 'title': "Python APIs", + 'text': "Python APIs Guidance Changelog", + 'tags': '', + 'url': '/firebase/3275', + }, +{ + 'title': "Go APIs", + 'text': "Go APIs Guidance Changelog", + 'tags': '', + 'url': '/firebase/3276', + }, +{ + 'title': "API completeness", + 'text': "API completeness Our customers expect that they can be as productive in their Apps programs as they can be sitting at the UI. When they can not, this is surprising and disappointing. Historically, Google Workspace has not insisted on this kind of completeness. However, we want to move towards that goal, hence this requirement for a plan, while we only advise completeness itself. For major changes, however, the desire for completeness will be amplified. Guidance Each action that can be performed in the UI should be possible to do via a public API. For example, if there is a button in the UI to add a widget, there should be some way to add a widget using the API. This simplifies the user\u0027s understanding of the API, and makes it easier to record UI actions to be replayed via the API. The question of when the completeness ought to be achieved is not fixed. Each team must have a plan for API completeness, even if it is a simple statement, such as, \"When we are given resources to do so.\" (We would prefer more, but if that is your plan, then so be it.)", + 'tags': '', + 'url': '/apps/2712', + }, +{ + 'title': "One team owns each type", + 'text': "One team owns each type This guidance supplements AIP-213. Sharing types is tempting, and it is possible. However, it is surrounded by some complicated issues. We will consider making shared types for classes that are useful across multiple Apps APIs, we just will not do it lightly. If you feel you have a case for this, please contact us at apps-api-reviewers@google.com. Guidance Each API owns its own types. If your API needs to reference another API\u0027s objects, your API must contain a reference (resource name or ID) that can be used to get the information from that other API. For example, if your API wants to reference a relevant Gmail message, you must store a Gmail message name, and the message itself will be accessed via the Gmail API, passing in that name. Your API must not contain an actual Gmail message object. For smaller types, it is also reasonable to make a copy of the class.", + 'tags': '', + 'url': '/apps/2713', + }, +{ + 'title': "Documenting authorization changes", + 'text': "Documenting authorization changes Authorization is critical to manage well. Understanding an API includes understanding not only what operations do, but when one is allowed to do them. Authorization changes, either new authorization constructs or new uses of existing authorization constructs, should be easy to find in a design rather than scattered through the document in individual sections. In order to make it easy to see what (if any) authorization constructs are being modified in your design, we want to be able to find them in a single, clear place. Note: This is not talking about RPC-level permissions, like those covered by RpcSecurityPolicy, but about authorization constructs used by your API for its own purposes. Definitions There are a couple of common types of authorization construct: A role refers to an authorization construct which is granted to an identity or an identity group on a resource. The most well known examples of roles in G Suite are the commenter, reader, writer, and owner roles from Drive. A permission refers to an authorization construct which is used to check whether a particular identity can execute some operation. For example, to check whether the current user can delete a file, the application may check whether the user has the file.delete permission on the file. Permissions are most often assigned to roles, so that only roles are granted to identities or identity groups, but some systems allow permissions to be granted directly. Applications often only use each permission to authorize a single operation on a resource, but there are cases where an application may use a permission to authorize multiple different operations. Within an application, authorization checks are made using only one of these authorization constructs (typically permissions, if the application has that concept). For example, in order to determine if a user can read a document, an application would either check whether the user has a doc.read permission or has the reader role, but not both. Guidance If your design creates new authorization constructs or extends/modifies the use of any existing authorization constructs, you must have a separate section in your design document that describes this. You may additionally discuss these in any other place in your document. It is not important whether this is a top-level section or subsection. It is important that all such changes are listed together in a distinct section so they are easy to find and analyze. If the identifier of an authorization construct that is new or modified is visible to users or developers, the way that it is identified should also be in your document. Examples of this are: If access is granted using roles and a new role is being added, the way that the role is identified in the role granting RPCs should be in your document. If there is an API that allows permissions assigned to roles to be manipulated, the way that the permission is identified in the role manipulation RPCs should be in your document.", + 'tags': '', + 'url': '/apps/2715', + }, +{ + 'title': "Standard terms in names", + 'text': "Standard terms in names APIs have a lot of identifier names (fields, constants, methods, ...), that often contain terms for things, such as url (getUrl(), doc_url, ...) or id (lookupId(), student_id). It is useful to have a standard set of terms for common concepts in these various names. This makes it easier for developers to understand new APIs based on previous experience. It is not (for example) that id is a better term than uid or other options, but it also is not worse, and having different choices in different APIs is confusing and unnecessary. This AIP defines terms to use for such common concepts. These terms should be used for the same concept in identifier names. This is supplemental to the API design guide, which lists standard field names and has other rules about identifiers. Guidance Absent other, more specific guidance, APIs should use the following standard terms (as opposed to alternatives) as parts of identifier names to refer to common concepts, and must not use them to refer to other things: uri for URIs/URLs (as opposed to url, link, href, etc.) id for a unique identifier, either globally unique or within a specified context index to indicate an ordinal number of an item within a collection, such as message_index on a message to say what place it occupies in a stream of message (unless there is a more specific name to use, such as if the number also is used as an ID, use id). APIs should avoid use of the term resource in fields that have resource names, as this is redundant. Any more specific guidance overrides these rules. For example, the AIP-122 rule to use name for the resource name overrides using the term id for unique identifiers. Fallback to schema.org If you are looking for standard terms for things, schema.org is a good place to look for terms that have been fairly widely vetted as being normal, customary, and/or clear. You should consult it when choosing identifier names when other strategies fail.", + 'tags': '', + 'url': '/apps/2716', + }, +{ + 'title': "Patterns for generic fields", + 'text': "Patterns for generic fields Developers have several options for how to represent generic values in proto messages. There are reasons to choose one over the other. Understanding them will lead to better and more consistent APIs. Guidance APIs should follow a consistent application of oneof vs. map\u003cstring, Foo\u003e vs. Any vs. Struct. oneof A oneof is used to create a restriction on a set of optional fields, enforcing that only one of them may be set (these fields are still separate individual fields). A common pattern is to have a message that contains a single oneof collection of various message types. Such a oneof message is conceptually similar to a C union, or C++ std::variant. These should be used in most places where a generic message type is needed, in preference to other approaches. Note: Adding additional possible values to an existing oneof is a non-breaking change, but moving existing fields into or out of a oneof is breaking (it creates a backwards-incompatible change in Go protobuf stubs). map\u003cstring, Foo\u003e If a more generic structure is needed, a map of strings to objects may be used. Such a map is represented by a normal JSON object, such as {\"a\": \"foo\", \"b\": \"bar\"}. The downside to such maps is that they are limited to flat structures, and they can be difficult to work with because many string constants may be needed. Any An Any allows any message to be packed into the field. This is conceptually similar to a \"bytes\" field containing a serialized message. The advantage of an Any is that a user-defined proto message can be stored along with type information. The user must be able to know which kind of object is in the Any, which complicates the design. The disadvantage is that working with and debugging any protos is much more complicated since the code may or may not know how to deserialize the packed message. Also, the developer must contend with unexpected types of messages in the Any. Any should not be used as a request parameter. Request parameters will either be a fixed set of types, in which case a oneof should be used, or a type descriptor would need to be sent along, in which case a struct should be used, which achieves essentially the same thing with much simpler semantics. Struct The Struct message can be used to represent arbitrary nested JSON. For example, given the following code: Struct.Builder builder = Struct.newBuilder(); Value town = Value.newBuilder().setStringValue(\"Springfield\").build(); Value population = Value.newBuilder().setNumberValue(273).build(); builder.putFields(\"town\", town); builder.putFields(\"population\", population); Struct survey = builder.build(); survey would serialize as the actual JSON {\"town\": \"Springfield\": \"population\": 273}. This message type is fairly uncommon, and should only be used rarely.", + 'tags': '', + 'url': '/apps/2717', + }, +{ + 'title': "References to objects in other APIs", + 'text': "References to objects in other APIs Your API may need to refer to objects in other APIs. For example, a Sheets cell may want to refer to the Slides deck that explains its meaning. This kind of cross reference should be as natural to use as possible with the target API. Guidance When your API refers to an object accessed via another API (the \"target\" API), the reference your API provides depends upon whether the reference is compliant with One Platform or not. If a field always holds a compliant reference to a single specific target API, the reference you provide must be a relative URI from the top level of the target API\u0027s naming hierarchy. For example, if the full URL of the object is https://koalas.googleapis.com/koalas/123435 the reference you return to it must be the relative URI koalas/123435. Further, your documentation must make clear that the reference is used with koalas.googleapis.com. This provides the developer with a natural way to use the reference, using the returned path directly. It also ensures that they know which API understands that reference. If a field always holds a compliant reference, but is not limited to a single target API, the reference you provide must be a relative URI that includes the path of its specific target API, such as koalas.googleapis.com/koalas/123435. This provides the developer with the correct target in a formalized, usable way. Otherwise, the reference you return must be chosen to be as natural to use as possible with the target API, and the API and its version must be documented. For example, if the Apiary-based Koala API uses an ID in its GetKoalaData method, you must return the ID that can be used as a parameter, as well as documenting that you are using IDs that work in Koala API 1.0. Naming For compliant references, you should avoid the use of the terms \"reference\" and \"name\" in the field name. That is, koala is preferred to koala_reference or koala_name (see [AIP-122][]). For other target APIs, you should echo that API\u0027s terminology in the name for clarity. For example, if the target API\u0027s GetKoalaDataRequest has a koala_num field, your field name should probably be koala_num, or it would include koala_num in its name, such as responsible_koala_num.", + 'tags': '', + 'url': '/apps/2718', + }, +{ + 'title': "Actions on Google AIP Process", + 'text': "Actions on Google AIP Process This AIP extends AIP-1 with details specific to Actions on Google AIPs. Any details of AIP-1 not modified or contradicted by this AIP also apply to Actions on Google AIPs. Stakeholders As with any process there are many different stakeholders when it comes to reviewing and working with AIPs. Below is a summary of the escalation path starting with the API producer. digraph d_front_back { rankdir=BT; ranksep=0.3; node [ style=\"filled,solid\" shape=box fontname=\"Roboto\" ]; producer [ label=\"API Producer\" ]; editors [ label=\"AIP Editors\" ]; aog_editors [ label=\"Actions on Google AIP Editors\" ]; tl_infra [ label=\"Infrastructure TL\" ]; tl_design [ label=\"Design TL\" ]; tl [ label=\"TL\" ]; producer -\u003e aog_editors; aog_editors -\u003e editors; editors -\u003e tl_infra -\u003e tl; editors -\u003e tl_design -\u003e tl; } Actions on Google Editors The Actions on Google editors are the set of people who make decisions on Actions on Google AIPs before escalation to the general editors defined in AIP-1. The list of Actions on Google AIP editors is currently: Ali Ibrahim (@ahahibrahim) Richard Frankel (@rofrankel) Shuyang Chen (@Canain) The Actions on Google editors have the same responsibilities as the general editors. They also have the additional responsibility of establishing correctness of, and leadership support for, the contents of Actions on Google AIPs. Actions on Google AIP editorship is by invitation of the current Actions on Google editors.", + 'tags': '', + 'url': '/aog/3001', + }, +{ + 'title': "Actions on Google Vertical Integration Webhook Format", + 'text': "Actions on Google Vertical Integration Webhook Format If an action is part of a vertical program that requires a webhook for Google to integrate with the action, the webhook format must follow this AIP. Guidance Custom method name Custom methods in a vertical program are defined by Google and implemented by third-party actions. Guidelines related to names of custom methods in AIP-136 should be applied. The name of the method should be a verb followed by a noun. The name must not contain prepositions (\u201cfor\u201d, \u201cwith\u201d, etc.). If word separation is required for the method name, lowerCamelCase should be used. Examples: getAccountBalance completeTransaction Base URL in Action Package The base URL configured in Action Package defines the common part of the actual execution URL of the webhook. The base URL may include a trailing slash, but must work if :customMethodName is appended directly. Google Cloud Functions base URLs without a trailing slash do not work, because the first segment of the path is used to identify the webhook. The endpoint must be HTTPS and must have a valid certificate. Examples: https://us-central1.cloudfunctions.net/myWebhook/ (not https://us-central1.cloudfunctions.net/myWebhook) https://test.com/assistant/api Actual execution URL The vertical program must compute the actual execution URL by appending baseUrl with :customMethodName. Examples: https://us-central1.cloudfunctions.net/myWebhook/:completeTransaction https://test.com/assistant/api:completeTransaction", + 'tags': '', + 'url': '/aog/3010', + }, +{ + 'title': "BII Schema Principles", + 'text': "BII Schema Principles Built-in intents (BIIs) allow third party developers to declare what their Actions can do. When a developer registers an Action for a BII, Google can then invoke that action to fulfill user requests matching that built-in intent. Terminology In the general principles below, we use the following terms: Built-in intents (BII): Fulfillment schemas that are used to call compatible APIs to perform Actions in response to a user query. Built-in intents allow your service to express its fulfillment capabilities to Google. By registering for built-in intents and mapping intent parameters to the fulfillment, it becomes possible for the Google Assistant to invoke the service to perform a task in response to natural language queries. A BII comprises an operation (full list below) and a Schema.org entity, otherwise known as a type. For example, CREATE_RESERVATION would be a BII for initiating a new reservation; this intent applies to various domains such as airline, hotel, restaurant, and other reservations. Operation: An Action which acts as a wrapper around a type. Type: The object on which the operation is acting upon. General principles Each BII should be treated like an API. While BIIs are technically fulfillment schemas, they fill the same role as an API, in that they tell third party developers about the structure of the request that their Action handles. This AIP details principles for schema creation, with operation-specific and type-specific information, followed by a list of operations for BIIs. Schema creation Existing Schema.org types and properties should be reused whenever the semantics needed already exist. The formula for naming a BII must be: Operation + Type := VERB [\"Operation\" from list below] + \u0027_\u0027 + NOUN [\"Type\" from Schema.org]. Types can be compound nouns which have more than one token. Types with more than one token have tokens separated by \u0027_\u0027. Example: CREATE + \u0027_\u0027 + MONEY_TRANSFER = CREATE_MONEY_TRANSFER BII names must be in CAPITAL_SNAKE_CASE (e.g. VERB_NOUN_NOUN). For more detail, see here. Operations Operations comprise a small catalog of simple, generalizable verbs. These can be found at the bottom of the AIP under \"List of BII Operations.\" There must not be overlap between the scope covered by any operations (mutual exclusivity). Example: GET and CREATE do not overlap in scope; while both involve presenting an object, GET is for retrieving an existing object, while CREATE assumes no object yet exists and creates one. Operation + type combos should make semantic sense. If there is no operation that can work with the type chosen, either: Choose a new type that is in semantic scope for the Action to attach to an existing operation, with a semantically sensible result. Example: Say you want to fulfill a request for checking into a reservation. CREATE_CHECKIN does not seem to make the most semantic sense, since nothing is being created. Upon further thought, you decide to choose a different operation and call the BII UPDATE_RESERVATION instead, which makes more sense with the semantics of checking into a reservation. Or, Create a new operation. Take this step only when there is no operation in the list that can cover the Action requested for the schema. Example: Imagine you only had the operations START, STOP, and RESUME for controlling an ongoing activity. A fulfillment request comes in for temporarily stopping an ongoing activity of media playback but not terminating it. You try to create a BII called STOP_MEDIA, but then realize that this operation means the API must terminate the activity. You then create a new operation, PAUSE, which acts to \"temporarily stop/pause activity\", and does not overlap in scope with the existing operation, STOP. Your new BII is PAUSE_MEDIA. Types Types must be defined as Schema.org types. The type must be the object upon which the operation is carried out. Semantic scope of the type should be generalizable, specificity may be in properties. Example: Reservation is a type, which has a property named provider. The provider property specifies the service provider, service operator, or service performer. This ensures that any BII created using the type Reservation is generalizable to any service provider, and that the service provider information is still passed forward through Reservation\u2019s property provider. Different types should take distinctly different properties. BIIs must be specific enough to avoid semantic ambiguity when calling an API. That is, we shouldn\u2019t inadvertently trigger an Action that the user isn\u2019t expecting. Example: brokerage account vs. account: If we do not specify brokerage account, a GET_ACCOUNT BII could call an API that fulfills the Action for getting another sort of account\u2019s information, such as a social media account. GET_BROKERAGE_ACCOUNT ensures the correct scope of financial account is retrieved by the API. The function prototype/set of parameters should be bound to the operation. That is, the operation decides the fulfillment boundaries of the Action. Each BII operation must take a Schema.org type. In BII schemas, the same Schema.org type, when combined with different verbs, may take different properties. Example: GET_MESSAGE and CREATE_MESSAGE use a different but overlapping set of properties of Message. Handling User Queries Generic/unresolved search criteria at the level of an object should be passed through the Description field. If a query argument can be recognized as a property of a type, it should be passed through as a property; if, on the other hand, an argument is recognized as just a description of the type, it should be passed through Description field. Example: \"find funky blues songs on YouTube\" -\u003e get_media_object(description=\"funky blues\"). List of BII Operations Verb Definition Example BII schema GET retrieve \u0026 present an object; if ambiguous, a list of objects GET_CALL_HISTORY CREATE create an object CREATE_ORDER DELETE remove or terminate an existing object DELETE_RESERVATION START control an ongoing activity: start activity START_GAME STOP control an ongoing activity: stop activity STOP_ALARM PAUSE control an ongoing activity: temporarily stop/pause activity PAUSE_SONG RESUME control an ongoing activity: continue activity RESUME_TIMER", + 'tags': '', + 'url': '/aog/3020', + }, +{ + 'title': "Type protos in Actions on Google APIs", + 'text': "Type protos in Actions on Google APIs Many Actions on Google fulfillment APIs need to represent typed data (datetime, money, etc.). In some cases, there are common components for representing these types. Guidance Fulfillment APIs must use the Actions on Google common types when applicable, and must not use alternative type protos. For example, an API which needs to represent a monetary amount must use google.type.Money, and must not use an alternative representation. APIs may wrap existing types in new protos. This may be useful in order to define compound types, provide additional metadata, provide semantic signals (if the typed value was obtained from a user query), etc. Actions on Google common types The Actions on Google common types include all the protobuf types and API types defined in AIP-213, as well as all the protos in google.actions.type.*. Adding new types If a given API needs a type for which there is no existing common type, and the type is not conceptually specific to that API, and the type is well understood enough to be modeled in a permanent/unversioned way, then API author should consider proposing a new Actions on Google common type in google.actions.type.*. The guidance in AIP-213 also applies to creating new Actions on Google common types. Specifically, API authors proposing new types should consider whether a new type should be a Google-wide common type rather than an Actions on Google common type. One exception to this is that new Actions on Google common types are not proposed by opening a GitHub ticket. Instead, Actions on Google API authors who want to create a new type should email the owners of the //google/actions/type directory directly.", + 'tags': '', + 'url': '/aog/3021', + }, +{ + 'title': "Built-in intent arguments and fulfillment APIs", + 'text': "Built-in intent arguments and fulfillment APIs Actions on Google\u0027s built-in intents (BIIs) are a fulfillment schema, and use Schema.org as a foreign vocabulary. BIIs are not a fulfillment API, and do not use the Actions on Google common types defined in AIP-3021. Actions on Google has two types of generic fulfillment APIs: URI-based APIs like App Actions, which can only support string arguments. Google standard APIs, which support JSON primitive types like string and the Actions on Google common types. These APIs do not support Schema.org JSON-LD objects. These APIs should support BII arguments by mapping them, or their properties, to the argument type schema they do support. For example, a BII argument of type MonetaryAmount may be mapped to an API field of type Money. BII argument paths Only certain Schema.org entity types should be mapped to a given common type. In order to support BII arguments with types that cannot be mapped to an appropriate type, APIs may support configuration via BII argument paths, strings which allow users to specify a property of a Schema.org entity which can be mapped to an appropriate type. APIs which support BII argument paths should use the syntax defined in this section. BII argument paths are dot-delimited strings that identify a specific Schema.org entity within the list of arguments to the BII. For example, take the following hypothetical BII arguments grant and date: { \"grant\": { \"@context\": \"http://schema.org\", \"@type\": \"MonetaryGrant\", \"funder\": { \"@type\": \"Organization\", \"name\": \"Google\" }, \"amount\": { \"@type\": \"MonetaryAmount\", \"currency\": \"USD\", \"value\": 100 } }, \"date\": \"2000-01-01\" } There is no common type to which MonetaryGrant can be mapped, but the grant argument contains an amount property of type MonetaryAmount, which can be mapped to Money. This property can be referenced with the path string \"grant.amount\". Similarly, grant.name can be mapped to a string field. A URI-based API which does not support Money would instead need to use the path strings \"grant.amount.currency\" and \"grant.amount.value\" to map grant.amount to two separate URI parameters. On the other hand, date can be mapped to DateTime, and so the path string \"date\" would be sufficient for either URI-based APIs or string fields in JSON APIs. Properties with multiple values Since any Schema.org property may have multiple values, values other than the first may be referenced by indexing with square brackets. For example, take this hypothetical BII argument: { \"menuItem\": { \"@context\": \"http://schema.org\", \"@type\": \"MenuItem\", \"name\": \"pizza\", \"menuAddOn\": { \"@type\": \"MenuItem\", \"name\": \"pineapple\" }, \"menuAddOn\": { \"@type\": \"MenuItem\", \"name\": \"extra cheese\" } }, \"date\": \"2000-01-01\" } In this example, the path \"menuItem.menuAddOn[1].name\" would evaluate to \"extra cheese\". When there are no square brackets, the first value is assumed; using [0] is a no-op. That is, \"menuItem.menuAddOn.name\" and \"menuItem.menuAddOn[0].name\" are equivalent, and would both evaluate to \"pineapple\". BII argument to common type mappings Google standard APIs which support BII argument mapping should support at least these type mappings from Schema.org entity type to Actions on Google common types: Common type Schema.org entity types Date Date DateTime DateTime TimeOfDay Time Duration Duration Money MonetaryAmount PostalAddress Place, PostalAddress BII argument to JSON type mappings Google standard APIs which support BII argument mapping should support at least these type mappings from Schema.org entity type to JSON type: JSON type Schema.org entity types string Text number Number bool Boolean BII argument to string mappings URI-based fulfillment APIs like App Actions can only map BII arguments to strings (URI parameters). These APIs should support mapping at least the following Schema.org entity types to URI parameters: Text Number Boolean Date DateTime Time", + 'tags': '', + 'url': '/aog/3022', + }, +]}; \ No newline at end of file diff --git a/assets/js/search/tipuesearch_set.js b/assets/js/search/tipuesearch_set.js new file mode 100644 index 0000000000..fa90ad3736 --- /dev/null +++ b/assets/js/search/tipuesearch_set.js @@ -0,0 +1,80 @@ + +/* +Tipue Search 6.1 +Copyright (c) 2017 Tipue +Tipue Search is released under the MIT License +http://www.tipue.com/search +*/ + + +/* +Stop words +Stop words list from http://www.ranks.nl/stopwords +*/ + +var tipuesearch_stop_words = ["a", "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"]; + + +// Word replace + +var tipuesearch_replace = {'words': [ + {'word': 'tip', 'replace_with': 'tipue'}, + {'word': 'javscript', 'replace_with': 'javascript'}, + {'word': 'jqeury', 'replace_with': 'jquery'} +]}; + + +// Weighting + +var tipuesearch_weight = {'weight': [ + {'url': 'http://www.tipue.com', 'score': 20}, + {'url': 'http://www.tipue.com/search', 'score': 30}, + {'url': 'http://www.tipue.com/is', 'score': 10} +]}; + + +// Illogical stemming + +var tipuesearch_stem = {'words': [ + {'word': 'e-mail', 'stem': 'email'}, + {'word': 'javascript', 'stem': 'jquery'}, + {'word': 'javascript', 'stem': 'js'} +]}; + + +// Related searches + +var tipuesearch_related = {'searches': [ + {'search': 'tipue', 'related': 'Tipue Search'}, + {'search': 'tipue', 'before': 'Tipue Search', 'related': 'Getting Started'}, + {'search': 'tipue', 'before': 'Tipue', 'related': 'jQuery'}, + {'search': 'tipue', 'before': 'Tipue', 'related': 'Blog'} +]}; + + +// Internal strings + +var tipuesearch_string_1 = 'No title'; +var tipuesearch_string_2 = 'Showing results for'; +var tipuesearch_string_3 = 'Search instead for'; +var tipuesearch_string_4 = '1 result'; +var tipuesearch_string_5 = 'results'; +var tipuesearch_string_6 = 'Back'; +var tipuesearch_string_7 = 'More'; +var tipuesearch_string_8 = 'Nothing found.'; +var tipuesearch_string_9 = 'Common words are largely ignored.'; +var tipuesearch_string_10 = 'Search too short'; +var tipuesearch_string_11 = 'Should be one character or more.'; +var tipuesearch_string_12 = 'Should be'; +var tipuesearch_string_13 = 'characters or more.'; +var tipuesearch_string_14 = 'seconds'; +var tipuesearch_string_15 = 'Searches related to'; + + +// Internals + + +// Timer for showTime + +var startTimer = new Date().getTime(); + diff --git a/assets/js/syntax.js b/assets/js/syntax.js new file mode 100644 index 0000000000..f9dbacd2b4 --- /dev/null +++ b/assets/js/syntax.js @@ -0,0 +1,112 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Ex post facto improvements to protobuf syntax highlighting. +// This applies special CSS classes to protobuf patterns that are overlooked +// or insufficiently distinguished by the usual Pygments/Rouge syntax parsers. +$.when($.ready).then(() => { + // ------------- + // -- Generic -- + // ------------- + // De-emphasize semicolon punctuation across the board. + $('.highlight .p:contains(;)').each((_, el) => { + el = $(el); + if (el.text() === ';') { + el.addClass('semi'); + } else if (el.text().match(/[;]$/)) { + let txt = el.text(); + el.text(txt.substring(0, txt.length - 1)); + $(';').insertAfter(el); + } + }); + + // -------------- + // -- Protobuf -- + // -------------- + // RPCs are always followed by three names (the RPC name, the request object, + // and the response object) -- designate those appropriately. + $('.language-proto .k:contains(rpc)').each((_, el) => { + $(el).nextAll('.n').slice(1, 3).addClass('nc'); + }); + + // Designate message names as such when using them to delcare fields. + $('.language-proto .n + .na + .o:contains(=)').prev().prev().addClass('nc'); + + // Colons in protocol buffers always come immediately after property keys. + $('.language-proto .n + .o:contains(:)') + .addClass('nk') + .prev() + .addClass('nk'); + + // Split up the beginning punctuation `[(` for field annotations, putting + // them in separate s so we can recolor only the latter. + $('.language-proto .p') + .filter((_, el) => $(el).text() === '[(') + .each((_, el) => { + $(el).text('['); + $('(').insertAfter($(el)); + }); + + // Designate protobuf annotations, which follow a consistent pattern with + // paerentheses. + $('.language-proto .p') + .filter((_, el) => $(el).text() === '(') + .each((_, el) => { + let open = $(el); // ( + let ann = open.next(); // google.api.foo + let close = ann.next(); // ) + + // Sanity check: Does this really look like an annotation? + // + // This checks the existing classes that Pygments uses for proto + // annotations, to ensure we do not get false positive matches + // (since the starting match is just a span with `(` in it). + let conditions = [ + ann.hasClass('n'), + !ann.hasClass('nc'), + close.hasClass('p'), + close.text() === ')', + close.next('.o').text() === '=', + ]; + if (!conditions.every((v) => v === true)) { + return; + } + + // This is an annotation, color it accordingly. + for (let e of [open, ann, close]) { + e.addClass('protobuf-annotation'); + } + }); + + // Highlight constants. + $('.language-proto .o + .n:not(.nc)') + .filter((_, el) => /^[A-Z0-9_]+$/.test($(el).text())) + .each((_, el) => { + $(el).addClass('mi').removeClass('n'); + }); + + // ---------------- + // -- TypeScript -- + // ---------------- + // Interfaces are always followed by what are effectively class names. + for (let lang of ['typescript', 'ts']) { + $(`.language-${lang} .kr:contains(interface)`).each((_, el) => { + if ($(el).nextAll('.nb').length > 0) { + $(el).nextAll('.nb').slice(0, 1).removeClass('nb').addClass('nc'); + } else { + $(el).nextAll('.nx').slice(0, 1).removeClass('nx').addClass('nc'); + } + }); + } +}); diff --git a/assets/misc/ebnf-filtering.txt b/assets/misc/ebnf-filtering.txt new file mode 100644 index 0000000000..7830348394 --- /dev/null +++ b/assets/misc/ebnf-filtering.txt @@ -0,0 +1,184 @@ +# Filter, possibly empty +filter + : [expression] + ; + + +# Expressions may either be a conjunction (AND) of sequences or a simple +# sequence. +# +# Note, the AND is case-sensitive. +# +# Example: `a b AND c AND d` +# +# The expression `(a b) AND c AND d` is equivalent to the example. +expression + : sequence {WS AND WS sequence} + ; + +# Sequence is composed of one or more whitespace (WS) separated factors. +# +# A sequence expresses a logical relationship between 'factors' where +# the ranking of a filter result may be scored according to the number +# factors that match and other such criteria as the proximity of factors +# to each other within a document. +# +# When filters are used with exact match semantics rather than fuzzy +# match semantics, a sequence is equivalent to AND. +# +# Example: `New York Giants OR Yankees` +# +# The expression `New York (Giants OR Yankees)` is equivalent to the +# example. +sequence + : factor {WS factor} + ; + + +# Factors may either be a disjunction (OR) of terms or a simple term. +# +# Note, the OR is case-sensitive. +# +# Example: `a < 10 OR a >= 100` +factor + : term {WS OR WS term} + ; + +# Terms may either be unary or simple expressions. +# +# Unary expressions negate the simple expression, either mathematically `-` +# or logically `NOT`. The negation styles may be used interchangeably. +# +# Note, the `NOT` is case-sensitive and must be followed by at least one +# whitespace (WS). +# +# Examples: +# * logical not : `NOT (a OR b)` +# * alternative not : `-file:".java"` +# * negation : `-30` +term + : [(NOT WS | MINUS)] simple + ; + +# Simple expressions may either be a restriction or a nested (composite) +# expression. +simple + : restriction + | composite + ; + +# Restrictions express a relationship between a comparable value and a +# single argument. When the restriction only specifies a comparable +# without an operator, this is a global restriction. +# +# Note, restrictions are not whitespace sensitive. +# +# Examples: +# * equality : `package=com.google` +# * inequality : `msg != 'hello'` +# * greater than : `1 > 0` +# * greater or equal : `2.5 >= 2.4` +# * less than : `yesterday < request.time` +# * less or equal : `experiment.rollout <= cohort(request.user)` +# * has : `map:key` +# * global : `prod` +# +# In addition to the global, equality, and ordering operators, filters +# also support the has (`:`) operator. The has operator is unique in +# that it can test for presence or value based on the proto3 type of +# the `comparable` value. The has operator is useful for validating the +# structure and contents of complex values. +restriction + : comparable [comparator arg] + ; + +# Comparable may either be a member or function. +comparable + : member + | function + ; + +# Member expressions are either value or DOT qualified field references. +# +# Example: `expr.type_map.1.type` +member + : value {DOT field} + ; + +# Function calls may use simple or qualified names with zero or more +# arguments. +# +# All functions declared within the list filter, apart from the special +# `arguments` function must be provided by the host service. +# +# Examples: +# * `regex(m.key, '^.*prod.*$')` +# * `math.mem('30mb')` +# +# Antipattern: simple and qualified function names may include keywords: +# NOT, AND, OR. It is not recommended that any of these names be used +# within functions exposed by a service that supports list filters. +function + : name {DOT name} LPAREN [argList] RPAREN + ; + +# Comparators supported by list filters. +comparator + : LESS_EQUALS # <= + | LESS_THAN # < + | GREATER_EQUALS # >= + | GREATER_THAN # > + | NOT_EQUALS # != + | EQUALS # = + | HAS # : + ; + +# Composite is a parenthesized expression, commonly used to group +# terms or clarify operator precedence. +# +# Example: `(msg.endsWith('world') AND retries < 10)` +composite + : LPAREN expression RPAREN + ; + +# Value may either be a TEXT or STRING. +# +# TEXT is a free-form set of characters without whitespace (WS) +# or . (DOT) within it. The text may represent a variable, string, +# number, boolean, or alternative literal value and must be handled +# in a manner consistent with the service's intention. +# +# STRING is a quoted string which may or may not contain a special +# wildcard `*` character at the beginning or end of the string to +# indicate a prefix or suffix-based search within a restriction. +value + : TEXT + | STRING + ; + +# Fields may be either a value or a keyword. +field + : value + | keyword + ; + +# Names may either be TEXT or a keyword. +name + : TEXT + | keyword + ; + +argList + : arg { COMMA arg} + ; + +arg + : comparable + | composite + ; + +keyword + : NOT + | AND + | OR + ; diff --git a/auth.html b/auth.html new file mode 100644 index 0000000000..10e7b30412 --- /dev/null +++ b/auth.html @@ -0,0 +1,394 @@ + + + + Auth AIPs + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + + +
    +
    + +
    +

    Auth

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    4110 + Application Default Credentials +
    4111 + Self-signed JWT +
    4112 + Service Account Keys +
    4113 + gcloud CLI Integration +
    4114 + Device Certificate Authentication via Mutual TLS +
    4115 + Default Credentials For Google Cloud Virtual Environments +
    4116 + Identity Tokens + + Draft + +
    4117 + External Account Credentials (Workload Identity Federation) +
    4118 + Mutual Authentication Using Workload Credentials + + Draft + +
    4119 + mTLS Token Binding + + Draft + +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4110.html b/auth/4110.html new file mode 100644 index 0000000000..c0e7680269 --- /dev/null +++ b/auth/4110.html @@ -0,0 +1,532 @@ + + + + AIP-4110: Application Default Credentials + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4110

    +

    Application Default Credentials

    +

    Google auth libraries use a strategy called Application Default Credentials +(ADC) to detect and select credentials based on environment or context. With +ADC, developers should be able to run the code in different environments and the +supporting systems fetch the appropriate credentials based on each environment +in an effortless manner.

    +

    Auth libraries following the standards in these AIPs are known as "Google +Unified Auth Clients", or GUAC for short. The resulting libraries are +colloquially called GUACs.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    Credential Types

    +

    This section outlines the supported credential types of the ADC.

    +
      +
    • +

      Gcloud Credential: A credential provided by the Gcloud tool that +identifies a human user that needs to authenticate to access Google APIs. The +auth libraries must support this credential type.

      +
    • +
    • +

      Service Account Key: A credential that identifies a non-human user that +needs to authenticate to access Google APIs. The auth libraries must support +this credential type.

      +
    • +
    • +

      OAuth Client ID: A credential that identifies the client application which +allows human users to sign-in through 3-legged OAuth flow, which grants the +permissions to the application to access Google APIs on behalf of the human +user. The auth libraries may support this credential type.

      +
    • +
    • +

      External Account Credential: A configuration file identifying +external non-Google credentials that can be exchanged for Google access +tokens to access Google APIs. The auth libraries must support this +credential type.

      +
    • +
    +

    Environment Variables

    +

    The auth libraries must support the following environment variables to allow +developers to provide authentication configuration for their application:

    +
      +
    • +

      GOOGLE_APPLICATION_CREDENTIALS: The specified value will be used as the +full path for ADC to locate the credentials file. The credentials file +should be one of the following types:

      +
        +
      • Gcloud credentials
      • +
      • Service account key
      • +
      • External account credentials
      • +
      +

      The credentials may be the OAuth Client ID if it is supported by the +auth library. Credentials file path specified at the program level (e.g. via +client options) must have priority over the value of this environment +variable.

      +
    • +
    • +

      GOOGLE_API_USE_CLIENT_CERTIFICATE: The specified value must be +either true or false. The client certificate must be ignored if this +variable is set to false. The default value is false if the value is unset.

      +
    • +
    +
    GOOGLE_API_USE_CLIENT_CERTIFICATE=[true|false]
    +
    +
      +
    • GOOGLE_CLOUD_QUOTA_PROJECT: The quota project id to be set on the credential. +The value from the environment variable will override any quota project that is +present in the credential detected by the ADC mechanism.
    • +
    +

    Inputs & Outputs

    +

    From the input/output perspective, the inputs of ADC should be the +credentials as well as the underlying environment such as environment variables +or metadata service that provides these credentials.

    +

    For example, the GOOGLE_APPLICATION_CREDENTIALS environment variable can provide +the default credential JSON as the input here, or the well-known path that +gCloud uses to store the default user credential JSON. The output is the access +token that application can use to access the Google APIs. This access token +may be a bearer token, a certificate-bound token, or an identity-bound token +depending on the chosen authentication flow.

    +

    Expected Behavior

    +

    This section outlines the expected behavior of the ADC. Auth libraries must +implement these concepts in order to be considered complete.

    +
    digraph d_front_back {
    +  rankdir=TB;
    +  ranksep=0.3;
    +  node [ style="filled,solid" shape=box fontname="Roboto" ];
    +
    +  check_env_var [ label="1. Check Environment Variables" ];
    +  load_credentials [ label="2. Load Credentials" ];
    +  check_metadata [ label="3. Check workload credentials" ];
    +  auth_flows [ label="4. Determine Auth Flows" ];
    +  execute [ label="5. Execute Auth Flows" ];
    +  post_processing [ label="6. Post Processing" ];
    +
    +  check_env_var -> load_credentials -> check_metadata -> auth_flows -> execute -> post_processing;
    +  load_credentials -> auth_flows;
    +  check_metadata -> post_processing;
    +}
    +
    +
      +
    1. Check environment variables
        +
      1. Check GOOGLE_APPLICATION_CREDENTIALS
          +
        1. If set, go to step (2.2)
        2. +
        3. If not set, go to step (2)
        4. +
        +
      2. +
      +
    2. +
    3. Load credentials
        +
      1. Check gcloud default credentials through its default path
          +
        1. If found go to step (2.2)
        2. +
        3. Otherwise go to step (3)
        4. +
        +
      2. +
      3. Check the provided credential type
          +
        1. If the credential is gcloud credentials, go to step (4)
        2. +
        3. If the credential is a service account key JSON, go to step (4)
        4. +
        5. If the credential is an external account JSON, go to step (4)
        6. +
        7. If the credential is unknown type, return an error saying that [END]
        8. +
        +
      4. +
      5. Credentials not found [END]
      6. +
      +
    4. +
    5. Check workload credentials (on GCE, GKE, GAE and Serverless)
        +
      1. If true,
          +
        1. If identity binding is enabled, by meeting the requirements in + mTLS Token Binding, use the mTLS Token Binding flow to fetch an + identity-bound access token. Go to step(6).
        2. +
        3. If there is an issue when obtaining bound access tokens, return an error + indicating that [END]
        4. +
        5. If identity binding is not enabled, use the virtual machine flow to + fetch an auth token associated with the current environment
            +
          1. If target audience is provided by the developer, get an identity token. Go to step(6).
          2. +
          3. Otherwise, get an access token. Go to step(6).
          4. +
          +
        6. +
        +
      2. +
      3. If false, go to step (2.3)
      4. +
      +
    6. +
    7. Determine auth flows
        +
      1. If the credential is gcloud credential go to step (5.3)
      2. +
      3. If target audience or scope is provided by the developer go to step (5.1)
      4. +
      5. If the credential is an external account go to step (5.4)
      6. +
      7. Otherwise, go to step (5.2)
      8. +
      +
    8. +
    9. Execute auth flows
        +
      1. Use 2LO flow to exchange for an auth token
          +
        1. If target audience is provided by the developer, get an identity token. Go to step(6).
        2. +
        3. Otherwise, get an access token. Go to step(6).
            +
          1. If client certificate is presented, the exchanged token will be a certificate bind token. Go to step(6).
          2. +
          +
        4. +
        +
      2. +
      3. Use self-signed JWT flow to create an access token locally.
          +
        1. If certificate is presented, embed the certificate into the JWT.
        2. +
        3. Use the regular self-signed JWT flow for an access token. Go to step(6).
        4. +
        +
      4. +
      5. Use user identity flow to exchange for an access token. Go to step(6).
      6. +
      7. Use external account flow to exchange for an access token. Go to step(6).
      8. +
      +
    10. +
    11. Post Processing
        +
      1. Update Quota Project
          +
        1. If a quota project is provided explicitly while initiating ADC, override the quota project in the credential with the explicit value. [END]
        2. +
        3. Else if the GOOGLE_CLOUD_QUOTA_PROJECT environment variable is set, override the quota project in the credential with this value. [END]
        4. +
        +
      2. +
      +
    12. +
    +

    Changelog

    +
      +
    • 2019-08-13: Add a link to virtual machine flow (AIP 4115).
    • +
    • 2019-08-18: Remove STS support from ADC.
    • +
    • 2021-01-20: Add identity token flow (AIP 4116).
    • +
    • 2021-06-29: Guidance for GOOGLE_API_KEY temporarily removed until consensus can be established.
    • +
    • 2021-12-10: Add external account credentials (AIP 4117).
    • +
    • 2023-01-23: Add Quota Project Environment variable.
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4111.html b/auth/4111.html new file mode 100644 index 0000000000..2cad4d16a1 --- /dev/null +++ b/auth/4111.html @@ -0,0 +1,449 @@ + + + + AIP-4111: Self-signed JWT + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4111

    +

    Self-signed JWT

    +

    Self-signed JWT (JSON Web Token) for Google APIs was introduced in 2014 to +provide a more efficient auth stack for Cloud APIs being accessed via service +accounts by bypassing the intermediate step of exchanging client assertions for +OAuth tokens. A self-signed JWT is a spec-conforming JWT that is locally signed +by the service account private key. Since many Cloud APIs accept self-signed JWT +in place of traditional access tokens, it is now considered a standard +authentication method.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    This section describes the general guidance of supporting self-signed +JWT as a means of authentication.

    +

    Application Default Credentials

    +

    Supporting self-signed JWT is considered a part of application default +credentials. To understand the overall flow, please read AIP-4110.

    +

    Scope vs. Audience

    +

    In the past, the self-signed JWT was only applicable with audience. Recently, +the usage of the "scope" claim in self-signed JWTs is now allowed in the Google +Cloud auth ecosystem, which makes the self-signed JWT usable with both audience +and scope. However, caller must not specify scope and audience at the same +time to prevent potential conflicts.

    +

    Opt-in Strategy

    +

    Currently, this scope support for JWT is gated behind a configurable boolean +option UseJWTAccessWithScope(the actual naming may vary depending on the +programming language), as the feature is not supported for all Cloud API service +backends. The default value of this boolean is false, and to use scope with +self-signed JWT, caller must specify this option as true. Otherwise the +OAuth exchange flow should be used instead when scope is provided. The API +clients should try to automatically determine this option with the +appropriate value based on the APIs, so this complexity is not exposed to the +upper-layer developer.

    +

    Default Authentication Method For Service Account Keys

    +

    Considering its better efficiency and reliability comparing with OAuth flow +(bypassing the exchanging step), ADC should use self-signed JWT as the +default authentication flow when service account key is provided as the source +credential.

    +

    In other words, ADC should choose the OAuth flow over the self-signed +JWT flow only if scope is provided and JWT is not enabled via +UseJWTAccessWithScope.

    +

    Expected Behavior

    +

    To support self-signed JWT, the auth libraries must follow the steps below:

    +

    1. Load the service account ID JSON file. Please note that the self-signed +JWT only supports service account ID credential type.

    +

    2. Using any standard JWT library, such as one found at jwt.io, create a JWT +with a header and payload like the following examples:

    +

    (1) Example of using audience:

    +
    {
    +  "alg": "RS256",
    +  "typ": "JWT",
    +  "kid": "abcdef1234567890"
    +}
    +{
    +  "iss": "123456-compute@developer.gserviceaccount.com",
    +  "sub": "123456-compute@developer.gserviceaccount.com",
    +  "aud": "https://pubsub.googleapis.com/",
    +  "iat": 1511900000,
    +  "exp": 1511903600
    +}
    +
    +

    (2) Example of using scope:

    +
    {
    +  "alg": "RS256",
    +  "typ": "JWT",
    +  "kid": "abcdef1234567890"
    +}
    +{
    +  "iss": "123456-compute@developer.gserviceaccount.com",
    +  "sub": "123456-compute@developer.gserviceaccount.com",
    +  "scope": "https://www.googleapis.com/auth/cloud-platform",
    +  "iat": 1511900000,
    +  "exp": 1511903600
    +}
    +
    +
      +
    • +

      For the kid field in the header, specify the service account's private key +ID. You can find this value in the private_key_id field of the service account +JSON file.

      +
    • +
    • +

      For the iss and sub fields, specify the service account's email address. +You can find this value in the client_email field of the service account JSON +file.

      +
    • +
    • +

      For the aud field, specify the audience. The default audience value +should be https://[SERVICE]/. (e.g. https://pubsub.googleapis.com/)

      +
    • +
    • +

      For the scope field, specify the scope. Please note that aud and scope +cannot be specified at the same time.

      +
    • +
    • +

      For the iat field, specify the current Unix time, and for the exp field, +the value must be exactly 3600 seconds later, when the JWT will expire.

      +
    • +
    +

    3. Sign the JWT with RSA-256 using the private key found in the service +account JSON file.

    +

    Changelog

    +
      +
    • 2019-08-13: Add a section for application default credential.
    • +
    • 2021-06-02: Update scope support.
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4112.html b/auth/4112.html new file mode 100644 index 0000000000..c4030f8e13 --- /dev/null +++ b/auth/4112.html @@ -0,0 +1,419 @@ + + + + AIP-4112: Service Account Keys + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4112

    +

    Service Account Keys

    +

    A service account is a special kind of account used by an application or a +virtual machine (VM) instance, not a person. Applications use service accounts +to make authorized API calls, authorized as either the service account itself, +or as Google Workspace or Cloud Identity users through domain-wide delegation. +Service accounts are associated with private/public RSA key-pairs that are used +for authentication, which is the focus of this AIP.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    This section describes the general guidance of supporting Service Account Key +authentication using traditional OAuth flow. For Service Account Key +authentication using self-signed JWT flow, please refer to the self-signed +JWT AIP.

    +

    Service Account Key Authentication Using OAuth

    +

    Under the latest ADC guidance, when Service Account Key is provided as the +source credential, we prefer to use the self-signed JWT flow by default, +which does not use the OAuth "scope" argument. Therefore, the client should +choose the OAuth flow over self-signed JWT flow only if the OAuth "scope" is +explicitly provided to the client.

    +

    Expected Behavior

    +

    To support Service Account Key authentication using OAuth flow, the auth +libraries must follow the steps below:

    +

    1. Load the Service Account ID JSON file from the file path specified by +GOOGLE_APPLICATION_CREDENTIALS environment variable, or an explicit +credentials file path specified through client options. The JSON file will +look like below:

    +
    {
    +  "type": "service_account",
    +  "project_id": "testproject",
    +  "private_key_id": "redacted",
    +  "private_key": "redacted",
    +  "client_email": "testserviceaccount@test.iam.gserviceaccount.com",
    +  "client_id": "113258942105700140798",
    +  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    +  "token_uri": "https://oauth2.googleapis.com/token",
    +  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    +  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/testserviceaccount%40test.iam.gserviceaccount.com"
    +}
    +
    +

    Note: A Service Account ID JSON file can be downloaded from Google Cloud Console.

    +

    2. Using any standard JWT library, such as one found at jwt.io, create a +JWT with a header and claims set like the following example:

    +
    {
    +  "alg": "RS256",
    +  "typ": "JWT",
    +  "kid": "abcdef1234567890"
    +}
    +{
    +  "iss": "123456-compute@developer.gserviceaccount.com",
    +  "sub": "123456-compute@developer.gserviceaccount.com",
    +  "scope": "https://www.googleapis.com/auth/pubsub",
    +}
    +
    +
      +
    • +

      For the kid field in the header, specify the service account's private +key ID. You can find this value in the private_key_id field of the +service account JSON file.

      +
    • +
    • +

      For the iss and sub fields, specify the service account's email +address. You can find this value in the client_email field of the +service account JSON file.

      +
    • +
    • +

      For the scope field, specify the scope parameter provided by the client. +Multiple scopes can be specified using single space (" ") as delimiter.

      +
    • +
    +

    3. Sign the JWT with RSA-256 using the private_key found in the service +account JSON file. The output will be used as the request payload (a.k.a. +assertion) for the 2-legged OAuth flow.

    +

    4. Define a parameter "grant_type" as +"urn:ietf:params:oauth:grant-type:jwt-bearer". Define a parameter "assertion" as +the payload from step 3.

    +

    5. Make a POST request to the token_uri endpoint with the parameters from +step 4 to obtain an OAuth2 Access Token.

    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4113.html b/auth/4113.html new file mode 100644 index 0000000000..b8648d3c63 --- /dev/null +++ b/auth/4113.html @@ -0,0 +1,427 @@ + + + + AIP-4113: gcloud CLI Integration + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4113

    +

    gcloud CLI Integration

    +

    gcloud is the CLI that manages authentication, local configuration, +developer workflow, and interactions with the Google Cloud Platform (GCP) APIs. +gcloud can generate default credentials by obtaining user access credentials +via 3-legged OAuth (3LO) web flow and saving them to well-known locations in +JSON format. These credentials are intended to be consumed by applications +other than gcloud. Application Default Credentials (ADC) and Google Unified +Auth Clients (GUAC) must support the gcloud default credentials.

    +

    Note: Although the sample code is written in Python, this AIP describes +guidance and requirements in a language-neutral way. It uses generic +terminology which may be imprecise or inappropriate in certain languages or +environments.

    +

    Guidance

    +

    This section describes the general guidance of supporting the gcloud default +credentials.

    +

    Credentials Generation

    +

    gcloud default credentials can be generated via command ‘gcloud auth +application-default login’.

    +
    $ gcloud auth application-default login
    +
    +

    The generated credentials are saved to well-known locations which vary as +platforms:

    +
      +
    • Linux, Mac: \$HOME/.config/gcloud/application_default_credentials.json
    • +
    • Windows: %APPDATA%/gcloud/application_default_credentials.json
    • +
    +

    Below is an example of the gcloud default credentials,

    +
    {
    +  "client_id": "fake_id.apps.googleusercontent.com",
    +  "client_secret": "fake_secret",
    +  "quota_project_id": "fake_project",
    +  "refresh_token": "fake_token",
    +  "type": "authorized_user"
    +}
    +
    +

    All the fields are populated by the login response from the Google +authorization backend except for ‘quota_project_id’ which is retrieved from +gcloud’s context. Additionally, the users can override ‘quota_project_id’ with +the ‘--client-id-file’ flag,

    +
    $ gcloud auth application-default login --client-id-file=clientid.json
    +
    +

    Expected Behaviors

    +

    The auth libraries will use the information in the gcloud default credentials +to exchange access tokens with Google authorization backend. The resulting +access tokens will be further used by applications to call GCP APIs.

    +

    The auth libraries and applications must follow the steps below:

    +
      +
    • +

      The auth library loads the gcloud default credentials from the well-known + location (see previous section) of the platform on + which it runs.

      +
    • +
    • +

      The auth library calls Google authorization backend with the refresh token, + client ID and client secret in the gcloud default credentials and procures an + access token. The URL for acquiring access tokens from Google authorization + backend is https://oauth2.googleapis.com/token. Below is an example code with + google-auth as the auth library and urllib3 as the http transport.

      +
    • +
    +
    from google.oauth2 import _client as google_auth_client
    +import google.auth.transport.urllib3 as google_auth_urllib3
    +import urllib3
    +
    +# Create an http transport for communicating with Google authorization backend.
    +http = urllib3.PoolManager()
    +request = google_auth_urllib3.Request(http)
    +
    +# Build parameters for the access token request. Assume the gcloud default
    +# credentials are deserialized are into a dictionary ‘gcloud_default’
    +# in the previous step.
    +token_uri = 'https://oauth2.googleapis.com/token'
    +refresh_token = gcloud_default['refresh_token']
    +client_id = gcloud_default['client_id']
    +client_secret = gcloud_default['client_secret']
    +scopes = ['https://www.googleapis.com/auth/cloud-platform']
    +
    +# Obtain an access token.
    +access_token, _, _, _ = google_auth_client.refresh_grant(
    +  request, token_uri, refresh_token, client_id, client_secret, scopes)
    +
    +
      +
    • The application calls GCP API with the access token obtained from the + previous step. ‘quota_project_id’ in the gcloud default credentials + should be added to the ‘X-Goog-User-Project’ http header so that the + associated account will be charged for billing and quota.
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4114.html b/auth/4114.html new file mode 100644 index 0000000000..7beec7e5ba --- /dev/null +++ b/auth/4114.html @@ -0,0 +1,461 @@ + + + + AIP-4114: Device Certificate Authentication via Mutual TLS + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4114

    +

    Device Certificate Authentication via Mutual TLS

    +

    Mutual TLS (a.k.a mTLS) authentication enables authentication of both client and +server identities in a TLS handshake and provides the foundation for Device +Certificate Authentication for Context Aware Access for GCP enterprise +customers. With Device Certificate Authentication, the server takes into account +the client certificate in the transport layer when making authorization +decisions. The use of a client certificate provides a stronger indication of the +access originating from a trusted device. This allows enterprise customers to +restrict access from untrusted devices.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    This section describes the general guidance of supporting Device Certificate +Authentication (a.k.a. DCA) via mTLS.

    +

    Application Default Credentials for DCA

    +

    Users should enable DCA through ADC instead of manual configuration via +client options.

    +

    There are two aspects of ADC for DCA. The first is the automatic procurement of +a device certificate. The second is the automatic switching of the service +endpoint to the mTLS version of the service endpoint. Clients must support +both of these aspects when supporting ADC for DCA.

    +

    Expected Behavior

    +

    Client support for DCA must give priority to user overrides specified via +client options. The following decision tree should be used:

    +
      +
    1. If user specifies both device certificate and endpoint override via client + options, use them as is.
    2. +
    3. If user does not specify device certificate, attempt to procure and use + a default device certificate.
    4. +
    5. If user does not specify endpoint override, use the default mTLS endpoint if + a device certificate is available and the default regular endpoint otherwise.
    6. +
    +

    Implications of the above logic:

    +
      +
    1. If user specifies a non-mTLS endpoint override but a device certificate is + available, pass along the certificate anyway and let the server decide what + to do.
    2. +
    3. If user specifies an mTLS endpoint override but device certificate is not + available, do not fail-fast, but let server return error when connecting.
    4. +
    +

    The above behavior avoids introducing client-side logic that parses whether the +endpoint override is an mTLS url, since the url pattern may change at anytime.

    +

    Obtaining the Default mTLS Endpoint

    +

    The default mTLS endpoint for a service should be read from the Discovery +Document field "mtlsRootUrl" instead of generated via regex patterns.

    +

    Obtaining the Default Device Certificate via SecureConnect

    +

    The default device certificate should be procured using the +EndpointVerification workflow, which fetches the certificate from a +platform-specific credential store (ex. KeyChain in macOS) via a native helper.

    +

    Exporting the certificate via the native helper involves executing a "cert +provider command" specified in a well-known gcloud metadata file of the +following format:

    +
    {
    +   "version": 1
    +   "min_cloud_sdk_version": "240.0.0"
    +   "has_client_cert": true
    +   "endpoint_verification_error": ""
    +   "cert_provider_command": "[absolute_path_to_provider_command] --fetch_client_cert"
    +}
    +
    +

    For Linux and macOS platforms, the above metadata file is located at +"~/.secureConnect/context_aware_metadata.json".

    +

    The cert provider command will print the certificate to stdout, which will be in +the form of an X.509 cert followed immediately by the private key:

    +
    -----BEGIN CERTIFICATE-----
    +Common Name: Google Endpoint Verification
    +Valid From: November 10, 2019
    +Valid To: November 10, 2020
    +Serial Number: 4921083229008411918 (0x444b331faf2dbd0e)
    +...
    +-----END CERTIFICATE-----
    +-----BEGIN PRIVATE KEY-----
    +...
    +-----END PRIVATE KEY-----
    +
    +

    Obtaining the Default Device Certificate via ECP

    +

    The Enterprise Certificate Proxy (ECP) project is the newly recommended way to +procure device certificates. It has two major advantages compared to the legacy +SecureConnect mechanism:

    +
      +
    1. Allows usage of enterprise certs and private keys stored in native keystores and TPMs + instead of relying on self-signed certs.
    2. +
    3. Delegates signing operations to keystores, so private keys never leave the security realm.
    4. +
    +

    Please see ECP Public Documentation for details on ECP configuration.

    +

    Environment Variables

    +

    There are situations where the ADC for DCA behavior needs to be modified, such +as for integration testing, or for failsafe. To accomodate those scenarios, the +following environment variables should be supported.

    +

    GOOGLE_API_USE_MTLS_ENDPOINT: If "always", always use mTLS endpoint. If +"never", always use regular endpoint. If "auto", use the default +behavior, which is to use the mTLS endpoint if a device certificate is +available. The default value of this environment variable will be "auto".

    +

    GOOGLE_API_USE_CLIENT_CERTIFICATE: If "true", device certificate +authentication will be supported as described in the general guidance. If +"false", the device certificate must not be used, even if specified by +the user. The default value should be "true" as of May 3, 2024. Users who +wish to disable DCA feature must explicitly set this environment variable +to "false".

    +

    Firewall and IP Address Guidance

    +

    For any given GCP service, its mTLS endpoint has a different IP address compared +to the non-mTLS endpoint but is expected to fall within the same IP range. The +GCP guidance for IP range management is on a service by service basis. See +Compute Engine IP Range Documentation for example. In the unlikely event +that an end-user has configured firewall rules based on exact IP addresses +instead of an IP range, they may be impacted by the "auto" mTLS endpoint +upgrade behavior. The best-practice recommendation in this case would be to +avoid adding rules that expect exact IP address matches, and instead use +range-based IP rules following public GCP documentation.

    +

    Changelog

    +
      +
    • *2024-11-25: GOOGLE_API_USE_CLIENT_CERTIFICATE should default to "true" as of May 3, 2024.
    • +
    • *2025-02-20: Add Firewall and IP Address Guidance
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4115.html b/auth/4115.html new file mode 100644 index 0000000000..09776f38c5 --- /dev/null +++ b/auth/4115.html @@ -0,0 +1,437 @@ + + + + AIP-4115: Default Credentials For Google Cloud Virtual Environments + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4115

    +

    Default Credentials For Google Cloud Virtual Environments

    +

    If the client runs on Google cloud virtual environments such as Google Compute Engine (GCE), +Serverless, or Google Kubernetes Engine (GKE), the auth library may leverage +Google’s default mutual TLS (mTLS) credentials and obtain bound tokens for the instance. +The auth library may use the default mTLS credentials and bound tokens to access Google APIs.

    +

    mTLS authentication enables authentication of both client and server identities in a TLS handshake. +Applications running in Google virtual environments can authenticate to Google APIs using X.509 +SPIFFE Verifiable Identity Documents (SVIDs). These SVIDs are X.509 certificates that contain SPIFFE +IDs specifying the identity of the certificate owner.

    +

    Bound tokens are access tokens that are bound to some property of the credentials used to establish +the mTLS connection. The advantage of bound tokens is that they can be used over secure channels +established via mTLS credentials with the correct binding information, when appropriate access +policies have been put in place. Therefore, using bound tokens is more secure than bearer tokens, +which can be stolen and adversarially replayed.

    +

    This AIP describes the flow of:

    +
      +
    1. Retrieving a configuration through a metadata server (MDS) endpoint. The configuration specifies + how to access Google’s default mTLS credentials.
    2. +
    3. Requesting bound tokens.
    4. +
    +

    Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses +generic terminology which may be imprecise or inappropriate in certain languages or environments.

    +

    Guidance

    +

    Access Default mTLS Credentials

    +

    Note: Before trying to use Google’s default mTLS credentials, the client must first check if the remote +Google API endpoint supports mTLS. If the remote endpoint does NOT support mTLS, the client should +connect to the endpoint using TLS. How to check if an endpoint supports mTLS is out of the scope of this +AIP. If the remote endpoint does support mTLS, the client should try to connect using mTLS first +before falling back to TLS. How to find the remote API’s mTLS endpoint is out of the scope of this AIP. +If users enabled Device Certificate Authentication (DCA), the client should give priority to DCA +as mTLS credentials.

    +

    To leverage Google’s default mTLS credentials, the client should retrieve configurations from +MDS. The MDS in all virtual environments (GCE, Serverless, and GKE) exposes an HTTP endpoint that +serves a configuration that specifies how to access Google's default mTLS credentials. This endpoint +is called the mTLS configuration endpoint.

    +

    The URL of the MDS's mTLS configuration endpoint is: +

    http://metadata.google.internal/computeMetadata/v1/instance/platform-security/auto-mtls-configuration
    +

    +

    The request to the MDS's mTLS configuration endpoint should be an HTTP GET request without any +parameter or payload.

    +

    The response from the MDS's mTLS configuration endpoint should contain the following +information:

    +
      +
    • The Secure Session Agent address: the client doesn’t have direct access to mTLS credentials. + The Secure Session Agent manages default mTLS credentials. The client can only use mTLS + credentials through the Secure Session Agent. The address can be an IP:port address or a file path + representing a Unix Domain Socket (UDS).
    • +
    +

    The client must follow the steps below to access Google’s default mTLS credentials.

    +
      +
    1. Check if the remote endpoint supports mTLS.
        +
      • If yes, go to step (2).
      • +
      • If not, go to step (3).
      • +
      +
    2. +
    3. Send a request to the MDS's mTLS configuration endpoint. If the request is successful and the + response contains a Secure Session Agent address, use the address to access Google's default mTLS + credentials, and go to step (4). If the request fails or the response contains an empty address, + go to step (3).
    4. +
    5. Fall back to TLS [END].
    6. +
    7. Configure the TLS library to use the Secure Session Agent (example) for client authentication + during the mTLS handshake.
    8. +
    +

    Request Bound Tokens

    +

    To access Google APIs with bound tokens, the client should request tokens from MDS. The MDS in +all virtual environments (GCE, Serverless, and GKE) exposes an HTTP endpoint that serves access tokens. +This endpoint is called the access token endpoint.

    +

    The URL of the MDS's access token endpoint is: +

    http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
    +

    +

    The request to the MDS's access token endpoint should be an HTTP GET request. The request may +have a “scopes” URL parameter with a list of comma-separated scopes. The auth library should allow +the caller to optionally specify a list of custom scopes, and add the “scopes” parameter to the request +when needed. Depending on the runtime environment, the request for custom scopes may be transparently +ignored or fulfilled by the server.

    +

    The response from the MDS's access token endpoint should contain an access token in the following +JSON format:

    +
    {
    +      "access_token": "YOUR_ACCESS_TOKEN",
    +      "expires_in": 3599,
    +      "token_type": "Bearer"
    + }
    +
    +

    The client must follow the steps below to request new access tokens for Google APIs if existing +tokens expire.

    +
      +
    1. Send an HTTP request to the MDS access token endpoint, retrieve the access token from the response + and go to step (2).
    2. +
    3. Attach the token from step (1) to the request to Google APIs.
    4. +
    +

    Changelog

    +
      +
    • 2020-12-14: Replace note on scopes with more detailed discussion.
    • +
    • 2021-07-13: Clarify GCE equivalent runtimes
    • +
    • 2023-02-16: Add mTLS configuration endpoint and unify the token binding flow.
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4116.html b/auth/4116.html new file mode 100644 index 0000000000..7ef9fc4cf8 --- /dev/null +++ b/auth/4116.html @@ -0,0 +1,386 @@ + + + + AIP-4116: Identity Tokens + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-4116

    +

    Identity Tokens

    +

    Identity Tokens (or ID Tokens) are JSON Web Tokens (JWT) with additional claims pertaining to the identity of the client or end-user (such as "email"). Which additional claims fields are included in the ID token are dependent on the ID +token provider.

    +

    The fetching of ID tokens is used to:

    + +

    The validation of ID tokens should be done by:

    + +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    This section describes the general guidance of ID tokens as a means of +authentication.

    +

    ID tokens obtained by Application Default Credentials

    +

    When a target audience is provided by the developer, ADC should fetch +an ID token with the credentials provided. For example, if service account keys +are provided, ADC will request an ID token from the OAuth token endpoint. If +virtual machine credentials are provided, ADC will request an ID token from +the virtual machine server.

    +

    Expected Behavior for Fetching ID Tokens

    +

    To support fetching ID Tokens, the auth libraries must follow the steps +below:

    +

    1. Accept a target audience parameter when Application Default Credentials +are requested. If a target audience and scope are both provided to the auth library, an exception must be thrown.

    +

    2. Virtual machine credentials return the ID token retrieved from the metadata +server's instance/service-accounts/default/identity endpoint, setting the +audience querystring parameter to the provided target audience.

    +

    3. Service account Keys use the JWT Bearer grant type, and set the +target_audience claim to the provided target audience. This will return a JSON +object containing an id_token key.

    +

    User Identity flows may be used to issue ID tokens, but are not required to.

    +

    Expected Behavior for Verifying ID Tokens

    +

    To support verifying ID Tokens, the auth libraries must provide a method to +validate a JWT token which can do the following:

    +

    1. Validate a JWT with an ES256 signature. +2. Validate JWT aud claim against a user-provided audience. +3. Validate JWT exp claim against the current timestamp.

    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4117.html b/auth/4117.html new file mode 100644 index 0000000000..9b636d2c34 --- /dev/null +++ b/auth/4117.html @@ -0,0 +1,1020 @@ + + + + AIP-4117: External Account Credentials (Workload Identity Federation) + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4117

    +

    External Account Credentials (Workload Identity Federation)

    +

    Using workload identity federation, your application can access Google Cloud +resources from Amazon Web Services (AWS), Microsoft Azure or any identity +provider that supports OpenID Connect (OIDC) or SAML 2.0.

    +

    Traditionally, applications running outside Google Cloud have used service +account keys to access Google Cloud resources. Using identity federation, +you can allow your workload to impersonate a service account. This lets you +access Google Cloud resources directly, eliminating the maintenance and +security burden associated with service account keys.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    This section describes the general guidance of supporting non-Google external +credentials (AWS, Azure, OIDC and SAML IdPs, etc) as a means of authentication.

    +

    Prerequisite

    +

    In order to use workload identity federation to access Google cloud resources +from non-Google cloud platforms, the following steps are needed to configure +workload identity pools, providers, service account impersonation and generate +the JSON configuration file to be used by the auth libraries.

    + +

    Configuration File Generation and Usage

    +

    After workload identity federation is configured, the JSON configuration file +should be generated. This sample shows how an AWS configuration file is +generated:

    +
    $ gcloud iam workload-identity-pools create-cred-config \
    +    projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \
    +    --service-account=$SERVICE_ACCOUNT_EMAIL \
    +    --aws \
    +    --output-file=$FILEPATH.json
    +
    +

    The following values would need to be replaced:

    +
      +
    • PROJECT_NUMBER: Project number of the project that contains the workload + identity pool.
    • +
    • POOL_ID: ID of the workload identity pool.
    • +
    • PROVIDER_ID: ID of the workload identity pool provider.
    • +
    • SERVICE_ACCOUNT_EMAIL: Email address of the service account to + impersonate.
    • +
    • FILEPATH: File to save configuration to.
    • +
    +

    If you are using AWS IMDSv2, +an additional flag --enable-imdsv2 should be added to the gcloud iam workload-identity-pools create-cred-config command:

    +
    $ gcloud iam workload-identity-pools create-cred-config \
    +    projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \
    +    --service-account=$SERVICE_ACCOUNT_EMAIL \
    +    --aws \
    +    --enable-imdsv2 \
    +    --output-file=$FILEPATH.json
    +
    +

    If you wish to configure the service account access token lifetime, +an additional flag --service-account-token-lifetime-seconds should be added to the gcloud iam workload-identity-pools create-cred-config command (this example uses an AWS configuration, but the token lifetime can be configured for all workload identity federation providers):

    +
    $ gcloud iam workload-identity-pools create-cred-config \
    +    projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \
    +    --service-account=$SERVICE_ACCOUNT_EMAIL \
    +    --aws \
    +    --service-account-token-lifetime-seconds=$TOKEN_LIFETIME \
    +    --output-file=$FILEPATH.json
    +
    +

    The service-account-token-lifetime-seconds flag is optional. If not provided, this defaults to one hour. The minimum allowed value is 600 (10 minutes) and the maximum allowed value is 43200 (12 hours). If a lifetime greater than one hour is required, the service account must be added as an allowed value in an Organization Policy that enforces the constraints/iam.allowServiceAccountCredentialLifetimeExtension constraint.

    +

    The external identities configuration file can be used with +Application Default Credentials. In order to use external identities with +Application Default Credentials, the full path to this file should be stored +in the GOOGLE_APPLICATION_CREDENTIALS environment variable.

    +
    export GOOGLE_APPLICATION_CREDENTIALS=/path/to/config.json
    +
    +

    The library can now automatically choose the right type of client and initialize +credentials from the context provided in the configuration file:

    +
    import google.auth
    +
    +credentials, project = google.auth.default()
    +
    +

    External account credentials can also be initialized explicitly using the +generated configuration file.

    +
    # Sample for Azure or OIDC/SAML providers.
    +import json
    +
    +from google.auth import identity_pool
    +
    +json_config_info = json.loads(function_to_get_json_config())
    +credentials = identity_pool.Credentials.from_info(json_config_info)
    +scoped_credentials = credentials.with_scopes(
    +    ['https://www.googleapis.com/auth/cloud-platform'])
    +
    +
    # Sample for AWS.
    +import json
    +
    +from google.auth import aws
    +
    +json_config_info = json.loads(function_to_get_json_config())
    +credentials = aws.Credentials.from_info(json_config_info)
    +scoped_credentials = credentials.with_scopes(
    +    ['https://www.googleapis.com/auth/cloud-platform'])
    +
    +

    Expected Behavior

    +

    The auth libraries should use the information in the JSON configuration file to +retrieve the external credentials and exchange them for Google access tokens +using the GCP Security Token Service (via the token exchange endpoint +https://sts.googleapis.com/v1/token) and then impersonating a service account +by calling the IamCredentials generateAccessToken API to access GCP +resources.

    +

    All external account JSON files must share the following fields:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameRequiredDescription
    typeYesThis identifies the new type of credential object. This must be "external_account"
    audienceYesThis is the STS audience which contains the resource name for the workload identity pool and the provider identifier in that pool.
    subject_token_typeYesThis is the STS subject token type based on the OAuth 2.0 token exchange spec.
    service_account_impersonation_urlNoThis is the URL for the service account impersonation request. If this is not available, the STS returned access token should be directly used without impersonation.
    service_account_impersonation.*NoThis object defines additional service account impersonation options. Only one field is currently supported: “token_lifetime_seconds": This is the requested access token lifetime, e.g. 2800.
    token_urlYesThis is the STS token exchange endpoint.
    credential_source.*YesThis object defines the mechanism used to retrieve the external credential from the local environment so that it can be exchanged for a GCP access token via the STS endpoint.
    +

    The auth libraries and applications must follow the steps below for all +types of external account credentials:

    +
      +
    • Check credential_source to determine the necessary logic to retrieve the + external credential which should be used to construct the subject token to + pass to the STS endpoint. This is covered in detail for every credential + configuration below.
    • +
    • Construct the STS request, based on rfc8693:
        +
      • STS audience should be constructed using the audience field.
      • +
      • grant_type must be urn:ietf:params:oauth:grant-type:token-exchange
      • +
      • requested_token_type must be + urn:ietf:params:oauth:token-type:access_token
      • +
      • subject_token_type is the subject_token_type field as described in + the RFC.
      • +
      • subject_token is the retrieved external credentials. Check the + subsequent sections on how this is retrieved in various environments.
      • +
      • scope: the list of space-delimited, case-insensitive OAuth scopes that + specify the desired scopes of the requested security token in the context + of the service or resource where the token should be used. If service + account impersonation is used, the cloud platform or IAM scope should be + passed to STS and then the customer provided scopes should be passed in the + IamCredentials call to generateAccessToken.
      • +
      • The STS token exchange URL should be the token_url (e.g. + https://sts.googleapis.com/v1/token).
      • +
      +
    • +
    • Send the STS token exchange request to get the Google access token and its + expiration.
    • +
    • If the service_account_impersonation_url is available, trigger service + account impersonation flow by POSTing to that endpoint with the previously + returned Google access token.
        +
      • If this is not available, end the flow and just use the STS access token + for authorization.
      • +
      • The list of scopes also need to be provided for this endpoint. The customer + provided scopes should be used for this endpoint.
      • +
      • In order to access this API, the (Cloud platform + https://www.googleapis.com/auth/cloud-platform or IAM scope + https://www.googleapis.com/auth/iam) are required in the underlying + access token.
      • +
      • The service account access token lifetime also needs to be provided for this endpoint. The value in + service_account_impersonation.token_lifetime_seconds will be used if it + was provided, otherwise it will default to 1 hour.
      • +
      +
    • +
    +

    Determining the subject token in AWS

    +

    External account configuration JSON files should contain the following +information in the credential_source object to facilitate retrieval of AWS +credentials to be passed as subject tokens to the GCP STS token exchange +endpoint.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameRequiredDescription
    environment_idYesThis is the environment identifier, of format aws${version}. A version should be specified to indicate to the auth library whether breaking changes were introduced to the underlying AWS implementation. So if aws1 is supported in the current version of the library but a credential file with aws2 is provided, an error should be thrown instructing the developer to upgrade to a newer version of the library.
    region_urlNoThis URL should be used to determine the current AWS region needed for the signed request construction when the region environment variables are not present.
    urlNoThis AWS metadata server URL should be used to retrieve the access key, secret key and security token needed to sign the GetCallerIdentity request. The $ROLE_NAME should be retrieved from calling this endpoint without any parameter and then calling again with the returned role name appended to this URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME
    regional_cred_verification_urlYesThis defines the regional AWS GetCallerIdentity action URL. This URL should be used to determine the AWS account ID and its roles. This should not actually be called by the Auth libraries. It should be called on the STS token server. The region should be substituted by SDK, e.g. sts.eu-west-1.amazonaws.com.
    imdsv2_session_token_urlNoPresence of this URL enforces the auth libraries to fetch a Session Token from AWS. This field is required for EC2 instances using IMDSv2. This Session Token would later be used while making calls to the metadata endpoint.
    +

    The JSON file for AWS configuration files should have the following form:

    +
    {
    +  "type": "external_account",
    +  "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
    +  "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request",
    +  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken",
    +  "token_url": "https://sts.googleapis.com/v1/token",
    +  "credential_source": {
    +    "environment_id": "aws1",
    +    "region_url": "http://169.254.169.254/latest/meta-data/placement/availability-zone",
    +    "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials",
    +    "regional_cred_verification_url": "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15",
    +    "imdsv2_session_token_url": "http://169.254.169.254/latest/api/token"
    +  }
    +}
    +
    +

    The auth libraries and applications must follow the steps below:

    +
      +
    • Check credential_source for environment ID. If the environment ID is + aws${version}, this should be an AWS native credential.
    • +
    • Inspect the version in the environment ID. If this is a newer unexpected + error, trigger an error that the auth library needs to be updated to handle + this type of credentials.
    • +
    • Validate the host for the url, regional_url and + imdsv2_session_token_url fields if they are provided. The host should + either be 169.254.169.254 or fd00:ec2::254.
    • +
    • If imdsv2_session_token_url is available, then fetch session token + from imdsv2_session_token_url. Note: only perform this step if you + need to communicate with the metadata server to fetch the region and/or + the security credentials
    • +
    • Check the environment variables in the following order (AWS_REGION and + then the AWS_DEFAULT_REGION) to determine the AWS region. If found, skip + using the AWS metadata server to determine this value.
    • +
    • If the region environment variables are not provided, use the region_url + to determine the current AWS region. The API returns the zone name, e.g. + us-east-1d. The region should be determined by stripping the last + character, e.g. us-east-1.
    • +
    • Check the environment variables AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY and the optional AWS_SESSION_TOKEN for the AWS + security credentials. If found, skip using the AWS metadata server to + determine these values.
    • +
    • If url is available and the security credentials environment variables + are not provided:
        +
      • Call url to retrieve the attached AWS IAM role name to the current + instance.
      • +
      • Call url/$ROLE_NAME to get the access key, secret key and security + token needed to sign the GetCallerIdentity request.
      • +
      +
    • +
    • +

      Construct the AWS signed request (AWS Signature Version 4) using the + GetCallerIdentity regional_cred_verification_url (with the region + substituted). This should be serialized by formatting it as a url-encoded + JSON and passed as the subject_token to STS endpoint. + Here is a sample of the JSON format used:

      +

      {
      +  "url": "https://sts.us-east-1.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15",
      +  "headers": [
      +    {
      +      "value": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
      +      "key": "x-goog-cloud-target-resource"
      +    },
      +    {
      +      "value": "20200228T225005Z",
      +      "key": "x-amz-date"
      +    },
      +    {
      +      "value": "AWS4-HMAC-SHA256 Credential=AKIASOZTBDV4D7ABCDEDF/20200228/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token;x-goog-cloud-target-resource, Signature=abcedefdfedfd",
      +      "key": "Authorization"
      +    },
      +    {
      +      "value": "sts.us-east-1.amazonaws.com",
      +      "key": "host"
      +    },
      +    {
      +      "value": "IQoJb3JpZ2luX2VjEIz//////////wEaCXVzLWVh...",
      +      "key": "x-amz-security-token"
      +    }
      +  ],
      +  "method": "POST",
      +  "body": ""
      +}
      +
      +For the AWS token, STS requires a special header x-goog-cloud-target-resource to recognize that the token is for a specific workload identity provider.

      +
    • +
    +

    Determining the subject token in Microsoft Azure and URL-sourced credentials

    +

    External account configuration JSON files should contain the following +information in the credential_source object to facilitate retrieval of Azure +and other URL-sourced credentials to be passed as subject tokens to the GCP STS +token exchange endpoint.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameRequiredDescription
    urlYesThis defines the local metadata server to retrieve the external credentials from. For Azure, this should be the Azure Instance Metadata Service (IMDS) URL used to retrieve the Azure AD access token.
    headersNoThis defines the headers to append to the GET request to credential_source.url.
    format.typeNoThis indicates the format of the URL response. This can be either "text" or "json". The default should be "text".
    format.subject_token_field_nameNoRequired for JSON URL responses. This indicates the JSON field name where the subject_token should be stored.
    +

    The JSON file for URL-sourced configuration files (OIDC / SAML) should have the +following form:

    +
    {
    +  "type": "external_account",
    +  "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
    +  "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
    +  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken",
    +  "token_url": "https://sts.googleapis.com/v1/token",
    +  "credential_source": {
    +    "url": "http://localhost:5000/token",
    +    "format": {
    +      "type": "json",
    +      "subject_token_field_name": "id_token"
    +    }
    +  }
    +}
    +
    +

    Azure configuration files are a type of OIDC URL-sourced credentials.

    +
    {
    +  "type": "external_account",
    +  "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
    +  "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
    +  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken",
    +  "token_url": "https://sts.googleapis.com/v1/token",
    +  "credential_source": {
    +    "headers": {
    +      "Metadata": "True"
    +    },
    +    "url": "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
    +    "format": {
    +      "type": "json",
    +      "subject_token_field_name": "access_token"
    +    }
    +  }
    +}
    +
    +

    The auth libraries and applications must follow the steps below:

    +
      +
    • Check credential_source has a url field and no environment_id, + otherwise skip the rest of the steps.
    • +
    • An HTTP GET request should be sent to this local url while injecting + the headers key/values (if provided in the configuration file) in the + request header. The request should respond with the external credentials + subject token to be passed to STS token endpoint.
    • +
    • Before parsing the token, check the format field.
    • +
    • If the format is not available, assume the external credential returned + by the URL response is provided in plain text format.
    • +
    • If available, check if the type is json
        +
      • If json, check the subject_token_field_name. + For Azure, this is set to access_token.
      • +
      • Parse the file as JSON and then retrieve the external credential from + the field name based on the value of subject_token_field_name.
      • +
      +
    • +
    +

    Determining the subject token in file-sourced credentials

    +

    External account configuration JSON files contain the following information +in the credential_source object to facilitate retrieval of file-sourced +credentials to be passed as subject tokens to the GCP STS token exchange +endpoint.

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameRequiredDescription
    fileYesThis is the source of the credential. This should be used for a credential locally available. This should take precedence over url when both are provided.
    format.typeNoThis indicates the format of the file where the token is stored. This can be either "text" or "json". The default should be "text".
    format.subject_token_field_nameNoRequired for JSON file formats. This indicates the JSON field name where the subject_token should be stored.
    +

    The JSON file for file-sourced configuration files (OIDC / SAML) should have +the following form:

    +
    {
    +  "type": "external_account",
    +  "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
    +  "subject_token_type": "urn:ietf:params:oauth:token-type:saml2",
    +  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL:generateAccessToken",
    +  "token_url": "https://sts.googleapis.com/v1/token",
    +  "credential_source": {
    +    "file": "/var/run/saml/assertion/token"
    +  }
    +}
    +
    +

    The auth libraries and applications must follow the steps below:

    +
      +
    • Check credential_source has a file field and no environment_id. If not, + this is not a file-sourced credential and the proceeding steps do not apply.
    • +
    • Get the external credential from the file location specified by the + credential_source.file field.
    • +
    • Before parsing the token, check the format field.
    • +
    • If the format is not available, assume the external credential is + provided in plain text format.
    • +
    • If available, check if the type is json
        +
      • If json, check the subject_token_field_name.
      • +
      • Parse the file as JSON and then retrieve the external credential from + the field name based on the value of subject_token_field_name.
      • +
      +
    • +
    +

    Determining the subject token in executable-sourced credentials

    +

    External account configuration JSON files contain the following information +in the credential_source object to facilitate retrieval of executable-sourced +credentials to be passed as subject tokens to the GCP STS token exchange +endpoint.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameRequiredDescription
    executableYesHolds the information necessary to run the executable.
    executable.commandYesSpecifies the full command to run to retrieve the subject token. This can include arguments. Must be an absolute path for the program.
    executable.timeout_millisNoSpecifies the timeout duration, in milliseconds. Defaults to 30 seconds when not provided.
    executable.output_fileNoSpecifies the absolute path to the output file where the executable will cache the response. By specifying this path, the auth libraries will first check this location before running the executable. The format of the file should match the JSON format expected by the auth libraries defined below.
    +

    The JSON file for executable-sourced configuration files (OIDC / SAML) should have +the following form:

    +
    {
    +  "type": "external_account",
    +  "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
    +  "subject_token_type": "urn:ietf:params:oauth:token-type:saml2",
    +  "token_url": "https://sts.googleapis.com/v1/token",
    +  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$EMAIL@project.iam.gserviceaccount.com:generateAccessToken",
    +  "credential_source": {
    +    "executable": {
    +      "command": "/path/to/executable --arg1=value1 --arg2=value2",
    +      "timeout_millis": 5000,
    +      "output_file": "/path/to/cached/credentials"
    +    }
    +  }
    +}
    +
    +

    To use executable-sourced credentials, the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable must be set to 1.

    +

    Additionally, the executable must adhere to the following response format:

    +

    Successful responses:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameTypeDescription
    versionnumberThe version of the JSON output. Currently only version 1 is supported.
    successbooleanThe status of the response. True in this case.
    token_typestringThe 3rd party subject token type. Must be urn:ietf:params:oauth:token-type:jwt, urn:ietf:params:oauth:token-type:id_token, or urn:ietf:params:oauth:token-type:saml2.
    id_token OR saml_responsestringThe 3rd party OIDC token or SAML response.
    expiration_timenumberThe optional 3rd party subject token expiration time in seconds (unix epoch time). Only required in the response when an output file is specified in the credential configuration.
    +

    A sample successful executable OIDC response: +

    {
    +  "version": 1,
    +  "success": true,
    +  "token_type": "urn:ietf:params:oauth:token-type:id_token",
    +  "id_token": "...",
    +  "expiration_time": 1620499962
    +}
    +

    +

    A sample successful executable SAML response: +

    {
    +  "version": 1,
    +  "success": true,
    +  "token_type": "urn:ietf:params:oauth:token-type:saml2",
    +  "saml_response": "...",
    +  "expiration_time": 1620499962
    +}
    +

    +

    Error responses:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameTypeDescription
    versionnumberThe version of the JSON output. Currently only version 1 is supported.
    successbooleanThe status of the response. False in this case.
    codestringThe error code.
    messagestringThe error message.
    +

    A sample executable error response: +

    {
    +  "version": 1,
    +  "success": false,
    +  "code": "401",
    +  "message": "Caller not authorized."
    +}
    +

    +

    The auth libraries and applications must follow the steps below:

    +
      +
    • Check credential_source has an executable field and no environment_id. If not, + this is not a executable-sourced credential and the proceeding steps do not apply.
    • +
    • Retrieve the external credential's executable information from the + credential_source.executable field.
    • +
    • Check that the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable is set to 1. If not, error out.
    • +
    • Before the next step, check if credential_source.executable.output_file was specified in the credential configuration.
        +
      • If present, check if there is an executable response at that location.
      • +
      • If the response is valid and unexpired, or there is no response at that location, continue execution.
      • +
      • If the response is malformed or invalid, error out.
      • +
      +
    • +
    • Ensure the following environment variables will be available to the executable:
        +
      • GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE: The audience field from the credential configuration. Must always be present.
      • +
      • GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE: The subject token type. Must always be present.
      • +
      • GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL: The service account email. Only present when service account impersonation is used.
      • +
      • GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE: The output file location from the credential configuration. Only present when specified in the credential configuration.
      • +
      +
    • +
    • Run the command specified at credential_source.executable.command.
        +
      • Fail in the following scenarios:
          +
        • The executable failed to complete in the timeout duration specified.
        • +
        • The executable's response is invalid, was unsuccessful or expired.
        • +
        • The executable finished with a non-zero exit code.
        • +
        +
      • +
      +
    • +
    • Parse the executable response as JSON and then retrieve the external credential from + the field name based on the value of token_type.
        +
      • The token_type value must be urn:ietf:params:oauth:token-type:jwt, + urn:ietf:params:oauth:token-type:id_token, or urn:ietf:params:oauth:token-type:saml2.
      • +
      • If the token_type is urn:ietf:params:oauth:token-type:saml2, the subject token will be parsed from the saml_response field.
      • +
      • Otherwise it will be parsed from the id_token field.
      • +
      +
    • +
    +

    Changelog

    +
      +
    • 2025-10-17: Corrections in specification and examples for External Account Credentials (AIP 4117).
    • +
    • 2021-12-10: Add AIP for External Account Credentials (AIP 4117).
    • +
    • 2022-05-18: Document executable-sourced credentials (AIP 4117).
    • +
    • 2022-08-31: Document configurable token lifetime (AIP 4117).
    • +
    • 2023-09-12: Mark region_url as optional (AIP 4117).
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4118.html b/auth/4118.html new file mode 100644 index 0000000000..c6fb8389d4 --- /dev/null +++ b/auth/4118.html @@ -0,0 +1,482 @@ + + + + AIP-4118: Mutual Authentication Using Workload Credentials + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-4118

    +

    Mutual Authentication Using Workload Credentials

    +

    Mutual TLS (a.k.a mTLS) authentication enables authentication of both client and +server identities in a TLS handshake. With workload credentials, applications +running in Google Cloud can authenticate to Google APIs using X.509 SPIFFE +Verifiable Identity Documents (SVIDs). These SVIDs are X.509 certificates +that contain SPIFFE IDs specifying the identity of the certificate owners. +mTLS authentication using X.509 SVIDs occurs when the client uses an X.509 SVID +when performing the TLS handshake.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    If users enable token binding, they should do so via ADC. This section +describes the general guidance of supporting such authentication.

    +

    Provisioning Workload Credentials in Google Cloud

    +

    On Google Cloud, workload credentials should be provisioned using one of the +following methods:

    + +

    In order for workload credentials to be properly used, the auth libraries +must support the automatic switching of the service endpoint to its mTLS +counterpart.

    +

    Using Workload Credentials

    +

    Users should configure ADC to use workload credentials via the +certificate configuration gcloud metadata file. Workload credentials can be +added as a "cert_configs" type as follows:

    +
    {
    +  "version": 1
    +  "cert_configs": {
    +    "workload": {
    +      "cert_path": "path/to/cert/file"
    +      "key_path": "path/to/key/file"
    +      "workload_identity_provider": "..."
    +      "authenticate_as_identity_type": "gsa/native"
    +      "service_account_email": "..."
    +    },
    +    "keychain": {
    +      ...
    +    },
    +    "pkcs11": {
    +      ...
    +    },
    +    "windows": {
    +      ...
    +    },
    +  },
    +  "libs": {
    +   ...
    +  }
    +}
    +
    +

    For Linux and macOS platforms, the above metadata file is located in the +well-known gcloud config directory at +"~/.config/gcloud/certificate_config.json". Note that the default location +of this file can be changed using the GOOGLE_API_CERTIFICATE_CONFIG +environment variable.

    +

    The following lists the fields of the "workload" certificate info type that +are relevant to workload credentials:

    +
      +
    • +

      "cert_path": The specified value will be used as the full path to locate +the workload certificate file. This file must contain a PEM-encoded +X.509 certificate chain (ordered from leaf to root) where the leaf +certificate is a valid X.509 SVID. The chain may consist of only the +leaf certificate.

      +
    • +
    • +

      "key_path": The specified value will be used as the full path to locate +the workload private key file. This file must contain a PEM-formatted +private key associated with the X.509 certificate specified by +“cert_path”.

      +
    • +
    +

    The description of the "workload_identity_provider", +"authenticate_as_identity_type" and "service_account_email" fields can +be found in mTLS Token Binding.

    +

    To enable mutual authentication to Google APIs using workload credentials, the +"workload" section and its "cert_path" and "key_path" values must be +present in the "~/.config/gcloud/certificate_config.json" configuration +file.

    +

    Expected Behavior

    +

    Support for mTLS authentication to Google APIs using workload credentials +must give priority to user mTLS endpoint override via client options. The +auth libraries must follow the steps below:

    +
      +
    • +

      Locate the workload certificate and private key files using the above +config file. If one of these files is not present, mTLS using workload +credentials may be disabled. The auth libraries must check that the +public and private keys in the certificate and key files match before +passing them to the TLS library.

      +
        +
      • Occasional mismatches may happen, since during certificate rotation the + client library may read the two files while another process is replacing + them. In that case, the library must retry reading the certificate + and private key files and checking their match status, up to a maximum + of four attempts. The library should wait for 5 seconds between + attempts.
      • +
      • If the certificate and private key files are loaded in memory (as + opposed to being read from disk for every mTLS connection), the auth + libraries must periodically reload them (at least every 10 minutes + or when the certificate expires) to refresh their copies in memory after + the infrastructure rotates them. Refreshing the credentials must be + done in a background thread and not upon usage.
      • +
      +
    • +
    • +

      Configure the TLS library to use the found, and matched, certificate and +key for client authentication during the TLS handshake.

      +
    • +
    • +

      If the user specifies the endpoint override via client options, use it as is +and connect to the specified endpoint using mTLS.

      +
    • +
    • +

      If the user does not specify the endpoint override, use the default mTLS +endpoint if the certificate and key files exist and the default regular +endpoint otherwise.

      +
    • +
    +

    Note that mTLS 1.3 must be the only supported version to preserve client +identity and certificate confidentiality.

    +

    One implication of the above logic is that if the user enables mTLS +authentication using workload credentials, provides valid certificate and key +files, and specifies a non-mTLS endpoint override, the client libraries +should use the certificate and key anyway and let the server decide what to +do. This avoids introducing client-side logic that parses whether the endpoint +override is an mTLS URL, since the URL pattern may change at any time.

    +

    Obtaining the Default mTLS Endpoint

    +

    The default mTLS endpoint for a service should be read from the Discovery +Document field "mtlsRootUrl" instead of generated via regex patterns.

    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/auth/4119.html b/auth/4119.html new file mode 100644 index 0000000000..7296d462fc --- /dev/null +++ b/auth/4119.html @@ -0,0 +1,483 @@ + + + + AIP-4119: mTLS Token Binding + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-4119

    +

    mTLS Token Binding

    +

    Token binding allows issuing Google access tokens that are bound to mTLS +credentials. The advantage of such mTLS bound tokens is that they are meant to +only be used over secure channels established via mTLS credentials they are +bound to. Therefore, using bound tokens is more secure than bearer tokens which +can be stolen and adversarially replayed.

    +

    This AIP describes the flow of (1) obtaining access tokens bound to X.509 +certificate identities, called identity-bound tokens and (2) how to use them to +access Google APIs using the Google auth libraries.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments.

    +

    Guidance

    +

    If users enable token binding, they should do so via ADC. This section +describes the general guidance of supporting such tokens.

    +

    Prerequisites

    +

    Identity-bound access tokens require that the clients have +X.509 SPIFFE Verifiable Identity Documents (SVIDs). Mutual Authentication +Using Workload Credentials describes how such SVIDs are provisioned in +Google Cloud.

    +

    Additionally, identity-bound access tokens tokens require configuring a workload +identity pool and identity provider with Google Cloud's IAM. The instructions on +how to do this are out of scope of this AIP.

    +

    Using mTLS Token Binding

    +

    The auth libraries must support the following values in the +"~/.config/gcloud/certificate_config.json" configuration file. Note that the +default location of this file can be changed using the +GOOGLE_API_CERTIFICATE_CONFIG environment variable.

    +
    {
    +  "version": 1
    +  "cert_configs": {
    +    "workload": {
    +      "cert_path": "path/to/cert/file"
    +      "key_path": "path/to/key/file"
    +      "workload_identity_provider": "..."
    +      "authenticate_as_identity_type": "gsa/native"
    +      "service_account_email": "..."
    +    },
    +    "keychain": {
    +      ...
    +    },
    +    "pkcs11": {
    +      ...
    +    },
    +    "windows": {
    +      ...
    +    },
    +  },
    +  "libs": {
    +   ...
    +  }
    +}
    +
    +

    The following lists the fields relevant to mTLS token binding configuration:

    +
      +
    • "workload_identity_provider": The specified value will be used to +populate the request to Security Token Service (STS) to request +identity-bound access tokens. This value refers to the fully qualified name +of the workload identity pool and identity provider configured in IAM. The +specified value must be of the following format.
    • +
    +
    "workload_identity_provider":"//iam.googleapis.com/projects/<project_number>/locations/global/workloadIdentityPools/<pool_identifier>/providers/<provider_identifier>"
    +
    +
      +
    • +

      "authenticate_as_identity_type": This field specifies what identity is +used to authenticate to Google APIs. The value can be set to gsa or +native, where gsa is the GCP service account of the workload, e.g., the +GCP service account of a GCE VM, and native is the native workload +identity, e.g., the GKE pod kubernetes service account. If not specified, +the default value is gsa.

      +
    • +
    • +

      "service_account_email": If set, the specified value will be used to +populate the request to the IAM Credentials service to request +identity-bound access tokens. This value refers to the service account email +to be used for resource access. If not set, the service account email will +be determined automatically by querying the following Metadata Service +endpoint: +http://metadata/computeMetadata/v1/instance/service-accounts/default/email. +The value of this field is only relevant if +"authenticate_as_identity_type" is set to gsa.

      +
    • +
    +

    The description of the "cert_path" and "key_path" fields can be found in +Mutual Authentication Using Workload Credentials.

    +

    To enable using token binding when communicating with Google APIs the following +conditions are required:

    +
      +
    • +

      Mutual Authentication Using Workload Credentials must be enabled.

      +
    • +
    • +

      The "workload_identity_provider" must be present, +"authenticate_as_identity_type" may be set and +"service_account_email" may be set in the "workload" +section of the "~/.config/gcloud/certificate_config.json" configuration +file.

      +
    • +
    +

    Expected Behavior

    +

    To support the usage of identity-bound access tokens, the auth libraries +must follow the steps below when sending requests to Google APIs:

    +
      +
    1. +

      Connect to the mTLS endpoint of the STS API using the workload +credentials provisioned as described in Mutual Authentication Using +Workload Credentials. This endpoint must be +sts.mtls.googleapis.com.

      +
    2. +
    3. +

      Send an HTTP request to STS’s ExchangeToken method requesting an +identity-bound token using the information in the +"workload_identity_provider" field in the +"~/.config/gcloud/certificate_config.json" configuration file. The +scope of the requested token must be +https://www.googleapis.com/auth/iam.

      +
    4. +
    5. +

      Connect to the mTLS endpoint of the IAM Credentials Service API using +the workload credentials provisioned as described in Mutual Authentication +Using Workload Credentials. This endpoint must be +iamcredentials.mtls.googleapis.com.

      +
    6. +
    7. +

      If "authenticate_as_identity_type" is set to gsa, send an HTTP +request to the IAM Credentials Service’s GenerateAccessToken method +requesting an identity bound token asserting the service account email in +the "service_account_email" field in the +"~/.config/gcloud/certificate_config.json" configuration file. The +scope of this token must be the same scope defined by the user for +accessing the requested Google API.

      +
    8. +
    9. +

      Attach the returned token in Step 4 to the request. Note that this request +must be sent over an mTLS channel using the same workload credentials +in Step 1.

      +
    10. +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/beta-blocker.html b/beta-blocker.html new file mode 100644 index 0000000000..abd9238b45 --- /dev/null +++ b/beta-blocker.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

    Redirecting…

    + Click here if you are not redirected. + + \ No newline at end of file diff --git a/client-libraries.html b/client-libraries.html new file mode 100644 index 0000000000..112a752ccd --- /dev/null +++ b/client-libraries.html @@ -0,0 +1,397 @@ + + + + Client libraries AIPs + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + + +
    +
    + +
    +

    Client libraries

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    4210 + Client library generators +
    4221 + Client-side retry +
    4222 + Routing headers +
    4223 + Client-side payload validation +
    4231 + Parsing resource names +
    4232 + Method signatures +
    4233 + Automatic pagination +
    4234 + Common service client mixins +
    4235 + Automatically populate fields in the request message +
    4236 + Version-aware clients +
    4290 + Docker interface +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4210.html b/client-libraries/4210.html new file mode 100644 index 0000000000..a0baf5a13a --- /dev/null +++ b/client-libraries/4210.html @@ -0,0 +1,540 @@ + + + + AIP-4210: Client library generators + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4210

    +

    Client library generators

    +

    API guidelines exist in order to promote simple, intuitive, and consistent +APIs. Users familiar with APIs that generally adhere to AIP guidance are able +to take what they learn in prior APIs and apply it to new ones.

    +

    Client libraries provide a mechanism for users to get started with APIs more +quickly, by simplifying common concerns (such as auth) and by a language-native +way to call API endpoints and receive language-native responses. However, for +these libraries to provide the most value, they also must be simple, intuitive, +and consistent. Code generators provide a means for producing consistent client +libraries at scale.

    +

    Code generators following the standards in these AIPs are known as "generated +API client generators", or GAPIC generators for short. The resulting +libraries are colloquially called GAPICs.

    +

    Note: Because this AIP describes guidance and requirements in a +language-neutral way, it uses generic terminology which may be imprecise or +inappropriate in certain languages or environments (for example, the use of the +term class even though languages such as Go do not have classes). This AIP's +particular use of vocabulary is best understood as an explanation of +principles, and precise adherence to exact vocabulary in this AIP is not an +expectation.

    +

    Guidance

    +

    The general flow of code generation for client libraries and supporting code in +most supported languages is outlined below.

    +

    Note: Exceptions to this pattern are typically due to use of a unique stack +e.g. Node.js use of protobuf.js and grpc-node which don't have code +generation, or Python using a protobuf wrapper in proto-plus-python, but the +general GAPIC flow remains the same.

    +
    digraph {
    +  node [ style="filled,solid" shape=box fontname="Roboto" ];
    +  splines=ortho;
    +  nodesep=0.3;
    +  center=true;
    +
    +  proto [ label="API Protobuf\nDescriptors" shape=rectangle fillcolor=aliceblue ];
    +
    +  subgraph cluster_code_generators {
    +    rank = same;
    +    style = filled;
    +    fillcolor = lightgrey;
    +    node [ shape=oval ];
    +
    +    protobuf [ label="protobuf\ngenerator" fillcolor=deepskyblue3 ];
    +    grpc [ label="gRPC\ngenerator" fillcolor=gold3 ];
    +    gapic [ label="GAPIC\ngenerator" fillcolor=darkseagreen ];
    +  }
    +
    +  proto -> protobuf;
    +  proto -> grpc;
    +  proto -> gapic;
    +
    +  subgraph cluster_generated_code {
    +    rank = same;
    +    style = filled;
    +    fillcolor = lightgrey;
    +    node [ shape=rectangle ];
    +
    +    protobuf_output [ label="Message & Enum\nCode" fillcolor=deepskyblue3 ];
    +    grpc_output [ label="Server & Client\nStubs" fillcolor=gold3 ];
    +    gapic_output [ label="Google API\nClient" fillcolor=darkseagreen ];
    +  }
    +
    +  protobuf -> protobuf_output;
    +  grpc -> grpc_output;
    +  gapic -> gapic_output;
    +
    +  assembly [ label="Package\nassembly" shape=oval fillcolor=aliceblue ];
    +
    +  protobuf_output -> assembly
    +  grpc_output -> assembly
    +  gapic_output -> assembly
    +
    +  assembled_package [ label="Package of\ngenerated code" fillcolor=aliceblue ];
    +
    +  assembly -> assembled_package
    +}
    +
    +

    The following sections focus on the "GAPIC generator" in the above diagram.

    +

    Protobuf plugins

    +

    The protobuf compiler, protoc, supports a plugin system for code +generation. The plugin system allows plugins to be written in and for any +language.

    +

    Code generators must be implemented as protoc plugins. The following +rules apply to the implementation of a client library generator as a protoc +plugin:

    +
      +
    • The plugin should be written in the language being targeted for + generation.
    • +
    • protoc expects plugins to be an executable in $PATH, and named + protoc-gen-{plugin_name}, corresponding to the --{plugin_name}_out option + sent to the protoc executable. As such:
        +
      • the plugin executable should be named protoc-gen-{lang}_gapic
      • +
      • the plugin option should follow the convention --{lang}_gapic_out
      • +
      +
    • +
    • The plugin must not leverage protoc "insertion points". Despite the + protoc plugin documentation indicating the existence of insertion points, + their use is unsupported and discouraged by the Protobuf team.
    • +
    +

    CLI options

    +

    Code generators should be able to run without any options or flags if at +all possible, and be able to generate a valid library from only the protos. If +options are required, protoc allows them to be passed as +--{plugin_name}_opt, and the string provided here becomes set as the +parameter string on the CodeGeneratorRequest.

    +

    Important: The CodeGeneratorRequest.parameter value is a comma-delimited +string of all associated plugin option values that appear at execution time. +This means that commas cannot be used to delimit list-like plugin option values.

    +

    Code generators must not rely on environment variables for configuration.

    +

    Expected behavior

    +

    This section outlines the expected behavioral attributes of the output of the +client library generator (in other words: the libraries that the generators +write). Client libraries must implement these concepts in order to be +considered complete.

    +

    Messages and Enums

    +

    Client library generators should not generate code for message or enum +descriptors which are already generated by the Protobuf-provided code +generators.

    +

    Services and methods

    +

    Each of the service and rpc directives in the requested protos must be +represented in the client library output, unless the language or transport is +unable to support it.

    +

    Note: While how to accomplish this may vary from language to language, in +most classical languages it is probably a class for each service, containing +methods for each RPC.

    +
      +
    • The classes generated for each service directive must honor the + google.api.default_host annotation if it is provided, and use that host as + the default hostname. These classes should provide a mechanism for the + end user to override the hostname.
        +
      • If the google.api.default_host annotation is not present on the service + directive, then the generated class should require a hostname when it + is instantiated.
      • +
      +
    • +
    • Additionally, if the classes generated for each service support using OAuth + and service credentials, they must honor the google.api.oauth_scopes + annotation (if it is provided), and use these scopes by default.
    • +
    • Services that have set the deprecated protobuf option to true should have an + equivalent deprecation tag generated in the generated class. If applicable, this + tag may include a comment that specifies when the service will be removed, which + is typically the next major version update. Similarly, RPCs with this option set + to true should have their generated language method(s) marked as deprecated.
    • +
    • Finally, service classes must also accept credentials, which are used + appropriately when requests are made. (Accepting a custom gRPC channel + satisfies this requirement.)
    • +
    • Code generators must not generate client stub classes, that would + normally be generated by gRPC, in addition to client library classes.
    • +
    +

    Long-running operations

    + + +

    An RPC is considered to be a "long-running" RPC if (and only if) the RPC's +return type is google.longrunning.Operation. Any API which has one or +more RPCs returning an Operation is expected to implement the Operations +service.

    +

    Because the response and metadata fields in Operation are of the +type google.protobuf.Any, it is necessary to know what message to use to +deserialize them. This is annotated on the RPC using the +google.longrunning.operation_info annotation.

    +

    Note: The values in this struct are strings, not message objects; the +code generator uses the string to determine the appropriate message to use. +Strings with no period (.) character refer to a message in the same proto +package.

    +

    Code generators should fail with an error if a type is provided in the +operation_info annotation which was not imported, or if no response type +or metadata type is provided. Code generators should fail with an error if +either the response_type or metadata_type keys are omitted.

    +

    Client libraries must honor the LRO interface; if an RPC has an +Operation as its return type, the generated method must intercept it +and return an appropriate idiomatic object for resolving the LRO (such as a +Future or Promise bound to the underlying Operation object).

    +

    Streaming

    +

    Client libraries must implement streaming to the extent that their +supporting transports allow. An RPC is considered to be streaming if the +stream keyword is present on the argument or response type. This is present +in the MethodDescriptorProto message using the client_streaming and +server_streaming keys.

    + + + +

    Changelog

    +
      +
    • 2023-06-22: Added code gen diagram, message/enum guidance, and cleaned up + plugin & option guidance.
    • +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4221.html b/client-libraries/4221.html new file mode 100644 index 0000000000..9b96782a38 --- /dev/null +++ b/client-libraries/4221.html @@ -0,0 +1,450 @@ + + + + AIP-4221: Client-side retry + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4221

    +

    Client-side retry

    +

    Many APIs have error modes that a client should retry. These error modes vary +across APIs, leaving users to hand-write retry logic around client libraries +based on available documentation. Client libraries have the opportunity to help +by implementing automatic client-side retries of well-known error modes.

    +

    Guidance

    +

    Client libraries should provide automatic, client-side retry logic. Client +libraries with automatic client-side retry logic should provide a mechanism +for users to specify error codes to be retried and delays for those retries.

    +

    Client libraries for API systems that support remotely-resolved client retry +configuration should respect the remotely-resolved configuration. However, +user configuration must be honored.

    +

    Client library generators implementing this feature must accept a retry +configuration. This retry configuration may be supplied via a protoc +plugin option. In the absence of a given retry configuration, client library +generators should not generate a default retry configuration.

    +

    Retry implementation

    +

    Client libraries should make client-side retry transparent to the user. The +user should not have to opt-in to client-side retry explicitly, but the +user must have a way to disable client-side retry altogether.

    +

    Retry configuration mechanisms

    +

    Client libraries should surface a mechanism through which users may control +the client-side retry configuration, including disabling client-side retry +altogether.

    +

    For example, Go client libraries for gRPC services can supply an option, +WithDisableRetry, at client initialization to disable the use of the +automatic client-side retry logic.

    +
    opts := []grpc.DialOption{
    +  grpc.WithDisableRetry(),
    +  grpc.WithTransportCredentials(creds),
    +}
    +
    +cc, err := grpc.Dial("my.api.net:443", opts...)
    +if err != nil {
    +  // ...
    +}
    +
    +

    Remotely-resolved client configuration

    +

    Some API systems have built-in mechanisms for clients to retrieve a +remotely-defined configuration that includes client-side retry configuration.

    +

    For example, gRPC supports the resolution of client configuration that +includes configuration for automatic client-side retry.

    +

    Client libraries should respect the remotely-resolved configuration, except +when a user overrides it via the aforementioned client library +retry configuration mechanisms.

    +

    Client library generator retry configuration

    +

    Client library generators that implement client-side retry must accept a +retry configuration. This is to enable API producers to supply a retry +configuration that best-suits their service.

    +

    For example, gRPC client-side retry is configured with a RetryPolicy +within a gRPC Service Config. Here is a configuration that applies the +RetryPolicy to all methods in the google.example.library.v1.LibraryService +service, except for those that are explicitly named which get no RetryPolicy.

    + +
    {
    +  "methodConfig": [{
    +    "name": [{ "service": "google.example.library.v1.LibraryService" }],
    +    "waitForReady": true,
    +    "timeout": "60s",
    +    "retryPolicy": {
    +      "maxAttempts": 3,
    +      "initialBackoff": "1s",
    +      "maxBackoff": "10s",
    +      "backoffMultiplier": 2,
    +      "retryableStatusCodes": ["UNAVAILABLE"]
    +    }
    +  },
    +  {
    +    "name": [
    +      { "service": "google.example.library.v1.LibraryService", "method": "CreatePublisher" },
    +      { "service": "google.example.library.v1.LibraryService", "method": "DeletePublisher" },
    +      { "service": "google.example.library.v1.LibraryService", "method": "CreateBook" },
    +      { "service": "google.example.library.v1.LibraryService", "method": "DeleteBook" },
    +      { "service": "google.example.library.v1.LibraryService", "method": "UpdateBook" },
    +      { "service": "google.example.library.v1.LibraryService", "method": "MoveBook" }
    +    ],
    +    "waitForReady": true,
    +    "timeout": "10s"
    +  }]
    +}
    +
    + + +

    The retry configuration may be a protoc plugin option. For example, a +generator could accept the file path of the configuration with an option like:

    +
      --{plugin_name}_opt="retry-config=/path/to/config.file"
    +
    +

    In the absence of a retry configuration, a generator should not generate a +"default" retry configuration. This results in a generated client library that +does not retry anything unless configured to do so by the user.

    + + + +

    Further reading

    +
      +
    • For which error codes to retry, see AIP-194.
    • +
    +

    Changelog

    +
      +
    • 2020-09-23: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
    • +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4222.html b/client-libraries/4222.html new file mode 100644 index 0000000000..a6d65a5df7 --- /dev/null +++ b/client-libraries/4222.html @@ -0,0 +1,588 @@ + + + + AIP-4222: Routing headers + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4222

    +

    Routing headers

    +

    In some situations, a gRPC API backend is able to route traffic more +efficiently if it knows about some values in the request; however, the request +payload can not be reasonably deconstructed on the wire to perform that +routing.

    +

    Guidance

    +

    Code generators must use the annotations to generate client libraries that, +on a per-RPC basis, extract routing information from the request payload and +add that information to the routing header.

    +

    There are two annotations that specify how to extract routing information from +the request payload:

    +
      +
    • the google.api.routing annotation that specifies how to construct +routing headers explicitly
    • +
    • the google.api.http annotation that may specify how to construct +routing headers implicitly.
    • +
    +

    For any given RPC, if the explicit routing headers annotation is present, the code +generators must use it and ignore any routing headers that might be implicitly +specified in the google.api.http annotation. If the explicit routing +headers annotation is absent, the code generators must parse the +google.api.http annotation to see if it specifies routing headers +implicitly, and use that specification.

    +

    Explicit Routing Headers (google.api.routing)

    +

    For an unary or server-streaming RPC the code generator must look at the routing +parameters specified in the google.api.routing annotation, if present. +Any given routing parameter specifies a field name and a pattern with exactly one +named resource ID path segment. For example:

    +
    rpc CreateTopic(CreateTopicRequest) {
    +  option (google.api.routing) = {
    +    routing_parameters {
    +      field: "parent"
    +      path_template: "{project=projects/*}/**"
    +    }
    +  }
    +}
    +
    +

    The value of the field field must be one of the following:

    +
      +
    1. a name of a field in the top-level of the request message
    2. +
    3. a dot-separated path of field names leading to a field in a sub-message of +the request message e.g. "book.author.name" where book is a message field in +the request message, author is a message field in the book message, and +name is a string field in the author message
    4. +
    +

    The actual field specified in the field field must have the following +characteristics: +- it is type string +- it either has a path-like value format resembling a resource name or contains + an unstructured value that would be appropriate as an individual path segment + e.g. a project_id.

    +

    Note: An empty google.api.routing annotation is acceptable. It means that no +routing headers should be generated for the RPC, when they otherwise would be +e.g. implicitly from the google.api.http annotation.

    +

    Note: It is acceptable to omit the pattern in the resource ID segment, {parent} +for example, is equivalent to {parent=*} and must be parsed, e.g.: +

    routing_parameters {
    +  field: "parent"
    +  path_template: "projects/{parent}"
    +}
    +

    +

    is the same as

    +
    routing_parameters {
    +  field: "parent"
    +  path_template: "projects/{parent=*}"
    +}
    +
    +

    Note: It is acceptable to omit the path_template field altogether. An omitted +path_template is equivalent to a path_template with the same resource ID name as +the field and the pattern **, and must be parsed, e.g.: +

    routing_parameters {
    +  field: "parent"
    +}
    +

    +

    is the same as

    +
    routing_parameters {
    +  field: "parent"
    +  path_template: "{parent=**}"
    +}
    +
    +

    Note: An omitted path_template field does not indicate that key-value +pairs with empty values can be sent. It's merely a shorthand.

    +

    When the user supplies an instance of CreateTopicRequest to the method, the +client library must match all the routing parameters in the order specified +to the fields of that instance. For each routing parameter, the pattern in the +path_template must be matched to the input message field specified by the +routing parameter's field field. In case of a match, the name of the resource ID +path segment must be used as a key, and the value of the resource ID path segment match +must be used as a value of a key-value pair to be appended to the x-goog-request-params +header.

    +

    Both the key and the value must be URL-encoded per RFC 6570 §3.2.2. +This can be done with standard library URL encoding. For example, adding this header +to a gRPC request in Ruby:

    +
    header_params = {}
    +if (pattern_matches("{project=projects/*}/**", request.parent))
    +  header_params["project"] = extract_match_value("{project=projects/*}/**", request.parent)
    +end
    +request_params_header = URI.encode_www_form header_params
    +metadata[:"x-goog-request-params"] = request_params_header
    +
    +

    In cases when multiple routing parameters have the same resource ID path segment name, +thus referencing the same header key, the "last one wins" rule is used to determine +which value to send. The "last" here is meant in terms of the order in which they're specified in the annotation. If some of the routing parameters with the same resource ID segment +name have failed to match the field, or if the field was unset, or if the extracted matched value +is an empty string, these parameters are not considered when determining which value +to send.

    +

    Example:

    +
    option (google.api.routing) = {
    +  routing_parameters {
    +    field: "parent"
    +    path_template: "{project=projects/*}/**"
    +  }
    +  routing_parameters {
    +    field: "parent"
    +    path_template: "{project=projects/*/subprojects/*}/**"
    +  }
    +  routing_parameters {
    +    field: "billing_project"
    +    path_template: "{project=**}"
    +  }
    +}
    +
    +

    In this case if in a given request the billing_project field is set to an non-empty value, +its value will be sent with the project key because the routing parameter looking at billing_project field is specified last. If the billing_project field is not set, the parent field will be considered, first trying to send a +project with a subproject specified, and then without. Note that if a given request has a +parent field with a value e.g. projects/100/subprojects/200/foo, patterns in both first and second routing_parameters will match it, but the second one will "win" since it is specified "last".

    +

    If all the routing parameters with the same resource ID segment name have failed +to match the field, the key-value pair corresponding to those routing parameters' +resource ID path segment name must not be sent.

    +

    If none of the routing parameters matched their respective fields, the routing header +must not be sent.

    +

    Much like URL parameters, if there is more than one key-value pair to be sent, the & +character is used as the separator.

    +

    path_template syntax

    +

    As seen in the above examples, the path_template can use a variety of symbols +that are interpreted by code generators during conversion to regular expressions +or non-regular expression matcher implementations. The path_template consists +of segments delimited by the segment delimiter. The syntax for path_template +is as follows:

    +
      +
    • The only acceptable segment delimiter is /.
        +
      • The last symbol in a path_template may be a delimiter - it will be + ignored.
      • +
      +
    • +
    • A segment must be of one of the following types:
        +
      • *: A single-segment wildcard. Corresponds to 1 or more non-/ symbols. + The regex describing it is [^/]+.
          +
        • A Single-segment wildcard typically represents a resource ID.
        • +
        +
      • +
      • **: A multi-segment wildcard. Corresponds to 0 or more segments.
          +
        • A multi-segment wildcard must only appear as the final segment or + make up the entire path_template.
        • +
        • In a multi-segment path_template, a multi-segment wildcard must + appear immediately following a segment delimiter. This delimiter is + consumed while matching so a path_template like foo/** matches all of + the following: foo, foo/, foo/bar/baz.
        • +
        • In a multi-segment path_template, when used as the last segment the + regex describing it is ([:/].*)?.
        • +
        • When used as the entire path_template, the regex describing it is .*.
        • +
        • Segment delimiters are consumed while matching, including any preceding + delimiter.
        • +
        +
      • +
      • LITERAL: A literal segment. A literal segment can contain any + alphanumeric symbol.
          +
        • A literal segment must not contain a symbol reserved in this syntax.
        • +
        • Literal segments typically represent a resource collection ID or base + path.
        • +
        +
      • +
      • {}: A variable segment. This matches part of the path as specified by its + template.
          +
        • A variable segment can be either of the following:
            +
          • {key}, where key is the name to be used in the key-value pair of the + header
          • +
          • {key=template}, where the template is the segment(s) (expressed in + this path_template syntax) to extract as the value paired with key
          • +
          +
        • +
        • A variable segment of just {key} defaults to a template of * which + matches 1 or more non-/ symbols.
            +
          • While {key=*} is technically valid syntax, the simpler syntax of + {key} should be used.
          • +
          +
        • +
        • A variable segment must not contain other variable segments. This + syntax is not recursive.
        • +
        +
      • +
      +
    • +
    • A segment must not represent a complex resource ID as described in + AIP-4231. A Generator should emit an error in this case.
    • +
    +

    Implicit Routing Headers (google.api.http)

    +

    Note: For an RPC annotated with the google.api.routing annotation, +the google.api.http annotation must be ignored for the purpose of adding +routing headers.

    +

    If an unary or server-streaming RPC is not annotated with the google.api.routing +annotation, code generators must look at URI-based variables declared in the +google.api.http annotation and transcribe these into the +x-goog-request-params header in unary calls. A URI-based variable is a +variable declared as a key in curly braces in the URI string. For example:

    +
    rpc CreateTopic(CreateTopicRequest) {
    +  option (google.api.http).post = "{parent=projects/*}/topics";
    +}
    +
    +

    Note: It is acceptable to omit the pattern in the resource ID segment, {parent} +for example, is equivalent to {parent=*} and must be parsed.

    +

    In this case, the applicable variable is parent, and it refers to the +parent field in CreateTopicRequest. When the user provides an instance of +CreateTopicRequest to the method (or once the client library has built it, in +the case of method overloads), the client library must extract the key and +value, and append them to the x-goog-request-params header. Both the key and +the value must be URL-encoded per RFC 6570 §3.2.2. This can be done +with standard library URL encoding. For example, adding this header to a gRPC +request in Go:

    +
    md := metadata.Pairs("x-goog-request-params",
    +  url.QueryEscape("parent") + "=" + url.QueryEscape(req.GetParent()))
    +
    +

    At runtime, if a field with the same name as the named parameter is unset on the +request message, the key-value pair corresponding to that parameter must not +be included in the routing header. If none of the parameters must be included in +the routing header, the routing header must not be sent.

    +

    If the google.api.http annotation contains additional_bindings, +these patterns must be parsed for additional request parameters. Fields +not duplicated in the top-level (or additional_bindings) pattern must +be included in request parameters, encoded in the same way.

    +

    Much like URL parameters, if there is more than one key-value pair, the & +character is used as the separator.

    + +

    Changelog

    +
      +
    • 2023-07-07: Include path_template syntax.
    • +
    • 2022-07-13: Updated to include the new google.api.routing annotation.
    • +
    • 2020-04-21: Explicitly parse path variables missing a trailing segment.
    • +
    • 2019-11-27: Include additional_bindings as a request parameter source.
    • +
    • 2019-06-26: Fix wording and example of key-value pair encoding.
    • +
    • 2019-06-20: Specify encoding of header parameters.
    • +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4223.html b/client-libraries/4223.html new file mode 100644 index 0000000000..730cf8b071 --- /dev/null +++ b/client-libraries/4223.html @@ -0,0 +1,372 @@ + + + + AIP-4223: Client-side payload validation + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4223

    +

    Client-side payload validation

    +

    Client-side payload validation is the practice of inspecting the request payload +for any misconfigurations (e.g. missing required fields, attempting to update an +immutable field) prior to executing a network call with the payload. Typically, +documentation communicates the expectations of the service with regards to each +request field, including any requirements on presence or format. The +google.api.field_behavior annotation defined in AIP-203 is the +machine-readable format that services use to document behavior in relation to +specific request fields.

    +

    Guidance

    +

    Client libraries must not implement client-side payload validation based +on the google.api.field_behavior annotation, except to prevent +local failures.

    +

    The reason for this is that the google.api.field_behavior annotation is +primarily a machine-readable form of documentation, and not a +configuration for payload validation. The annotation conveys how the service +already handles the field, and alludes to a service's own payload validation +or expectations.

    +

    Admittedly, depending on services to implement payload validation means clients +will sometimes make network calls that are bound to result in errors. Furthermore, users +then depend on services to provide actionable errors, when the client could have +provided a language-idiomatic, localized error. However, robust server-side +payload validation means that all types of client (first party, third party, +curl, etc.) will benefit from the same validation, and that there is no +lag between service and clients when the field behavior changes.

    +

    Local failures

    +

    Client libraries may implement client-side payload validation based on the +google.api.field_behavior annotation only to the extent that it prevents +local failures, such as crashes within the client library code itself.

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4231.html b/client-libraries/4231.html new file mode 100644 index 0000000000..9cbcb0435d --- /dev/null +++ b/client-libraries/4231.html @@ -0,0 +1,568 @@ + + + + AIP-4231: Parsing resource names + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4231

    +

    Parsing resource names

    +

    In resource-oriented design (AIP-121), resources represent the primary +nouns within APIs, and often have resource names (AIP-122). These +resource names convey information about the structure and hierarchy of the +resource structure in that API. APIs accept these resource names as parameters +when retrieving and modifying resources, and when referencing them in other +objects. However, users may struggle to piece together resource names to send, +and client libraries have the opportunity to make this easier through the use +of helper components.

    +

    Guidance

    +

    Client libraries may provide helper classes or functions to make +constructing resource names more straightforward. However, client libraries +that choose to implement this feature must always accept the plain strings +also, for two reasons:

    +
      +
    1. An existing API that adds resource descriptor annotations should be able to + do so without incurring a breaking change.
    2. +
    3. Resource name patterns occasionally evolve, and users need to be able to + send and receive resource names that a statically-compiled client library + may not yet acknowledge.
    4. +
    +

    Resource messages

    +

    A resource in an API always has a message that describes the representation of +that resource in that API. Client library generators are able to recognize +these messages when they are annotated with the google.api.resource +annotation:

    +
    // A representation of a Topic in Pub/Sub.
    +message Topic {
    +  option (google.api.resource) = {
    +    type: "pubsub.googleapis.com/Topic"
    +    pattern: "projects/{project}/topics/{topic}"
    +  };
    +
    +  // name and so on...
    +}
    +
    +
      +
    • The type field provides the unified resource type name.
        +
      • Client libraries should name their helper component based on this + value.
      • +
      • The universal resource type usually (but not always) ends with a name that + matches the name of the message.
      • +
      +
    • +
    • The pattern field provides the structure of this resource type's names.
        +
      • The components in braces represent variable substitutions. Client libraries + implementing this feature must accept variables based on these names + when building resource name strings.
      • +
      • Variable substitution names are usually specified in snake_case, but this + is not guaranteed. Client libraries should be able to accept any + annotation that uses any coherent case system.
      • +
      • Patterns are usually slash-separated, but this is not guaranteed. Client + libraries should use string interpolation to piece together the + resource name.
      • +
      +
    • +
    • The defining message is expected to contain a field called name, which is + the field holding the resource name.
        +
      • APIs are able to override the name field's name by setting the name_field + property on the google.api.resource annotation.
      • +
      • Code generators should fail with an error if a message is annotated as + a resource and has no name field (either the default of name or the field + provided in the name_field property of the annotation). Code generators + should also fail with an error if the field is not a string).
      • +
      +
    • +
    +

    Multi-pattern resources

    +

    Occasionally, a resource may have more than one pattern. The common case for +this is when a resource can live under more than one parent type. In this +situation, the pattern field on the annotation can be specified more than +once:

    +
    message LogEntry {
    +  option (google.api.resource) = {
    +    type: "logging.googleapis.com/Log"
    +    pattern: "projects/{project}/logs/{log}"
    +    pattern: "organizations/{organization}/logs/{log}"
    +    pattern: "folders/{folder}/logs/{log}"
    +    pattern: "billingAccounts/{billing_account}/logs/{log}"
    +  };
    +
    +  // name and so on...
    +}
    +
    +

    If necessary, client libraries may create a separate helper component for +each pattern, and may provide a rollup component.

    +

    Resources without messages

    +

    Occasionally, a resource may be implicitly defined by an API service, but not +have an explicit message representing that resource. (For example, the +Firestore API defines databases as a common ancestor to its resources, but +does not define a database message.)

    +

    In this situation, APIs annotate the resource on the file instead of on a +message, using the google.api.resource_definition annotation:

    +
    option (google.api.resource_definition) = {
    +  type: "firestore.googleapis.com/Database"
    +  pattern: "projects/{project}/databases/{database}"
    +};
    +
    +

    Client library generators implementing this feature must generate the same +utility components that would be generated when encountering a +resource message.

    +

    Referencing other resources

    +

    APIs often use resource names for referencing fields defined elsewhere. This is +particularly common with the request messages for the standard methods, such as +Get and Update; however, resources and other structures +use resource name strings as references also.

    +

    Client libraries implementing this feature should also provide their helper +components when resources are being referenced. Client libraries are able to +recognize these fields when they are annotated with the +google.api.resource_reference annotation:

    +
    message GetTopicRequest {
    +  // The name of the topic to retrieve.
    +  string name = 1 [(google.api.resource_reference) = {
    +    type: "pubsub.googleapis.com/Topic"
    +  }];
    +}
    +
    +

    The resource reference references the unified resource type name.

    +

    Some methods also refer to the parent of a type, and in situations where +there are multiple parents, it is repetitive and error-prone to refer to each +individual parent type. In these situations, API producers specify child_type +rather than type:

    +
    message ListLogEntriesRequest {
    +  // The collection of log entries to list.
    +  string parent = 1 [(google.api.resource_reference) = {
    +    child_type: "logging.googleapis.com/Log"
    +  }];
    +}
    +
    +

    In this situation, client library generators implementing this feature must +derive the set of parent resources from the child type. Client library +generators must fail with an error if both type and child_type are +provided.

    +

    Referencing an arbitrary resource

    +

    Occasionally, a field may reference an arbitrary resource. In this case, APIs +use the special value * in their resource reference.

    +
    message GetIamPolicyRequest {
    +  string resource = 1 [(google.api.resource_reference) = {
    +    type: "*"
    +  }];
    +}
    +
    +

    In this situation, client library generators implementing this feature may +provide a generic utility class or function to address that resource name.

    +

    Complex resource ID path segments

    +

    Warning: Complex resource ID path segments should not generally be used +in new APIs. AIP-124 contains advice on handling many-to-many associations.

    +

    Resource patterns may contain resource ID path segments which contain +multiple pattern variables separated by a variable separator:

    +
    message FeedItemTarget {
    +  option (google.api.resource) = {
    +    type: "googleads.googleapis.com/FeedItemTarget"
    +    pattern: "customers/{customer}/feedItemTargets/{feed}~{feed_item}"
    +  };
    +
    +  // name and other fields...
    +}
    +
    +

    This is only used when the resource ID is naturally in multiple parts and it is +useful for the user to be able to manipulate the separate ID parts.

    +
      +
    • A variable separator is one character long, and must only one of: _, + -, ., ~ (underscore, hyphen, period, tilde).
    • +
    • A variable separator must not appear before the first pattern variable or + after the last pattern variable.
    • +
    +

    Backwards compatibility

    +

    Client libraries implementing helper components for resources must conform +to the following backwards-compatibility expectations:

    +
      +
    • The addition of a google.api.resource annotation on an existing message + must be a backwards-compatible change.
    • +
    • An existing resource must be able to add new patterns (including the "*" + wildcard pattern) without breaking changes as long as the following + conditions are met:
        +
      • New patterns must always be appended to the list.
      • +
      • New patterns must use a distinct sequence of collection identifiers (see + AIP-122) compared with all existing patterns within this resource.
      • +
      +
    • +
    • The identifiers within the pattern variables are final - they must not be + changed. These identifiers are used in the surface of generated client + libraries.
    • +
    • The addition of a google.api.resource_reference annotation on an existing + field must be a backwards-compatible change.
    • +
    • Changing a google.api.resource_reference from child_type to type + must be a backwards-compatible change when the child_type referenced + has a single pattern and the newly referenced type is the matching + parent resource pattern (see the + Referencing other resources section for + more info).
    • +
    • For references that appear in a request, changing from type to + child_type must be a backwards-compatible change when the resource + pattern originally referenced via the type is included in the set of + possible resource patterns derived through child_type resolution (see + the above Multi-pattern resources and + Referencing other resources sections for + more examples).
    • +
    +

    Note: The ORIGINALLY_SINGLE_PATTERN and FUTURE_MULTI_PATTERN flags are +deprecated, and must not be used.

    +

    Further reading

    +
      +
    • For more on resource names and patterns, see AIP-122.
    • +
    • For more on unified resource types, see AIP-123.
    • +
    +

    Changelog

    +
      +
    • 2023-03-25: Include compatibility guidance for type and child_type.
    • +
    • 2022-10-28: Pattern variables are considered final
    • +
    • 2020-09-14: Disallow simultaneous use of both type and child_type.
    • +
    • 2020-05-14: Added complex resource ID path segments.
    • +
    • 2020-05-07: Updated backwards compatibility guidance.
    • +
    • 2019-09-16: Added guidance for resources without messages.
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4232.html b/client-libraries/4232.html new file mode 100644 index 0000000000..c2ad18a265 --- /dev/null +++ b/client-libraries/4232.html @@ -0,0 +1,433 @@ + + + + AIP-4232: Method signatures + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4232

    +

    Method signatures

    +

    In protocol buffer RPCs, each RPC takes exactly one argument: a message. +However, sending a full message structure can be cumbersome in the case of +extremely simple requests.

    +

    Many RPCs provide information about which pieces of the request are important +and commonly used. In many languages, functions and methods take multiple +positional or keyword arguments.

    +

    Guidance

    +

    Some APIs provide annotations to hint how to effectively translate from a +single request object to individual arguments, and client libraries may +provide overloads based on these hints.

    +

    However, client libraries implementing this feature must retain the default +behavior of accepting the full request object. Put another way, if an API +adds this annotation to an already-published API, the resulting library +change must be backwards-compatible.

    +

    Client library generators may also choose to provide this functionality in +some cases but not others, as appropriate in the environment. For example, any +of the following strategies would be permissible:

    +
      +
    • Providing overloads iff all arguments in the signature are primitives.
    • +
    • Providing overloads only for the first of multiple signatures when providing + more than one would produce a conflict.
    • +
    • Any combination of the above.
    • +
    +

    In all of these situations, the requirement that the request object is always +accepted still applies.

    +

    Furthermore, client library generators may choose to support this +functionality for a subset of RPC types, those being:

    +
      +
    • Unary
    • +
    • Server Streaming
    • +
    • Client Streaming
    • +
    • Bi-directional Streaming
    • +
    +

    Method Signatures

    +

    An RPC with the google.api.method_signature annotation +indicates that an overload with a flattened method signature is desired where +supported. The string contains comma-separated arguments, in order. If a +field's name contains a period (.) character, this indicates a nested field.

    +

    An RPC can provide this annotation more than once to specify multiple +signatures. Order matters here: In some situations, it may not be possible to +generate an overload for every signature provided. In this situation, client +library generators must follow a "first match wins" strategy (generate an +overload for the first signature in the conflict set, and drop the rest).

    +

    Note: A corollary to this is that it is only guaranteed to be a +backwards-compatible change to append method signature annotations.

    +

    Required Arguments

    +

    Often, certain fields on the request message are consistently required, as +described in AIP-203.

    +

    While client libraries generally should not perform validation on this (that is +the server's role), client libraries may distinguish required arguments in +method signatures from optional ones if appropriate for the language. A field +is considered required for this purpose if annotated with the +google.api.field_behavior annotation value of REQUIRED:

    +
    message TranslateTextRequest {
    +  // The text to translate.
    +  string q = 1 [(google.api.field_behavior) = REQUIRED];
    +}
    +
    +

    Note: The annotation for field behavior is attached to the field, not the +method.

    +

    Restrictions

    +

    If an RPC lists a nested field in +google.api.method_signature (for example, +"foo.bar.baz"), none of the individual component fields may be repeated +except for the last one (continuing the example, baz could be repeated but +foo or bar could not be). Code generators implementing this feature +must error with a descriptive error message if encountering a non-terminal +repeated field as a field name.

    +

    If any fields are required arguments, all required arguments are expected to +appear before any optional ones. Code generators implementing this feature +should error with a descriptive error message if encountering a required +field after an optional one, and must do so if the resulting client library +would not be valid.

    +

    Compatibility

    +

    Removing, reordering or altering an existing google.api.method_signature +entry is a breaking change for client libraries. The associated generated +method is either removed entirely or its signature is altered, both of which +break user code.

    +

    Changelog

    +
      +
    • 2020-07-14: Added caveat for supporting some RPC types
    • +
    • 2019-09-27: Added a Compatibility section.
    • +
    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4233.html b/client-libraries/4233.html new file mode 100644 index 0000000000..2e3ec9d192 --- /dev/null +++ b/client-libraries/4233.html @@ -0,0 +1,382 @@ + + + + AIP-4233: Automatic pagination + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4233

    +

    Automatic pagination

    +

    Many API responses, particularly to list and search methods, are paginated +(AIP-158). Users calling these methods are then required to implement their +own pagination logic, which is common boilerplate.

    +

    Guidance

    +

    Client libraries may provide automatic resolution of pagination (meaning +that it performs requests in the background on an as-needed basis).

    +

    Pagination can be inferred for an RPC when all of the following conditions +are met:

    +
      +
    • The request message contains an int32 page_size field.
        +
      • For APIs that predate AIP-158, a field named max_results and/or + typed as google.protobuf.UInt32Value or google.protobuf.Int32Value + are permissible alternatives.
      • +
      +
    • +
    • The request message contains a string page_token field.
    • +
    • The response message contains a string next_page_token field.
    • +
    • The response message contains one non-primitive repeated field.
    • +
    +

    Client library generators implementing this feature must ensure that it is +a backwards-compatible change to add client-side pagination functionality where +it was previously absent.

    +

    Implementing pagination

    +

    For the client library to implement pagination (as defined by AIP-158), it +should use the next_page_token value from the response message to +populate the page_token value of an otherwise-identical request message, +continuing indefinitely until the next_page_token value is empty.

    +

    Important: Client libraries that are implementing automatic resolution of +pagination should only perform requests for future pages on an as-needed basis, +and avoid greedily resolving potentially long and unnecessary result sets.

    +

    Client libraries that are implementing automatic pagination must still +provide access to the individual fields on the response message, in the usual +fashion.

    +

    Note: If the response message has more than one non-primitive repeated +field, the first one (in order of appearance in the file and field number) is +used. If the first field by order of appearance in the message and the first +field by field number do not match, code generators that implement automatic +pagination should fail with an error.

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4234.html b/client-libraries/4234.html new file mode 100644 index 0000000000..8bf3e3e8f9 --- /dev/null +++ b/client-libraries/4234.html @@ -0,0 +1,445 @@ + + + + AIP-4234: Common service client mixins + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4234

    +

    Common service client mixins

    +

    Often, APIs can have common features for administering resources that are +separated into utility services. These common, utility services are shared among +the discrete product services. These common services each have a +centrally-defined surface, but individual instances are hosted alongside each +product service. Thus, the surfaces of each common service hosted by the product +service are "mixed in" at runtime.

    +

    Guidance

    +

    Client libraries may provide client methods for the common services that its +API declares to be mixed-in. Such methods improve the user experience by +presenting the mixin methods from a client configured to communicate with the +product service that hosts the mixin service.

    +

    If client libraries support mixin services, they must support the following +common services (and may support others):

    +
      +
    • google.cloud.location.Locations
    • +
    • google.iam.v1.IAMPolicy
    • +
    • google.longrunning.Operations
    • +
    +

    Note: The list of supported mixin services and the mixin services +themselves both change infrequently. Any new common service to be supported +must be added to the list here and generators must be updated.

    +

    To be generated into a client library, a mixin service must be declared +under apis in a google.api.Service. Furthermore, only the RPCs with +google.api.http bindings declared in the http configuration of the same +google.api.Service can be generated (more details on these bindings in +AIP-127). If a mixin service RPC does not have a google.api.http rule declared +in the google.api.Service, it must not be generated.

    +

    Implementing mixin support

    +

    Generator configuration

    +

    Client library generators must accept the file path of a +google.api.Service in YAML form. This file is specified via a flag that +must be optional. In other words, the flag must not be required for +basic client generation that omits the mixin methods.

    +

    Mixin API client configuration

    +

    If a mixin API utilizes client library configuration (i.e. annotations, default +retry settings, etc.) such as google.api.method_signature or request header +injection, generators may support it in the generated mixin methods if the +configuration is accessible.

    +

    Where client library configuration calls for a fully-qualified name, the +mixin's fully-qualified name must be used. That is to say, the host +service must not refer to a mixin element as if it was in its own package.

    +

    For example, configuring google.iam.v1.IAMPolicy.GetIAMPolicy with default +retry and timeout settings would be as follows:

    +
    {
    +  "name": [{ "service": "google.iam.v1.IAMPolicy", "method": "GetIAMPolicy" }],
    +  "timeout": "60s",
    +  "retryPolicy": {
    +    "initialBackoff": "0.1s",
    +    "maxBackoff": "5s",
    +    "backoffMultiplier": 1.3,
    +    "retryableStatusCodes": ["UNKNOWN"]
    +  }
    +}
    +
    +

    Generating mixin methods

    +

    The mixin API RPCs should be generated as methods on the surface of the +host API's service client library, alongside the host service's RPCs. This +presents them as top-level methods on the client, but under-the-hood, the +appropriate mixin API stub or request should be invoked. However, generators +may choose to present the mixin API RPCs in a different manner if it is more +language idiomatic.

    +

    Note: For gRPC clients, the mixin API gRPC stub must be used in order +to properly construct the gRPC request. For example, the generated, Go gRPC stub +LocationsClient must be used to invoke RPCs for the +google.cloud.location.Locations mixin, as opposed to that of the host +service's gRPC stub.

    +

    Multiple host service clients

    +

    If there are multiple services defined by the host API that would result in +multiple clients being generated, generators must include the mixin +methods on all eligible, generated service clients.

    +

    Overriding a duplicate RPC

    +

    Client library generators must not generate a mixin method on any host +service client if a host service already defines an RPC with the same name. For +example, take the following service definition:

    +
    service LibraryService {
    +  rpc ListBooks(ListBooksRequest) returns (ListBooksResponse);
    +
    +  // Other host API RPCs...
    +
    +  // Redefinitions of the google.iam.v1.IAMPolicy mixin service.
    +  rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest)
    +      returns (google.iam.v1.Policy);
    +
    +  rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest)
    +      returns (google.iam.v1.Policy);
    +
    +  rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest)
    +      returns (google.iam.v1.TestIamPermissionsResponse);
    +}
    +
    +

    Should the host API declare the google.iam.v1.IAMPolicy as a mixin service, +client library generators must not generate the resulting mixin methods that +match the names explicitly declared above for any service client in the host +proto package, but they must generate the other methods for this mixin. In +this case, the generator may log a warning indicating that a collision was +avoided, or silently skip the mixin methods in question.

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4235.html b/client-libraries/4235.html new file mode 100644 index 0000000000..101e0076da --- /dev/null +++ b/client-libraries/4235.html @@ -0,0 +1,385 @@ + + + + AIP-4235: Automatically populate fields in the request message + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4235

    +

    Automatically populate fields in the request message

    +

    For APIs that leverage request idempotency as described via AIP-155, APIs may +choose to have the client libraries automatically populate fields such as +request_id if they are not already set by the customer.

    +

    Note: This feature is primarily written for request_id fields within the +request message. Nonetheless, this feature must work for a field of any +name, as long as the conditions below hold true.

    +

    Guidance

    +

    APIs may configure fields in the request message for automatic population. +For a field to be automatically populated, all the conditions below +must be true:

    + +

    Expected Generator and Client Library Behavior

    +

    If the aforementioned requirements are met for a given field, client library +generators must enable automatic population of said field in the +generated client.

    +

    The field must be automatically populated if and only if one of the +following conditions holds:

    +
      +
    • The field supports explicit presence, and has not been set by the user
    • +
    • The field doesn't support explicit presence, and its value is the empty + string (i.e. the default value)
    • +
    +

    If a field is specified in the auto_populated_fields, but does not meet the +structural requirements, the client library generators must not enable +automatic population for that field. Client library generators may emit an +error during generation.

    +

    Client libraries must reuse automatically populated values for retries of +the same request. In other words, the automatically populated fields +must not be regenerated for each RPC attempt with the same request message.

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4236.html b/client-libraries/4236.html new file mode 100644 index 0000000000..bc96f86716 --- /dev/null +++ b/client-libraries/4236.html @@ -0,0 +1,444 @@ + + + + AIP-4236: Version-aware clients + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4236

    +

    Version-aware clients

    +

    APIs can annotate API interfaces with +google.api.api_version. If google.api.api_version is +specified, version-aware clients must include the value of +google.api.api_version in the request to the API and in the documentation of +the per-API interface clients.

    +

    Generator and client library behavior

    +

    If an API interface is annotated with google.api.api_version, client +library generators must include either an HTTP query parameter $apiVersion +or HTTP header/gRPC metadata key X-Goog-Api-Version, but a request +must not contain both.

    +

    Generated client documentation

    +

    Generated client documentation for a given API interface must include the +value of google.api.api_version, if it exists in the source protos. The +comment must include the original API interface name and the exact contents +of the annotation.

    +

    Note: The text does not need to match exactly to the examples below, but it +still needs to fulfill the requirements desribed herein.

    +

    For example, the following API interface definition would produce the following +Go client documentation:

    +
    service LibraryService {
    +    option (google.api.api_version) = "2026-01-01";
    +}
    +
    +
    // The LibraryClient is a client for interacting with the Cloud Library...
    +//
    +// This client uses LibraryService version 2026-01-01.
    +type LibraryClient struct {}
    +
    +

    Any generated documentation for an entire API service's client +package must include a section that lists the client-interface-version +tuples present in the package. For example, the following API interface +defintions would produce the following client package documentation section:

    +
    service LibraryService {
    +    option (google.api.api_version) = "2026-01-01";
    +}
    +service BookService {
    +    option (google.api.api_version) = "2026-05-15";
    +}
    +service ShelfService {
    +    option (google.api.api_version) = "2026-02-05";
    +}
    +
    +
    ## API Versions
    +
    +* LibraryClient uses LibraryService version 2026-01-01
    +* BookClient uses BookService version 2026-05-15
    +* ShelfClient uses ShelfService version 2026-02-05
    +
    +

    If all API interfaces share the same API version, this list should be +reduced to a single sentence for brevity. For example, if all versions were the +same in the definitions above, the generated client package documentation would +be as follows:

    +
    ## API Versions
    +
    +All clients use API version 2026-01-01.
    +
    +

    Version opacity

    +

    Clients and generators must treat the value of google.api.api_version as +opaque to ensure robust compatibility. This means that the specific format or +structure of the version string must not be parsed or interpreted for any +purpose beyond identifying the intended API version.

    +

    Rationale

    +

    Necessity for Versioning

    +

    Explicit API versioning using the google.api.api_version annotation is +essential for maintaining compatibility between clients and services over time. +As services evolve, their schemas and behaviors may change. By specifying the +API version, a client communicates its expectations to the API service. This +allows the API service to respond in a manner consistent with the client's +intended semantics, preventing errors or unexpected results due to incompatible +changes.

    +

    Importance of Opaque Treatment

    +

    Treating the google.api.api_version value as opaque is important for ensuring +robust compatibility guarantees. By using this identifier opaquely, clients +avoid making assumptions about the underlying versioning scheme, which may +change independently of the API itself. This flexibility allows API service +providers to evolve their versioning strategies without impacting client +compatibility.

    +

    Mutual Exclusivity of Query and Header

    +

    Both the query parameter and header mechanisms exist to provide flexibility for +different client environments. However, allowing both simultaneously could lead +to ambiguity if the values differ. To ensure consistent version identification +and prevent potential conflicts, only one mechanism should be used at a time.

    +

    Inclusion in documentation

    +

    The API version identifies the iteration of the API contract being consumed by +the client and thus the end user. The end user needs a means of relating the +API version in use by the client to other API artifacts (such as product +documentation and other client surfaces) and vice versa.

    +

    Changelog

    +
      +
    • 2025-12-08: Add documentation generation requirements and reformat.
    • +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/client-libraries/4290.html b/client-libraries/4290.html new file mode 100644 index 0000000000..ffbf87c75b --- /dev/null +++ b/client-libraries/4290.html @@ -0,0 +1,498 @@ + + + + AIP-4290: Docker interface + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-4290

    +

    Docker interface

    +

    A consequence of using individual generators for API client library generation +is that each generator has its own set of dependencies and requirements in +order to run.

    +

    This is reasonable for a user who wishes to generate many libraries for a +single environment, but presents challenges for a user wishing to generate a +single API for many languages or environments. Users need a way to generate +libraries easily and quickly, with minimal ramp-up per language.

    +

    Guidance

    +

    Client library generators should ship Docker images providing the +generator and exposing a common interface, so that generating the same API in +multiple languages usually only requires substituting in the appropriate Docker +image. Docker images for Google-authored generators will follow a consistent +scheme.

    +

    CLI usage

    +

    The expected user command to invoke the code generator in a Docker image (from +the proto import root, on a POSIX machine):

    +
    $ docker run --rm --user $UID \
    +  --mount type=bind,source=`pwd`/a/b/c/v1/,destination=/in/a/b/c/v1/,readonly \
    +  --mount type=bind,source=/path/to/dest/,destination=/out/ \
    +  gcr.io/gapic-images/{GENERATOR} \
    +  [-- additional options...]
    +
    +

    Note: Even though each component of this is standard in the Docker +ecosystem (other than the destination path issue, which is a result of how +protoc handles imports), this is still a rather long command. We can provide a +shortcut script to further simplify this, but such a script would be for +convenience and not a replacement for this interface.

    +

    Container composition

    +

    Containers must include:

    +
      +
    • A current version of protoc, the protocol buffer compiler.
    • +
    • Common protos permitted to be used by all APIs (googleapis).
    • +
    • The applicable code generator plugin, as well as any dependencies it + requires.
        +
      • The code generator plugin itself should be added using an ADD or + COPY statement from the host machine at build time and installed locally; + it should not pull from a package manager. (This leads to catch-22 + situations when cutting releases.)
      • +
      • Images may include either a pre-compiled binary of the plugin, or the + installed source code, depending on the needs of the applicable ecosystem.
      • +
      • Installation of dependencies should use appropriate package managers.
      • +
      +
    • +
    +

    The common protos and the protoc compiler are supplied by an independent image +(gcr.io/gapic-images/api-common-protos). Both protoc and the common protos +can be retrieved from this image into a generator's image using the +COPY --from syntax (see multi-stage builds). This is the preferred +approach as it follows Docker conventions, and allows the protos to be +versioned independently.

    +

    Base images

    +

    TL;DR: Each language probably wants language:x.y-alpine or +language:x.y-slim. For example, ruby:2.5-alpine or python:3.7-slim. +(Alpine images are smaller but idiosyncratic.)

    +

    The following guidelines apply to selecting base images (sorted roughly from +most important to least important):

    +
      +
    • Images should generally be based off an official image for the latest + stable version of the language in which the generator is implemented.
    • +
    • Images should be able to install required system dependencies from a + well-understood package manager.
    • +
    • Images should be ultimately based off of Alpine, Debian, or Ubuntu. This + is to ensure we benefit from GCR's vulnerability scanning.
    • +
    • Images should endeavor to be as small as possible, in line with the general + expectations of the Docker community:
        +
      • Use the smallest base image you can. Alpine-based images are great if + possible, but may not always be reasonable. "Slim" Debian images are + usually the next best (and probably significantly more feasible in many + situations).
      • +
      +
    • +
    +

    Mount points

    +

    protoc must read protos (representing the API to be generated) from disk, and +must write the final output (the client library) to disk. Because the user has +the API protos on the host machine, and will ultimately need the output to go +to said host machine, Docker images should use two mount points. This +creates a hole in the abstraction layer: the user must mount the appropriate +locations on the host machine to the appropriate locations in the container.

    +

    The expected locations in the container must be constant, and consistent +between all generator container images:

    +
      +
    • /in/: The location of the protos to be generated. This must be the + import root.
        +
      • Example: If generating protos for the Language API, the protos in the + Docker image must live in /in/google/cloud/language/v1/.
      • +
      +
    • +
    • /out/: The location to which the client library shall be written.
    • +
    +

    Plugin options

    +

    Some micro-generators support configuration provided via protoc plugin options. +In such cases, the options must be routed from the CLI input to the protoc +command.

    +

    The ultimate protoc invocation could look like the following:

    +
    protoc --proto_path {path/to/common/protos} --proto_path /in/ \
    +       --{LANG}_gapic_out /out/ \
    +       --{LANG}_gapic_opt "go-gapic-package=GO_PACKAGE_VALUE" \
    +       `find /in/ -name *.proto`
    +
    +

    A resulting invocation of the Docker image would be as follows:

    +
    $ docker run --rm --user $UID \
    +      --mount type=bind,source=`pwd`/a/b/c/v1/,destination=/in/a/b/c/v1/,readonly \
    +      --mount type=bind,source=/path/to/dest/,destination=/out/ \
    +      gcr.io/gapic-images/{GENERATOR} \
    +      --go-gapic-package GO_PACKAGE_VALUE
    +
    +

    Thus shortcut scripts written to wrap the Docker image invocation must pass +all options occurring after -- to the underlying docker run command. The +internal Docker image must provide the conversion from usual shell syntax +to the protoc option syntax.

    +

    Client library generators that make use of plugin options must accept those +options as either flags or key=value pairs. (If a generator receives a string +without an = character, that is a flag, and the implied value is true.) If +multiple options are provided, they are comma-separated, to conform with the +protoc behavior if multiple --opt flags are specified.

    +

    Additionally, generators should prefix all understood option keys with the +target language for that generator (e.g. go-gapic-package, +java-gapic-package), and should use kebab-case for keys (in order to +match Docker, since protoc is inconsistent).

    +

    Microgenerators must not error on option keys that they do not recognize, +although they may issue a warning.

    +

    Publishing images

    +

    Images for Google-created generators should be published in +gcr.io/gapic-images, a dedicated project in Google Container Registry.

    +

    Images should follow the naming scheme:

    +
      gcr.io/gapic-images/gapic-generator-{lang}
    +
    +

    CI should be configured to push a new Docker image to the registry when +releases are made. When a release is tagged in GitHub (with a version number, +such as 1.0.3), the CI service should build an image based on the code at that +tag.

    +

    The resulting image should be tagged with each component of the version +number, as well as latest, and the resulting tags pushed the registry. (This +is in addition to pushing to a package manager if appropriate, which is outside +the scope of this AIP.)

    +

    This means that a release tag of 1.0.3 in GitHub would result in pushing the +following four tags to GCR:

    +
      +
    • gcr.io/gapic-images/gapic-generator-{lang}:1
    • +
    • gcr.io/gapic-images/gapic-generator-{lang}:1.0
    • +
    • gcr.io/gapic-images/gapic-generator-{lang}:1.0.3
    • +
    • gcr.io/gapic-images/gapic-generator-{lang}:latest
    • +
    +

    Note: These rules assumes that releases have ever-increasing version +numbers; this process will need to be amended slightly if a generator needs to +maintain multiple version streams simultaneously.

    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/cloud.html b/cloud.html new file mode 100644 index 0000000000..13ec926721 --- /dev/null +++ b/cloud.html @@ -0,0 +1,325 @@ + + + + Google Cloud Platform AIPs + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + + +
    +
    + +
    +

    Google Cloud Platform APIs

    + + + + + + + + + + + + + +
    NumberTitle
    2510 + Project identifiers +
    +

    Cloud SDK

    + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    2602 + Parameter-dependent arguments +
    2603 + List command arguments +
    2604 + Numeric arguments +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/cloud/2510.html b/cloud/2510.html new file mode 100644 index 0000000000..b5cf1d057b --- /dev/null +++ b/cloud/2510.html @@ -0,0 +1,434 @@ + + + + AIP-2510: Project identifiers + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-2510

    +

    Project identifiers

    +

    Historically, Google had two kinds of projects: API projects and App Engine +projects. API projects used project numbers (e.g. 12345) as identifiers, and +App Engine projects used project IDs (e.g. happy-armadillo-789) as +identifiers. Later, Google converged API projects and App Engine projects, so +now each project has both unique and immutable identifiers.

    +

    The two types of identifiers are used differently in different contexts, and +create a lot of complexity for application development. One critical issue is +that applications cannot reliably join data from different services, because +different services use different project identifiers.

    +

    Guidance

    +

    TL;DR: The project number is the canonical identifier, and the project ID +is an alias; however, unlike normal aliases, it should be returned if it +is what the user sent. Additionally, third-party services are unable to +accept project IDs.

    +

    The rationale for this is:

    +
      +
    • Each resource should always have one canonical identifier.
    • +
    • Because Google's privacy policy restricts the use of project IDs, both + internally and with partners, only the project number can be the canonical + identifier.
    • +
    • However, even though the project number is the canonical identifier, a policy + of returning it even if the user sent a project ID has proven to be + unfriendly to both humans and declarative tools.
    • +
    +

    Google APIs

    +

    Externally-facing Google APIs should accept both project IDs and project +numbers for incoming API requests.

    +

    However, even though the project number is the canonical identifier as +described in AIP-122, services should return whichever ID the user sent. +The reason for this is because automatic translation between user-friendly +project IDs and user-unfriendly project numbers has proven to cause real-world +difficulty for users, and also for declarative tools (see AIP-128 for more on +declarative-friendliness).

    +

    Two additional points:

    +
      +
    • Error responses must return the originally-provided value without + modification. Error responses must not perform any translation between + project IDs and project numbers.
    • +
    • If a service receives a resource name for a resource that the service does + not own, it should not perform any translation between project IDs and + project numbers for those resource names.
    • +
    +

    Internal Google services

    +

    Internal Google services must use project numbers for internal data storage +and for output. Project identifiers are widely used as storage keys, which +often appear in logs and metrics. Project IDs are user-settable and thus +considered PII and user data, but project numbers are not.

    +

    Therefore, when an internal service calls an external Google APIs, it +should use project numbers for making API requests.

    +

    Resource References

    +

    Project identifiers also appear in resource names. These resource +names are used both to identify the resource itself and can refer to +other resources (example).

    +

    When project identifiers are provided, the response should +include the identifier as it occurred in the request: if the project ID +was provided it should be returned, and if the project number was +provided, that is what should be in the response.

    +

    For example, consider a Book resource,

    +
    message Book {
    +  option (google.api.resource) = {
    +    type: "pubsub.googleapis.com/Book"
    +    pattern: "projects/{project}/books/{book}"
    +  };
    +
    +  // The resource name of the Book.
    +  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
    +
    +  // A reference to another resource, a Shelf.
    +  string shelf = 2 [(google.api.resource_reference) = {
    +    type: "library.googleapis.com/Shelf"
    +  }];
    +
    +  // Other fields...
    +}
    +
    +

    with the following book submitted from a previous create request (represented as +JSON in this example),

    +
    {
    +  "name": "projects/my-project/books/les-miserables",
    +  "shelf": "projects/12345/shelves/top-shelf"
    +}
    +
    +

    and a GetBookRequest,

    +
    message GetBookRequest {
    +  // The name of the Book to retrieve.
    +  // Format: projects/{project}/books/{book}
    +  string name = 1 [
    +    (google.api.field_behavior) = REQUIRED,
    +    (google.api.resource_reference) = {
    +      type: "library.googleapis.com/Book"
    +    }];
    +}
    +
    +

    and if the value of name on such a request is,

    +
    projects/my-project/books/les-miserables
    +
    +

    then the value of the field, name, returned for the Book, should match: +the project ID and not the number should be returned. But, the value for the +field, shelf should use the project number, as the create request had +submitted a shelf with the project number in the resource name.

    +

    In other words, the following values should be returned:

    +
    book: projects/my-project/books/les-miserables
    +shelf: projects/12345/shelves/top-shelf
    +
    +

    This guidance is to ensure that there is a minimal difference between user +input and output.

    +

    Third-party services

    +

    Third-party services that are +integrated with Google Cloud Platform must only store or provide project +numbers. Google's privacy policy prohibits sharing project IDs with third-party +services, or providing a service for third-party services to translate between +project IDs and project numbers at runtime.

    +

    Project identifier format

    +

    Services must use project resource names as defined by the Resource +Manager API to refer to projects, such as projects/123456. This allows the +same API to work with other resources similar to projects, such as +organizations and folders.

    +

    Changelog

    +
      +
    • 2022-10-19: Clarified guidance for project identifiers in resource + references.
    • +
    • 2021-07-29: Reversed previous guidance on returning project IDs; this AIP + now advocates returning what the user sent.
    • +
    • 2019-08-11: Add an exception for resources that a service does not own.
    • +
    • 2019-06-19: Clarify how error messages should be treated
    • +
    • 2019-06-10: Minor language and organization tweaks
    • +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/cloud/2602.html b/cloud/2602.html new file mode 100644 index 0000000000..1a083ed026 --- /dev/null +++ b/cloud/2602.html @@ -0,0 +1,392 @@ + + + + AIP-2602: Parameter-dependent arguments + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-2602

    +

    Parameter-dependent arguments

    +

    When designing CLI commands, a common scenario is that a command corresponding +to some conceptual action may take different, largely non-overlapping arguments +depending on the value of a particular parameter.

    +

    For instance, suppose we're designing a new gcloud surface for managing images, +and we need a command that formats an image as JPEG, GIF, or PNG. Regardless of +the image format, the command will need arguments for the source and +destination files, but otherwise depending on the format, an entirely different +set of options will apply. JPEG, for example, might take arguments for +smoothing, subsampling, and DCT method, which are only relevant for JPEG +images. GIF, on the other hand, might take arguments for controlling animated +gifs e.g. whether to loop forever, and a delay time in between frames. Finally, +PNG might take arguments for color type and bits per channel.

    +

    Guidance

    +

    When the parameter-specific arguments are numerous relative to the other +arguments, create a command group for the action, with separate subcommands +named after each of the parameter values. In the example above, we would thus +create a gcloud images format command group, with subcommands called jpeg, +gif, and png. These subcommands can then take their own format-specific +flags.

    +

    Example usage:

    +
    $ gcloud images format jpeg --help
    +
    +$ gcloud images format jpeg --source-file=foo --destination-file=bar \
    +    --dct-method=integer --smoothing=0.1 --subsampling=4:4:4
    +
    +$ gcloud images format png --source-file=foo --destination-file=bar \
    +    --color-type=0 --bits-per-channel=16
    +
    +$ gcloud images format gif --source-file=foo --destination-file=bar \
    +    --loop-forever --frame-delay=1ms
    +
    +

    It's possible that over time more and more arguments are added that are common +to all parameters. In that case, it may make sense to instead use a single +command that takes an argument for the parameter. This can be done without +breaking backward compatibility by making the parameter a positional argument. +In the example above, this would involve changing format from a command group +to a command, and having it take a positional image format argument which can +be one of: jpeg, gif, or png. Note that all the example commands above +would still function identically (except for the first one, but since it only +affects help text it's not considered a breaking change.)

    +

    Alternatives considered

    +

    There are several other possibilities for the design of such a command, +outlined below:

    +

    Single command with an explicit flag corresponding to the parameter

    +

    In the example, this would involve a --type flag to specify the image format:

    +
    $ gcloud images format --source-file=source --destination-file=dest \
    +    --type=JPEG --dct-method=integer --smoothing=0.1 --subsampling=4:4:4
    +
    +$ gcloud images format --source-file=source --destination-file=dest \
    +    --type=GIF --loop-forever --frame-delay=1ms
    +
    +$ gcloud images format --source-file=source --destination-file=dest \
    +    --type=PNG --color-type=0 --bits-per-channel=16
    +
    +

    Conceptually it makes the most sense to just have a single format command. +However, this approach has several drawbacks:

    +
      +
    • Unnecessary help text. The user will see all of the format-specific options, + most of which will be irrelevant since they apply to different formats. In + graphical image editing programs such as Photoshop or GIMP, the UI can + selectively show these format-specific options once the user chooses the + desired format from a dropdown. On the CLI, however, we have no such + capability because the help text is statically generated.
    • +
    • Additional logic needed for validation. Since some arguments will be invalid + depending on the format, the command author needs to ensure specifying + invalid combinations returns an appropriate error. While this can be + accomplished with appropriately nested mutex groups, the nesting has the + potential to become overly deep and complex.
    • +
    +

    Multiple commands named after the action hyphenated with the parameter value

    +

    In the example, this would look like:

    +
    $ gcloud images format-jpeg ...
    +$ gcloud images format-gif ...
    +$ gcloud images format-png ...
    +
    +

    This is similar to the recommended design in that each parameter value gets its +own command. However, there are disadvantages:

    +
      +
    • Backward compatibility. If in the future it becomes desirable to make the + parameter value an argument to a single command, this would necessitate a + breaking change.
    • +
    • It's less elegant from a command tree layout perspective. Grouping the + parameter-specific commands into a command group allows for a natural + decomposition of the command space, in keeping with gcloud's CLI design + philosophy, and allows for + progressive disclosure + in the help text and in autocompletion.
    • +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/cloud/2603.html b/cloud/2603.html new file mode 100644 index 0000000000..1d1da8692e --- /dev/null +++ b/cloud/2603.html @@ -0,0 +1,339 @@ + + + + AIP-2603: List command arguments + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-2603

    +

    List command arguments

    +

    Some list requests take argument(s) for the parent collection in which to list +resources. For example, suppose an API has book resources belonging to publisher +resources, and consider a request to list books belonging to a publisher:

    +
    message ListBooksRequest {
    +  // The parent, which owns this collection of books.
    +  // Format: publishers/{publisher}
    +  string parent = 1 [
    +    (google.api.field_behavior) = REQUIRED,
    +    (google.api.resource_reference) = {
    +      child_type: "library.googleapis.com/Book"
    +    }];
    +
    +  // The maximum number of items to return.
    +  int32 page_size = 2;
    +
    +  // The next_page_token value returned from a previous List request, if any.
    +  string page_token = 3;
    +}
    +
    +

    For the corresponding gcloud list command, we have the choice between +gcloud publishers books list PUBLISHER (positional) and +gcloud publishers books list --publisher=PUBLISHER (flag).

    +

    Guidance

    +

    All list command arguments should be flags, not positionals. In gcloud's +resource model, command groups generally correspond to resources, and the +positional arguments for commands in a group are reserved for those resources. +In the case of a list command that takes an argument, the argument will refer +to the parent resource and not the command group's resource; therefore, it +should be a flag instead of a positional.

    +

    In the example above, the list command takes an argument for a publisher. Commands +in the books command group should reserve positional arguments for book +resources. Thus, the publisher argument for the list command should be a flag:

    +
    gcloud publishers books list --publisher=PUBLISHER
    +
    +

    Changelog

    +
      +
    • 2020-09-23: Changed the examples from "shelves" to "publishers", to + present a better example of resource ownership.
    • +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/cloud/2604.html b/cloud/2604.html new file mode 100644 index 0000000000..99271563ce --- /dev/null +++ b/cloud/2604.html @@ -0,0 +1,384 @@ + + + + AIP-2604: Numeric arguments + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    + +

    AIP-2604

    +

    Numeric arguments

    +

    Some API fields refer to either a percentage or a fixed number. For example, in +GCE a group can be created with a configurable limit for either the percentage +or number of instances in the group that can undergo maintenance +simultaneously:

    +
    message ConcurrencyControl {
    +  enum LimitType {
    +    INVALID = 0;
    +    PERCENT = 1;
    +    FIXED = 2;
    +  }
    +  optional int32 concurrency_limit = 1;
    +  optional LimitType limit_type = 2;
    +}
    +
    +

    Guidance

    +

    Flag layout

    +

    In gcloud, such API fields should correspond to a mutually exclusive group +consisting of two flags: one for specifying a number, and the other for +specifying a percentage. The API field in the example above would thus +correspond to the following surface specification in gcloud:

    +
    - group:
    +    mutex: true
    +    arguments:
    +      - name: concurrency-limit
    +        help_text: |
    +          Maximum number of instances in the group that can undergo maintenance
    +          simultaneously.
    +      - name: concurrency-limit-percent
    +        help_text: |
    +          Integer from 0 to 100 representing the maximum percentage of instances
    +          in the group that can undergo maintenance simultaneously.
    +
    +

    Flag naming

    +

    Any flag taking a percentage should end with -percent (not -percentage).

    +

    Flag type

    +

    Any flag taking a percentage should take an integer from 0 to 100. If more +precision is required, it is acceptable to take a float from 0 to 100.

    +

    Alternatives considered

    +

    One flag, where percentage is specified if the flag value ends with '%', and number is assumed otherwise

    +

    In other words, to specify 10% one would use --concurrency-limit=10%, and to +specify 10 instances one would use --concurrency-limit=10.

    +

    This would be a cleaner design since it naturally maps a single concept (the +limit) to a single flag (--concurrency-limit), avoiding the need for +additional flags that clutter the help text.

    +

    However, the main reason not to prefer this approach is that it significantly +increases the risk of user error. For instance, suppose a group currently +contains 20 instances with a concurrency limit of 10%, and a user wishes to +update the limit to 20%. If the user issues a describe command (or performs a +GET request) to see the existing limit, the API response will contain something +like:

    +
    concurrencyControl:
    +  concurrencyLimit: 10
    +  limitType: PERCENT
    +
    +

    It's easy for the user to gloss over limitType and just assume that +--concurrency-limit=20 will update the limit to 20%. However, in reality this +would set the limit to 20 instances (100% of the group), potentially leading to +catastrophic consequences.

    +

    The recommend approach avoids this ambiguity at the expense of some elegance, +but we deem this tradeoff necessary.

    +

    One flag, where percentage is specified if the flag value ends with '%', and number is specified if the flag value ends with 'n'

    +

    In other words, to specify 10% one would use --concurrency-limit=10%, and to +specify 10 instances one would use --concurrency-limit=10n. It would be an +error to provide a value that doesn't end in '%' or 'n'.

    +

    While this avoids the potential for a user to confuse percentages and numbers, +requiring 'n' at the end of a number is inelegant UX. A number should obviously +resemble a number, and the choice of 'n' is also rather arbitrary.

    +

    Exceptions

    +

    This CIP does not apply for API fields like timestamps, where we allow the user +to enter either absolute times or durations in the same flag. This is because +absolute times and durations have natural formats that differ, and thus there's +no potential for a user to confuse the two. In general if this is the case, one +flag that accepts both formats should be preferred for the sake of UX +simplicity.

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/config/header.yaml b/config/header.yaml deleted file mode 100644 index 4d8476fc9b..0000000000 --- a/config/header.yaml +++ /dev/null @@ -1,12 +0,0 @@ -type: static -links: - - title: Browse AIPs - relative_url: /general - - title: News - relative_url: /news - - title: FAQ - relative_url: /faq - - title: Contributing - relative_url: /contributing - - title: API Linter - absolute_url: https://linter.aip.dev/ diff --git a/config/hero.yaml b/config/hero.yaml deleted file mode 100644 index f73960c367..0000000000 --- a/config/hero.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -buttons: - - text: Explore the AIPs - href: /general - - text: Learn how it works - href: /1 -shortcuts: - - title: Curious about the basics? - description: | - AIPs are a combination of design guidance and a system we use to manage - and track that guidance. Learn more about how the AIP program works in - the first AIP! - button: - href: /1 - text: Read AIP-1 - - title: Want to help? - description: | - Interested in helping with AIPs? Contribute by proposing new guidance, - commenting on existing AIPs, or fixing typos. All contributions are - welcome! - button: - href: /contributing - text: Contribute to the project - - title: Want to use AIPs for your organization? - description: | - AIPs are designed to be useful outside of Google. Take a look at how you - might choose which AIPs are best suited to your API design needs. - button: - href: /adopting - text: Learn more - - title: Still have questions? - description: | - Free free to take a look at the frequently asked - questions. If you don't find an answer there, file an issue on our - GitHub repository. - button: - href: https://github.com/aip-dev/google.aip.dev/issues - text: Ask us on GitHub diff --git a/config/urls.yaml b/config/urls.yaml deleted file mode 100644 index 39a9b22ee2..0000000000 --- a/config/urls.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -site: https://google.aip.dev -repo: https://github.com/aip-dev/google.aip.dev diff --git a/contributing.html b/contributing.html new file mode 100644 index 0000000000..3f4bc301cf --- /dev/null +++ b/contributing.html @@ -0,0 +1,752 @@ + + + + Contributing + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Contributing

    +

    We'd love to accept your patches and contributions to this project.

    +

    Development Environment

    +

    If you are contributing AIP content (rather than code) and want to be able to +view it in your browser, the easiest way to do so is to run the provided +development server.

    +

    We use GitHub Pages to make this documentation available, and a specific +site generator to build the site.

    +

    If you have Docker installed, clone this repository and run the serve.sh +file at the root of the repository. This script does two things:

    +
      +
    • It builds the provided Docker image (unless you already have it) and tags it + as aip-site.
    • +
    • It runs the aip-site image.
    • +
    +

    The development server uses port 4000; point your web browser to +http://localhost:4000, and you should see the site.

    +

    Note: After building the Docker image for the first time, you may +experience issues if Python dependencies change underneath you. If this +happens, remove your Docker image (docker rmi aip-site) and run serve.sh +again.

    +

    Arguments

    +

    Any arguments provided to serve.sh (or docker run) are forwarded (however, +the current site generator does not honor any; this may change in the future).

    +

    Hot reloading

    +

    The development server recognizes when files change (including static files) +and local changes will be automatically reflected in your browser upon reload.

    +

    Local Installation

    +

    It is possible to run the development server locally also. The general gist of +how to do so correctly is:

    +
      +
    • Install Python 3.8 if you do not already have it (direct install is fine, but + pyenv is probably the best way if you have other Python projects).
    • +
    • Create a Python 3.8 venv. Once it is created, activate it in your shell + (source path/to/venv/bin/activate).
    • +
    • pip install git+https://github.com/aip-dev/site-generator.git
    • +
    • aip-site-serve .
    • +
    +

    Contributor License Agreement

    +

    Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution, +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to https://cla.developers.google.com/ to see +your current agreements on file or to sign a new one.

    +

    You generally only need to submit a CLA once, so if you have already submitted +one (even if it was for a different project), you probably do not need to do it +again.

    +

    Code reviews

    +

    All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +GitHub Help for more +information on using pull requests.

    +

    Formatting

    +

    We use prettier to format Markdown, JavaScript, and (most) HTML, in order +to ensure a consistent style throughout our source. You can add prettier as a +plugin in most development environments.

    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/faq.html b/faq.html new file mode 100644 index 0000000000..a83fe6255b --- /dev/null +++ b/faq.html @@ -0,0 +1,730 @@ + + + + Frequently asked questions + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Frequently asked questions

    +

    Note: Have a question not answered here? Ask us on GitHub!

    +

    Why Protocol Buffers?

    +

    At Google, we define all of our APIs using Protocol Buffers (.proto files). +While we realize there are lots of other, newer ways of defining these +interfaces (e.g., OpenAPI, RAML, etc), we had to standardize on something and +since we're Google, we use protos.

    +

    This also leads to some very Google-specific ways of mapping proto RPCs to +RESTful URIs (google.api.http annotations). If you're not using protos, feel +free to follow the spirit of the API guidance since you won't be able to +follow the example snippets exactly as provided.

    +

    What's all this Googley stuff?

    +

    Originally, our API guidance was written by and for Googlers only. We're in the +process of making this guidance more general to the world, but that's far from +complete. If you see things like "Submit a CL" or "Talk to your PA lead", feel +free to send pull requests to fix these oversights.

    +

    (CL stands for "Change List" which is sort of like a GitHub Pull Request, and +PA stands for "Product Area" meaning things like "Google Maps" or +"Google Workspace".)

    +

    I like most of these AIPs, but some make no sense for me. What do I do?

    +

    Sometimes guidance from AIPs makes lots of sense for Google (perhaps due to its +size or scale) but no sense at all for others. This is much more common than we +originally thought, so we added a way for sub-teams to override guidance that +doesn't make sense for those teams.

    +

    If you want to adopt most of the AIPs but have a few that make no sense for +your team, you can override those few and stick to just the ones that make +sense for you.

    +

    Why aren't all of Google's products listed here?

    +

    When this project was first published, the AIP program was still relatively new. +Even with time, not all of Google has adopted AIPs as the way of documenting +their API guidance and policies. We're working on broadening the scope to more +and more areas, both inside and outside Google, so this will continue to evolve.

    +

    If you work at Google and want your team to adopt AIPs for documenting how your +team does APIs, feel free to reach out to get in touch with us!

    +

    I have a question that isn't answered here. What do I do?

    +

    We're still pretty new and haven't built up a long list of frequently asked +questions, so if you have a question not answered here, you can always ask us +on GitHub by filing an issue.

    +

    And if you already know the answer to a question that would be helpful for +others, send us a pull request adding it to this page!

    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase.html b/firebase.html new file mode 100644 index 0000000000..e97b12a275 --- /dev/null +++ b/firebase.html @@ -0,0 +1,400 @@ + + + + Firebase AIPs + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + + +
    +
    + +
    +

    Firebase

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    3201 + Projects and Apps + + Draft + +
    3260 + Firebase CLI + + Draft + +
    3270 + JavaScript APIs + + Draft + +
    3271 + Android APIs + + Draft + +
    3272 + iOS APIs + + Draft + +
    3273 + C++ APIs + + Draft + +
    3274 + .NET APIs + + Draft + +
    3275 + Python APIs + + Draft + +
    3276 + Go APIs + + Draft + +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3201.html b/firebase/3201.html new file mode 100644 index 0000000000..5f4e46fac5 --- /dev/null +++ b/firebase/3201.html @@ -0,0 +1,355 @@ + + + + AIP-3201: Projects and Apps + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3201

    +

    Projects and Apps

    +

    Guidance

    +

    Resource Hierarchy

    +

    APIs that utilize an App ID as part of a resource name must include a +Project identifier in the parent:

    +
    apps/*/items
    +
    +

    Must instead be:

    +
    projects/*/apps/*/items
    +
    +

    Project identifiers must follow Cloud guidance. As App IDs are +globally unique, Firebase APIs should allow the unique resource +lookup pattern, allowing a - in place of a Project +ID/Number. For example:

    +
    projects/-/apps/1:111222333444:web:abcdef0123456789/things
    +
    +

    Referencing App IDs

    +

    When referencing an App ID in an SDK or API field, method, or parameter, the +platform-correct initialism of app_id must be used (as opposed to e.g. +app, application_id, or gmp_app_id).

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3260.html b/firebase/3260.html new file mode 100644 index 0000000000..6e9ade1d10 --- /dev/null +++ b/firebase/3260.html @@ -0,0 +1,428 @@ + + + + AIP-3260: Firebase CLI + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3260

    +

    Firebase CLI

    +

    Guidance

    +

    Command Naming

    +

    Commands must be named in lowercase using colons to separate namespaces. +The final segment of a command should be an action verb, for example +list, deploy, or clone. A "get" of a single resource may omit the +action for the sake of brevity (e.g. apps:sdkconfig instead of +apps:sdkconfig:get).

    +

    Project Selection

    +

    The Firebase CLI works with "project directories" that can be associated with +one or more Firebase projects via the use command. This ambient project +selection can be overridden by passing the -P or --project flag.

    +

    All Firebase CLI commands must determine the intended project for a command +based on common project selection, except when a command involves multiple +projects (e.g. a command that clones configuration from one project to +another).

    +

    JSON Output

    +

    All Firebase CLI commands support machine-readable output via the --json +flag. If a command correlates to a single API call, the unmodified response of +that API call should be provided as the JSON response (with wrapped CLI +metadata).

    +

    If a command does not directly correlate to an API call, the output should +include all information a user might reasonably need for programmatic +interpretation of the command. Output must be formatted in snake-case and +generally conform to all standard Google API guidance (e.g. field +names).

    +

    Arguments and Flags

    +

    Required inputs for a command must be represented as arguments (e.g. +database:get /path) unless doing so would be confusing to the user. For +instance, appdistribution:distribute requires as input both a file to +distribute and an App ID, so --app <appId> as a required flag is more clear +than two unrelated arguments with no clear hierarchy.

    +

    Flags must be named using kebab case (e.g. --example-flag) and may +provide a single-letter alias that does not conflict with defined global +flags.

    +

    Common Flags

    +
      +
    • --app <appId> - used to refer to a specific app within a Firebase project.
    • +
    • --force - used to indicate that a command should proceed without additional + prompting regarding potentially destructive actions. For example, deploying + Cloud Functions with --force will automatically delete functions, while + without the user is prompted.
    • +
    • -o, --output <path> - this flag may be used to allow convenient output + of a serialized response to a local file. If the output is JSON, it must + output equivalent JSON to --json without wrapped CLI metadata. If the + command fetches a deployable resource, it must fetch it in a + deploy-compatible format. The string path may be optional if a clear + default path exists. If a file already exists at the path, a confirmation + prompt must be displayed unless a --force flag is also provided.
    • +
    +

    Common Command Types

    +

    List Commands

    +

    Commands that return a list of like resources must use a :list suffix +(e.g. projects:list).

    +

    List commands must not require manual pagination (e.g. a --page-token +flag) and will generally fetch all results (via multiple API calls if +necessary). List commands may include a --limit <int> flag when a +natural ordering exists, such as a reverse chronological list of releases. +A --limit 0 flag indicates that all results should be fetched and +returned.

    +

    The JSON output of a list command must be a concatenated array of all +fetched resources in their original wire format.

    +

    Clone Commands

    +

    If a command's purpose is to copy information from one resource to another, it +must be suffixed with :clone and must take a from and to +argument:

    +
      firebase example:clone <fromProject> <toProject>
    +
    +

    To avoid confusion and accidental misuse, clone commands must explicitly +require both arguments and must not rely on project selection to populate +either.

    +

    If a clone operation is destructive (replaces existing state), the command +should prompt the user for confirmation before proceeding. If a prompt is +added, the command must allow a --force flag to bypass the prompt.

    +

    Deployment

    +

    Behavior that takes local state (e.g. a rules file) and applies it to the live +operation of a Firebase project must integrate with the deploy command.

    +

    Scoped Deployments

    +

    If a service has multiple deployable resources, it may allow specifying +which resources are deployed through colon namespacing, for example:

    +
      firebase deploy --only functions:func1,functions:func2,hosting:site3
    +
    +

    Colon namespacing may be used to identify one of many like resources (as +with functions above) or to identify specific resource type (e.g. +firestore:indexes vs. firestore:rules).

    +

    If the service integrates with deploy targets, the targets +must be addressable via colon namespacing.

    + + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3270.html b/firebase/3270.html new file mode 100644 index 0000000000..c040e3a5db --- /dev/null +++ b/firebase/3270.html @@ -0,0 +1,335 @@ + + + + AIP-3270: JavaScript APIs + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3270

    +

    JavaScript APIs

    +

    Guidance

    +

    Changelog

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3271.html b/firebase/3271.html new file mode 100644 index 0000000000..cf5a5a802b --- /dev/null +++ b/firebase/3271.html @@ -0,0 +1,335 @@ + + + + AIP-3271: Android APIs + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3271

    +

    Android APIs

    +

    Guidance

    +

    Changelog

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3272.html b/firebase/3272.html new file mode 100644 index 0000000000..5e75baebe4 --- /dev/null +++ b/firebase/3272.html @@ -0,0 +1,335 @@ + + + + AIP-3272: iOS APIs + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3272

    +

    iOS APIs

    +

    Guidance

    +

    Changelog

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3273.html b/firebase/3273.html new file mode 100644 index 0000000000..e438984e2c --- /dev/null +++ b/firebase/3273.html @@ -0,0 +1,335 @@ + + + + AIP-3273: C++ APIs + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3273

    +

    C++ APIs

    +

    Guidance

    +

    Changelog

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3274.html b/firebase/3274.html new file mode 100644 index 0000000000..be4ba89367 --- /dev/null +++ b/firebase/3274.html @@ -0,0 +1,335 @@ + + + + AIP-3274: .NET APIs + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3274

    +

    .NET APIs

    +

    Guidance

    +

    Changelog

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3275.html b/firebase/3275.html new file mode 100644 index 0000000000..3d2a6d881f --- /dev/null +++ b/firebase/3275.html @@ -0,0 +1,335 @@ + + + + AIP-3275: Python APIs + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3275

    +

    Python APIs

    +

    Guidance

    +

    Changelog

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/firebase/3276.html b/firebase/3276.html new file mode 100644 index 0000000000..ccf7d8697e --- /dev/null +++ b/firebase/3276.html @@ -0,0 +1,335 @@ + + + + AIP-3276: Go APIs + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +

    + This AIP is currently a draft. This means that it is being actively debated + and discussed, and it may change in non-trivial ways. +

    +

    AIP-3276

    +

    Go APIs

    +

    Guidance

    +

    Changelog

    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/general.html b/general.html new file mode 100644 index 0000000000..a8a7613a0a --- /dev/null +++ b/general.html @@ -0,0 +1,1244 @@ + + + + General AIPs + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + + +
    + + + +
    +
    + +
    +

    Meta

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    1 + AIP Purpose and Guidelines +
    2 + AIP Numbering +
    3 + AIP Versioning +
    200 + Precedent +
    8 + AIP Style and Guidance +
    9 + Glossary +
    +

    Process

    + + + + + + + + + + + + + + + + + +
    NumberTitle
    100 + API Design Review FAQ +
    205 + Beta-blocking changes +
    +

    API Concepts

    + + + + + + + + + + + + + +
    NumberTitle
    111 + Planes +
    +

    Resource Design

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    121 + Resource-oriented design +
    122 + Resource names +
    123 + Resource types +
    124 + Resource association +
    126 + Enumerations +
    128 + Declarative-friendly interfaces +
    129 + Server-Modified Values and Defaults +
    156 + Singleton resources +
    236 + Policy preview +
    +

    Operations

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    130 + Methods +
    131 + Standard methods: Get +
    132 + Standard methods: List +
    133 + Standard methods: Create +
    134 + Standard methods: Update +
    135 + Standard methods: Delete +
    136 + Custom methods +
    151 + Long-running operations +
    231 + Batch methods: Get +
    233 + Batch methods: Create +
    234 + Batch methods: Update +
    235 + Batch methods: Delete +
    +

    Fields

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    140 + Field names +
    202 + Fields +
    203 + Field behavior documentation +
    141 + Quantities +
    142 + Time and duration +
    143 + Standardized codes +
    144 + Repeated fields +
    145 + Ranges +
    146 + Generic fields +
    147 + Sensitive fields +
    148 + Standard fields +
    149 + Unset field values +
    216 + States +
    +

    Design Patterns

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    152 + Jobs +
    153 + Import and export +
    154 + Resource freshness validation +
    155 + Request identification +
    157 + Partial responses +
    158 + Pagination +
    159 + Reading across collections +
    160 + Filtering +
    161 + Field masks +
    162 + Resource Revisions + + Draft + +
    163 + Change validation +
    164 + Soft delete +
    165 + Criteria-based delete +
    210 + Unicode +
    211 + Authorization checks +
    214 + Resource expiration +
    217 + Unreachable resources +
    +

    Compatibility and Versioning

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    180 + Backwards compatibility +
    181 + Stability levels +
    182 + External software dependencies + + Reviewing + +
    185 + API Versioning +
    +

    Polish

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    190 + Naming conventions +
    191 + File and directory structure +
    192 + Documentation +
    193 + Errors +
    194 + Automatic retry configuration +
    +

    Protocol buffers

    + + + + + + + + + + + + + + + + + + + + + +
    NumberTitle
    127 + HTTP and gRPC Transcoding +
    213 + Common components +
    215 + API-specific protos +
    + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000000..0814050b7e --- /dev/null +++ b/index.html @@ -0,0 +1,262 @@ + + + + API Improvement Proposals + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    +
    +
    + API Improvement Proposals +
    +
    + Focused design documents for flexible API development. +
    + +
    + +
    +

    Welcome

    +

    + AIPs are design documents that summarize Google's API design + decisions. They also provide a framework and system for others to + document their own API design rules and practices. +

    +
    + +
    + +
    +

    Curious about the basics?

    +
    AIPs are a combination of design guidance and a system we use to manage +and track that guidance. Learn more about how the AIP program works in +the first AIP! +
    + + Read AIP-1 » + +
    + +
    +

    Want to help?

    +
    Interested in helping with AIPs? Contribute by proposing new guidance, +commenting on existing AIPs, or fixing typos. All contributions are +welcome! +
    + + Contribute to the project » + +
    + +
    +

    Want to use AIPs for your organization?

    +
    AIPs are designed to be useful outside of Google. Take a look at how you +might choose which AIPs are best suited to your API design needs. +
    + + Learn more » + +
    + +
    +

    Still have questions?

    +
    Free free to take a look at the frequently asked +questions. If you don't find an answer there, file an issue on our +GitHub repository. +
    + + Ask us on GitHub » + +
    + +
    + +
    + +
    + + + + + \ No newline at end of file diff --git a/licensing.html b/licensing.html new file mode 100644 index 0000000000..939cc9f19f --- /dev/null +++ b/licensing.html @@ -0,0 +1,747 @@ + + + + Content licensing + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Content licensing

    +

    We are pleased to license much of the AIP content under terms that explicitly +encourage people to take, modify, reuse, re-purpose, and remix our work as they +see fit.

    +

    You will find the following notice at the bottom of many pages:

    +
    +

    Except as otherwise noted, the content of this page is licensed under the +Creative Commons Attribution 4.0 License, and code samples are +licensed under the Apache 2.0 License. For details, see +content licensing.

    +
    +

    When you see a page with this notice you are free to use +nearly everything on the page in your own creations. For +example, you could quote the text in a book, cut-and-paste sections to your +blog, record it as an audiobook for the visually impaired, or even translate it +into Swahili. Really. That's what open content licenses are all about. We just +ask that you give us attribution when you reuse our work.

    +

    In addition, you are free to use the computer source code that appears in the +content (such as in examples) in the code of your own projects.

    +

    Restrictions

    +

    We say "nearly everything" as there are a few simple conditions that apply.

    +

    Google's trademarks and other brand features are not included in this license. +Please see our standard guidelines for third party use of Google brand +features for information about this usage.

    +

    In some cases, a page may include content consisting of images, audio or video +material, or a link to content on a different webpage (such as videos or slide +decks). This content is not covered by the license, unless specifically noted.

    +

    Attribution

    +

    Proper attribution is required when you reuse or create modified versions of +content that appears on a page made available under the terms of the Creative +Commons Attribution license. The complete requirements for attribution can be +found in section 3 of the Creative Commons legal code.

    +

    In practice we ask that you provide attribution to Google to the best of the +ability of the medium in which you are producing the work.

    +

    There are several typical ways in which this might apply:

    +

    Exact reproductions

    +

    If your online work exactly reproduces text or images from this site, in +whole or in part, please include a paragraph at the bottom of your page that +reads:

    +
    +

    Portions of this page are reproduced from work created and shared by +Google and used according to terms described in the Creative +Commons 4.0 Attribution License.

    +
    +

    Also, please link back to the original source page so that readers can refer to +it for more information.

    +

    Modified versions

    +

    If your online work shows modified text or images based on the content from +this site, please include a paragraph at the bottom of your page that reads:

    +
    +

    Portions of this page are modifications based on work created and shared by +Google and used according to terms described in the Creative +Commons 4.0 Attribution License.

    +
    +

    Again, please link back to the original source page so that readers can refer +to it for more information. This is even more important when the content has +been modified.

    +

    Other media

    +

    If you produce non-hypertext works, such as books, audio, or video, we ask that +you make a best effort to include a spoken or written attribution in the spirit +of the messages above.

    + +

    This page was adapted from the site policies for developers.google.com. +Last updated: May 13, 2019

    +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news.html b/news.html new file mode 100644 index 0000000000..8f02006d86 --- /dev/null +++ b/news.html @@ -0,0 +1,861 @@ + + + + News + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    News

    +

    Want to keep up with the AIP system, and what we are working on? Welcome to the +AIP newsletter, a monthly publication covering new AIP guidance, and any +other developments useful to API producers.

    +

    March 2021

    +
    Auth and Field Masks
    +

    Publishing long-standing guidance around permissions and field masks.

    +
    +

    Highlights:

    +
      + +
    • Reviewing: + +
    • + + +
    • Approval of AIPs discussed in the October 2020 newsletter.
    • + +
    +
    + +

    October 2020

    +
    Declarative-friendly APIs
    +

    Why and how to make an API interface "declarative friendly", in order to +enable automation on top of it.

    +
    +

    Highlights:

    +
      + +
    • Reviewing: + +
    • + + +
    • Declarative-friendly updates to existing AIPs.
    • + +
    +
    + +

    August 2020

    +
    Field patterns, redux
    +

    Patterns around sensitive fields.

    +
    +

    Highlights:

    +
      + +
    • Reviewing: + +
    • + + +
    +
    + +

    June 2020

    +
    Field patterns
    +

    Patterns around ranges and generic fields.

    +
    +

    Highlights:

    + +
    + +

    May 2020

    +
    Jobs and filters
    +

    Formalizing the Job pattern; clarifications coming to filtering.

    +
    +

    Highlights:

    + +
    + +

    April 2020

    +
    Data Series
    +

    This month's AIPs revolve around handling lists and series of data, which +present specific challenges in APIs.

    +
    +

    Highlights:

    + +
    + +

    March 2020

    +
    Welcome to the AIP Newsletter
    +

    The first edition of the AIP newsletter outlines the plan for reviewing +outstanding proposals, and announces the release of the API linter.

    +
    +

    Highlights:

    + +
    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news/2020-03.html b/news/2020-03.html new file mode 100644 index 0000000000..a2e790c2aa --- /dev/null +++ b/news/2020-03.html @@ -0,0 +1,828 @@ + + + + Welcome to the AIP Newsletter + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Welcome to the AIP Newsletter

    +

    Welcome to the first (hopefully monthly) edition of the AIP newsletter, +which is designed to keep you up to date about the AIP program, and particular +proposals making their way through the system.

    +

    In this edition, we will discuss five pending proposals. This is intended as a +"public comment" period: the AIP editors are happy with these proposals, but we +want to ensure that you are too. Assuming feedback is sufficiently positive, we +intend to formally approve these proposals on Friday, March 27, 2020.

    +

    API linter

    +

    As many readers know, we have published an API linter, which is able to +check much of the guidance provided in API Improvement Proposals for APIs +defined in protocol buffers.

    +

    The linter now has over 150 rules, and is running on many new and existing APIs +at Google, hopefully pushing us toward greater consistency.

    +

    AIPs under review

    +

    AIP-153: Import and export

    +
    +

    Many users want to be able to load data into an API, or get their existing +data out of an API. This is particularly important for enterprise users, who +are often concerned about vendor lock.

    +
    +

    Import and export are particularly important concepts for enterprise +APIs, although they are increasing in importance for consumer and SaaS APIs as +well.

    +

    We have actually had a reasonably consistent import and export story in Google +Cloud for a long time, but it has largely been passed along by tribal knowledge +("go look at X and copy what they did"). Therefore, this AIP attempts to codify +what we believe is a long-standing practice.

    +

    Summary: AIP-153 mandates that both import and export methods return +long-running operations. Unlike most API methods, they do support +partial failures, which are handled through the LRO metadata. Finally, they +have a specified place for per-source and per-destination configuration, +distinct from configuration for the data itself.

    +

    We are aiming to approve AIP-153 on March 27. If you have feedback, please +leave a comment.

    +

    AIP-162: Resource revisions

    +
    +

    Some APIs need to have resources with a revision history, where users can +reason about the state of the resource over time.

    +
    +

    Resource revisions is a concept we are seeing crop up more and more, +and we are seeing an increasing number of situations where audit logging is a +necessary but insufficient solution. Several APIs have struggled with how to +model a resource's history over time, and handle common use cases like commit +and rollback, which is what prompted this AIP.

    +

    This is new guidance, put together by the AIP team as well as several API teams +who needed this functionality near the end of 2019. It has been positively +received by the teams that needed it, and so we would like to codify it.

    +

    Summary: AIP-162 mandates the use of revision IDs that are appended to +a resource name with the @ character for signifying revisions, and sets out +method structures for most common operations (listing revisions, rollback, +etc.). It also proposes a tagging mechanism for user-friendly revision names.

    +

    We are aiming to approve AIP-162 on March 27. If you have feedback, please +leave a comment.

    +

    AIP-163: Change validation

    +
    +

    Occasionally, a user wants to validate an intended change to see what the +result will be before actually making the change. For example, a request to +provision new servers in a fleet will have an impact on the overall fleet +size and cost, and could potentially have unexpected downstream effects.

    +
    +

    Change validation is the concept of performing a "dry run" on an API +request, and returning back the result without making any changes.

    +

    This is effectively a migration of long-standing guidance that was not very +fleshed out. The previous API design guide mentioned validate_only as an +entry in the standard fields table with minimal explanation. This proposal +fleshes that out with an example, and addresses some questions we have received +over time.

    +

    Summary: AIP-163 offers guidance for "dry run" requests using a +bool validate_only field in the request message, and addresses some common +situations around permissions and incomplete output.

    +

    We are aiming to approve AIP-163 on March 27. If you have feedback, please +leave a comment.

    +

    AIP-165: Criteria-based delete

    +
    +

    Occasionally, an API may need to provide a mechanism to delete a large number +of resources based on some set of filter parameters, rather than requiring +the individual resource name of the resources to be deleted.

    +
    +

    Criteria-based delete is designed to address problems where a user +needs to delete so many items that batch delete simply becomes +infeasible.

    +

    This proposal represents a concession of sorts: we have long tried to avoid +delete-by-filter because of concerns that users would accidentally delete +important records and be unable to recover them. However, several APIs have had +legitimate reasons to need to do this, because the number of records the user +would want to delete was so high.

    +

    Summary: AIP-165 offers guidance for criteria-based delete, with a +common name (Purge) and structure, and mandates a dry-run by default with a +force flag to actually perform the purge.

    +

    We are aiming to approve AIP-165 on March 27. If you have feedback, please +leave a comment.

    +

    AIP-194: Retries for gRPC clients

    +
    +

    RPCs sometimes fail. When one does, the client performing the RPC needs to +know whether it is safe to retry the operation. When status codes are used +consistently across multiple APIs, clients can respond to failures +appropriately.

    +
    +

    Retries for gRPC clients handles how to deal with errors, and in +particular when a client can transparently retry those errors.

    +

    This proposal came about because of a need for first-party client libraries to +be able to transparently retry some server errors. gRPC offers a configuration +strategy for this, which is defined by API producers.

    +

    Summary: AIP-194 offers guidance for configuring what error codes from +an API are safe to retry. It recommends usually retrying UNAVAILABLE and +nothing else.

    +

    We are aiming to approve AIP-194 on March 27. If you have feedback, please +leave a comment.

    +

    Recent updates

    +

    In addition to the new AIPs under review, we have added the following guidance +to existing AIPs:

    +
      +
    • AIP-8: AIPs have reverse-chronological changelogs + (#425)
    • +
    • AIP-135: Delete methods send 403 errors if the user lacks access + (#409)
    • +
    • AIP-140: display_name and title standard fields + (#405)
    • +
    • AIP-158: Field order for pagination response messages + (#419)
    • +
    • AIP-193: Added reference to new ErrorInfo message + (#396)
    • +
    +

    What is coming?

    +

    We have more coming over the course of the next few months, including +long-awaited public guidance for filtering and versioning.

    +

    You also may notice some pull requests around making AIPs more generic. We are +exploring the possibility of bringing AIPs to even more API producers across +multiple companies, so that others can publish their standards under a common +information architecture. This effort is still nascent, but we are excited and +hopeful. Stay tuned!

    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news/2020-04.html b/news/2020-04.html new file mode 100644 index 0000000000..761629d065 --- /dev/null +++ b/news/2020-04.html @@ -0,0 +1,768 @@ + + + + Data Series + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Data Series

    +

    Welcome to the second edition of the AIP newsletter, which is designed to +keep you up to date about the AIP program, and particular proposals making +their way through the system.

    +

    This month's new AIPs (unintentionally) share a common theme: handling lists +and series of data, whether in fields, resource relationships, or actual list +methods. These new AIPs are long overdue: they codify knowledge that has long +been reasonably consistent, but tribal.

    +

    The AIP newsletter kicks off what is effectively a "public comment" period: the +AIP editors are happy with these proposals, but we want to ensure that you are +too. Assuming feedback is sufficiently positive, we intend to formally approve +these proposals on Friday, April 24, 2020.

    +

    AIPs under review

    +

    AIP-124: Resource associations

    +
    +

    APIs sometimes have resource hierarchies that can not be cleanly expressed in +the usual tree structure.

    +
    +

    Resource association comes into play when a resource needs something +other than a direct parent-child relationship. This might mean a many-to-many +relationship, or it might be a one-to-many association that is distinct from +the parent-child relationship.

    +

    We have had several APIs struggle with unusual associations over the past year +or so. In general, this has been handled reasonably consistently, but we never +codified the guidance into an official AIP.

    +

    Summary: AIP-124 provides patterns for the two most common +associations: a resource with multiple different one-to-many relationships, and +a resource with a many-to-many association with another resource.

    +

    We are aiming to approve AIP-124 on April 24. If you have feedback, please +leave a comment.

    +

    AIP-144: Repeated fields

    +
    +

    Representing lists of data in an API is trickier than it often appears. Users +often need to modify lists in place, and longer data series within a single +resource pose a challenge for pagination.

    +
    +

    Repeated fields are somewhat common in APIs, and a common question +that we get is how to handle adding or removing a single item from them +atomically. Additionally, repeated fields can become a trap if they are +unbounded in size and become too large.

    +

    This is codification of guidance that we have been giving on a case-by-case +basis for some time. In particular, this documents the various restrictions on +the two update strategies.

    +

    Summary: AIP-144 lays out guidance for repeated fields, and details two +distinct strategies for updating repeated fields.

    +

    We are aiming to approve AIP-144 on April 24. If you have feedback, please +leave a comment.

    +

    AIP-160: Filtering

    +
    +

    Often, when listing resources, it is desirable to filter over the collection +and only return results that the user is interested in.

    +
    +

    Filtering involves taking a list of resources (usually) and only +providing the results that the user wants, specified using a familiar syntax +similar to that of Google search.

    +

    This is likely the most-requested AIP of all time. We have had internal +filtering documents for ages, but we have not had a public version, and one has +been sorely needed for years. Also, this work would likely still be unfinished +if not for the efforts of Tristan Swadell; we are grateful for his efforts.

    +

    Summary: AIP-160 offers a detailed breakdown of the filtering syntax +and how to provide filtering results in list and search methods.

    +

    We are aiming to approve AIP-160 on April 24. If you have feedback, please +leave a comment.

    +

    Recent updates

    +

    In addition to the new AIPs under review, we have added the following guidance +to existing AIPs:

    +
      +
    • AIP-133: Clarify which fields can be required + (#460)
    • +
    • AIP-140: Add guidance about message and field name conflicts + (#470)
    • +
    • AIP-151: Clarify that both response_type and metadata_type are + expected (#469)
    • +
    • AIP-231: Clarify Batch Get behavior if no resource names are sent + (#474)
    • +
    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news/2020-05.html b/news/2020-05.html new file mode 100644 index 0000000000..b0a2016925 --- /dev/null +++ b/news/2020-05.html @@ -0,0 +1,748 @@ + + + + Jobs and filters + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Jobs and filters

    +

    Welcome to the third edition of the AIP newsletter, which is designed to +keep you up to date about the AIP program, and particular proposals making +their way through the system.

    +

    This month, we have one new AIP, which is around jobs: resources created for +managing a task that may be repeated. We also have one AIP from April that we +have delayed finalizing.

    +

    As always, the AIP newsletter kicks off what is effectively a "public comment" +period: the AIP editors are happy with these proposals, but we want to ensure +that you are too. Assuming feedback is sufficiently positive, we intend to +formally approve these proposals on Friday, May 29, 2020.

    +

    AIPs under review

    +

    AIP-152: Jobs

    +
    +

    Occasionally, APIs may need to expose a task that takes significant time to +complete, and where a transient long-running operation is not appropriate. +For example, a task could need to run repeatedly, or have separate +permissions for configuring the task as opposed to running it.

    +
    +

    Jobs are resources that are created that represent a (usually) +repeated task in an API. The idea is that the job is configured once, and +exists as an independent resource, which can either be executed by a user, or +by the system on a schedule.

    +

    Jobs are useful when more structure or more permanence is needed than a simple +RPC with a long-running operation can provide. They can also be useful if a +service requires a permission model that distinguishes between who can +configure a job as opposed to who can run it.

    +

    Summary: AIP-152 provides patterns for jobs: first-class resources that +represent tasks that are run repeatedly, whether by a user or by the system on +a schedule.

    +

    We are aiming to approve AIP-152 on May 29. If you have feedback, please +leave a comment.

    +

    AIP-160: Filtering

    +
    +

    Often, when listing resources, it is desirable to filter over the collection +and only return results that the user is interested in.

    +
    +

    Filtering involves taking a list of resources (usually) and only +providing the results that the user wants, specified using a familiar syntax +similar to that of Google search.

    +

    This AIP is a holdover from last month's newsletter: we intended to approve it +in April, but several teams brought forth issues and clarifications that +necessitated further iteration. (Thanks!!) These are now represented in the +approval pull request (#473), and we hope to approve this AIP in May.

    +

    Summary: AIP-160 offers a detailed breakdown of the filtering syntax +and how to provide filtering results in list and search methods.

    +

    We are aiming to approve AIP-160 on May 29. If you have feedback, please leave +a comment.

    +

    Recent updates

    +

    In addition to the new AIPs under review, we have added the following guidance +to existing AIPs:

    +
      +
    • AIP-122: Tighten restrictions on resource names + (#496)
    • +
    • AIP-192: Mandate use of absolute links in comments + (#480)
    • +
    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news/2020-06.html b/news/2020-06.html new file mode 100644 index 0000000000..2596e48661 --- /dev/null +++ b/news/2020-06.html @@ -0,0 +1,750 @@ + + + + Field patterns + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Field patterns

    +

    Welcome to the fourth edition of the AIP newsletter, which is designed to +keep you up to date about the AIP program, and particular proposals making +their way through the system.

    +

    This month, we have two new AIPs, both around patterns for specific kinds of +fields.

    +

    As always, the AIP newsletter kicks off what is effectively a "public comment" +period: the AIP editors are happy with these proposals, but we want to ensure +that you are too. Assuming feedback is sufficiently positive, we intend to +formally approve these proposals on Friday, June 26, 2020.

    +

    AIPs under review

    +

    AIP-145: Ranges

    +
    +

    Services often need to represent ranges of discrete or continuous values. +These have wide differences in meaning, and come in many types: integers, +floats, and timestamps, just to name a few, and the expected meaning of a +range can vary in subtle ways depending on the type of range being discussed.

    +
    +

    Ranges are fields that represent a range of discrete or continuous +values. These are often integers or floats, but can be other values where +ranges make sense, such as dates.

    +

    The primary challenge for ranges is whether their values (particularly their +end values) should be inclusive or exclusive. Most developers are used to +exclusive end values, but with some notable and precise exceptions (example: +dates are an exception, but not timestamps), and the AIP attempts to encode +this using the idea of "colloquial precedent".

    +

    Summary: AIP-145 provides patterns for ranges of values: two fields +that represent a start and end value.

    +

    We are aiming to approve AIP-145 on June 26. If you have feedback, please +leave a comment.

    +

    AIP-146: Generic fields

    +
    +

    Occasionally it is appropriate to have a generic or polymorphic field of some +kind that can conform to multiple schemata, or even be entirely free-form.

    +
    +

    Generic fields discusses the various ways to approach a polymorphic +or entirely generic field in the API. These provide implementation flexibility, +but the tradeoff is a less clear API contract. There are several ways to +provide a generic field, and the AIP enumerates them and discussed the +tradeoffs.

    +

    Summary: AIP-146 offers four patterns for generic fields, and describes +the tradeoffs of each.

    +

    We are aiming to approve AIP-146 on June 26. If you have feedback, please +leave a comment.

    +

    Recent updates

    +

    In addition to the new AIPs under review, we have added the following guidance +to existing AIPs:

    +
      +
    • AIP-122: Corrected a mistaken piece of guidance about + capitalization (#513)
    • +
    • AIP-132: Removed mandate to document default ordering + (#512)
    • +
    • AIP-140: Add guidance for URI fields + (#519)
    • +
    • AIP-143: Change guidance for countries to region_code + (#507)
    • +
    • AIP-203: Clarified behavior for updating immutable fields + (#516)
    • +
    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news/2020-08.html b/news/2020-08.html new file mode 100644 index 0000000000..d4fe2b7ffe --- /dev/null +++ b/news/2020-08.html @@ -0,0 +1,733 @@ + + + + Field patterns, redux + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Field patterns, redux

    +

    Welcome to the fifth edition of the AIP newsletter, which is designed to +keep you up to date about the AIP program, and particular proposals making +their way through the system. (Our apologies for not publishing a newsletter in +July.)

    +

    We have one new AIP this month, on sensitive fields. As always, the AIP +newsletter kicks off what is effectively a "public comment" period: the AIP +editors are happy with this proposal, but we want to ensure that you are too. +Assuming feedback is sufficiently positive, we intend to formally approve these +proposals on Friday, August 28, 2020.

    +

    AIPs under review

    +

    AIP-147: Sensitive fields

    +
    +

    Sometimes APIs need to collect sensitive information such as private +encryption keys meant to be stored by the underlying service but not +intended to be read after writing due to the sensitive nature of the data.

    +
    +

    Sensitive fields are fields that are stored by a service but, once +set, not retrievable by the user, such as passwords or private keys. These are +not particularly common in APIs, and often it is sufficient to set them as +INPUT_ONLY (as described in AIP-203).

    +

    However, there is a challenge in situations where the service needs to provide +some kind of indication that a value has been provided, or provide an +obfuscated value that the original user ought to recognize. This AIP provides a +standard for each of those situations.

    +

    A special thanks to Michael Bleigh for writing this AIP.

    +

    Summary: AIP-147 provides patterns for indicators around sensitive +fields.

    +

    We are aiming to approve AIP-147 on August 28. If you have feedback, please +leave a comment.

    +

    Recent updates

    +

    In addition to the new AIPs under review, we have added the following guidance +to existing AIPs:

    +
      +
    • AIP-135: Add "get" guidance for soft delete. + (#526)
    • +
    • AIP-140: Word segments in field names must not begin with a number. + (#528)
    • +
    • AIP-151: Add guidance for parallel operations. + (#535)
    • +
    • AIP-158: Clarify that page_size is always an optional field. + (#537)
    • +
    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news/2020-10.html b/news/2020-10.html new file mode 100644 index 0000000000..7a6eb79237 --- /dev/null +++ b/news/2020-10.html @@ -0,0 +1,806 @@ + + + + Declarative-friendly APIs + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Declarative-friendly APIs

    +

    Welcome to the sixth edition of the AIP newsletter, which is designed to +keep you up to date about the AIP program, and particular proposals making +their way through the system.

    +

    We have an exciting slate of AIPs entering review this cycle, all around the +theme of "declarative-friendly APIs". The linchpin here is AIP-128, which +introduces and explains the topic.

    +

    The idea behind declarative-friendly APIs addresses an important need: the +ability to integrate with popular, declarative tools, such as Kubernetes or +Terraform. These tools and others are used by numerous developers, and the +follow a straightforward paradigm: the user provides the tool with the desired +state, and the tool brings that state into fruition.

    +

    Integration with these tools is critical for cloud providers, but with the +number of services and the number of tools continuously increasing, support +is difficult without a reliance on automation. Automation, in turn, requires +strong consistency.

    +

    While ordinarily AIPs stay in review for about a month, we intend for this +review cycle to be longer, to allow time for APIs to be released that follow +this guidance. Assuming the feedback is sufficiently positive, we will probably +be looking at formal approval around the end of the year.

    +

    AIPs under review

    +

    AIP-128: Declarative-friendly interfaces

    +
    +

    Many services need to interact with common DevOps tools, particularly those +that create and manage network-addressible resources (such as virtual +machines, load balancers, database instances, and so on). These tools revolve +around the principle of "configuration as code": the user specifies the +complete intended landscape, and tooling is responsible for making whatever +changes are necessary to achieve the user's specification.

    +

    These tools are declarative: rather than specifying specific actions to +take, they specify the desired outcome, with the actions being derived +based on the differences between the current landscape and the intended one.

    +
    +

    Declarative-friendly interfaces describes patterns for making +interfaces that are friendly to automated tooling. The basic idea is that by +being more strict and consistent, it becomes possible to write tools that +"translate" the interface to a declarative form without having to know anything +about the specific API.

    +

    This reduces feature latency for users. Essentially, the adapter or plugin can +be automatically generated, and so an automated pipeline becomes possible: as +soon as the service launches new features, they become available in the +adapters also.

    +

    Because declarative-friendliness is a wide-ranging concept, impacting the +guidance in numerous other AIPs as well, it was difficult to determine how to +structure the information. Therefore, this AIP also has a robust "further +reading" section that points to declarative-friendly guidance in other AIPs.

    +

    Summary: AIP-128 provides an explanation of what it means for a service +to be declarative-friendly, and why a service might want to adopt these +patterns. It also indexes declarative-friendly guidance found in other AIPs.

    +

    AIP-148: Standard fields

    +
    +

    Certain concepts are common throughout any corpus of APIs. In these +situations, it is useful to have a standard field name that is used +consistently to communicate that concept.

    +
    +

    Standard fields is, in some ways, an overdue AIP. It describes +fields common throughout our corpus, such as name, parent, and +create_time, that were on the list of standard fields in the original API +style guide and did not get a full treatment in other AIPs. Common fields that +are covered in other AIPs are not discussed in this one. (As an example, +language_code is given extensive treatment in AIP-143, so not repeated +here.)

    +

    This takes on new importance with our focus on declarative-friendly APIs +because tools written to marshal between a declarative tool and the service can +see those tools and know what they mean.

    +

    Summary: AIP-148 describes common fields that are already in common use +throughout our API corpus. It also describes certain fields that are expected +on declarative-friendly resources.

    +

    AIP-164: Soft delete

    +
    +

    There are several reasons why a client could desire soft delete and undelete +functionality, but one over-arching reason stands out: recovery from +mistakes. A service that supports undelete makes it possible for users to +recover resources that were deleted by accident.

    +
    +

    Soft delete is increasingly critical for APIs that need to cater to +enterprise users, due to the need to be able to recover from mistakes without +data loss. While AIP-135 previously discussed soft delete, it was clear +that a more thorough treatment is necessary.

    +

    This AIP goes through the request patterns in more detail, and discusses topics +such as LROs and errata, that are relevant to soft delete and undelete.

    +

    Summary: AIP-164 expands the guidance on soft delete and undelete and +provides a more detailed look at both.

    +

    AIP sections under review

    +

    Because of the need to add declarative-friendly guidance into existing AIPs, +certain sections needed to be introduced into existing, approved AIPs in a +reviewing state. These are all in use for declarative-friendly guidance and +would be approved alongside AIP-128:

    + +

    Additionally, new sections in AIP-154 +and AIP-163 mandate the use of these +concepts for declarative-friendly resources.

    +

    Recent updates

    +

    In addition to the new AIPs under review, we have added the following guidance +to existing AIPs:

    +
      +
    • AIP-122: Clarified when to use full resource names + (#629)
    • +
    • AIP-132: Loosened guidance around top-level resources + (#602)
    • +
    • AIP-132: Added PERMISSION_DENIED guidance + (#582)
    • +
    • AIP-151: Clarified that stream and LROs are mutually incompatible + (#597)
    • +
    • AIP-216: Clarified that states are not directly set on Create + (#606)
    • +
    +

    Special thanks to Andrew Paseltiner and Peter Novotney for some of these +changes, and to several others who send minor corrections not noted here.

    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/news/2021-03.html b/news/2021-03.html new file mode 100644 index 0000000000..d3261dc10d --- /dev/null +++ b/news/2021-03.html @@ -0,0 +1,770 @@ + + + + Auth and Field Masks + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +

    Auth and Field Masks

    +

    Welcome to the seventh edition of the AIP newsletter, which is designed to +keep you up to date about the AIP program, and particular proposals making +their way through the system.

    +

    We have three new AIPs this month. As always, the AIP newsletter kicks off what +is effectively a "public comment" period: the AIP editors are happy with this +proposal, but we want to ensure that you are too. Assuming feedback is +sufficiently positive, we intend to formally approve these proposals on Friday, +March 26, 2021.

    +

    AIPs under review

    +

    AIP-149: Unset field values

    +
    +

    In many messages, many fields are optional: the user is not required to +provide them, or for output fields, the service might not populate the field.

    +
    +

    Unset field values refer to primitive fields where the service makes +a meaningful distinction between an empty value (such as 0 or false) and +not setting the value at all. While this is generally discouraged if an +alternative design is feasible, there are certainly occasions where this is the +best approach.

    +

    Summary: AIP-149 provides guidance around use of the optional keyword +for primitives.

    +

    We are aiming to approve AIP-149 on March 26. If you have feedback, please +leave a comment.

    +

    AIP-161: Field masks

    +
    +

    Often, when updating resources, it is desirable to specify exactly which +fields are being updated, so that the service can ignore the rest, even if +the user sends new values.

    +
    +

    Field masks are the way that users are able to specify exactly which +fields to read or update. They are necessary to ensure that adding fields to +existing messages remains backwards-compatible.

    +

    While we have had an internal specification for field masks for some time, this +AIP publicizes the specification.

    +

    Summary: AIP-161 provides a public specification for field masks.

    +

    We are aiming to approve AIP-161 on March 26. If you have feedback, please +leave a comment.

    +

    AIP-211: Authorization checks

    +
    +

    The majority of operations, whether reads or writes, require authorization: +permission to do the thing the user is asking to do. Additionally, it is +important to be careful how much information is provided to unauthorized +users, since leaking information can be a security concern.

    +
    +

    Authorization checks discusses when in the logical process of a +request the authorization check ought to occur, and what error to send when an +auth check fails.

    +

    In particular, if an authorization check fails, regardless of whether the +resource exists, the service consistently returns PERMISSION_DENIED with an +error message that also indicates that the resource might not exist.

    +

    Summary: AIP-211 provides guidance about authorization checks: when to +perform them, and what error to send.

    +

    We are aiming to approve AIP-211 on March 26. If you have feedback, please +leave a comment.

    +

    Additional approvals

    +

    We also intend to approve the AIPs that were placed under review in the October +2020 newsletter. This includes AIP-128 (#708), AIP-148 (#710), +and AIP-164 (#709). If you have feedback, please leave a comment in the +referenced pull requests.

    +

    Recent updates

    +

    In addition to the new AIPs under review, we have added the following guidance +to existing AIPs:

    +
      +
    • AIP-144: Expand Add and Remove guidance. + (#648)
    • +
    • AIP-154: Etag failures should use ABORTED. + (#705)
    • +
    • AIP-162: Forbid deleting the only remaining revision. + (#692)
    • +
    • AIP-162: Restrict revision tags to lower-case. + (#707)
    • +
    • AIP-165: Make implicit recommendations more explicit. + (#662)
    • +
    • AIP-203: Add UNORDERED_LIST to field behaviors. + (#671)
    • +
    + + +
    + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/not-precedent.html b/not-precedent.html new file mode 100644 index 0000000000..32ed0d049b --- /dev/null +++ b/not-precedent.html @@ -0,0 +1,13 @@ + + + + Redirecting… + + + + + +

    Redirecting…

    + Click here if you are not redirected. + + \ No newline at end of file diff --git a/pages/general/adopting.md b/pages/general/adopting.md deleted file mode 100644 index 3320d8e190..0000000000 --- a/pages/general/adopting.md +++ /dev/null @@ -1,109 +0,0 @@ -# Adopting AIPs in your company - -**Note:** We're working on some tooling to make this better. Keep an eye on -[this GitHub issue][] for progress. - -While AIPs originated at Google and were aimed for Googlers writing Google -APIs, much of the guidance documented is useful outside of Google. This -document describes how you might adopt AIPs as the way you document your own -APIs even if you don't work at Google. - -## The problem - -Sometimes private organizations might have API guidance that they don't want or -care to share with the rest of the world. For example, maybe in your company -(let's say, Acme, Inc), you identify your resources with a special field called -`string acme_id`. - -This rule could be written as an AIP, but there's no reason to share this rule -with everyone -- it's only for you and your development team. However, you -don't want this to conflict with a future AIP (e.g., if you make this AIP-1234, -maybe that AIP will get written in the future and then you'll have a conflict). -So what do you do? - -## The 9000 block - -Much like the Unicode specification, we've reserved the 9000 block of AIP -numbers (that is, AIP-9000 through AIP-9999) to be for "internal use". This -means that these AIPs will never have public documentation and are free for -private companies to use for their own API guidance. As a result, all you have -to do is write your AIPs as usual and give them a number in the 9000 block. - -## Custom AIP domains - -We're working on a separate fork-able repository that you can copy and use as -your 9000 block AIP repository. The page rendered by GitHub Pages will serve -only the AIPs in that block and redirect all other pages to [aip.dev][]. - -In short, this means that you can create your own AIP domain (e.g., -`aip.example.com`) and point that to the forked GitHub repository which will -redirect for all well-known AIPs and serve all internal AIPs from your own -repository. Once you've done that, you can cite all AIPs specifically using -that domain name (e.g., `aip.example.com/1234`) and you'll always get sent to -the right place. - -## Forking AIP - -You can fork the AIP project and run it in your own domain if necessary. This -will allow you to customize the AIPs to your organization's needs. Or you could -use the infrastructure to create your own set of AIPs. - -### Updating the URL - -To run the AIP infrastructure as a GitHub Page in a another repository, the -`_config.yaml` file must be updated to work correctly in the new repo. - -If a new custom domain and CNAME have been created for your AIP, only the `url` -property will need to be updated to the new domain. - -``` -url: https://aip.dev -``` - -If you are not creating a new domain, it will be necessary to add the `baseurl` -property to the `_config.yaml`. This property should contain any additional -path information that may be appended to the domain in the `url`. - -For example, assume GitHub user jdoe123 forked the aip project into a -repository named my-aips. If this user served the content from their master -branch, the url to the GitHub pages would be -`https://jdoe123.github.io/my-aips/`. The accompanying `_config.yaml` would be -configured as follows: - -``` -url: https://jdoe123.github.io -baseurl: /my-aips -``` - -For more information about about how these values are used by GitHub Pages, see -the [release notes][] that standardized these configurations in Jekyll. - -### Configuring Navigation - -The navigation headers and bar are generated dynamically based on the -`_data/header.yaml` and `_data/nav.yaml` files respectively. - -The schema for the navigation bar can be viewed under -`assets/schemas/nav-schema.yaml`. It supports two types of navigation -components; `static_group` and `matter_group`. A `static_group` menu component -will always show the same navigation elements, regardless of the content of the -page and the repository. A `matter_group` component is generated dynamically -based on the AIPs in the domain, or the current page in the site. The -configurations for a `matter_group` can be viewed in the -`assets/schemas/nav-components.yaml#defintions/matter_group` schema. - -The header is just a specially rendered `static_group` component. The schema -can be viewed at `assets/schemas/static_group.yaml`. - -### Testing Configuration - -The `tests` folder contains an npm test module that will validate your data -files. Running these tests requires npm and mocha. Once these are installed -that tests can be ran with the `npm test` command. - - -[this github issue]: https://github.com/googleapis/aip/issues/98 -[npm]: https://www.npmjs.com/get-npm -[mocha]: https://www.npmjs.com/package/mocha -[release notes]: https://jekyllrb.com/news/2016/10/06/jekyll-3-3-is-here/#2-relative_url-and-absolute_url-filters - diff --git a/pages/general/faq.md b/pages/general/faq.md deleted file mode 100644 index 8b722d517b..0000000000 --- a/pages/general/faq.md +++ /dev/null @@ -1,59 +0,0 @@ -# Frequently asked questions - -**Note:** Have a question not answered here? [Ask us on GitHub!][bug] - -### Why Protocol Buffers? - -At Google, we define all of our APIs using Protocol Buffers (`.proto` files). -While we realize there are lots of other, newer ways of defining these -interfaces (e.g., OpenAPI, RAML, etc), we had to standardize on something and -since we're Google, we use protos. - -This also leads to some very Google-specific ways of mapping proto RPCs to -RESTful URIs (`google.api.http` annotations). If you're not using protos, feel -free to follow the _spirit_ of the API guidance since you won't be able to -follow the example snippets exactly as provided. - -### What's all this Googley stuff? - -Originally, our API guidance was written by and for Googlers only. We're in the -process of making this guidance more general to the world, but that's far from -complete. If you see things like "Submit a CL" or "Talk to your PA lead", feel -free to send pull requests to fix these oversights. - -(CL stands for "Change List" which is sort of like a GitHub Pull Request, and -PA stands for "Product Area" meaning things like "Google Maps" or -"Google Workspace".) - -### I like most of these AIPs, but some make no sense for me. What do I do? - -Sometimes guidance from AIPs makes lots of sense for Google (perhaps due to its -size or scale) but no sense at all for others. This is much more common than we -originally thought, so we added a way for sub-teams to override guidance that -doesn't make sense for those teams. - -If you want to adopt most of the AIPs but have a few that make no sense for -your team, you can override those few and stick to just the ones that make -sense for you. - -### Why aren't all of Google's products listed here? - -When this project was first published, the AIP program was still relatively new. -Even with time, not all of Google has adopted AIPs as the way of documenting -their API guidance and policies. We're working on broadening the scope to more -and more areas, both inside and outside Google, so this will continue to evolve. - -If you work at Google and want your team to adopt AIPs for documenting how your -team does APIs, feel free to reach out to get in touch with us! - -### I have a question that isn't answered here. What do I do? - -We're still pretty new and haven't built up a long list of frequently asked -questions, so if you have a question not answered here, you can always [ask us -on GitHub][bug] by filing an issue. - -And if you already know the answer to a question that would be helpful for -others, [send us a pull request adding it to this page][pull request]! - -[bug]: https://github.com/aip-dev/google.aip.dev/issues/new?labels=question -[pull request]: https://github.com/aip-dev/google.aip.dev/edit/master/pages/general/faq.md diff --git a/pages/general/licensing.md b/pages/general/licensing.md deleted file mode 100644 index ed6bb11b80..0000000000 --- a/pages/general/licensing.md +++ /dev/null @@ -1,84 +0,0 @@ -# Content licensing - -We are pleased to license much of the AIP content under terms that explicitly -encourage people to take, modify, reuse, re-purpose, and remix our work as they -see fit. - -You will find the following notice at the bottom of many pages: - -> Except as otherwise noted, the content of this page is licensed under the -> [Creative Commons Attribution 4.0 License][ccal-4.0], and code samples are -> licensed under the [Apache 2.0 License][apache-2.0]. For details, see -> [content licensing][licensing]. - -When you see a page with this notice you are free to use -[nearly everything](#restrictions) on the page in your own creations. For -example, you could quote the text in a book, cut-and-paste sections to your -blog, record it as an audiobook for the visually impaired, or even translate it -into Swahili. Really. That's what open content licenses are all about. We just -ask that you give us [attribution](#attribution) when you reuse our work. - -In addition, you are free to use the computer source code that appears in the -content (such as in examples) in the code of your own projects. - -## Restrictions - -We say "nearly everything" as there are a few simple conditions that apply. - -Google's trademarks and other brand features are not included in this license. -Please see our [standard guidelines for third party use of Google brand -features][branding] for information about this usage. - -In some cases, a page may include content consisting of images, audio or video -material, or a link to content on a different webpage (such as videos or slide -decks). This content is not covered by the license, unless specifically noted. - -## Attribution - -Proper attribution is required when you reuse or create modified versions of -content that appears on a page made available under the terms of the Creative -Commons Attribution license. The complete requirements for attribution can be -found in section 3 of the [Creative Commons legal code][legal-code]. - -In practice we ask that you provide attribution to Google to the best of the -ability of the medium in which you are producing the work. - -There are several typical ways in which this might apply: - -### Exact reproductions - -If your online work _exactly reproduces_ text or images from this site, in -whole or in part, please include a paragraph at the bottom of your page that -reads: - -> Portions of this page are reproduced from work created and [shared by -> Google][licensing] and used according to terms described in the [Creative -> Commons 4.0 Attribution License][ccal-4.0]. - -Also, please link back to the original source page so that readers can refer to -it for more information. - -### Modified versions - -If your online work shows modified text or images based on the content from -this site, please include a paragraph at the bottom of your page that reads: - -> Portions of this page are modifications based on work created and [shared by -> Google][licensing] and used according to terms described in the [Creative -> Commons 4.0 Attribution License][ccal-4.0]. - -Again, please link back to the original source page so that readers can refer -to it for more information. This is even more important when the content has -been modified. - -### Other media - -If you produce non-hypertext works, such as books, audio, or video, we ask that -you make a best effort to include a spoken or written attribution in the spirit -of the messages above. - -[apache-2.0]: https://www.apache.org/licenses/LICENSE-2.0 -[ccal-4.0]: https://creativecommons.org/licenses/by/4.0/ -[branding]: http://www.google.com/permissions/guidelines.html -[legal-code]: https://creativecommons.org/licenses/by/4.0/legalcode -[licensing]: ./licensing.md diff --git a/pages/general/licensing.yaml b/pages/general/licensing.yaml deleted file mode 100644 index 188fd7857b..0000000000 --- a/pages/general/licensing.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -footer: | - This page was adapted from the [site policies][] for developers.google.com. - Last updated: May 13, 2019 - - [site policies]: https://developers.google.com/terms/site-policies diff --git a/pages/general/news.md.j2 b/pages/general/news.md.j2 deleted file mode 100644 index 0d500195bf..0000000000 --- a/pages/general/news.md.j2 +++ /dev/null @@ -1,35 +0,0 @@ -# News - -Want to keep up with the AIP system, and what we are working on? Welcome to the -**AIP newsletter**, a monthly publication covering new AIP guidance, and any -other developments useful to API producers. - -{% for n in site.collections.news.pages.values() | sort(reverse=True, attribute='code') -%} -### {{ n.config.news.month }} {{ n.config.news.year }} - -##### [**{{ n.title }}**]({{ n.relative_uri }}) - -{{ n.config.news.description | default('AIP newsletter') }} - -{% if n.config.news.aips.reviewing is defined or n.config.news.other is defined %} - -
    -

    Highlights:

    -
      - {% if n.config.news.aips.reviewing is defined %} -
    • Reviewing: -
        - {% for aip in n.config.news.aips.reviewing %} -
      • AIP-{{ aip }}
      • - {% endfor %} -
      -
    • - {% endif %} - {% for other in n.config.news.other | default([]) %} -
    • {{ other }}
    • - {% endfor %} -
    -
    - -{% endif %} -{% endfor -%} diff --git a/pages/news/2020-03.md b/pages/news/2020-03.md deleted file mode 100644 index 3e4528c912..0000000000 --- a/pages/news/2020-03.md +++ /dev/null @@ -1,176 +0,0 @@ -# Welcome to the AIP Newsletter - -Welcome to the first (hopefully monthly) edition of the **AIP newsletter**, -which is designed to keep you up to date about the AIP program, and particular -proposals making their way through the system. - -In this edition, we will discuss five pending proposals. This is intended as a -"public comment" period: the AIP editors are happy with these proposals, but we -want to ensure that you are too. Assuming feedback is sufficiently positive, we -intend to formally approve these proposals on Friday, March 27, 2020. - -## API linter - -As many readers know, we have published an [API linter][], which is able to -check much of the guidance provided in API Improvement Proposals for APIs -defined in protocol buffers. - -The linter now has over 150 rules, and is running on many new and existing APIs -at Google, hopefully pushing us toward greater consistency. - -[api linter]: https://github.com/api-linter - -## AIPs under review - -### AIP-153: Import and export - -> Many users want to be able to load data into an API, or get their existing -> data out of an API. This is particularly important for enterprise users, who -> are often concerned about vendor lock. - -[Import and export][aip-153] are particularly important concepts for enterprise -APIs, although they are increasing in importance for consumer and SaaS APIs as -well. - -We have actually had a reasonably consistent import and export story in Google -Cloud for a long time, but it has largely been passed along by tribal knowledge -("go look at X and copy what they did"). Therefore, this AIP attempts to codify -what we believe is a long-standing practice. - -**Summary:** [AIP-153][] mandates that both import and export methods return -[long-running operations][aip-151]. Unlike most API methods, they do support -partial failures, which are handled through the LRO metadata. Finally, they -have a specified place for per-source and per-destination configuration, -distinct from configuration for the data itself. - -We are aiming to approve AIP-153 on March 27. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/422). - -[aip-151]: ../151 -[aip-153]: ../153 - -### AIP-162: Resource revisions - -> Some APIs need to have resources with a revision history, where users can -> reason about the state of the resource over time. - -[Resource revisions][aip-162] is a concept we are seeing crop up more and more, -and we are seeing an increasing number of situations where audit logging is a -necessary but insufficient solution. Several APIs have struggled with how to -model a resource's history over time, and handle common use cases like commit -and rollback, which is what prompted this AIP. - -This is new guidance, put together by the AIP team as well as several API teams -who needed this functionality near the end of 2019. It has been positively -received by the teams that needed it, and so we would like to codify it. - -**Summary:** [AIP-162][] mandates the use of revision IDs that are appended to -a resource name with the `@` character for signifying revisions, and sets out -method structures for most common operations (listing revisions, rollback, -etc.). It also proposes a tagging mechanism for user-friendly revision names. - -We are aiming to approve AIP-162 on March 27. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/436). - -[aip-162]: ../162 - -### AIP-163: Change validation - -> Occasionally, a user wants to validate an intended change to see what the -> result will be before actually making the change. For example, a request to -> provision new servers in a fleet will have an impact on the overall fleet -> size and cost, and could potentially have unexpected downstream effects. - -[Change validation][aip-163] is the concept of performing a "dry run" on an API -request, and returning back the result without making any changes. - -This is effectively a migration of long-standing guidance that was not very -fleshed out. The previous API design guide mentioned `validate_only` as an -entry in the standard fields table with minimal explanation. This proposal -fleshes that out with an example, and addresses some questions we have received -over time. - -**Summary:** [AIP-163][] offers guidance for "dry run" requests using a -`bool validate_only` field in the request message, and addresses some common -situations around permissions and incomplete output. - -We are aiming to approve AIP-163 on March 27. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/437). - -[aip-163]: ../163 - -### AIP-165: Criteria-based delete - -> Occasionally, an API may need to provide a mechanism to delete a large number -> of resources based on some set of filter parameters, rather than requiring -> the individual resource name of the resources to be deleted. - -[Criteria-based delete][aip-165] is designed to address problems where a user -needs to delete so many items that [batch delete][aip-235] simply becomes -infeasible. - -This proposal represents a concession of sorts: we have long tried to avoid -delete-by-filter because of concerns that users would accidentally delete -important records and be unable to recover them. However, several APIs have had -legitimate reasons to need to do this, because the number of records the user -would want to delete was so high. - -**Summary:** [AIP-165][] offers guidance for criteria-based delete, with a -common name (`Purge`) and structure, and mandates a dry-run by default with a -`force` flag to actually perform the purge. - -We are aiming to approve AIP-165 on March 27. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/438). - -[aip-165]: ../165 -[aip-235]: ../235 - -### AIP-194: Retries for gRPC clients - -> RPCs sometimes fail. When one does, the client performing the RPC needs to -> know whether it is safe to retry the operation. When status codes are used -> consistently across multiple APIs, clients can respond to failures -> appropriately. - -[Retries for gRPC clients][aip-194] handles how to deal with errors, and in -particular when a client can transparently retry those errors. - -This proposal came about because of a need for first-party client libraries to -be able to transparently retry some server errors. gRPC offers a configuration -strategy for this, which is defined by API producers. - -**Summary:** [AIP-194][] offers guidance for configuring what error codes from -an API are safe to retry. It recommends usually retrying `UNAVAILABLE` and -nothing else. - -We are aiming to approve AIP-194 on March 27. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/439). - -[aip-194]: ../194 - -## Recent updates - -In addition to the new AIPs under review, we have added the following guidance -to existing AIPs: - -- [AIP-8](../8): AIPs have reverse-chronological changelogs - ([#425](https://github.com/aip-dev/google.aip.dev/pull/425)) -- [AIP-135](../135): Delete methods send 403 errors if the user lacks access - ([#409](https://github.com/aip-dev/google.aip.dev/pull/409)) -- [AIP-140](../140): `display_name` and `title` standard fields - ([#405](https://github.com/aip-dev/google.aip.dev/pull/405)) -- [AIP-158](../158): Field order for pagination response messages - ([#419](https://github.com/aip-dev/google.aip.dev/pull/419)) -- [AIP-193](../193): Added reference to new `ErrorInfo` message - ([#396](https://github.com/aip-dev/google.aip.dev/pull/396)) - -## What is coming? - -We have more coming over the course of the next few months, including -long-awaited public guidance for filtering and versioning. - -You also may notice some pull requests around making AIPs more generic. We are -exploring the possibility of bringing AIPs to even more API producers across -multiple companies, so that others can publish their standards under a common -information architecture. This effort is still nascent, but we are excited and -hopeful. Stay tuned! diff --git a/pages/news/2020-03.yaml b/pages/news/2020-03.yaml deleted file mode 100644 index bcfd90a92f..0000000000 --- a/pages/news/2020-03.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -news: - year: 2020 - month: March - description: | - The first edition of the AIP newsletter outlines the plan for reviewing - outstanding proposals, and announces the release of the API linter. - aips: - reviewing: [153, 162, 163, 165, 194] - other: - - The API linter is here! diff --git a/pages/news/2020-04.md b/pages/news/2020-04.md deleted file mode 100644 index 36747cc8dc..0000000000 --- a/pages/news/2020-04.md +++ /dev/null @@ -1,100 +0,0 @@ -# Data Series - -Welcome to the second edition of the **AIP newsletter**, which is designed to -keep you up to date about the AIP program, and particular proposals making -their way through the system. - -This month's new AIPs (unintentionally) share a common theme: handling lists -and series of data, whether in fields, resource relationships, or actual list -methods. These new AIPs are long overdue: they codify knowledge that has long -been reasonably consistent, but tribal. - -The AIP newsletter kicks off what is effectively a "public comment" period: the -AIP editors are happy with these proposals, but we want to ensure that you are -too. Assuming feedback is sufficiently positive, we intend to formally approve -these proposals on Friday, April 24, 2020. - -## AIPs under review - -### AIP-124: Resource associations - -> APIs sometimes have resource hierarchies that can not be cleanly expressed in -> the usual tree structure. - -[Resource association][aip-124] comes into play when a resource needs something -other than a direct parent-child relationship. This might mean a many-to-many -relationship, or it might be a one-to-many association that is distinct from -the parent-child relationship. - -We have had several APIs struggle with unusual associations over the past year -or so. In general, this has been handled reasonably consistently, but we never -codified the guidance into an official AIP. - -**Summary:** [AIP-124][] provides patterns for the two most common -associations: a resource with multiple different one-to-many relationships, and -a resource with a many-to-many association with another resource. - -We are aiming to approve AIP-124 on April 24. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/475). - -[aip-124]: ../124 - -### AIP-144: Repeated fields - -> Representing lists of data in an API is trickier than it often appears. Users -> often need to modify lists in place, and longer data series within a single -> resource pose a challenge for pagination. - -[Repeated fields][aip-144] are somewhat common in APIs, and a common question -that we get is how to handle adding or removing a single item from them -atomically. Additionally, repeated fields can become a trap if they are -unbounded in size and become too large. - -This is codification of guidance that we have been giving on a case-by-case -basis for some time. In particular, this documents the various restrictions on -the two update strategies. - -**Summary:** [AIP-144][] lays out guidance for repeated fields, and details two -distinct strategies for updating repeated fields. - -We are aiming to approve AIP-144 on April 24. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/476). - -[aip-144]: ../144 - -### AIP-160: Filtering - -> Often, when listing resources, it is desirable to filter over the collection -> and only return results that the user is interested in. - -[Filtering][aip-160] involves taking a list of resources (usually) and only -providing the results that the user wants, specified using a familiar syntax -similar to that of Google search. - -This is likely the most-requested AIP of all time. We have had internal -filtering documents for ages, but we have not had a public version, and one has -been sorely needed for years. Also, this work would likely still be unfinished -if not for the efforts of [Tristan Swadell][]; we are grateful for his efforts. - -**Summary:** [AIP-160][] offers a detailed breakdown of the filtering syntax -and how to provide filtering results in list and search methods. - -We are aiming to approve AIP-160 on April 24. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/473). - -[aip-160]: ../160 -[tristan swadell]: https://github.com/tristonianjones - -## Recent updates - -In addition to the new AIPs under review, we have added the following guidance -to existing AIPs: - -- [AIP-133](../133): Clarify which fields can be required - ([#460](https://github.com/aip-dev/google.aip.dev/pull/460)) -- [AIP-140](../140): Add guidance about message and field name conflicts - ([#470](https://github.com/aip-dev/google.aip.dev/pull/470)) -- [AIP-151](../151): Clarify that both `response_type` and `metadata_type` are - expected ([#469](https://github.com/aip-dev/google.aip.dev/pull/469)) -- [AIP-231](../231): Clarify Batch Get behavior if no resource names are sent - ([#474](https://github.com/aip-dev/google.aip.dev/pull/474)) diff --git a/pages/news/2020-04.yaml b/pages/news/2020-04.yaml deleted file mode 100644 index 28b83c252a..0000000000 --- a/pages/news/2020-04.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -news: - year: 2020 - month: April - description: | - This month's AIPs revolve around handling lists and series of data, which - present specific challenges in APIs. - aips: - reviewing: [124, 144, 160] diff --git a/pages/news/2020-05.md b/pages/news/2020-05.md deleted file mode 100644 index 94355505f4..0000000000 --- a/pages/news/2020-05.md +++ /dev/null @@ -1,75 +0,0 @@ -# Jobs and filters - -Welcome to the third edition of the **AIP newsletter**, which is designed to -keep you up to date about the AIP program, and particular proposals making -their way through the system. - -This month, we have one new AIP, which is around _jobs_: resources created for -managing a task that may be repeated. We also have one AIP from April that we -have delayed finalizing. - -As always, the AIP newsletter kicks off what is effectively a "public comment" -period: the AIP editors are happy with these proposals, but we want to ensure -that you are too. Assuming feedback is sufficiently positive, we intend to -formally approve these proposals on Friday, May 29, 2020. - -## AIPs under review - -### AIP-152: Jobs - -> Occasionally, APIs may need to expose a task that takes significant time to -> complete, and where a transient long-running operation is not appropriate. -> For example, a task could need to run repeatedly, or have separate -> permissions for configuring the task as opposed to running it. - -[Jobs][aip-152] are resources that are created that represent a (usually) -repeated task in an API. The idea is that the job is configured once, and -exists as an independent resource, which can either be executed by a user, or -by the system on a schedule. - -Jobs are useful when more structure or more permanence is needed than a simple -RPC with a long-running operation can provide. They can also be useful if a -service requires a permission model that distinguishes between who can -_configure_ a job as opposed to who can _run_ it. - -**Summary:** [AIP-152][] provides patterns for jobs: first-class resources that -represent tasks that are run repeatedly, whether by a user or by the system on -a schedule. - -We are aiming to approve AIP-152 on May 29. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/504). - -[aip-152]: ../152 - -### AIP-160: Filtering - -> Often, when listing resources, it is desirable to filter over the collection -> and only return results that the user is interested in. - -[Filtering][aip-160] involves taking a list of resources (usually) and only -providing the results that the user wants, specified using a familiar syntax -similar to that of Google search. - -This AIP is a holdover from last month's newsletter: we intended to approve it -in April, but several teams brought forth issues and clarifications that -necessitated further iteration. (Thanks!!) These are now represented in the -approval pull request ([#473][]), and we hope to approve this AIP in May. - -**Summary:** [AIP-160][] offers a detailed breakdown of the filtering syntax -and how to provide filtering results in list and search methods. - -We are aiming to approve AIP-160 on May 29. If you have feedback, please [leave -a comment][#473]. - -[#473]: https://github.com/aip-dev/google.aip.dev/pull/473 -[aip-160]: ../160 - -## Recent updates - -In addition to the new AIPs under review, we have added the following guidance -to existing AIPs: - -- [AIP-122](../122): Tighten restrictions on resource names - ([#496](https://github.com/aip-dev/google.aip.dev/pull/496)) -- [AIP-192](../192): Mandate use of absolute links in comments - ([#480](https://github.com/aip-dev/google.aip.dev/pull/480)) diff --git a/pages/news/2020-05.yaml b/pages/news/2020-05.yaml deleted file mode 100644 index ab96e84a63..0000000000 --- a/pages/news/2020-05.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -news: - year: 2020 - month: May - description: | - Formalizing the Job pattern; clarifications coming to filtering. - aips: - reviewing: [152, 160] diff --git a/pages/news/2020-06.md b/pages/news/2020-06.md deleted file mode 100644 index 090ab9a9f2..0000000000 --- a/pages/news/2020-06.md +++ /dev/null @@ -1,75 +0,0 @@ -# Field patterns - -Welcome to the fourth edition of the **AIP newsletter**, which is designed to -keep you up to date about the AIP program, and particular proposals making -their way through the system. - -This month, we have two new AIPs, both around patterns for specific kinds of -fields. - -As always, the AIP newsletter kicks off what is effectively a "public comment" -period: the AIP editors are happy with these proposals, but we want to ensure -that you are too. Assuming feedback is sufficiently positive, we intend to -formally approve these proposals on Friday, June 26, 2020. - -## AIPs under review - -### AIP-145: Ranges - -> Services often need to represent ranges of discrete or continuous values. -> These have wide differences in meaning, and come in many types: integers, -> floats, and timestamps, just to name a few, and the expected meaning of a -> range can vary in subtle ways depending on the type of range being discussed. - -[Ranges][aip-145] are fields that represent a range of discrete or continuous -values. These are often integers or floats, but can be other values where -ranges make sense, such as dates. - -The primary challenge for ranges is whether their values (particularly their -end values) should be inclusive or exclusive. Most developers are used to -exclusive end values, but with some notable and precise exceptions (example: -dates are an exception, but not timestamps), and the AIP attempts to encode -this using the idea of "colloquial precedent". - -**Summary:** [AIP-145][] provides patterns for ranges of values: two fields -that represent a start and end value. - -We are aiming to approve AIP-145 on June 26. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/523). - -[aip-145]: ../145 - -### AIP-146: Generic fields - -> Occasionally it is appropriate to have a generic or polymorphic field of some -> kind that can conform to multiple schemata, or even be entirely free-form. - -[Generic fields][aip-146] discusses the various ways to approach a polymorphic -or entirely generic field in the API. These provide implementation flexibility, -but the tradeoff is a less clear API contract. There are several ways to -provide a generic field, and the AIP enumerates them and discussed the -tradeoffs. - -**Summary:** [AIP-146][] offers four patterns for generic fields, and describes -the tradeoffs of each. - -We are aiming to approve AIP-146 on June 26. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/524). - -[aip-146]: ../146 - -## Recent updates - -In addition to the new AIPs under review, we have added the following guidance -to existing AIPs: - -- [AIP-122](../122): Corrected a mistaken piece of guidance about - capitalization ([#513](https://github.com/aip-dev/google.aip.dev/pull/513)) -- [AIP-132](../132): Removed mandate to document default ordering - ([#512](https://github.com/aip-dev/google.aip.dev/pull/512)) -- [AIP-140](../140): Add guidance for URI fields - ([#519](https://github.com/aip-dev/google.aip.dev/pull/519)) -- [AIP-143](../143): Change guidance for countries to `region_code` - ([#507](https://github.com/aip-dev/google.aip.dev/pull/507)) -- [AIP-203](../203): Clarified behavior for updating immutable fields - ([#516](https://github.com/aip-dev/google.aip.dev/pull/516)) diff --git a/pages/news/2020-06.yaml b/pages/news/2020-06.yaml deleted file mode 100644 index 977f472fa6..0000000000 --- a/pages/news/2020-06.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -news: - year: 2020 - month: June - description: Patterns around ranges and generic fields. - aips: - reviewing: [145, 146] diff --git a/pages/news/2020-08.md b/pages/news/2020-08.md deleted file mode 100644 index a4cf24aa93..0000000000 --- a/pages/news/2020-08.md +++ /dev/null @@ -1,55 +0,0 @@ -# Field patterns, redux - -Welcome to the fifth edition of the **AIP newsletter**, which is designed to -keep you up to date about the AIP program, and particular proposals making -their way through the system. (Our apologies for not publishing a newsletter in -July.) - -We have one new AIP this month, on sensitive fields. As always, the AIP -newsletter kicks off what is effectively a "public comment" period: the AIP -editors are happy with this proposal, but we want to ensure that you are too. -Assuming feedback is sufficiently positive, we intend to formally approve these -proposals on Friday, August 28, 2020. - -## AIPs under review - -### AIP-147: Sensitive fields - -> Sometimes APIs need to collect sensitive information such as private -> encryption keys meant to be _stored_ by the underlying service but not -> intended to be _read_ after writing due to the sensitive nature of the data. - -[Sensitive fields][aip-147] are fields that are stored by a service but, once -set, not retrievable by the user, such as passwords or private keys. These are -not particularly common in APIs, and often it is sufficient to set them as -`INPUT_ONLY` (as described in AIP-203). - -However, there is a challenge in situations where the service needs to provide -some kind of indication that a value has been provided, or provide an -obfuscated value that the original user ought to recognize. This AIP provides a -standard for each of those situations. - -A special thanks to [Michael Bleigh][] for writing this AIP. - -**Summary:** [AIP-147][] provides patterns for indicators around sensitive -fields. - -We are aiming to approve AIP-147 on August 28. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/583). - -[michael bleigh]: https://github.com/mbleigh -[aip-147]: ../147 - -## Recent updates - -In addition to the new AIPs under review, we have added the following guidance -to existing AIPs: - -- [AIP-135](../135): Add "get" guidance for soft delete. - ([#526](https://github.com/aip-dev/google.aip.dev/pull/526)) -- [AIP-140](../140): Word segments in field names must not begin with a number. - ([#528](https://github.com/aip-dev/google.aip.dev/pull/528)) -- [AIP-151](../151): Add guidance for parallel operations. - ([#535](https://github.com/aip-dev/google.aip.dev/pull/535)) -- [AIP-158](../158): Clarify that `page_size` is always an optional field. - ([#537](https://github.com/aip-dev/google.aip.dev/pull/537)) diff --git a/pages/news/2020-08.yaml b/pages/news/2020-08.yaml deleted file mode 100644 index c725995519..0000000000 --- a/pages/news/2020-08.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -news: - year: 2020 - month: August - description: Patterns around sensitive fields. - aips: - reviewing: [147] diff --git a/pages/news/2020-10.md b/pages/news/2020-10.md deleted file mode 100644 index d9397802d7..0000000000 --- a/pages/news/2020-10.md +++ /dev/null @@ -1,142 +0,0 @@ -# Declarative-friendly APIs - -Welcome to the sixth edition of the **AIP newsletter**, which is designed to -keep you up to date about the AIP program, and particular proposals making -their way through the system. - -We have an exciting slate of AIPs entering review this cycle, all around the -theme of "declarative-friendly APIs". The linchpin here is AIP-128, which -introduces and explains the topic. - -The idea behind declarative-friendly APIs addresses an important need: the -ability to integrate with popular, declarative tools, such as Kubernetes or -Terraform. These tools and others are used by numerous developers, and the -follow a straightforward paradigm: the user provides the tool with the desired -state, and the tool brings that state into fruition. - -Integration with these tools is critical for cloud providers, but with the -number of services _and_ the number of tools continuously increasing, support -is difficult without a reliance on automation. Automation, in turn, requires -strong consistency. - -While ordinarily AIPs stay in review for about a month, we intend for this -review cycle to be longer, to allow time for APIs to be released that follow -this guidance. Assuming the feedback is sufficiently positive, we will probably -be looking at formal approval around the end of the year. - -## AIPs under review - -### AIP-128: Declarative-friendly interfaces - -> Many services need to interact with common DevOps tools, particularly those -> that create and manage network-addressible resources (such as virtual -> machines, load balancers, database instances, and so on). These tools revolve -> around the principle of "configuration as code": the user specifies the -> complete intended landscape, and tooling is responsible for making whatever -> changes are necessary to achieve the user's specification. -> -> These tools are **declarative**: rather than specifying specific actions to -> take, they specify the desired _outcome_, with the actions being derived -> based on the differences between the current landscape and the intended one. - -[Declarative-friendly interfaces][aip-128] describes patterns for making -interfaces that are friendly to automated tooling. The basic idea is that by -being more strict and consistent, it becomes possible to write tools that -"translate" the interface to a declarative form without having to know anything -about the specific API. - -This reduces feature latency for users. Essentially, the adapter or plugin can -be automatically generated, and so an automated pipeline becomes possible: as -soon as the service launches new features, they become available in the -adapters also. - -Because declarative-friendliness is a wide-ranging concept, impacting the -guidance in numerous other AIPs as well, it was difficult to determine how to -structure the information. Therefore, this AIP also has a robust "further -reading" section that points to declarative-friendly guidance in other AIPs. - -**Summary:** [AIP-128][] provides an explanation of what it means for a service -to be declarative-friendly, and why a service might want to adopt these -patterns. It also indexes declarative-friendly guidance found in other AIPs. - -[aip-128]: /128 - -### AIP-148: Standard fields - -> Certain concepts are common throughout any corpus of APIs. In these -> situations, it is useful to have a standard field name that is used -> consistently to communicate that concept. - -[Standard fields][aip-148] is, in some ways, an overdue AIP. It describes -fields common throughout our corpus, such as `name`, `parent`, and -`create_time`, that were on the list of standard fields in the original API -style guide and did not get a full treatment in other AIPs. Common fields that -are covered in other AIPs are not discussed in this one. (As an example, -`language_code` is given extensive treatment in [AIP-143][], so not repeated -here.) - -This takes on new importance with our focus on declarative-friendly APIs -because tools written to marshal between a declarative tool and the service can -see those tools and know what they mean. - -**Summary:** [AIP-148][] describes common fields that are already in common use -throughout our API corpus. It also describes certain fields that are expected -on declarative-friendly resources. - -[aip-143]: /143 -[aip-148]: /148 - -### AIP-164: Soft delete - -> There are several reasons why a client could desire soft delete and undelete -> functionality, but one over-arching reason stands out: recovery from -> mistakes. A service that supports undelete makes it possible for users to -> recover resources that were deleted by accident. - -[Soft delete][aip-164] is increasingly critical for APIs that need to cater to -enterprise users, due to the need to be able to recover from mistakes without -data loss. While [AIP-135][] previously discussed soft delete, it was clear -that a more thorough treatment is necessary. - -This AIP goes through the request patterns in more detail, and discusses topics -such as LROs and errata, that are relevant to soft delete and undelete. - -**Summary:** [AIP-164][] expands the guidance on soft delete and undelete and -provides a more detailed look at both. - -[aip-135]: /135 -[aip-164]: /164 - -## AIP sections under review - -Because of the need to add declarative-friendly guidance into existing AIPs, -certain sections needed to be introduced into existing, approved AIPs in a -reviewing state. These are all in use for declarative-friendly guidance and -would be approved alongside AIP-128: - -- AIP-134: [Create or update](/134#create-or-update) -- AIP-135: [Delete if existing](/135#delete-if-existing) -- AIP-136: [Custom method restrictions](/136#declarative-friendly-resources) - -Additionally, new sections in [AIP-154](/154#declarative-friendly-resources) -and [AIP-163](/163#declarative-friendly-resources) mandate the use of these -concepts for declarative-friendly resources. - -## Recent updates - -In addition to the new AIPs under review, we have added the following guidance -to existing AIPs: - -- [AIP-122](/122): Clarified when to use full resource names - ([#629](https://github.com/aip-dev/google.aip.dev/pull/629)) -- [AIP-132](/132): Loosened guidance around top-level resources - ([#602](https://github.com/aip-dev/google.aip.dev/pull/602)) -- [AIP-132](/132): Added `PERMISSION_DENIED` guidance - ([#582](https://github.com/aip-dev/google.aip.dev/pull/582)) -- [AIP-151](/151): Clarified that `stream` and LROs are mutually incompatible - ([#597](https://github.com/aip-dev/google.aip.dev/pull/597)) -- [AIP-216](/216): Clarified that states are not directly set on Create - ([#606](https://github.com/aip-dev/google.aip.dev/pull/606)) - -Special thanks to Andrew Paseltiner and Peter Novotney for some of these -changes, and to several others who send minor corrections not noted here. diff --git a/pages/news/2020-10.yaml b/pages/news/2020-10.yaml deleted file mode 100644 index fe670e84cb..0000000000 --- a/pages/news/2020-10.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -news: - year: 2020 - month: October - description: | - Why and how to make an API interface "declarative friendly", in order to - enable automation on top of it. - aips: - reviewing: [128, 148, 164] - other: - - Declarative-friendly updates to existing AIPs. diff --git a/pages/news/2021-03.md b/pages/news/2021-03.md deleted file mode 100644 index 79c88bf856..0000000000 --- a/pages/news/2021-03.md +++ /dev/null @@ -1,107 +0,0 @@ -# Auth and Field Masks - -Welcome to the seventh edition of the **AIP newsletter**, which is designed to -keep you up to date about the AIP program, and particular proposals making -their way through the system. - -We have three new AIPs this month. As always, the AIP newsletter kicks off what -is effectively a "public comment" period: the AIP editors are happy with this -proposal, but we want to ensure that you are too. Assuming feedback is -sufficiently positive, we intend to formally approve these proposals on Friday, -March 26, 2021. - -## AIPs under review - -### AIP-149: Unset field values - -> In many messages, many fields are optional: the user is not required to -> provide them, or for output fields, the service might not populate the field. - -[Unset field values][aip-149] refer to primitive fields where the service makes -a meaningful distinction between an empty value (such as `0` or `false`) and -not setting the value at all. While this is generally discouraged if an -alternative design is feasible, there are certainly occasions where this is the -best approach. - -**Summary:** [AIP-149][] provides guidance around use of the `optional` keyword -for primitives. - -We are aiming to approve AIP-149 on March 26. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/711). - -[aip-149]: ../149 - -### AIP-161: Field masks - -> Often, when updating resources, it is desirable to specify exactly which -> fields are being updated, so that the service can ignore the rest, even if -> the user sends new values. - -[Field masks][aip-161] are the way that users are able to specify exactly which -fields to read or update. They are necessary to ensure that adding fields to -existing messages remains backwards-compatible. - -While we have had an internal specification for field masks for some time, this -AIP publicizes the specification. - -**Summary:** [AIP-161][] provides a public specification for field masks. - -We are aiming to approve AIP-161 on March 26. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/718). - -[aip-161]: ../161 - -### AIP-211: Authorization checks - -> The majority of operations, whether reads or writes, require authorization: -> permission to do the thing the user is asking to do. Additionally, it is -> important to be careful how much information is provided to _unauthorized_ -> users, since leaking information can be a security concern. - -[Authorization checks][aip-211] discusses when in the logical process of a -request the authorization check ought to occur, and what error to send when an -auth check fails. - -In particular, if an authorization check fails, regardless of whether the -resource exists, the service consistently returns `PERMISSION_DENIED` with an -error message that also indicates that the resource might not exist. - -**Summary:** [AIP-211][] provides guidance about authorization checks: when to -perform them, and what error to send. - -We are aiming to approve AIP-211 on March 26. If you have feedback, please -[leave a comment](https://github.com/aip-dev/google.aip.dev/pull/719). - -[aip-211]: ../211 - -## Additional approvals - -We also intend to approve the AIPs that were placed under review in the October -2020 newsletter. This includes [AIP-128][] ([#708][]), [AIP-148][] ([#710][]), -and [AIP-164][] ([#709][]). If you have feedback, please leave a comment in the -referenced pull requests. - -[aip-128]: ../128 -[aip-148]: ../148 -[aip-164]: ../164 -[#708]: https://github.com/aip-dev/google.aip.dev/pull/708 -[#709]: https://github.com/aip-dev/google.aip.dev/pull/709 -[#710]: https://github.com/aip-dev/google.aip.dev/pull/710 - -## Recent updates - -In addition to the new AIPs under review, we have added the following guidance -to existing AIPs: - -- [AIP-144](../144): Expand Add and Remove guidance. - ([#648](https://github.com/aip-dev/google.aip.dev/pull/648)) -- [AIP-154](../154): Etag failures should use `ABORTED`. - ([#705](https://github.com/aip-dev/google.aip.dev/pull/705)) -- [AIP-162](../162): Forbid deleting the only remaining revision. - ([#692](https://github.com/aip-dev/google.aip.dev/pull/692)) -- [AIP-162](../162): Restrict revision tags to lower-case. - ([#707](https://github.com/aip-dev/google.aip.dev/pull/707)) -- [AIP-165](../165): Make implicit recommendations more explicit. - ([#662](https://github.com/aip-dev/google.aip.dev/pull/662)) -- [AIP-203](../203): Add `UNORDERED_LIST` to field behaviors. - ([#671](https://github.com/aip-dev/google.aip.dev/pull/671)) diff --git a/pages/news/2021-03.yaml b/pages/news/2021-03.yaml deleted file mode 100644 index ec173e7b61..0000000000 --- a/pages/news/2021-03.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -news: - year: 2021 - month: March - description: | - Publishing long-standing guidance around permissions and field masks. - aips: - reviewing: [149, 161, 211] - other: - - Approval of AIPs discussed in the October 2020 newsletter. diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 133b557193..0000000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -aip-site-generator==0.6.0 diff --git a/search.html b/search.html new file mode 100644 index 0000000000..ee5223dd55 --- /dev/null +++ b/search.html @@ -0,0 +1,679 @@ + + + + Search + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +
    + +
    + +
    +
    +
    +
    + + + +
    +
    + + + View on GitHub + +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    + +
    +
    + +
    + +

    Search results

    +
    +
    + + + +
    +
    + +
    + + + + + \ No newline at end of file diff --git a/serve.sh b/serve.sh deleted file mode 100755 index cb7e607bae..0000000000 --- a/serve.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# ----------------------------------------------------------------------------- -# This script runs a "development server" from Docker. -# ----------------------------------------------------------------------------- - -# Build the image (if and only if it is not already built). -if [[ "$(docker images -q aip-site 2> /dev/null)" == "" ]]; then - docker build -t aip-site . - if [ $? != 0 ]; then - exit $? - fi -fi - -# Run the image. -docker run --rm \ - -p 4000:4000/tcp -p 4000:4000/udp \ - -p 35729:35729/tcp -p 35729:35729/udp \ - --mount type=bind,source=`pwd`,destination=/code/,readonly \ - aip-site \ - "$@"