diff --git a/.github/workflows/build-lint-test.yml b/.github/workflows/build-lint-test.yml index f1c62db872..8abd190a07 100644 --- a/.github/workflows/build-lint-test.yml +++ b/.github/workflows/build-lint-test.yml @@ -175,6 +175,28 @@ jobs: exit 1 fi + build-test-snaps: + name: Build "@metamask/test-snaps" + runs-on: ubuntu-latest + needs: prepare + steps: + - uses: actions/checkout@v3 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' + cache: yarn + - run: yarn --immutable --immutable-cache + - name: Build + run: yarn workspace @metamask/test-snaps run build + - name: Require clean working directory + shell: bash + run: | + if ! git diff --exit-code; then + echo "Working tree dirty at end of job" + exit 1 + fi + policy: name: Generate LavaMoat policy runs-on: ubuntu-latest diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f3ebafed4e..bb24828902 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,6 +48,7 @@ jobs: uses: ./.github/workflows/publish-release.yml secrets: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + PUBLISH_PAGES_TOKEN: ${{ secrets.PUBLISH_PAGES_TOKEN }} all-jobs-complete: name: All jobs complete diff --git a/.github/workflows/publish-github-pages.yml b/.github/workflows/publish-github-pages.yml new file mode 100644 index 0000000000..85a187047b --- /dev/null +++ b/.github/workflows/publish-github-pages.yml @@ -0,0 +1,49 @@ +name: Publish to GitHub Pages + +on: + workflow_call: + inputs: + build_script: + required: true + type: string + destination_dir: + required: true + type: string + publish_dir: + required: true + type: string + secrets: + PUBLISH_PAGES_TOKEN: + required: true + +jobs: + publish-environment: + name: Publish to GitHub Pages + runs-on: ubuntu-latest + environment: github-pages + permissions: + contents: write + steps: + - name: Ensure `build_script` is not empty + if: ${{ inputs.destination_dir == '' }} + run: exit 1 + - name: Ensure `destination_dir` is not empty + if: ${{ inputs.destination_dir == '' }} + run: exit 1 + - name: Ensure `publish_dir` is not empty + if: ${{ inputs.publish_dir == '' }} + run: exit 1 + - uses: actions/checkout@v3 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' + - run: yarn --immutable + - name: Run build script + run: ${{ inputs.build_script }} + - name: Deploy to `${{ inputs.destination_dir }}` directory of `gh-pages` branch + uses: peaceiris/actions-gh-pages@de7ea6f8efb354206b205ef54722213d99067935 + with: + personal_token: ${{ secrets.PUBLISH_PAGES_TOKEN }} + publish_dir: ${{ inputs.publish_dir }} + destination_dir: ${{ inputs.destination_dir }} diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 66a3c8db5b..cedd7e56dd 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -5,6 +5,8 @@ on: secrets: NPM_TOKEN: required: true + PUBLISH_PAGES_TOKEN: + required: true jobs: publish-release: @@ -100,3 +102,19 @@ jobs: uses: ./.github/workflows/publish-environment.yml with: destination_dir: ${{ needs.get-release-version.outputs.RELEASE_VERSION }} + + publish-test-snaps: + needs: get-release-version + name: Publish test snaps + # The `rc/1.0.0` branch does not have `test-snaps` package, so we only run + # this job on the `main` branch. + if: ${{ github.ref_name == 'main' }} + permissions: + contents: write + uses: ./.github/workflows/publish-github-pages.yml + with: + build_script: yarn workspace @metamask/test-snaps build + destination_dir: test-snaps/${{ needs.get-release-version.outputs.RELEASE_VERSION }} + publish_dir: ./packages/test-snaps/public + secrets: + PUBLISH_PAGES_TOKEN: ${{ secrets.PUBLISH_PAGES_TOKEN }} diff --git a/package.json b/package.json index f8e8f864d8..6c0ba84745 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "build:source": "yarn workspaces foreach --parallel --verbose run build:source", "build:types": "tsc --build tsconfig.build.json", "build:post-tsc": "yarn workspaces foreach --parallel --topological --topological-dev --verbose run build:post-tsc", - "build:post-tsc:ci": "yarn workspaces foreach --parallel --topological --topological-dev --verbose --exclude root --exclude \"@metamask/snaps-simulator\" --exclude \"@metamask/snaps-execution-environments\" --exclude \"@metamask/snaps-jest\" --exclude \"@metamask/example-snaps\" run build:post-tsc", + "build:post-tsc:ci": "yarn workspaces foreach --parallel --topological --topological-dev --verbose --exclude root --exclude \"@metamask/snaps-simulator\" --exclude \"@metamask/snaps-execution-environments\" --exclude \"@metamask/snaps-jest\" --exclude \"@metamask/example-snaps\" --exclude \"@metamask/test-snaps\" run build:post-tsc", "clean": "yarn workspaces foreach --parallel --verbose run clean", "test": "yarn workspaces foreach --parallel --verbose run test", "test:browser": "yarn workspaces foreach --verbose run test:browser", diff --git a/packages/examples/package.json b/packages/examples/package.json index 0c23f77b56..3a0cd0ca38 100644 --- a/packages/examples/package.json +++ b/packages/examples/package.json @@ -17,6 +17,7 @@ "build:post-tsc": "yarn build", "clean": "yarn workspaces foreach --parallel --verbose --no-private run clean", "start": "yarn workspaces foreach --parallel --verbose --interlaced --no-private --jobs unlimited run start", + "start:test": "yarn start", "test": "yarn workspaces foreach --parallel --verbose --interlaced --no-private run test", "lint": "yarn workspaces foreach --parallel --verbose --interlaced --no-private run lint", "lint:eslint": "eslint . --cache --ext js,ts,jsx,tsx", diff --git a/packages/examples/packages/notifications/snap.manifest.json b/packages/examples/packages/notifications/snap.manifest.json index 7a3706f505..188e0dd528 100644 --- a/packages/examples/packages/notifications/snap.manifest.json +++ b/packages/examples/packages/notifications/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "/lLHUZ/SWHARUnhQ3KaAcyg7dEY2JLpr0SX+rWJBbHU=", + "shasum": "2Sf6Y9KD0+pmcCQSbxMPteQz8sabuZi8Z6zHJ+uVUSY=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/notifications/src/index.test.ts b/packages/examples/packages/notifications/src/index.test.ts index 3d1809d48d..f0b628f60a 100644 --- a/packages/examples/packages/notifications/src/index.test.ts +++ b/packages/examples/packages/notifications/src/index.test.ts @@ -35,7 +35,7 @@ describe('onRpcRequest', () => { expect(response).toRespondWith(null); expect(response).toSendNotification( - 'Hello, Jest, from within MetaMask!', + 'Hello from within MetaMask!', NotificationType.InApp, ); diff --git a/packages/examples/packages/notifications/src/index.ts b/packages/examples/packages/notifications/src/index.ts index 24f2f5dd62..e50236868a 100644 --- a/packages/examples/packages/notifications/src/index.ts +++ b/packages/examples/packages/notifications/src/index.ts @@ -28,7 +28,7 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ // We're using the `NotificationType` enum here, but you can also use // the string values directly, e.g. `type: 'inApp'`. type: NotificationType.InApp, - message: `Hello, ${origin}, from within MetaMask!`, + message: `Hello from within MetaMask!`, }, }); diff --git a/packages/examples/packages/rollup-plugin/package.json b/packages/examples/packages/rollup-plugin/package.json index ba8a21392a..5c190f9777 100644 --- a/packages/examples/packages/rollup-plugin/package.json +++ b/packages/examples/packages/rollup-plugin/package.json @@ -26,7 +26,7 @@ "lint:misc": "prettier --no-error-on-unmatched-pattern --loglevel warn \"**/*.json\" \"**/*.md\" \"**/*.html\" \"!CHANGELOG.md\" \"!snap.manifest.json\" --ignore-path ../../../../.gitignore", "test": "yarn test:e2e", "test:e2e": "jest", - "start": "rollup watch", + "start": "yarn build --watch", "prepare-manifest:preview": "../../../../scripts/prepare-preview-manifest.sh", "publish:preview": "yarn npm publish --tag preview" }, diff --git a/packages/examples/packages/wasm/package.json b/packages/examples/packages/wasm/package.json index 54f395bb81..0bd682aa69 100644 --- a/packages/examples/packages/wasm/package.json +++ b/packages/examples/packages/wasm/package.json @@ -25,7 +25,7 @@ "lint:eslint": "eslint . --cache --ext js,ts,jsx,tsx", "lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write", "lint:misc": "prettier --no-error-on-unmatched-pattern --loglevel warn \"**/*.json\" \"**/*.md\" \"**/*.html\" \"!CHANGELOG.md\" \"!snap.manifest.json\" --ignore-path ../../../../.gitignore", - "start": "webpack watch", + "start": "concurrently --names webpack,server \"webpack watch\" \"http-server --no-dotfiles --port 8019 .\"", "test": "yarn test:e2e", "test:e2e": "jest", "prepare-manifest:preview": "../../../../scripts/prepare-preview-manifest.sh", @@ -55,6 +55,7 @@ "@typescript-eslint/eslint-plugin": "^5.42.1", "@typescript-eslint/parser": "^5.42.1", "assemblyscript": "^0.27.5", + "concurrently": "^8.2.0", "deepmerge": "^4.2.2", "eslint": "^8.27.0", "eslint-config-prettier": "^8.5.0", @@ -63,6 +64,7 @@ "eslint-plugin-jsdoc": "^39.6.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^4.2.1", + "http-server": "^14.1.1", "jest": "^29.0.2", "prettier": "^2.7.1", "prettier-plugin-packagejson": "^2.2.11", @@ -71,7 +73,8 @@ "ts-node": "^10.9.1", "typescript": "~4.8.4", "webpack": "^5.86.0", - "webpack-cli": "^5.1.4" + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^4.13.3" }, "engines": { "node": ">=16.0.0" diff --git a/packages/test-snaps/.eslintrc.js b/packages/test-snaps/.eslintrc.js new file mode 100644 index 0000000000..a47fd0b65d --- /dev/null +++ b/packages/test-snaps/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + + parserOptions: { + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/test-snaps/.swcrc b/packages/test-snaps/.swcrc new file mode 100644 index 0000000000..85936b5b2d --- /dev/null +++ b/packages/test-snaps/.swcrc @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/swcrc", + "jsc": { + "parser": { + "syntax": "typescript", + "tsx": true + }, + "transform": { + "react": { + "runtime": "automatic" + } + } + } +} diff --git a/packages/test-snaps/CHANGELOG.md b/packages/test-snaps/CHANGELOG.md new file mode 100644 index 0000000000..aa399df1be --- /dev/null +++ b/packages/test-snaps/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +[Unreleased]: https://github.com/MetaMask/snaps/ diff --git a/packages/test-snaps/LICENSE b/packages/test-snaps/LICENSE new file mode 100644 index 0000000000..25d1e2c814 --- /dev/null +++ b/packages/test-snaps/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2023 MetaMask + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/packages/test-snaps/README.md b/packages/test-snaps/README.md new file mode 100644 index 0000000000..934b1b64aa --- /dev/null +++ b/packages/test-snaps/README.md @@ -0,0 +1,5 @@ +# `@metamask/test-snaps` + +The test snaps website for MetaMask Snaps, used for (automated) end-to-end +testing. The test snaps website is a simple static website, containing a way to +interact with [the example snaps](../examples), to test their functionality. diff --git a/packages/test-snaps/jest.config.js b/packages/test-snaps/jest.config.js new file mode 100644 index 0000000000..4fe88c9573 --- /dev/null +++ b/packages/test-snaps/jest.config.js @@ -0,0 +1,14 @@ +const deepmerge = require('deepmerge'); + +const baseConfig = require('../../jest.config.base'); + +module.exports = deepmerge(baseConfig, { + coverageThreshold: { + global: { + branches: 0, + functions: 0, + lines: 0, + statements: 0, + }, + }, +}); diff --git a/packages/test-snaps/package.json b/packages/test-snaps/package.json new file mode 100644 index 0000000000..099fbd94d1 --- /dev/null +++ b/packages/test-snaps/package.json @@ -0,0 +1,89 @@ +{ + "name": "@metamask/test-snaps", + "version": "0.35.2-flask.1", + "private": true, + "description": "The test snaps website for MetaMask Snaps, used for end-to-end testing.", + "repository": { + "type": "git", + "url": "https://github.com/MetaMask/snaps.git" + }, + "license": "ISC", + "sideEffects": false, + "files": [], + "scripts": { + "test": "jest --passWithNoTests && yarn posttest", + "posttest": "jest-it-up", + "test:ci": "yarn test", + "start": "yarn workspaces foreach --parallel --verbose --interlaced --all --include \"@metamask/test-snaps\" --include \"@metamask/example-snaps\" run start:test", + "start:test": "cross-env NODE_ENV=development webpack serve", + "build": "cross-env NODE_ENV=production webpack", + "build:clean": "yarn clean && yarn build", + "build:post-tsc": "yarn build", + "clean": "rimraf 'dist'", + "lint:eslint": "eslint . --cache --ext js,ts,jsx,tsx", + "lint:misc": "prettier --no-error-on-unmatched-pattern --loglevel warn \"**/*.json\" \"**/*.md\" \"**/*.html\" \"!CHANGELOG.md\" --ignore-path ../../.gitignore", + "lint": "yarn lint:eslint && yarn lint:misc --check && yarn lint:changelog", + "lint:ci": "yarn lint", + "lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write", + "lint:changelog": "yarn auto-changelog validate" + }, + "dependencies": { + "@metamask/snaps-utils": "workspace:^", + "@metamask/utils": "^6.0.1", + "@popperjs/core": "^2.11.8", + "@reduxjs/toolkit": "^1.9.5", + "bootstrap": "^5.2.2", + "gl-matrix": "^3.4.3", + "react": "^18.2.0", + "react-bootstrap": "^2.5.0", + "react-dom": "^18.2.0", + "react-redux": "^8.0.5", + "simplex-noise": "^4.0.0" + }, + "devDependencies": { + "@metamask/auto-changelog": "^3.1.0", + "@metamask/eslint-config": "^11.0.0", + "@metamask/eslint-config-jest": "^11.0.0", + "@metamask/eslint-config-nodejs": "^11.0.1", + "@metamask/eslint-config-typescript": "^11.0.0", + "@metamask/providers": "^11.0.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", + "@swc/core": "^1.3.66", + "@swc/jest": "^0.2.26", + "@types/jest": "^27.5.1", + "@types/node": "^20.3.1", + "@types/webpack-env": "^1.18.1", + "@typescript-eslint/eslint-plugin": "^5.42.1", + "@typescript-eslint/parser": "^5.42.1", + "copy-webpack-plugin": "^11.0.0", + "cross-env": "^7.0.3", + "css-loader": "^6.7.3", + "deepmerge": "^4.2.2", + "eslint": "^8.27.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jest": "^27.1.5", + "eslint-plugin-jsdoc": "^39.6.2", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^4.2.1", + "favicons": "^7.1.2", + "favicons-webpack-plugin": "^6.0.0", + "html-webpack-plugin": "^5.5.0", + "jest": "^29.0.2", + "jest-it-up": "^2.0.0", + "prettier": "^2.7.1", + "rimraf": "^4.1.2", + "style-loader": "^3.3.2", + "swc-loader": "^0.2.3", + "terser-webpack-plugin": "^5.3.9", + "ts-node": "^10.9.1", + "tsconfig-paths-webpack-plugin": "^4.0.1", + "typescript": "~4.8.4", + "webpack": "^5.86.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^4.13.3" + }, + "engines": { + "node": ">=16.0.0" + } +} diff --git a/packages/test-snaps/src/App.tsx b/packages/test-snaps/src/App.tsx new file mode 100644 index 0000000000..e0fba97ea7 --- /dev/null +++ b/packages/test-snaps/src/App.tsx @@ -0,0 +1,23 @@ +import { FunctionComponent } from 'react'; +import { Container, Row } from 'react-bootstrap'; + +import { Logo } from './components'; +import { InstalledSnaps, snaps } from './features'; + +export const App: FunctionComponent = () => { + return ( + + + + + {/* Installed Snaps list */} + + + {/* Snap test UI */} + {Object.values(snaps).map((Component, index) => ( + + ))} + + + ); +}; diff --git a/packages/test-snaps/src/api.ts b/packages/test-snaps/src/api.ts new file mode 100644 index 0000000000..aa32d5b4dd --- /dev/null +++ b/packages/test-snaps/src/api.ts @@ -0,0 +1,137 @@ +import { MetaMaskInpageProvider } from '@metamask/providers'; +import { RequestArguments } from '@metamask/providers/dist/BaseProvider'; +import { logError } from '@metamask/snaps-utils'; +import { JsonRpcError, JsonRpcParams } from '@metamask/utils'; +import { BaseQueryFn, createApi } from '@reduxjs/toolkit/query/react'; + +declare global { + // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + interface Window { + ethereum: MetaMaskInpageProvider; + } +} + +export enum Tag { + Accounts = 'Accounts', + InstalledSnaps = 'Installed Snaps', + TestState = 'Test State', +} + +/** + * Base request function for all API calls. + * + * @param args - The request arguments. + * @param args.method - The RPC method to call. + * @param args.params - The parameters to pass to the RPC method. + * @returns The response from the RPC method. + */ +export const request: BaseQueryFn = async ({ + method, + params, +}) => { + try { + const data = await window.ethereum.request({ method, params }); + + return { data }; + } catch (error: any) { + // eslint-disable-next-line no-alert + alert(error.message ?? error.toString()); + logError(error); + + return { error }; + } +}; + +export type GetSnapsResult = Record< + string, + { error?: string; version: string } +>; + +export type InvokeSnapArgs = { + snapId: string; + method: string; + params?: JsonRpcParams; + tags?: Tag[]; +}; + +export type InvokeSnapResult = unknown; + +export type InstallSnapArgs = { + snapId: string; + version: string; +}; + +export type InstallSnapResult = Record; + +export const baseApi = createApi({ + reducerPath: 'base', + baseQuery: request, + tagTypes: [Tag.Accounts, Tag.InstalledSnaps, Tag.TestState], + endpoints(build) { + return { + getAccounts: build.query({ + query: () => ({ + method: 'eth_requestAccounts', + }), + providesTags: [Tag.Accounts], + }), + + getSnaps: build.query({ + query: () => ({ + method: 'wallet_getSnaps', + }), + providesTags: [Tag.InstalledSnaps], + }), + + invokeQuery: build.query({ + query: ({ snapId, method, params }) => ({ + method: 'wallet_invokeSnap', + params: { snapId, request: params ? { method, params } : { method } }, + }), + providesTags: (_result, _error, { tags = [] }) => tags, + }), + + request: build.query({ + query: (args: RequestArguments) => args, + }), + + invokeMutation: build.mutation({ + query: ({ snapId, method, params }) => ({ + method: 'wallet_invokeSnap', + params: { snapId, request: params ? { method, params } : { method } }, + }), + invalidatesTags: (_result, _error, { tags = [] }) => tags, + }), + + installSnap: build.mutation({ + query: ({ snapId, version }) => ({ + method: 'wallet_requestSnaps', + params: { + [snapId]: { + version, + }, + }, + }), + transformResponse: (snaps: InstallSnapResult, _, { snapId }) => { + if (snaps[snapId].error) { + logError(snaps[snapId].error); + throw new Error(snaps[snapId].error.message); + } + + return snaps; + }, + invalidatesTags: [Tag.InstalledSnaps], + }), + }; + }, +}); + +export const { + useGetAccountsQuery, + useLazyGetAccountsQuery, + useGetSnapsQuery, + useInvokeQueryQuery: useInvokeQuery, + useLazyRequestQuery, + useInvokeMutationMutation: useInvokeMutation, + useInstallSnapMutation, +} = baseApi; diff --git a/packages/test-snaps/src/assets/icon.svg b/packages/test-snaps/src/assets/icon.svg new file mode 100644 index 0000000000..42ad3f17c0 --- /dev/null +++ b/packages/test-snaps/src/assets/icon.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + diff --git a/packages/test-snaps/src/components/ButtonSpinner.tsx b/packages/test-snaps/src/components/ButtonSpinner.tsx new file mode 100644 index 0000000000..959623038c --- /dev/null +++ b/packages/test-snaps/src/components/ButtonSpinner.tsx @@ -0,0 +1,18 @@ +import { FunctionComponent } from 'react'; + +export type ButtonSpinnerProps = { + children?: string; +}; + +export const ButtonSpinner: FunctionComponent = ({ + children, +}) => ( + <> + + {children && {children}} + +); diff --git a/packages/test-snaps/src/components/Connect.tsx b/packages/test-snaps/src/components/Connect.tsx new file mode 100644 index 0000000000..8d2eb89b51 --- /dev/null +++ b/packages/test-snaps/src/components/Connect.tsx @@ -0,0 +1,71 @@ +import { logError } from '@metamask/snaps-utils'; +import { ChangeEvent, FormEvent, FunctionComponent, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; + +import packageJson from '../../package.json'; +import { useInstallSnapMutation } from '../api'; +import { useInstalled } from '../utils'; +import { ButtonSpinner } from './ButtonSpinner'; + +type ConnectProps = { + name: string; + testId: string; + snapId?: string; + version?: string; +}; + +export const Connect: FunctionComponent = ({ + name, + testId, + snapId: defaultSnapId = '', + version: defaultVersion, +}) => { + const [installSnap, { isLoading }] = useInstallSnapMutation(); + const [snapId, setSnapId] = useState(defaultSnapId); + const isInstalled = useInstalled(snapId); + + const handleChange = (event: ChangeEvent) => { + setSnapId(event.target.value); + }; + + const handleConnect = (event: FormEvent) => { + event.preventDefault(); + + installSnap({ + snapId, + version: defaultVersion ?? packageJson.version, + }).catch(logError); + }; + + return ( +
+ + Snap ID + + + + +
+ ); +}; diff --git a/packages/test-snaps/src/components/Logo/Fox.tsx b/packages/test-snaps/src/components/Logo/Fox.tsx new file mode 100644 index 0000000000..4f0b723029 --- /dev/null +++ b/packages/test-snaps/src/components/Logo/Fox.tsx @@ -0,0 +1,433 @@ +/* eslint-disable */ + +import { vec2, vec3 } from 'gl-matrix'; +import { Component } from 'react'; +import { FoxRenderer } from './fox-render'; + +const MIN_DISTANCE = 100; +const MAX_DISTANCE = 800; + +const getOffset = (event: any) => { + let el = event.target; + let x = 0; + let y = 0; + + while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) { + x += el.offsetLeft - el.scrollLeft; + y += el.offsetTop - el.scrollTop; + el = el.offsetParent; + } + x = event.clientX - x + window.scrollX; + y = event.clientY - y + window.scrollY; + + return { x, y }; +}; + +export interface MetamaskBoxAnimationProps { + noGLFallback: React.ReactNode; + left: number; + phi: number; + theta: number; + distance: number; + hemisphereAxis: number[]; + hemisphereColor0: number[]; + hemisphereColor1: number[]; + interiorColor0: number[]; + interiorColor1: number[]; + fogColor: number[]; + enableZoom?: boolean; + + // if set, follow mouse + followMouse?: boolean; + lookPixel?: number[]; +} + +/** + * + * @param value + * @param min + * @param max + */ +function clamp(value: number, min: number, max: number) { + return Math.min(Math.max(value, min), max); +} + +export class Fox extends Component { + // webgl state + public static canvas: HTMLCanvasElement | null = null; + + public static gl: WebGLRenderingContext | null = null; + + public static glFailed = false; + + public static renderer: FoxRenderer | null = null; + + public static initWebGL() { + if (this.gl || this.glFailed) { + return; + } + + const canvas = document.createElement('canvas'); + canvas.width = canvas.height = 512; + Object.assign(canvas.style, { + left: 0, + top: 0, + width: '100%', + height: '100%', + margin: 0, + padding: 0, + 'pointer-events': 'none', + position: 'absolute', + }); + + try { + this.gl = canvas.getContext('webgl', { + premultipliedAlpha: true, + alpha: true, + antialias: true, + }); + } catch (err) { + this.glFailed = true; + throw err; + } + const { gl } = this; + if (!gl) { + this.glFailed = true; + throw new Error('Failed to get WebGL context'); + } + + this.canvas = canvas; + + // create animation + this.renderer = new FoxRenderer(gl); + } + + // glue stuff + private container: HTMLDivElement | null = null; + + private resizeObserver: ResizeObserver | null = null; + + private intersectionObserver: IntersectionObserver | null = null; + + private raf = 0; + + constructor(props: MetamaskBoxAnimationProps) { + super(props); + Fox.initWebGL(); + } + + public componentWillUnmount() { + if (this.container) { + this._handleMouseUp(); + this.container.removeEventListener('touchstart', this._handleTouchStart); + this.container.removeEventListener('wheel', this._handleWheel); + const { canvas } = Fox; + if (canvas && canvas.parentNode) { + canvas.parentNode.removeChild(canvas); + } + } + + if (this.raf) { + cancelAnimationFrame(this.raf); + } + } + + private frame = (timestamp: number) => { + const { gl } = Fox; + if (!gl) { + return; + } + const { renderer } = Fox; + if (renderer) { + renderer.animate(timestamp); + renderer.draw(); + } + this.raf = requestAnimationFrame(this.frame); + }; + + private updateSize = () => { + const { container } = this; + const { canvas } = Fox; + if (!container || !canvas) { + return; + } + + if (canvas.parentNode) { + canvas.parentNode.removeChild(canvas); + } + const bounds = container.getBoundingClientRect(); + canvas.width = Math.ceil(bounds.width * window.devicePixelRatio); + canvas.height = Math.ceil(bounds.height * window.devicePixelRatio); + container.appendChild(canvas); + Fox?.renderer?.draw(); + }; + + private updateVisibility = (entries: { isIntersecting: boolean }[]) => { + const e = entries[0]; + if (!this.container || !e) { + if (this.raf) { + cancelAnimationFrame(this.raf); + this.raf = 0; + } + return; + } + + if (e.isIntersecting) { + if (!this.raf) { + this.raf = requestAnimationFrame(this.frame); + } + } else if (this.raf) { + cancelAnimationFrame(this.raf); + this.raf = 0; + } + }; + + private _prevPos = vec2.fromValues(0, 0); + + private _handleMouseDown = (x: number, y: number) => { + if (!Fox.renderer) { + return; + } + this._prevPos[0] = x; + this._prevPos[1] = y; + Fox.renderer.explodeRay(x, y, 100); + document.body.addEventListener('mousemove', this._handleMouseMove, { + passive: false, + }); + + document.body.addEventListener('touchmove', this._handleTouchMove, { + passive: false, + }); + document.body.addEventListener('mouseup', this._handleMouseUp); + document.body.addEventListener('touchend', this._handleMouseUp); + }; + + private _lastPinchDist = 0; + + private _handleMove(posX: number, posY: number) { + const { renderer } = Fox; + if (!renderer) { + return; + } + renderer.explodeRay(posX, posY, 30); + const { _prevPos } = this; + _prevPos[0] = posX; + _prevPos[1] = posY; + } + + private _handleTouchMove = (ev: TouchEvent) => { + const { renderer } = Fox; + if (!renderer) { + return; + } + ev.preventDefault(); + if (ev.touches.length === 0) { + return; + } else if (ev.touches.length > 1 && this.props.enableZoom) { + const dist = Math.hypot( + ev.touches[0].pageX - ev.touches[1].pageX, + ev.touches[0].pageY - ev.touches[1].pageY, + ); + const dx = this._lastPinchDist - dist; + this._lastPinchDist = dist; + renderer.distance = clamp( + renderer.distance + dx * 0.1, + MIN_DISTANCE, + MAX_DISTANCE, + ); + return; + } + + const touch = ev.touches[0]; + const offset = getOffset(touch); + this._handleMove( + // @ts-expect-error + touch.layerX || offset?.x || touch.clientX, + + // @ts-expect-error + touch.layerY || offset?.y || touch.clientY, + ); + }; + + private _handleMouseMove = (ev: MouseEvent) => { + const { renderer } = Fox; + if (!renderer) { + return; + } + ev.preventDefault(); + const offset = getOffset(ev); + this._handleMove( + // @ts-expect-error + ev.layerX || offset?.x || ev.clientX, + + // @ts-expect-error + ev.layerY || offset?.y || ev.clientY, + ); + }; + + private _handleMouseUp = () => { + document.body.removeEventListener('mousemove', this._handleMouseMove); + document.body.removeEventListener('touchmove', this._handleTouchMove); + document.body.removeEventListener('mouseup', this._handleMouseUp); + document.body.removeEventListener('touchend', this._handleMouseUp); + }; + + private _handleTouchStart = (ev: TouchEvent) => { + const { renderer } = Fox; + if (!renderer) { + return; + } + ev.preventDefault(); + const touch = ev.touches[0]; + if (!touch) { + return; + } + + if (ev.touches.length === 1) { + const offset = getOffset(touch); + this._handleMouseDown( + // @ts-expect-error + touch.layerX || offset?.x || touch.clientX, + + // @ts-expect-error + touch.layerY || offset?.y || touch.clientY, + ); + } else { + this._lastPinchDist = Math.hypot( + ev.touches[0].pageX - ev.touches[1].pageX, + ev.touches[0].pageY - ev.touches[1].pageY, + ); + } + }; + + private _handleWheel = (ev: WheelEvent) => { + const { renderer } = Fox; + if (!renderer) { + return; + } + + if (this.props.enableZoom) { + ev.stopPropagation(); + ev.preventDefault(); + const { deltaY } = ev; + renderer.distance = clamp( + renderer.distance + deltaY * 0.1, + MIN_DISTANCE, + MAX_DISTANCE, + ); + } + }; + + public render() { + if (!Fox.gl) { + return this.props.noGLFallback; + } + + if (Fox.renderer) { + const { renderer } = Fox; + + renderer.phi = this.props.phi; + renderer.theta = this.props.theta; + renderer.distance = this.props.distance; + vec3.normalize(renderer.hemisphereAxis, this.props.hemisphereAxis as any); + vec3.copy(renderer.hemisphereColor0, this.props.hemisphereColor0 as any); + vec3.copy(renderer.hemisphereColor1, this.props.hemisphereColor1 as any); + vec3.copy(renderer.interiorColor0, this.props.interiorColor0 as any); + vec3.copy(renderer.interiorColor1, this.props.interiorColor1 as any); + vec3.copy(renderer.fogColor, this.props.fogColor as any); + + if (this.props.lookPixel) { + renderer.foxLookAt(this.props.lookPixel[0], this.props.lookPixel[1]); + } + } + const { left } = this.props; + + return ( +
{ + if (Fox.renderer) { + const offset = getOffset(ev); + this._handleMouseDown( + // @ts-expect-error + ev.layerX || offset?.x || ev.clientX, + + // @ts-expect-error + ev.layerY || offset?.y || ev.clientY, + ); + } + }} + onMouseMove={(ev) => { + if (this.props.followMouse && Fox.renderer) { + const offset = getOffset(ev); + Fox.renderer.foxLookAt( + // @ts-expect-error + ev.layerX || offset?.x || ev.clientX, + + // @ts-expect-error + ev.layerY || offset?.y || ev.clientY, + ); + } + }} + ref={(container) => { + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + this.resizeObserver = null; + } + + if (this.intersectionObserver) { + this.intersectionObserver.disconnect(); + this.intersectionObserver = null; + } + + if (!container) { + return; + } + + if (typeof window.ResizeObserver !== 'undefined') { + this.resizeObserver = new ResizeObserver(this.updateSize); + this.resizeObserver.observe(container); + } else { + this.updateSize(); + } + + if (typeof window.IntersectionObserver !== 'undefined') { + this.intersectionObserver = new IntersectionObserver( + this.updateVisibility, + ); + this.intersectionObserver.observe(container); + } else { + this.updateVisibility([ + { + isIntersecting: true, + }, + ]); + } + + if (!this.container) { + this.container = container; + container.addEventListener('touchstart', this._handleTouchStart, { + passive: false, + }); + + if (this.props.enableZoom) { + container.addEventListener('wheel', this._handleWheel, { + passive: false, + }); + } + this.updateSize(); + } + }} + /> + ); + } +} diff --git a/packages/test-snaps/src/components/Logo/Logo.tsx b/packages/test-snaps/src/components/Logo/Logo.tsx new file mode 100644 index 0000000000..e4a0bc2547 --- /dev/null +++ b/packages/test-snaps/src/components/Logo/Logo.tsx @@ -0,0 +1,36 @@ +import { FunctionComponent } from 'react'; +import { Container } from 'react-bootstrap'; + +import { Fox } from './Fox'; + +export const Logo: FunctionComponent = () => { + // Prevent SSR from rendering the logo. + if (typeof document === 'undefined') { + return ; + } + + return ( + + + + ); +}; diff --git a/packages/test-snaps/src/components/Logo/fox-animate.ts b/packages/test-snaps/src/components/Logo/fox-animate.ts new file mode 100644 index 0000000000..a2201192f5 --- /dev/null +++ b/packages/test-snaps/src/components/Logo/fox-animate.ts @@ -0,0 +1,350 @@ +/* eslint-disable */ + +import { mat3, mat4, quat, vec3, vec4 } from 'gl-matrix'; +import { createNoise4D } from 'simplex-noise'; +import { FoxBox } from './fox-geometry'; + +const noise = createNoise4D(); + +const K_POS_DAMPING = 0.8; +const K_ROT_DAMPING = 0.4; + +const K_POS_RECOVER = 0.1; +const K_ROT_RECOVER = 0.1; + +const NOISE_MAG = 4; +const NOISE_SCALE = 0.008; +const WAVE_FREQ = 0.012; + +/** + * + * @param N + * @param stride + */ +function allocBuffer(N: number, stride: number): any { + const buffer = new Float64Array(N * stride); + const result: Float64Array[] = []; + for (let i = 0; i < buffer.length; i += stride) { + result.push(buffer.subarray(i, i + stride)); + } + return result; +} + +export class FoxAnimation { + public N: number; + + public boxTransforms: mat4[] = []; + + public animRotation: quat = quat.identity(quat.create()); + + // box parameters + public centers: vec3[] = []; + + public weights: vec4[] = []; + + // box physics stuff + public restPosition: number[] = []; + + public curPosition: vec3[] = []; + + public nextPosition: vec3[] = []; + + public velocity: vec3[] = []; + + public restRotation: number[] = []; + + public curRotation: quat[] = []; + + public nextRotation: quat[] = []; + + public angularVelocity: quat[] = []; + + constructor(boxes: FoxBox[]) { + const N = (this.N = boxes.length); + + this.boxTransforms = allocBuffer(N, 16); + this.centers = allocBuffer(N, 3); + this.weights = allocBuffer(N, 4); + this.curPosition = allocBuffer(N, 3); + this.nextPosition = allocBuffer(N, 3); + this.velocity = allocBuffer(N, 3); + + this.nextRotation = allocBuffer(N, 4); + this.curRotation = allocBuffer(N, 4); + this.angularVelocity = allocBuffer(N, 4); + + for (let i = 0; i < boxes.length; ++i) { + mat4.identity(this.boxTransforms[i]); + + vec3.set(this.centers[i], boxes[i].cx, boxes[i].cy, boxes[i].cz); + vec4.set( + this.weights[i], + boxes[i].bx, + boxes[i].by, + boxes[i].bz, + boxes[i].bw, + ); + + const P = vec3.scaleAndAdd( + vec3.create(), + this.centers[i], + this.weights[i] as vec3, + -150, + ); + P[1] += 40 * Math.random(); + vec3.copy(this.curPosition[i], P); + vec3.copy(this.nextPosition[i], P); + + quat.identity(this.curRotation[i]); + quat.identity(this.nextRotation[i]); + + this.restPosition.push(-1); + this.restRotation.push(-1); + } + } + + private _qTmp = quat.create(); + + public preintegrate(dt: number) { + for (let i = 0; i < this.curPosition.length; ++i) { + vec3.scaleAndAdd( + this.nextPosition[i], + this.curPosition[i], + this.velocity[i], + dt, + ); + } + + for (let i = 0; i < this.curRotation.length; ++i) { + vec4.scaleAndAdd( + this.nextRotation[i], + this.curRotation[i], + this.angularVelocity[i], + dt, + ); + quat.normalize(this.nextRotation[i], this.nextRotation[i]); + } + } + + public postintegrate(dt: number) { + const VELOCITY_SCALE = Math.exp(-K_POS_DAMPING * dt) / dt; + for (let i = 0; i < this.curPosition.length; ++i) { + vec3.subtract( + this.velocity[i], + this.nextPosition[i], + this.curPosition[i], + ); + vec3.scale(this.velocity[i], this.velocity[i], VELOCITY_SCALE); + vec3.copy(this.curPosition[i], this.nextPosition[i]); + } + + const ROTATION_SCALE = Math.exp(-K_ROT_DAMPING * dt) / dt; + for (let i = 0; i < this.curRotation.length; ++i) { + vec4.subtract( + this.angularVelocity[i], + this.nextRotation[i], + this.curRotation[i], + ); + + vec4.scale( + this.angularVelocity[i], + this.angularVelocity[i], + ROTATION_SCALE, + ); + quat.copy(this.curRotation[i], this.nextRotation[i]); + } + } + + public updateTransforms() { + for (let i = 0; i < this.boxTransforms.length; ++i) { + mat4.fromRotationTranslation( + this.boxTransforms[i], + this.curRotation[i], + this.curPosition[i], + ); + } + } + + private _lastExplode = 1; + + private _displacement = vec3.create(); + + private _linePoint = vec3.create(); + + private _velocity = vec3.create(); + + private _angVelocity = vec3.create(); + + public explode(center: vec3, direction: vec3, mag: number) { + this._lastExplode = 1; + const M = mat3.fromQuat(this._tmpMat, this.animRotation); + for (let i = 0; i < this.curPosition.length; ++i) { + // calculate closest point + const disp = vec3.subtract( + this._displacement, + this.curPosition[i], + center, + ); + const t = vec3.dot(disp, direction); + const P = vec3.scaleAndAdd(this._linePoint, center, direction, t); + + const weight = this.weights[i]; + + // calculate ditance and force magnitude + const d = vec3.subtract(this._velocity, this.curPosition[i], P); + const scale = Math.min(10, (weight[3] * mag) / (1 + vec3.sqrLen(d))); + if (scale < 0.01 || vec3.squaredLength(this.velocity[i]) > 100) { + continue; + } + + this.restPosition[i] = this.restRotation[i] = -1; + + // update linear velocity + vec3.scaleAndAdd(this.velocity[i], this.velocity[i], d, scale); + + const extForce = vec3.transformMat3(this._tmpPos, weight as vec3, M); + vec3.scaleAndAdd( + this.velocity[i], + this.velocity[i], + extForce, + -10 * scale, + ); + + // update angular velocity + vec3.normalize(disp, disp); + vec3.cross(this._angVelocity, direction, weight as vec3); + vec3.scaleAndAdd( + this.angularVelocity[i] as vec3, + this.angularVelocity[i] as vec3, + this._angVelocity, + scale, + ); + // vec3.scaleAndAdd(this.angularVelocity[i] as vec3, this.angularVelocity[i] as vec3, weight as vec3, scale) + } + } + + private _tmpPos = vec3.create(); + + private _tmpPos2 = vec3.create(); + + private _tmpMat = mat3.create(); + + private _tmpMat2 = mat3.create(); + + public applyPositionConstraints(dt: number) { + const R0 = this._prevAnimRotation; + const R1 = this.animRotation; + const M0 = mat3.fromQuat(this._tmpMat, R0); + const M1 = mat3.fromQuat(this._tmpMat2, R1); + + const invDT = 1 / Math.max(0.01, dt); + const DR = invDT * vec4.distance(R0, R1); + + const tpos = K_POS_RECOVER * dt; + for (let i = 0; i < this.nextPosition.length; ++i) { + const C0 = vec3.transformMat3(this._tmpPos, this.centers[i], M0); + const C1 = vec3.transformMat3(this._tmpPos2, this.centers[i], M1); + const DC = vec3.distance(C0, C1); + vec3.lerp( + this.nextPosition[i], + this.nextPosition[i], + C1, + tpos * + Math.max( + 0.25, + 1 / (1 + 0.001 * vec3.sqrDist(C1, this.nextPosition[i])), + ), + ); + + if (this.restPosition[i] < 0) { + this.restPosition[i] = Math.min(0, this.restPosition[i] + dt); + } else if ( + this.restPosition[i] > 0 || + (vec3.distance(this.nextPosition[i], C1) < 1.5 + DC && + vec3.length(this.velocity[i]) < 0.01 + invDT * DC) + ) { + vec3.copy(this.nextPosition[i], C1); + vec3.copy(this.curPosition[i], C1); + vec3.set(this.velocity[i], 0, 0, 0); + this.restPosition[i] = 1; + } + } + + const trot = K_ROT_RECOVER * dt; + for (let i = 0; i < this.curRotation.length; ++i) { + quat.lerp(this.nextRotation[i], this.nextRotation[i], R1, trot); + quat.normalize(this.nextRotation[i], this.nextRotation[i]); + if (this.restRotation[i] < 0) { + this.restRotation[i] = Math.min(0, this.restRotation[i] + dt); + } + + if ( + this.restRotation[i] > 0 || + (vec4.distance(this.nextRotation[i], R1) < 0.01 + DR && + vec4.sqrLen(this.angularVelocity[i]) < 0.01 + invDT * DR) + ) { + quat.copy(this.nextRotation[i], R1); + quat.copy(this.curRotation[i], R1); + quat.set(this.angularVelocity[i], 0, 0, 0, 0); + this.restRotation[i] = 1; + } + } + } + + private _tmpRot = quat.create(); + + private applyWaveForce(t: number) { + const tx = 0.001 * t; // 0.1 * t + const ty = 0; // 0.01 * t + const tz = 0; // 0.02 * t + const tw = 0.00001 * t; // 0.5 * t + const S = NOISE_SCALE; + + const M = Math.cos(WAVE_FREQ * t); + + const MR = mat3.fromQuat(this._tmpMat, this.animRotation); + + for (let i = 0; i < this.curPosition.length; ++i) { + const [cx, cy, cz] = this.centers[i]; + const n = + NOISE_MAG * + (M * noise(tx + S * cx, ty + S * cy, tz + S * cz, tw) - + this._lastExplode - + 0.05); + if (n > 0) { + const rotDir = vec3.transformMat3( + this._tmpPos, + this.weights[i] as vec3, + MR, + ); + vec3.scaleAndAdd(this.velocity[i], this.velocity[i], rotDir, -n); + + const omega = quat.mul( + this._tmpRot, + this.animRotation, + this.weights[i], + ); + vec4.scaleAndAdd( + this.angularVelocity[i], + this.angularVelocity[i], + omega, + 0.0025 * n, + ); + this.restPosition[i] = -1; + this.restRotation[i] = -1; + } + } + } + + private _prevAnimRotation = quat.identity(quat.create()); + + public update(t: number, dt: number) { + this._lastExplode = Math.max(0, this._lastExplode - 0.003 * dt); + this.applyWaveForce(t); + this.preintegrate(dt); + this.applyPositionConstraints(dt); + this.postintegrate(dt); + this.updateTransforms(); + quat.copy(this._prevAnimRotation, this.animRotation); + } +} diff --git a/packages/test-snaps/src/components/Logo/fox-data.ts b/packages/test-snaps/src/components/Logo/fox-data.ts new file mode 100644 index 0000000000..bc3899d52a --- /dev/null +++ b/packages/test-snaps/src/components/Logo/fox-data.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ + +export const FOX_BOXES: { + diameter: number; + lo: number[]; + hi: number[]; + gridLo: number[]; + gridHi: number[]; + boundary: number[][]; + colors: number[][]; + verts: number[][]; + centers: number[][]; + boxes: [number, number[][]][][]; +} = JSON.parse( + '{"diameter":24,"lo":[-122.117996,-93.589897,-48.3596],"hi":[122.117996,116.560997,150.722],"gridLo":[-6,-4,-3],"gridHi":[6,5,7],"boundary":[[1,-1.0228501601261542e-8,-8.182801281009233e-8],[0.8504238128662109,0.5260981917381287,-1.4851688945327624e-7],[0.9753293991088867,0.22075463831424713,0],[0.9318280220031738,-0.029862413182854652,0.3616693913936615],[0.6086949110031128,0.1307537704706192,-0.7825560569763184],[0.7692264318466187,-0.4090452790260315,0.49088966846466064],[0.6057133674621582,-0.0806102603673935,-0.791589081287384],[0.928680419921875,-0.1129331886768341,0.35326868295669556],[0.5919687151908875,-0.10947707295417786,-0.7984910011291504],[0.958467423915863,0.28251686692237854,0.03904382511973381],[3.578383100943938e-8,0.00819921214133501,-0.9999663829803467],[0.9070162773132324,0.021739618852734566,0.42053404450416565],[0.1539635807275772,0.3540334701538086,-0.9224724769592285],[0.691635251045227,-0.3628727197647095,0.6244710087776184],[0.784731924533844,0.010816571302711964,-0.619740903377533],[0.8598924279212952,-0.5087252259254456,0.04223278537392616],[0.37431079149246216,6.907908556286202e-8,-0.9273033142089844],[0.1287173330783844,0.029887380078434944,0.991230845451355],[-0.020404832437634468,0.9970798492431641,-0.07358956336975098],[0.40505528450012207,0.24923235177993774,-0.8796666860580444],[0.17178530991077423,-0.08574546873569489,0.9813957214355469],[0.6653342843055725,0.039334554225206375,0.74550861120224],[0.46152201294898987,0.36289262771606445,-0.8095099925994873],[0.12342957407236099,-0.2401389181613922,0.9628595113754272],[0.559287965297699,0.345054030418396,-0.7537471055984497],[0.6184812784194946,0.058198366314172745,-0.7836413979530334],[0.7976707816123962,0.487419068813324,0.35516759753227234],[0.5121573805809021,0.09600565582513809,0.8535090684890747],[0.6188085079193115,-0.11088787019252777,-0.777675986289978],[0.6283224821090698,-0.13398867845535278,-0.7663275003433228],[0.8813585042953491,0.05751384049654007,0.4689342975616455],[0.8742813467979431,0.19956395030021667,0.4425000846385956],[0.9681146144866943,-0.024797307327389717,0.249277263879776],[0.47877171635627747,-0.4782499074935913,-0.7362436056137085],[0.8734856247901917,-0.059241488575935364,0.48323217034339905],[0.8539445400238037,-0.00919655803591013,0.5202827453613281],[0.18029572069644928,-0.03767537325620651,-0.9828906655311584],[0.842650830745697,-0.05346041917800903,0.5357999205589294],[0.7632421255111694,-0.08555842190980911,0.6404227018356323],[0.2080230414867401,0.5657850503921509,-0.7978807687759399],[-0.09287610650062561,0.43706464767456055,-0.8946220278739929],[0.4301705062389374,-0.6620780229568481,0.6136823296546936],[0.46222370862960815,-0.6380462050437927,0.6158297657966614],[0.021654121577739716,0.4250352680683136,-0.9049177169799805],[0.3062419593334198,-0.7296712398529053,0.6113883852958679],[0.16853012144565582,-0.9582940340042114,-0.23080337047576904],[-0.192888081073761,6.6745324822647945e-9,-0.9812207818031311],[-0.10028168559074402,0.5626676082611084,0.8205782771110535],[-0.3619228005409241,0.931859016418457,-0.025508828461170197],[-0.10588056594133377,0.8907723426818848,-0.44194334745407104],[0.18446508049964905,-0.055371034890413284,0.9812780618667603],[-0.27150487899780273,0.7506008744239807,0.6023980975151062],[0.37552425265312195,0.541515588760376,-0.752158522605896],[0.29006507992744446,0.47813302278518677,-0.8290060758590698],[0.6695849299430847,0.5103926062583923,0.539588212966919],[0.7860305309295654,0.4910293221473694,0.3755612075328827],[0.40285488963127136,-0.009069381281733513,0.9152189493179321],[0.48654937744140625,0.5294649600982666,-0.6949363350868225],[0.3734573721885681,0.34247031807899475,-0.8621158003807068],[0.615329384803772,0.45650190114974976,0.6426318883895874],[0.686672568321228,0.49250203371047974,0.5347172617912292],[0.7976697087287903,0.4874206483364105,0.35516777634620667],[0.7944169044494629,0.47826308012008667,0.3743877708911896],[0.6283327341079712,-0.13398811221122742,-0.766319215297699],[0.43592602014541626,-0.1162395179271698,-0.8924443125724792],[0.6849081516265869,0.04826570302248001,0.7270290851593018],[0.7501806020736694,0.10661425441503525,0.6525813937187195],[0.7976812124252319,0.48740747570991516,0.3551599681377411],[0.2148367464542389,-0.8510902523994446,-0.47905173897743225],[0.2119349241256714,-0.820659875869751,-0.53066086769104],[0.32612982392311096,-0.451395720243454,-0.8305909037590027],[0.6815271377563477,-0.09007009118795395,0.7262287139892578],[0.7267503142356873,-0.09161580353975296,0.6807646155357361],[0,0,0],[0.4296804368495941,-0.13970164954662323,-0.8921088576316833],[0.16000711917877197,-0.8071871995925903,-0.5681958794593811],[0.6737505793571472,-0.15837571024894714,0.7217875719070435],[0.6821427941322327,-0.2986332178115845,0.6674574017524719],[0.3366634249687195,-0.7477033734321594,0.5723612308502197],[0.3897724151611328,0.3912390470504761,-0.833672285079956],[0.24118272960186005,0.31700995564460754,-0.917243480682373],[0.6438280940055847,-0.7000151872634888,0.30897262692451477],[0.37137049436569214,-0.7565067410469055,0.5383135676383972],[0.28994810581207275,-0.7387804985046387,0.6083859801292419],[-0.029022594913840294,0.21302327513694763,-0.9766159653663635],[0.10623830556869507,-0.9039110541343689,0.4143165647983551],[-0.5242925882339478,-0.691795289516449,-0.49652451276779175],[0.045820824801921844,0.727557897567749,0.6845144033432007],[0.2860824465751648,0.7249541282653809,0.6265767216682434],[-0.07101839780807495,0.9968384504318237,0.03562932834029198],[0.15933385491371155,0.9871649742126465,-0.010862834751605988],[0.7517606019973755,0.5348491072654724,-0.38573625683784485],[0.8840624690055847,0.21576282382011414,-0.41458413004875183],[0.018008733168244362,0.6169819831848145,0.7867712378501892],[0.3793635964393616,0.6295909881591797,0.6780106425285339],[0.6842378973960876,0.5092427134513855,0.522006094455719],[0,0,0],[0,0,0],[0.718989372253418,0.07999280840158463,-0.6904023885726929],[0.8652060031890869,-0.1826101392507553,-0.4669818580150604],[0.3657165467739105,0.5571408271789551,0.7455504536628723],[0.6216648817062378,0.46267110109329224,0.6320350170135498],[0,0,0],[0,0,0],[0,0,0],[0.25862187147140503,-0.21363435685634613,-0.9420589804649353],[0.5028197765350342,-0.7806774377822876,-0.37109968066215515],[0.0036175164859741926,0.012109405361115932,0.999920129776001],[0.5712440609931946,0.10384996980428696,0.8141838908195496],[0,0,0],[0,0,0],[0,0,0],[0.25603532791137695,-0.7564913034439087,-0.6018030047416687],[0.1741376668214798,-0.6343281865119934,-0.7531957030296326],[0.033627405762672424,0.00992205087095499,0.9993851780891418],[0.7223114371299744,-0.06096583604812622,0.6888754367828369],[0,0,0],[0,0,0],[0.3972948491573334,0,-0.9176909923553467],[0.5539597272872925,-0.32300037145614624,-0.7673326730728149],[0.056240759789943695,-0.1909746378660202,0.9799824953079224],[0.5774157643318176,-0.3515545725822449,0.7368856072425842],[0.6043931245803833,-0.3460192084312439,0.7176207900047302],[0,0,0],[0,0,0],[0.13135556876659393,0.22701804339885712,-0.9649914503097534],[0.434695839881897,-0.43956470489501953,0.7860168218612671],[0.5646017789840698,-0.7522140741348267,0.3397040069103241],[0.5768170356750488,-0.7642378211021423,0.2884834408760071],[-0.47263607382774353,-0.6383809447288513,-0.6075235605239868],[-0.510698676109314,-0.521359384059906,-0.6836456060409546],[0.051212504506111145,-0.9781743884086609,0.20137567818164825],[0.24527010321617126,-0.939034640789032,0.24094931781291962],[-0.26060721278190613,-0.9281308054924011,-0.26581403613090515],[0,0.7304578423500061,0.6829577684402466],[-5.0502226400794825e-8,0.8134666085243225,0.5816116333007812],[7.581520549138077e-7,0.9962686896324158,0.08630593121051788],[6.75359956403554e-7,0.9962690472602844,0.08630179613828659],[0,0.9999812841415405,-0.006120717152953148],[0.19600951671600342,0.9691318273544312,-0.14954538643360138],[0.5475984811782837,0.5951905250549316,-0.5881191492080688],[0.058225084096193314,0.4855789244174957,-0.8722516298294067],[0,0.6179631352424622,0.7862070798873901],[0,0.6889469623565674,0.7248117327690125],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0.6118707060813904,-0.6830028295516968,-0.39890027046203613],[0.6896105408668518,-0.5374903678894043,-0.4853260815143585],[0.3415726125240326,-0.11777069419622421,-0.9324474334716797],[7.766939802422712e-8,0.617996871471405,0.7861805558204651],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0.4677516222000122,-0.37623345851898193,-0.7997854948043823],[0.4580691158771515,-0.7272529602050781,-0.5111514925956726],[0.13695773482322693,-0.8290615081787109,-0.5421251058578491],[0,0.012373906560242176,0.9999234676361084],[4.753531968049174e-8,0.22587385773658752,0.9741565585136414],[0,0,0],[0,0,0],[0,0,0],[0.5975387692451477,-0.37761804461479187,-0.7073556780815125],[0.2294560819864273,-0.5082189440727234,-0.8300984501838684],[8.755198450671742e-7,0.012386549264192581,0.9999232888221741],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0.32224398851394653,-0.4693700075149536,-0.822101354598999],[0.1531381756067276,-0.5010979175567627,-0.8517332673072815],[0,-0.19334284961223602,0.9811312556266785],[-0.0000011492429621284828,-0.48097100853919983,0.8767365217208862],[0,0,0],[0,0,0],[-0.006786562502384186,-0.6001333594322205,-0.7998711466789246],[0.01698807068169117,-0.5352197885513306,-0.8445420265197754],[0,-0.5094355940818787,0.8605087995529175],[-0.0000012202144716866314,-0.9803447723388672,0.19729198515415192],[0,0,0],[-0.005824109073728323,-0.5999711751937866,-0.8000004291534424],[-0.5568259954452515,-0.6208491325378418,-0.551807165145874],[8.859131526151032e-7,-0.9803468585014343,0.1972816437482834],[0,-0.980341911315918,0.1973060667514801],[0,-0.7136216163635254,-0.7005313634872437],[0,0.7304578423500061,0.6829578280448914],[1.2248696634742373e-7,0.8134666085243225,0.5816116333007812],[-0.0000017363280448989826,0.9962686896324158,0.08630591630935669],[-6.734330213475914e-7,0.9962690472602844,0.08630181103944778],[0,0.9999812841415405,-0.006120717152953148],[-0.19600948691368103,0.9691318273544312,-0.14954537153244019],[-0.5475984811782837,0.5951905250549316,-0.5881191492080688],[-0.058225084096193314,0.4855789244174957,-0.8722516298294067],[0,0.6179631352424622,0.7862070798873901],[-5.132795308782079e-7,0.6889469623565674,0.7248117923736572],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[-0.6118705868721008,-0.6830028295516968,-0.3989003300666809],[-0.6896105408668518,-0.5374903678894043,-0.4853260815143585],[-0.3415726125240326,-0.117770716547966,-0.9324474334716797],[-9.328940109298856e-8,0.617996871471405,0.7861805558204651],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[-0.46775156259536743,-0.3762334883213043,-0.7997854948043823],[-0.4580690860748291,-0.7272529602050781,-0.5111514925956726],[-0.13695773482322693,-0.8290615081787109,-0.5421250462532043],[0,0.01237390749156475,0.9999234676361084],[4.1781046888900164e-7,0.22587385773658752,0.9741565585136414],[0,0,0],[0,0,0],[0,0,0],[-0.5975387692451477,-0.37761804461479187,-0.7073556780815125],[-0.2294560968875885,-0.5082190036773682,-0.8300983905792236],[-0.0000012726986824418418,0.012386549264192581,0.9999232888221741],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[-0.32224398851394653,-0.4693700075149536,-0.822101354598999],[-0.1531381756067276,-0.5010979175567627,-0.8517332673072815],[0,-0.19334284961223602,0.9811312556266785],[6.375142902470543e-7,-0.4809710383415222,0.8767364621162415],[0,0,0],[0,0,0],[0.0067865620367228985,-0.6001333594322205,-0.7998712062835693],[-0.01698807254433632,-0.5352198481559753,-0.8445419669151306],[-7.513564810324169e-7,-0.5094356536865234,0.8605087399482727],[0,-0.9803447723388672,0.19729198515415192],[0,0,0],[0.00582482386380434,-0.5999711751937866,-0.8000004291534424],[0.5568259954452515,-0.6208491325378418,-0.551807165145874],[-8.87011765371426e-7,-0.9803468585014343,0.19728167355060577],[-0.000009180573215417098,-0.980341911315918,0.1973060667514801],[0,-0.7136216163635254,-0.7005313634872437],[-0.045820824801921844,0.727557897567749,0.6845144033432007],[-0.2860824763774872,0.7249540686607361,0.6265767216682434],[0.07101936638355255,0.996838390827179,0.035629309713840485],[-0.15933384001255035,0.9871649742126465,-0.010862831957638264],[-0.7517606019973755,0.5348491072654724,-0.38573622703552246],[-0.8840624690055847,0.21576280891895294,-0.41458413004875183],[-0.018008733168244362,0.6169819831848145,0.7867712378501892],[-0.37936311960220337,0.6295911073684692,0.6780107617378235],[-0.6842378973960876,0.5092427134513855,0.522006094455719],[0,0,0],[0,0,0],[-0.7189893126487732,0.07999280840158463,-0.6904023885726929],[-0.8652060627937317,-0.1826101392507553,-0.46698182821273804],[-0.36571651697158813,0.5571408271789551,0.7455504536628723],[-0.621664822101593,0.4626711308956146,0.6320350170135498],[0,0,0],[0,0,0],[0,0,0],[-0.25862187147140503,-0.21363435685634613,-0.9420589804649353],[-0.5028197765350342,-0.7806774377822876,-0.37109968066215515],[-0.0036175164859741926,0.012109405361115932,0.999920129776001],[-0.5712443590164185,0.10384996235370636,0.8141836524009705],[0,0,0],[0,0,0],[0,0,0],[-0.25603532791137695,-0.7564913034439087,-0.6018029451370239],[-0.174137681722641,-0.6343281865119934,-0.7531957030296326],[-0.03362578898668289,0.009922051802277565,0.9993852376937866],[-0.7223113775253296,-0.06096583604812622,0.6888754963874817],[0,0,0],[0,0,0],[-0.39729487895965576,7.514982414136284e-9,-0.9176909923553467],[-0.5539597868919373,-0.32300034165382385,-0.7673326134681702],[-0.056240759789943695,-0.1909746378660202,0.9799824953079224],[-0.5774155259132385,-0.35155466198921204,0.7368857860565186],[-0.6043931245803833,-0.3460192084312439,0.7176207900047302],[0,0,0],[0,0,0],[-0.13135559856891632,0.2270180881023407,-0.9649914503097534],[-0.43469467759132385,-0.439564973115921,0.7860172986984253],[-0.5646011829376221,-0.7522144317626953,0.3397041857242584],[-0.5768170356750488,-0.7642378211021423,0.2884834408760071],[0.4726351499557495,-0.63838130235672,-0.6075239181518555],[0.510698676109314,-0.521359384059906,-0.6836456060409546],[-0.05121250078082085,-0.9781743884086609,0.20137566328048706],[-0.2452538162469864,-0.9390385746955872,0.24095036089420319],[0.26060721278190613,-0.9281308054924011,-0.26581403613090515],[0.10028168559074402,0.5626676082611084,0.8205782771110535],[0.3619228005409241,0.931859016418457,-0.025508830323815346],[0.10588056594133377,0.8907723426818848,-0.44194334745407104],[-0.18446508049964905,-0.05537102743983269,0.9812780618667603],[0.27150487899780273,0.7506008744239807,0.6023980975151062],[-0.37552422285079956,0.5415156483650208,-0.7521584630012512],[-0.29006507992744446,0.47813302278518677,-0.8290060758590698],[-0.6695849299430847,0.5103926062583923,0.539588212966919],[-0.7860305309295654,0.4910293221473694,0.3755612075328827],[-0.40285488963127136,-0.00906938873231411,0.9152189493179321],[-0.48654940724372864,0.5294649600982666,-0.6949363946914673],[-0.3734573721885681,0.34247031807899475,-0.8621158003807068],[-0.615329384803772,0.45650190114974976,0.6426318883895874],[-0.686672568321228,0.49250203371047974,0.5347172617912292],[-0.7976697087287903,0.4874206483364105,0.35516780614852905],[-0.7944168448448181,0.47826310992240906,0.37438780069351196],[-0.6283327341079712,-0.13398811221122742,-0.766319215297699],[-0.4359259605407715,-0.1162395030260086,-0.892444372177124],[-0.6849080920219421,0.0482657253742218,0.7270291447639465],[-0.7501806020736694,0.10661424696445465,0.6525813937187195],[-0.7976812124252319,0.48740747570991516,0.3551599681377411],[-0.2148367464542389,-0.8510902523994446,-0.47905173897743225],[-0.2119349241256714,-0.820659875869751,-0.53066086769104],[-0.32612982392311096,-0.451395720243454,-0.8305909037590027],[-0.6815271377563477,-0.09007009118795395,0.7262287139892578],[-0.726750373840332,-0.09161581844091415,0.6807646155357361],[0,0,0],[-0.4296804368495941,-0.13970164954662323,-0.8921088576316833],[-0.16000711917877197,-0.8071871399879456,-0.5681959390640259],[-0.6737505793571472,-0.15837572515010834,0.7217875719070435],[-0.6821427941322327,-0.2986332178115845,0.6674574017524719],[-0.33666345477104187,-0.7477033734321594,0.5723612308502197],[-0.3897723853588104,0.3912390470504761,-0.833672285079956],[-0.24118269979953766,0.31700995564460754,-0.917243480682373],[-0.6438280940055847,-0.7000151872634888,0.30897265672683716],[-0.3713705241680145,-0.7565067410469055,0.5383135676383972],[-0.28994810581207275,-0.7387804985046387,0.6083859205245972],[0.029022516682744026,0.2130233198404312,-0.9766159653663635],[-0.10623829811811447,-0.9039110541343689,0.4143165349960327],[0.5242925882339478,-0.691795289516449,-0.49652451276779175],[-0.1287173330783844,0.029887378215789795,0.991230845451355],[0.02040487341582775,0.9970798492431641,-0.07358957082033157],[-0.40505528450012207,0.24923236668109894,-0.8796666860580444],[-0.17178530991077423,-0.08574546873569489,0.9813957214355469],[-0.6653342247009277,0.03933454677462578,0.74550861120224],[-0.46152207255363464,0.36289262771606445,-0.8095099329948425],[-0.1234295591711998,-0.2401389181613922,0.9628595113754272],[-0.5592880249023438,0.34505409002304077,-0.7537470459938049],[-0.6184812784194946,0.058198366314172745,-0.7836413979530334],[-0.7976707816123962,0.487419068813324,0.35516759753227234],[-0.5121573209762573,0.0960056409239769,0.8535090684890747],[-0.6188084483146667,-0.11088787764310837,-0.777675986289978],[-0.6283224821090698,-0.13398867845535278,-0.7663275003433228],[-0.8813585042953491,0.057513847947120667,0.4689342975616455],[-0.8742813467979431,0.19956395030021667,0.4425000846385956],[-0.9681146144866943,-0.024797270074486732,0.249277263879776],[-0.47877174615859985,-0.4782499074935913,-0.7362436056137085],[-0.8734856247901917,-0.059241484850645065,0.48323217034339905],[-0.8539445400238037,-0.009196560829877853,0.5202827453613281],[-0.18029579520225525,-0.037675391882658005,-0.9828906059265137],[-0.842650830745697,-0.05346041917800903,0.5357999801635742],[-0.7632421255111694,-0.0855584368109703,0.6404227018356323],[-0.20802299678325653,0.5657850503921509,-0.7978807687759399],[0.09287610650062561,0.43706461787223816,-0.8946220278739929],[-0.4301705062389374,-0.6620780229568481,0.6136823296546936],[-0.4622236490249634,-0.6380462050437927,0.6158297657966614],[-0.021654125303030014,0.4250352382659912,-0.9049177765846252],[-0.3062419593334198,-0.7296712398529053,0.6113883852958679],[-0.16853021085262299,-0.9582939743995667,-0.23080343008041382],[0.1928880661725998,2.447328384391767e-8,-0.9812207818031311],[-0.8504238128662109,0.5260981917381287,-1.4851688945327624e-7],[-0.9753293991088867,0.22075465321540833,0],[-0.9318280220031738,-0.02986246347427368,0.36166948080062866],[-0.6086949110031128,0.1307537853717804,-0.7825560569763184],[-0.7692264914512634,-0.4090452194213867,0.49088963866233826],[-0.6057133674621582,-0.08061026781797409,-0.791589081287384],[-0.928680419921875,-0.11293315142393112,0.35326865315437317],[-0.5919687151908875,-0.10947707295417786,-0.7984909415245056],[-0.958467423915863,0.2825167775154114,0.039044059813022614],[3.2375847780485856e-8,0.008199185132980347,-0.9999663829803467],[-0.9070162773132324,0.021739643067121506,0.42053401470184326],[-0.15396356582641602,0.3540334701538086,-0.9224724769592285],[-0.691635251045227,-0.3628727197647095,0.6244710087776184],[-0.7847319841384888,0.010816599242389202,-0.6197408437728882],[-0.8598924279212952,-0.5087252855300903,0.04223283752799034],[-0.37431085109710693,6.907909977371673e-8,-0.9273033142089844],[-1,-1.0228501601261542e-8,-8.182801281009233e-8]],"colors":[[119,57,0],[36,51,67],[228,116,36],[192,172,157],[214,194,178],[228,119,25],[205,98,0],[0,0,0],[247,132,25],[225,119,25],[255,255,255]],"verts":[[-120,-37.7892,35.8291],[-120,-36.6286,36.716],[-122.118,-36.8894,35.025],[-120,-46.2467,33.8367],[-120,-35.3009,36.4838],[-120,-31.5318,36.1684],[-120,-37.6315,34.5894],[-96,-72,39.2838],[-114.171,-72,30.5661],[-109.284,-93.5899,27.8243],[-96,-88.2215,35.4622],[-96,-88.482,25.9453],[-96,-72,27.3853],[-96,-48,44.9379],[-119.603,-48,33.614],[-96,-48,29.4823],[-96,-47.9854,44.9413],[-96,-43.9824,48],[-105.866,-34.8883,48],[-104.932,-24,46.862],[-117.023,-24,37.7757],[-103.544,-24,48],[-96,-46.0406,29.6535],[-96,-24,35.3589],[-96,-24,48],[-96,-33.6734,55.877],[-96,-24,54.1857],[-103.28,-22.7608,48],[-100.745,0,48],[-107.535,0,42.8975],[-96,0,41.5714],[-96,0,48],[-96,-17.3006,53.0144],[-96,0,51.5664],[-96,19.4792,43.5412],[-101.217,15.9822,46.3082],[-96,17.5257,45.9055],[-107.071,24,48],[-106.895,23.3557,48],[-104.062,24,46.6121],[-96,24,42.9923],[-99.0095,15.587,48],[-96,16.3467,48],[-96,14.4528,36.6911],[-96,23.8717,37.8459],[-96,9.16753,43.9445],[-107.229,24,48],[-96,24,37.7854],[-107.391,24,48.1478],[-96,15.0482,50.3069],[-96,48,41.4178],[-100.555,48,42.0944],[-96,45.9969,40.2972],[-110.131,35.2227,48],[-106.881,31.9455,46.9133],[-108.663,43.2332,46.3154],[-111.558,40.4547,48],[-108.784,30.2823,48],[-96,33.0554,41.8927],[-96,40.5511,40.9646],[-113.615,48,48],[-113.372,47.108,48],[-109.864,48,46.2699],[-112.571,39.117,48],[-96.7162,48,28.5453],[-96,48,27.8948],[-96,41.1182,31.8106],[-96,41.0395,29.7579],[-109.944,29.2427,48],[-99.3192,48,34.0931],[-114.045,48,48],[-113.485,38.6049,49.1215],[-110.843,28.4821,49.1762],[-114.456,48,48.3878],[-96,59.7655,48],[-102.349,58.0794,48],[-111.025,52.6046,46.2259],[-111.442,57.482,48],[-114.099,49.7733,48],[-96,54.7409,26.1534],[-114.699,48.8655,48],[-96,56.3735,27.7442],[-96,48.4013,27.6664],[-108.602,72,48],[-96,72,31.6987],[-96,49.6932,29.7516],[-96,72,48],[-96,62.0865,49.2985],[-96,72,52.8843],[-112.684,72,53.2808],[-115.284,48.6815,48.6841],[-96,92.2861,48],[-96,77.4494,33.0777],[-106.383,83.339,48],[-96,85.1202,57.6299],[-114.025,87.6733,58.9818],[-96,96,63.2865],[-109.35,96,63.3046],[-96,96,51.7353],[-109.35,96,63.3046],[-96,112.76,72],[-99.9447,112.749,72],[-96,115.636,72],[-96,113.044,68.878],[-97.1045,115.197,72],[-96,112.76,72],[-96,114.525,72.918],[-97.8045,116.561,73.9788],[-96,115.257,73.6248],[-96,116.15,72.6201],[-72,-79.2139,24],[-82.248,-83.1941,24],[-72,-79.2536,22.5504],[-76.6606,-72,24],[-72,-72,23.1842],[-72,-72,24],[-77.8321,-72,48],[-74.1939,-79.409,48],[-72,-78.5569,48],[-72,-72,48],[-72,-72,50.798],[-72,-78.5224,49.2614],[-72,-62.6628,24],[-91.6412,-48,48],[-95.9656,-48,44.9544],[-87.9439,-51.408,48],[-90.4079,-48,28.5034],[-72,-54.4498,24.7176],[-72,-48,26.3872],[-72,-48,48],[-72,-58.1816,54.0535],[-72,-48,61.8332],[-72,-24,32.5997],[-72,-24,48],[-72,-34.6943,72],[-75.8053,-31.1868,72],[-74.2728,-24,72],[-72,-24,72],[-72,-30.7182,75.0381],[-72,-24,73.8635],[-81.5177,0,24],[-72,0,2.6242],[-72,-15.5759,24],[-72,0,24],[-88.9823,0,40.7646],[-72,-22.1847,33.0696],[-72,0,48],[-72.933,0,68.9023],[-72,-13.342,72],[-72,0,69.6672],[-75.0543,24,0],[-72,24,-5.52097],[-72,7.41659,-7.55404],[-76.0976,8.6179,0],[-72,1.91218,0],[-72,24,0],[-88.3315,24,24],[-89.1159,12.4346,24],[-72,24,24],[-89.2561,24,39.9642],[-74.1182,24,44.2164],[-72,22.405,48],[-72,24,45.1663],[-95.9152,24,37.7083],[-72,0.699737,69.5449],[-72,10.7513,68.7036],[-73.4266,48,0],[-72,48,-2.57866],[-72,48,0],[-87.4647,36.7804,24],[-80.0463,48,11.9658],[-91.7119,48,24],[-87.8363,48,20.4799],[-90.3725,45.8621,24],[-87.7728,48,18.9946],[-91.5988,44.7631,24],[-72,48,24],[-72,48,37.8523],[-72.1133,35.4918,30.8714],[-72,36.3606,31.3406],[-72,35.462,30.9393],[-72,24.6267,44.0529],[-72,65.2415,0],[-72,63.8365,-1.41315],[-72.9833,64.3942,0],[-72.6699,59.1559,0],[-72,60.1691,-1.08677],[-72,62.2821,-1.88711],[-73.6152,61.7746,0],[-73.4456,62.0312,0],[-72,62.3938,-1.77823],[-73.4535,61.0338,0],[-72,61.8481,-1.78354],[-72,61.3496,-1.49988],[-73.0807,60.4387,0],[-72,61.3442,-1.64038],[-73.2539,60.2834,0],[-73.2544,61.2966,0],[-72,61.9366,-1.64082],[-72,61.3496,-1.49988],[-72.6699,59.1559,0],[-72,72,7.9374],[-72,66.2729,1.03736],[-74.9388,72,9.34433],[-86.3925,72,19.2706],[-94.1569,55.32,24],[-92.9562,57.137,24],[-93.0121,50.0754,24],[-90.0486,72,24],[-91.6028,51.9364,24],[-72,72,24],[-72,66.1387,48],[-72,66.1387,48],[-72,72,48],[-72,72,51.2791],[-80.2914,72,52.5109],[-72,85.3321,24],[-80.1235,82.1041,24],[-89.6834,73.8666,24],[-72,96,36.8528],[-87.254,96,44.1557],[-91.6899,96,48],[-72,96,48],[-72,77.2326,54.2065],[-72,81.7207,55.8299],[-72,87.4502,58.8087],[-79.5788,96,63.2642],[-72,96,67.0639],[-72,105.252,48],[-88.614,98.6504,48],[-94.4385,112.764,72],[-72,97.9182,68.9159],[-87.719,109.275,72],[-72,110.688,54.5486],[-95.1765,115.963,72],[-95.1765,115.963,72],[-53.4261,-72,24],[-53.1359,-72,19.882],[-55.1176,-72,48],[-55.8606,-72,58.5411],[-48,-69.8926,24],[-48,-70.0252,19.1556],[-68.5108,-55.6723,24],[-48,-62.8589,19.7817],[-51.9841,-48.3324,24],[-48,-53.5369,22.1947],[-52.1872,-48,24],[-48,-48,14.5961],[-48,-69.8926,24],[-48,-48,24],[-48,-69.2356,48],[-52.2385,-48,24.1153],[-48,-48,48],[-48,-68.3778,63.1656],[-48,-67.5893,63.7681],[-58.3556,-48,71.4429],[-48,-68.8233,63.0607],[-56.7632,-48,72],[-48,-53.3163,72],[-48,-48,72],[-48,-48,75.0662],[-56.1484,-24,0],[-48,-24,-10.1115],[-48,-34.6899,0],[-48,-24,0],[-48,-43.2961,8.14058],[-56.1883,-24,0.049491],[-66.8524,-24,24],[-48,-24,24],[-70.6104,-24,32.4399],[-48,-24,48],[-59.1073,-46.5779,72],[-48,-24,72],[-67.7668,-30.197,78.4178],[-48,-29.302,85.8503],[-66.7206,-24,78.1921],[-48,-24,85.3165],[-52.5592,0,-24],[-48,0,-28.3655],[-48,-6.14545,-24],[-48,0,-24],[-63.6937,0,-13.3385],[-48,-18.8826,-14.9521],[-56.2384,-23.882,0],[-66.3727,0,-10.014],[-70.8316,0,0],[-48,0,0],[-48,0,24],[-48,0,48],[-69.1549,0,72],[-48,0,72],[-48,-3.48636,82.3449],[-51.7359,0,80.8291],[-56.1688,0,79.7916],[-48,-14.3653,84.3465],[-48,0,81.709],[-62.6689,0,77.3179],[-54.8995,24,-24],[-48,24,-30.4683],[-48,6.07826,-32.6832],[-57.2328,6.29981,-24],[-48,24,-24],[-69.4985,24,-10.0427],[-69.1676,6.5862,-12.7757],[-61.1724,24,-18.1191],[-48,24,0],[-48,24,24],[-65.6813,24,48],[-48,24,48],[-48,13.2617,72],[-48,24,54.048],[-55.1404,24,52.7271],[-59.9372,11.9408,72],[-68.4355,3.37312,72],[-67.6996,9.98131,72],[-68.4355,3.37312,72],[-61.1809,8.8142,76.9968],[-48,8.36691,80.183],[-51.6825,48,-24],[-50.1532,48,-25.4835],[-52.3729,43.1654,-24],[-48,48,-27.5021],[-48,48,-24],[-69.9546,48,-6.27598],[-48,48,0],[-48,48,24],[-70.4821,48,37.6268],[-52.4428,48,48],[-57.3493,48,47.0365],[-52.6089,30.3641,42.5561],[-48,33.9187,44.5518],[-48,45.1567,48],[-48,27.6177,48],[-48,27.692,47.8759],[-53.9638,26.9578,48],[-48,48,48],[-48,48,48.8724],[-48,60.0894,-24],[-48,54.5679,-26.6624],[-50.6063,55.537,-24],[-48,52.6897,-26.9225],[-65.2383,68.0988,0],[-70.2365,62.8362,-3.9475],[-71.633,65.5577,0],[-60.5693,72,0],[-57.0731,72,-10.6155],[-48,72,-18.257],[-48,72,0],[-61.5331,72,2.92635],[-48,72,24],[-67.9774,67.2068,48],[-58.3687,51.7925,48],[-48,72,48],[-67.3524,72,50.5887],[-63.8003,72,53.1338],[-48,72,56.2364],[-48,82.5023,0],[-48,78.3163,-15.2114],[-48,94.8689,24],[-48,86.2489,13.6145],[-48,94.9837,48],[-48,96,46.8565],[-49.1332,96,48],[-48,96,25.3628],[-66.192,80.898,55.3943],[-48,72.4747,56.3821],[-48,80.579,64.2071],[-69.345,96,68.395],[-48,105.225,36.4772],[-63.303,108.708,48],[-37.8542,-48,0],[-36.4276,-48,-1.77032],[-36.5925,-49.6552,0],[-24,-48,-1.77032],[-24,-49.6552,0],[-24,-48,0],[-26.9644,-66.8147,24],[-34.4872,-66.8147,24],[-38.2486,-66.2756,17.7762],[-24,-66.8147,24],[-24,-66.2756,17.7762],[-37.9885,-66.8147,24],[-38.2486,-65.8205,24],[-39.5064,-66.5937,24],[-46.0039,-48,10.113],[-24,-60.0878,11.1581],[-24,-48,24],[-24,-66.9564,25.635],[-24,-68.3179,41.3526],[-37.6784,-66.2457,48],[-41.6728,-66.1706,48],[-38.2486,-64.7302,38.9099],[-36.9857,-68.8938,48],[-24,-68.8938,48],[-44.3565,-67.8205,48],[-24,-48,48],[-43.2728,-67.7881,72],[-47.4625,-68.6061,63.3697],[-41.6786,-70.1434,72],[-36.1728,-70.2469,72],[-30.8838,-70.9728,72],[-24,-69.8278,58.7822],[-24,-70.9728,72],[-35.9829,-70.9728,72],[-43.7944,-66.8072,72],[-43.6523,-65.0899,72],[-44.8516,-55.2264,72],[-24,-48,72],[-29.3572,-68.8589,96],[-31.6217,-65.5132,96],[-35.6042,-71.758,81.0639],[-29.2165,-70.8259,96],[-24,-71.758,81.0639],[-24,-70.8259,96],[-33.5938,-61.8046,96],[-33.0565,-55.3116,96],[-33.9455,-48,96],[-43.4414,-48,76.6612],[-24,-48,96],[-24,-66.3727,108.809],[-24,-64.025,111.7],[-24,-70.0647,108.198],[-24,-57.0996,118.572],[-24,-48,116.726],[-25.1337,-48,113.946],[-34.7541,-24,-24],[-34.2508,-24,-24.4819],[-34.2993,-24.6131,-24],[-24,-24,-24.4819],[-24,-24.6131,-24],[-24,-24,-24],[-43.7468,-24,-15.3894],[-35.0758,-34.4329,-16.2809],[-24,-34.4329,-16.2809],[-24,-24,0],[-24,-24,24],[-24,-24,48],[-24,-24,72],[-42.5213,-24,87.4015],[-39.7195,-28.9271,88.9638],[-39.9976,-24,87.9921],[-36.1383,-29.9652,96],[-26.8765,-24,96],[-30.7302,-24,90.7785],[-24,-24,96],[-24,-46.9538,116.514],[-24,-33.4838,119.849],[-24,-24,99.8975],[-24,-46.9538,116.514],[-32.3531,0,-43.3477],[-24,0,-43.3477],[-24,0,-24],[-24,0,0],[-24,0,24],[-24,0,48],[-24,0,72],[-24,-14.444,91.0796],[-24,-2.54379,86.7302],[-40.775,-10.2288,85.2764],[-24.2042,0,87.3138],[-24,0,87.3101],[-24,-22.1473,96],[-24,-20.3111,92.1371],[-30.6087,24,-48],[-30.5648,24,-48.0487],[-30.8525,20.0646,-48],[-24,24,-48.0487],[-24,20.0646,-48],[-24,24,-48],[-37.6891,24,-40.1348],[-31.903,5.692,-47.822],[-24,0.957561,-44.1004],[-24,5.692,-47.822],[-24,24,-24],[-37.6891,24,-40.1348],[-24,24,0],[-24,24,24],[-24,24,48],[-27.0998,15.5745,72],[-41.6321,24,55.2261],[-24,20.4795,72],[-24,24,70.1206],[-24,13.7773,75.5779],[-24,7.55249,85.9844],[-24,0.126053,87.3389],[-29.1221,48,-48],[-28.8106,48,-48.346],[-27.1933,48,-48.346],[-24,45.7139,-48.3177],[-24,48,-48.346],[-24,48,-48],[-45.2742,48,-30.0575],[-24,48,-24],[-24,48,0],[-24,48,24],[-40.0368,40.0604,48],[-47.8925,27.6296,48],[-24,48,48],[-29.7423,48,52.4577],[-24,48,57.3084],[-27.8467,49.7558,-48],[-24,49.7558,-48],[-24,49.1003,-48.3596],[-28.7302,49.1003,-48.3596],[-28.7302,49.7558,-48],[-29.0484,49.1895,-48],[-41.1811,72,-24],[-38.4981,72,-26.2598],[-47.2634,54.294,-27.4148],[-24,52.6097,-46.4344],[-24,72,-35.797],[-28.7302,72,-35.797],[-24,72,-24],[-38.4981,72,-26.2598],[-24,72,0],[-24,72,24],[-24,72,48],[-24,52.4288,54.9442],[-24,61.3621,57.6852],[-46.9748,72,56.4377],[-24,63.2399,59.4982],[-36.1253,72,61.8773],[-24,72,49.642],[-27.5329,91.9268,-24],[-28.7302,91.7311,-24.9726],[-28.8163,91.9268,-24],[-24,91.9268,-24],[-24,91.7311,-24.9726],[-30.6502,90.3945,-24],[-24,96,-3.76025],[-24,92.5044,-21.1302],[-30.6074,96,-3.76025],[-31.8458,96,0],[-24,96,0],[-45.1534,96,24],[-38.7387,96,20.929],[-24,96,24],[-24,96,29.6914],[-30.9891,96,29.6914],[-24,77.3373,43.6368],[-24,73.4594,48],[-24,96.7567,0],[-30.9401,96.7567,0],[-34.8503,100.094,24],[-24,101.587,24],[-33.064,101.587,24],[-24,101.852,25.3186],[-33.1807,101.852,25.3186],[0,-48,-1.77032],[0,-49.6552,0],[0,-48,0],[0,-66.8147,24],[0,-66.2756,17.7762],[0,-49.6653,0.010813],[0,-48,24],[0,-68.1031,38.8721],[0,-68.8938,48],[-19.9826,-68.8938,48],[0,-48,48],[0,-69.0168,49.4201],[-19.1243,-69.0168,49.4201],[-18.1808,-70.9728,72],[0,-70.4365,65.8085],[0,-70.9728,72],[0,-48,72],[-17.8021,-71.758,81.0639],[-8.54682,-70.8259,96],[-16.6288,-70.8259,96],[0,-70.8259,96],[0,-71.758,81.0639],[0,-48,96],[-19.3194,-64.2005,120],[-19.9706,-63.2383,120],[-18.9526,-69.3281,120],[0,-69.9651,109.793],[0,-69.3281,120],[-14.7434,-69.3281,120],[-23.3932,-56.802,120],[-22.6649,-48,120],[0,-48,120],[-11.3326,-50.8701,144],[0,-58.855,138.614],[0,-50.8701,144],[-12.9445,-50.8701,144],[-13.7962,-68.5757,132.057],[0,-68.5757,132.057],[-13.2044,-50.226,144],[-14.8446,-52.6096,140.113],[-15.2674,-62.32,129.688],[-14.279,-48,140.565],[-13.0117,-48,144],[0,-48,144],[0,-49.7716,144.741],[-12.8917,-49.7716,144.741],[-12.8918,-48,144.325],[-12.6775,-48,145.633],[-9.2584,-48,145.633],[0,-48,145.633],[0,-24,-24.4819],[0,-24.6131,-24],[0,-24,-24],[0,-34.4329,-16.2809],[0,-24,0],[0,-24,24],[0,-24,48],[0,-24,72],[0,-24,96],[-11.8644,-24,120],[-13.6401,-24,114.086],[-12.7674,-26.2283,120],[-22.4608,-45.5333,120],[-23.9231,-33.5061,120],[-14.592,-27.4963,120],[-15.2373,-24,111.77],[0,-24,120],[-10.1763,-24,125.622],[-9.5692,-34.3939,141.672],[-12.8928,-36.7035,141.672],[-4.68798,-34.7015,144],[0,-34.7015,144],[0,-34.3939,141.672],[-9.5273,-34.7015,144],[-12.892,-46.6164,144],[-12.5233,-37.0111,144],[-11.9959,-36.417,144],[-1.69953,-24,125.622],[0,-24,125.622],[0,-34.997,146.236],[-9.4063,-35.5898,150.722],[0,-35.5898,150.722],[-11.4565,-37.8994,150.722],[0,-36.6311,150.722],[0,-37.8994,150.722],[0,-43.4856,147.908],[-22.4016,0,-43.3477],[0,-13.4201,-32.7985],[0,0,-43.3477],[0,0,-24],[0,0,0],[0,0,24],[0,0,48],[0,0,72],[-16.6605,-16.2883,93.6187],[-23.9269,-2.5103,86.7365],[-14.3898,-12.4491,96],[-16.3091,-17.1855,96],[-20.9872,0,87.2566],[-13.8378,0,90.2312],[-0.577762,0,94.12],[0,-0.344472,94.3786],[0,0,94.12],[0,-2.50434,96],[-11.8744,0,94.12],[-11.6222,-2.50434,96],[-16.4738,-17.3,96],[-10.389,-20.3589,120],[-11.1691,-7.0037,99.3776],[0,-7.0037,99.3776],[0,-20.3589,120],[0,-21.7553,122.156],[0,24,-48.0487],[0,20.0646,-48],[0,24,-48],[0,5.692,-47.822],[0,24,-24],[0,24,0],[0,24,24],[0,24,48],[-21.7752,24,72],[0,24,72],[-12.596,7.1655,88.741],[-13.9754,24,78.5888],[0,7.1655,88.741],[-2.8757,24,78.5888],[0,24,78.5888],[0,28.5319,-48.1049],[0,48,-48.346],[0,48,-48],[0,48,-24],[0,48,0],[0,48,24],[0,48,48],[-14.8707,34.9256,72],[-15.942,48,64.1154],[0,34.9256,72],[0,48,64.1154],[0,28.9804,75.5853],[0,49.7558,-48],[0,49.1003,-48.3596],[0,70.4157,-36.6661],[0,72,-35.797],[0,72,-24],[0,72,0],[0,72,24],[0,71.4982,48],[0,72,47.6251],[-0.826165,72,47.6251],[-1.39778,71.4982,48],[-22.0012,72,47.6251],[-21.8133,71.4982,48],[-22.3728,72,48],[-16.7623,58.0109,58.0782],[0,58.0109,58.0782],[0,91.9268,-24],[0,91.7311,-24.9726],[-2.61677,96,-3.76025],[0,96,-3.76025],[0,96,0],[0,96,24],[0,72.7252,47.0831],[0,96,29.6914],[0,96.7567,0],[0,96.4278,-1.63461],[0,101.587,24],[0,101.852,25.3186],[0.02328,-49.6552,0],[3.83474,-48,-1.77032],[24,-48,-1.77032],[24,-49.6552,0],[24,-48,0],[24,-66.2756,17.7762],[24,-66.8147,24],[24,-48,24],[24,-68.8938,48],[19.9826,-68.8938,48],[24,-68.3179,41.3526],[16.5495,-68.8938,48],[24,-48,48],[24,-69.8278,58.7822],[24,-70.9728,72],[18.1808,-70.9728,72],[19.1243,-69.0168,49.4201],[7.22507,-70.9728,72],[24,-48,72],[24,-71.758,81.0639],[17.8021,-71.758,81.0639],[16.6288,-70.8259,96],[24,-70.8259,96],[24,-48,96],[24,-66.3727,108.809],[19.3194,-64.2005,120],[18.9526,-69.3281,120],[24,-70.0647,108.198],[24,-64.025,111.7],[19.9706,-63.2383,120],[6.32498,-69.3281,120],[14.7434,-69.3281,120],[24,-57.0996,118.572],[23.3932,-56.802,120],[24,-48,116.726],[22.6649,-48,120],[13.7962,-68.5757,132.057],[15.2674,-62.32,129.688],[14.8446,-52.6096,140.113],[13.2044,-50.226,144],[12.9445,-50.8701,144],[14.279,-48,140.565],[13.0117,-48,144],[12.8917,-49.7716,144.741],[12.8918,-48,144.325],[12.6775,-48,145.633],[17.6606,-24,-24.4819],[18.684,-24.6131,-24],[24,-24,-24.4819],[24,-24.6131,-24],[24,-24,-24],[24,-27.7977,-21.4966],[24,-34.4329,-16.2809],[24,-39.2428,-11.1365],[24,-24,0],[24,-24,24],[24,-24,48],[24,-24,72],[24,-24,96],[11.8644,-24,120],[12.7674,-26.2283,120],[13.6401,-24,114.086],[24,-46.9538,116.514],[22.4608,-45.5333,120],[24,-33.4838,119.849],[23.9231,-33.5061,120],[14.592,-27.4963,120],[15.2373,-24,111.77],[24,-24,99.8975],[24,-46.9538,116.514],[10.1763,-24,125.622],[9.5692,-34.3939,141.672],[12.8928,-36.7035,141.672],[9.5273,-34.7015,144],[12.892,-46.6164,144],[12.5233,-37.0111,144],[11.9959,-36.417,144],[9.4063,-35.5898,150.722],[11.4565,-37.8994,150.722],[24,0,-43.3477],[24,0,-24],[24,0,0],[24,0,24],[24,0,48],[24,0,72],[16.6605,-16.2883,93.6187],[24,-14.444,91.0796],[24,-2.54379,86.7302],[23.9269,-2.5103,86.7365],[14.3898,-12.4491,96],[16.3091,-17.1855,96],[13.8378,0,90.2312],[11.8744,0,94.12],[11.6222,-2.50434,96],[24,0,87.3101],[20.9872,0,87.2566],[16.4738,-17.3,96],[24,-22.1473,96],[24,-20.3111,92.1371],[3.62261,-2.50434,96],[11.1691,-7.0037,99.3776],[10.389,-20.3589,120],[1.05728,-20.3589,120],[6.33018,24,-48.0487],[11.8272,20.0646,-48],[24,24,-48.0487],[24,20.0646,-48],[24,24,-48],[24,5.692,-47.822],[24,11.3499,-47.8921],[24,24,-24],[24,24,0],[24,24,24],[24,24,48],[24,20.4795,72],[24,24,70.1206],[21.7752,24,72],[12.596,7.1655,88.741],[24,13.7773,75.5779],[13.9754,24,78.5888],[24,7.55249,85.9844],[24,0.126053,87.3389],[24,48,-48.346],[24,48,-48],[24,48,-24],[24,48,0],[24,48,24],[24,48,48],[24,48,57.3084],[15.942,48,64.1154],[14.8707,34.9256,72],[3.43278,34.9256,72],[10.982,48,64.1154],[24,49.7558,-48],[24,49.1003,-48.3596],[2.13542,72,-35.797],[24,72,-35.797],[24,72,-24],[24,72,0],[24,72,24],[22.3728,72,48],[22.0012,72,47.6251],[21.8133,71.4982,48],[24,72,48],[24,63.2399,59.4982],[16.7623,58.0109,58.0782],[24,61.3621,57.6852],[24,52.4288,54.9442],[24,72,49.642],[24,91.9268,-24],[24,91.7311,-24.9726],[24,88.2217,-26.8978],[24,96,-3.76025],[24,96,0],[24,96,24],[24,73.4594,48],[24,77.3373,43.6368],[24,93.793,31.3406],[24,96,29.6914],[2.01228,96.7567,0],[24,96.7567,0],[24,101.587,24],[24,100.351,17.861],[24,101.852,25.3186],[37.8542,-48,0],[36.5925,-49.6552,0],[36.4276,-48,-1.77032],[37.9885,-66.8147,24],[34.4872,-66.8147,24],[38.2486,-66.2756,17.7762],[38.2486,-65.8205,24],[39.5064,-66.5937,24],[48,-70.0252,19.1556],[48,-69.8926,24],[48,-62.8589,19.7817],[48,-53.5369,22.1947],[46.0039,-48,10.113],[48,-48,14.5961],[48,-69.8926,24],[48,-48,24],[37.6784,-66.2457,48],[38.2486,-64.7302,38.9099],[41.6728,-66.1706,48],[36.9857,-68.8938,48],[44.3565,-67.8205,48],[48,-69.2356,48],[48,-48,48],[41.6786,-70.1434,72],[47.4625,-68.6061,63.3697],[43.2728,-67.7881,72],[36.1728,-70.2469,72],[30.8838,-70.9728,72],[35.9829,-70.9728,72],[43.7944,-66.8072,72],[43.6523,-65.0899,72],[44.8516,-55.2264,72],[48,-68.3778,63.1656],[48,-68.8233,63.0607],[48,-67.5893,63.7681],[48,-53.3163,72],[48,-48,72],[29.3572,-68.8589,96],[29.2165,-70.8259,96],[35.6042,-71.758,81.0639],[31.6217,-65.5132,96],[33.5938,-61.8046,96],[33.0565,-55.3116,96],[33.9455,-48,96],[43.4414,-48,76.6612],[48,-48,75.0662],[25.1337,-48,113.946],[34.7541,-24,-24],[34.2993,-24.6131,-24],[34.2508,-24,-24.4819],[43.7468,-24,-15.3894],[35.0758,-34.4329,-16.2809],[48,-24,-10.1115],[48,-34.6899,0],[48,-24,0],[48,-43.2961,8.14058],[48,-24,24],[48,-24,48],[48,-24,72],[42.5213,-24,87.4015],[39.9976,-24,87.9921],[39.7195,-28.9271,88.9638],[36.1383,-29.9652,96],[48,-29.302,85.8503],[48,-24,85.3165],[26.8765,-24,96],[30.7302,-24,90.7785],[48,0,-28.3655],[48,-6.14545,-24],[32.3531,0,-43.3477],[48,0,-24],[48,-18.8826,-14.9521],[48,0,0],[48,0,24],[48,0,48],[48,0,72],[40.775,-10.2288,85.2764],[48,-14.3653,84.3465],[48,-3.48636,82.3449],[24.2042,0,87.3138],[48,0,81.709],[30.6087,24,-48],[30.8525,20.0646,-48],[30.5648,24,-48.0487],[37.6891,24,-40.1348],[48,24,-30.4683],[48,6.07826,-32.6832],[31.903,5.692,-47.822],[48,24,-24],[37.6891,24,-40.1348],[48,24,0],[48,24,24],[48,24,48],[27.0998,15.5745,72],[41.6321,24,55.2261],[48,13.2617,72],[48,24,54.048],[48,8.36691,80.183],[29.1221,48,-48],[28.8106,48,-48.346],[45.2742,48,-30.0575],[48,48,-27.5021],[48,48,-24],[48,48,0],[48,48,24],[48,45.1567,48],[40.0368,40.0604,48],[48,33.9187,44.5518],[47.8925,27.6296,48],[48,27.692,47.8759],[48,27.6177,48],[48,48,48],[48,48,48.8724],[29.7423,48,52.4577],[28.7302,49.7558,-48],[29.0484,49.1895,-48],[28.7302,49.1003,-48.3596],[41.1811,72,-24],[48,60.0894,-24],[48,54.5679,-26.6624],[47.2634,54.294,-27.4148],[38.4981,72,-26.2598],[48,52.6897,-26.9225],[28.7302,72,-35.797],[38.4981,72,-26.2598],[48,72,-18.257],[48,72,0],[48,72,24],[48,72,48],[36.1253,72,61.8773],[46.9748,72,56.4377],[48,72,56.2364],[30.6502,90.3945,-24],[28.7302,91.7311,-24.9726],[28.8163,91.9268,-24],[48,78.3163,-15.2114],[48,82.5023,0],[30.6074,96,-3.76025],[31.8458,96,0],[45.1534,96,24],[48,94.8689,24],[48,86.2489,13.6145],[38.7387,96,20.929],[30.9891,96,29.6914],[48,94.9837,48],[48,96,46.8565],[26.5142,96,29.6914],[48,96,25.3628],[48,80.579,64.2071],[48,72.4747,56.3821],[30.9401,96.7567,0],[34.8503,100.094,24],[33.064,101.587,24],[31.5574,101.587,24],[48,105.225,36.4772],[33.1807,101.852,25.3186],[53.4261,-72,24],[53.1359,-72,19.882],[72,-79.2536,22.5504],[72,-79.2139,24],[72,-72,23.1842],[72,-72,24],[55.1176,-72,48],[72,-78.5569,48],[72,-72,48],[72,-72,50.798],[55.8606,-72,58.5411],[72,-78.5224,49.2614],[72,-62.6628,24],[68.5108,-55.6723,24],[51.9841,-48.3324,24],[52.1872,-48,24],[72,-54.4498,24.7176],[72,-48,26.3872],[52.2385,-48,24.1153],[72,-48,48],[72,-58.1816,54.0535],[72,-48,61.8332],[58.3556,-48,71.4429],[56.7632,-48,72],[56.1484,-24,0],[56.1883,-24,0.049491],[66.8524,-24,24],[72,-24,32.5997],[70.6104,-24,32.4399],[72,-24,48],[72,-34.6943,72],[59.1073,-46.5779,72],[72,-24,72],[72,-30.7182,75.0381],[67.7668,-30.197,78.4178],[66.7206,-24,78.1921],[72,-24,73.8635],[52.5592,0,-24],[63.6937,0,-13.3385],[66.3727,0,-10.014],[56.2384,-23.882,0],[70.8316,0,0],[72,0,2.6242],[72,-15.5759,24],[72,0,24],[72,-22.1847,33.0696],[72,0,48],[69.1549,0,72],[72,-13.342,72],[72,0,69.6672],[56.1688,0,79.7916],[51.7359,0,80.8291],[62.6689,0,77.3179],[54.8995,24,-24],[57.2328,6.29981,-24],[69.4985,24,-10.0427],[69.1676,6.5862,-12.7757],[61.1724,24,-18.1191],[72,24,-5.52097],[72,7.41659,-7.55404],[72,1.91218,0],[72,24,0],[72,24,24],[72,22.405,48],[72,24,45.1663],[65.6813,24,48],[59.9372,11.9408,72],[55.1404,24,52.7271],[72,10.7513,68.7036],[67.6996,9.98131,72],[68.4355,3.37312,72],[72,0.699737,69.5449],[68.4355,3.37312,72],[61.1809,8.8142,76.9968],[51.6825,48,-24],[52.3729,43.1654,-24],[50.1532,48,-25.4835],[69.9546,48,-6.27598],[72,48,-2.57866],[72,48,0],[72,48,24],[72,48,37.8523],[70.4821,48,37.6268],[72,36.3606,31.3406],[57.3493,48,47.0365],[52.6089,30.3641,42.5561],[72,35.462,30.9393],[52.4428,48,48],[72,24.6267,44.0529],[53.9638,26.9578,48],[50.6063,55.537,-24],[65.2383,68.0988,0],[71.633,65.5577,0],[70.2365,62.8362,-3.9475],[72,65.2415,0],[72,63.8365,-1.41315],[57.0731,72,-10.6155],[60.5693,72,0],[72,60.1691,-1.08677],[72,62.2821,-1.88711],[72,62.3938,-1.77823],[72,61.8481,-1.78354],[72,61.3496,-1.49988],[72,61.3442,-1.64038],[72,61.9366,-1.64082],[72,61.3496,-1.49988],[61.5331,72,2.92635],[72,72,7.9374],[72,66.2729,1.03736],[72,72,24],[72,66.1387,48],[67.9774,67.2068,48],[58.3687,51.7925,48],[72,66.1387,48],[72,72,48],[72,72,51.2791],[67.3524,72,50.5887],[63.8003,72,53.1338],[72,85.3321,24],[49.1332,96,48],[72,96,36.8528],[72,96,48],[72,77.2326,54.2065],[72,81.7207,55.8299],[66.192,80.898,55.3943],[72,87.4502,58.8087],[72,96,67.0639],[69.345,96,68.395],[63.303,108.708,48],[72,105.252,48],[72,97.9182,68.9159],[72,110.688,54.5486],[82.248,-83.1941,24],[76.6606,-72,24],[96,-72,39.2838],[77.8321,-72,48],[74.1939,-79.409,48],[96,-88.2215,35.4622],[96,-88.482,25.9453],[96,-72,27.3853],[96,-48,44.9379],[95.9656,-48,44.9544],[87.9439,-51.408,48],[91.6412,-48,48],[96,-48,29.4823],[90.4079,-48,28.5034],[96,-47.9854,44.9413],[96,-43.9824,48],[96,-46.0406,29.6535],[96,-24,35.3589],[96,-24,48],[96,-33.6734,55.877],[75.8053,-31.1868,72],[74.2728,-24,72],[96,-24,54.1857],[81.5177,0,24],[96,0,41.5714],[88.9823,0,40.7646],[96,0,48],[96,0,51.5664],[72.933,0,68.9023],[96,-17.3006,53.0144],[75.0543,24,0],[76.0976,8.6179,0],[88.3315,24,24],[89.1159,12.4346,24],[74.1182,24,44.2164],[96,17.5257,45.9055],[96,19.4792,43.5412],[89.2561,24,39.9642],[96,24,42.9923],[96,16.3467,48],[95.9152,24,37.7083],[96,23.8717,37.8459],[96,14.4528,36.6911],[96,9.16753,43.9445],[96,24,37.7854],[96,15.0482,50.3069],[73.4266,48,0],[80.0463,48,11.9658],[87.4647,36.7804,24],[91.7119,48,24],[90.3725,45.8621,24],[87.8363,48,20.4799],[91.5988,44.7631,24],[87.7728,48,18.9946],[96,48,41.4178],[72.1133,35.4918,30.8714],[96,45.9969,40.2972],[96,33.0554,41.8927],[96,40.5511,40.9646],[96,48,27.8948],[96,41.1182,31.8106],[96,41.0395,29.7579],[72.9833,64.3942,0],[72.6699,59.1559,0],[73.6152,61.7746,0],[73.4456,62.0312,0],[73.4535,61.0338,0],[73.0807,60.4387,0],[73.2539,60.2834,0],[73.2544,61.2966,0],[72.6699,59.1559,0],[74.9388,72,9.34433],[86.3925,72,19.2706],[94.1569,55.32,24],[92.9562,57.137,24],[93.0121,50.0754,24],[90.0486,72,24],[91.6028,51.9364,24],[96,59.7655,48],[96,54.7409,26.1534],[96,56.3735,27.7442],[96,48.4013,27.6664],[96,72,31.6987],[96,49.6932,29.7516],[96,72,48],[80.2914,72,52.5109],[96,62.0865,49.2985],[96,72,52.8843],[80.1235,82.1041,24],[89.6834,73.8666,24],[87.254,96,44.1557],[91.6899,96,48],[96,92.2861,48],[96,77.4494,33.0777],[96,85.1202,57.6299],[79.5788,96,63.2642],[96,96,63.2865],[96,96,51.7353],[88.614,98.6504,48],[94.4385,112.764,72],[87.719,109.275,72],[96,112.76,72],[95.1765,115.963,72],[96,115.636,72],[96,113.044,68.878],[96,112.76,72],[95.1765,115.963,72],[96,114.525,72.918],[96,115.257,73.6248],[96,116.15,72.6201],[109.284,-93.5899,27.8243],[114.171,-72,30.5661],[119.603,-48,33.614],[120,-37.7892,35.8291],[120,-46.2467,33.8367],[120,-36.6286,36.716],[105.866,-34.8883,48],[104.932,-24,46.862],[120,-35.3009,36.4838],[120,-31.5318,36.1684],[117.023,-24,37.7757],[103.544,-24,48],[120,-37.6315,34.5894],[100.745,0,48],[103.28,-22.7608,48],[107.535,0,42.8975],[101.217,15.9822,46.3082],[107.071,24,48],[104.062,24,46.6121],[106.895,23.3557,48],[99.0095,15.587,48],[107.229,24,48],[107.391,24,48.1478],[100.555,48,42.0944],[106.881,31.9455,46.9133],[110.131,35.2227,48],[111.558,40.4547,48],[108.663,43.2332,46.3154],[108.784,30.2823,48],[113.372,47.108,48],[113.615,48,48],[109.864,48,46.2699],[96.7162,48,28.5453],[112.571,39.117,48],[109.944,29.2427,48],[99.3192,48,34.0931],[114.045,48,48],[113.485,38.6049,49.1215],[110.843,28.4821,49.1762],[114.456,48,48.3878],[102.349,58.0794,48],[111.025,52.6046,46.2259],[111.442,57.482,48],[114.099,49.7733,48],[114.699,48.8655,48],[108.602,72,48],[112.684,72,53.2808],[115.284,48.6815,48.6841],[106.383,83.339,48],[114.025,87.6733,58.9818],[109.35,96,63.3046],[109.35,96,63.3046],[99.9447,112.749,72],[97.1045,115.197,72],[97.8045,116.561,73.9788],[122.118,-36.8894,35.025]],"centers":[[-132,-36,36],[-108,-84,36],[-108,-60,36],[-108,-36,36],[-108,-36,60],[-108,-12,36],[-108,-12,60],[-108,12,36],[-108,12,60],[-108,36,36],[-108,36,60],[-108,60,36],[-108,60,60],[-108,84,36],[-108,84,60],[-108,108,60],[-108,108,84],[-84,-84,12],[-84,-84,36],[-84,-84,60],[-84,-60,12],[-84,-60,36],[-84,-60,60],[-84,-36,36],[-84,-36,60],[-84,-36,84],[-84,-12,12],[-84,-12,36],[-84,-12,60],[-84,-12,84],[-84,12,-12],[-84,12,12],[-84,12,36],[-84,12,60],[-84,36,-12],[-84,36,12],[-84,36,36],[-84,60,-12],[-84,60,12],[-84,60,36],[-84,60,60],[-84,84,12],[-84,84,36],[-84,84,60],[-84,108,36],[-84,108,60],[-84,108,84],[-60,-84,12],[-60,-84,36],[-60,-84,60],[-60,-60,12],[-60,-60,36],[-60,-60,60],[-60,-60,84],[-60,-36,-12],[-60,-36,12],[-60,-36,36],[-60,-36,60],[-60,-36,84],[-60,-12,-36],[-60,-12,-12],[-60,-12,12],[-60,-12,36],[-60,-12,60],[-60,-12,84],[-60,12,-36],[-60,12,-12],[-60,12,12],[-60,12,36],[-60,12,60],[-60,12,84],[-60,36,-36],[-60,36,-12],[-60,36,12],[-60,36,36],[-60,36,60],[-60,60,-36],[-60,60,-12],[-60,60,12],[-60,60,36],[-60,60,60],[-60,84,-12],[-60,84,12],[-60,84,36],[-60,84,60],[-60,108,36],[-60,108,60],[-36,-60,-12],[-36,-60,12],[-36,-60,36],[-36,-60,60],[-36,-60,84],[-36,-60,108],[-36,-36,-36],[-36,-36,-12],[-36,-36,12],[-36,-36,36],[-36,-36,60],[-36,-36,84],[-36,-36,108],[-36,-12,-36],[-36,-12,-12],[-36,-12,12],[-36,-12,36],[-36,-12,60],[-36,-12,84],[-36,-12,108],[-36,12,-60],[-36,12,-36],[-36,12,-12],[-36,12,12],[-36,12,36],[-36,12,60],[-36,12,84],[-36,36,-60],[-36,36,-36],[-36,36,-12],[-36,36,12],[-36,36,36],[-36,36,60],[-36,60,-60],[-36,60,-36],[-36,60,-12],[-36,60,12],[-36,60,36],[-36,60,60],[-36,84,-36],[-36,84,-12],[-36,84,12],[-36,84,36],[-36,84,60],[-36,108,-12],[-36,108,12],[-36,108,36],[-12,-60,-12],[-12,-60,12],[-12,-60,36],[-12,-60,60],[-12,-60,84],[-12,-60,108],[-12,-60,132],[-12,-60,156],[-12,-36,-36],[-12,-36,-12],[-12,-36,12],[-12,-36,36],[-12,-36,60],[-12,-36,84],[-12,-36,108],[-12,-36,132],[-12,-36,156],[-12,-12,-36],[-12,-12,-12],[-12,-12,12],[-12,-12,36],[-12,-12,60],[-12,-12,84],[-12,-12,108],[-12,-12,132],[-12,12,-60],[-12,12,-36],[-12,12,-12],[-12,12,12],[-12,12,36],[-12,12,60],[-12,12,84],[-12,36,-60],[-12,36,-36],[-12,36,-12],[-12,36,12],[-12,36,36],[-12,36,60],[-12,36,84],[-12,60,-60],[-12,60,-36],[-12,60,-12],[-12,60,12],[-12,60,36],[-12,60,60],[-12,84,-36],[-12,84,-12],[-12,84,12],[-12,84,36],[-12,84,60],[-12,108,-12],[-12,108,12],[-12,108,36],[12,-60,-12],[12,-60,12],[12,-60,36],[12,-60,60],[12,-60,84],[12,-60,108],[12,-60,132],[12,-60,156],[12,-36,-36],[12,-36,-12],[12,-36,12],[12,-36,36],[12,-36,60],[12,-36,84],[12,-36,108],[12,-36,132],[12,-36,156],[12,-12,-36],[12,-12,-12],[12,-12,12],[12,-12,36],[12,-12,60],[12,-12,84],[12,-12,108],[12,-12,132],[12,12,-60],[12,12,-36],[12,12,-12],[12,12,12],[12,12,36],[12,12,60],[12,12,84],[12,36,-60],[12,36,-36],[12,36,-12],[12,36,12],[12,36,36],[12,36,60],[12,36,84],[12,60,-60],[12,60,-36],[12,60,-12],[12,60,12],[12,60,36],[12,60,60],[12,84,-36],[12,84,-12],[12,84,12],[12,84,36],[12,84,60],[12,108,-12],[12,108,12],[12,108,36],[36,-60,-12],[36,-60,12],[36,-60,36],[36,-60,60],[36,-60,84],[36,-60,108],[36,-36,-36],[36,-36,-12],[36,-36,12],[36,-36,36],[36,-36,60],[36,-36,84],[36,-36,108],[36,-12,-36],[36,-12,-12],[36,-12,12],[36,-12,36],[36,-12,60],[36,-12,84],[36,-12,108],[36,12,-60],[36,12,-36],[36,12,-12],[36,12,12],[36,12,36],[36,12,60],[36,12,84],[36,36,-60],[36,36,-36],[36,36,-12],[36,36,12],[36,36,36],[36,36,60],[36,60,-60],[36,60,-36],[36,60,-12],[36,60,12],[36,60,36],[36,60,60],[36,84,-36],[36,84,-12],[36,84,12],[36,84,36],[36,84,60],[36,108,-12],[36,108,12],[36,108,36],[60,-84,12],[60,-84,36],[60,-84,60],[60,-60,12],[60,-60,36],[60,-60,60],[60,-60,84],[60,-36,-12],[60,-36,12],[60,-36,36],[60,-36,60],[60,-36,84],[60,-12,-36],[60,-12,-12],[60,-12,12],[60,-12,36],[60,-12,60],[60,-12,84],[60,12,-36],[60,12,-12],[60,12,12],[60,12,36],[60,12,60],[60,12,84],[60,36,-36],[60,36,-12],[60,36,12],[60,36,36],[60,36,60],[60,60,-36],[60,60,-12],[60,60,12],[60,60,36],[60,60,60],[60,84,-12],[60,84,12],[60,84,36],[60,84,60],[60,108,36],[60,108,60],[84,-84,12],[84,-84,36],[84,-84,60],[84,-60,12],[84,-60,36],[84,-60,60],[84,-36,36],[84,-36,60],[84,-36,84],[84,-12,12],[84,-12,36],[84,-12,60],[84,-12,84],[84,12,-12],[84,12,12],[84,12,36],[84,12,60],[84,36,-12],[84,36,12],[84,36,36],[84,60,-12],[84,60,12],[84,60,36],[84,60,60],[84,84,12],[84,84,36],[84,84,60],[84,108,36],[84,108,60],[84,108,84],[108,-84,36],[108,-60,36],[108,-36,36],[108,-36,60],[108,-12,36],[108,-12,60],[108,12,36],[108,12,60],[108,36,36],[108,36,60],[108,60,36],[108,60,60],[108,84,36],[108,84,60],[108,108,60],[108,108,84],[132,-36,36]],"boxes":[[[5,[[0,1,2],[0,2,3]]],[8,[[2,4,5],[1,4,2]]],[9,[[2,6,3],[2,5,6]]],[10,[[0,3,6],[0,6,1],[1,6,4],[4,6,5]]]],[[5,[[7,8,9,10]]],[9,[[9,11,10],[8,12,11,9]]],[10,[[10,11,12],[7,10,12],[7,12,8]]]],[[5,[[7,13,14,8]]],[9,[[8,14,15,12]]],[10,[[7,12,15],[7,15,13],[7,8,12],[13,15,14]]]],[[5,[[0,16,17,18,1],[0,3,14,13,16]]],[8,[[4,19,20,5],[1,18,21,19,4]]],[9,[[3,6,22,15,14],[5,20,23,22,6]]],[10,[[0,1,6],[1,4,6],[0,6,3],[4,5,6],[16,22,17],[13,22,16],[17,22,23],[17,23,24],[13,15,22],[13,14,15],[19,23,20],[19,21,24],[19,24,23],[17,24,18],[18,24,21]]]],[[5,[[17,25,18]]],[8,[[18,25,26,21]]],[10,[[17,24,25],[24,26,25],[21,26,24],[17,18,24],[18,21,24]]]],[[8,[[19,27,28,29,20],[19,21,27]]],[9,[[20,29,30,23]]],[10,[[23,30,24],[24,30,31],[19,20,23],[19,24,21],[19,23,24],[28,30,29],[28,31,30],[21,24,27],[27,31,28],[24,31,27]]]],[[8,[[27,32,33,28],[21,26,32,27]]],[10,[[24,32,26],[24,31,32],[31,33,32],[21,24,26],[28,33,31],[27,28,31],[21,27,24],[24,27,31]]]],[[0,[[34,35,36],[35,39,37,38],[34,40,39,35]]],[8,[[28,41,35,29],[35,41,42,36]]],[9,[[35,44,43],[29,35,45,30],[35,43,45],[35,38,46,47,44]]],[10,[[36,45,43],[34,36,43],[36,42,45],[34,43,44],[34,44,40],[40,44,47],[31,45,42],[30,45,31],[28,29,30],[28,30,31],[39,40,47],[39,47,46],[37,39,46],[37,46,38],[28,31,41],[31,42,41]]]],[[0,[[37,48,38]]],[8,[[28,33,49,41],[41,49,42]]],[9,[[38,48,46]]],[10,[[31,49,33],[31,42,49],[28,31,33],[37,46,48],[37,38,46],[28,41,31],[31,41,42]]]],[[0,[[50,51,52],[53,54,55,56],[37,39,54,57],[39,40,58,54],[54,58,59,55],[55,62,60,61],[51,62,55,59,52]]],[9,[[53,63,64,65,66,54],[54,66,67,68,57],[46,68,67,47],[55,69,64,63,56],[55,61,70,69]]],[10,[[52,59,66],[50,52,65],[52,66,65],[40,47,58],[47,66,58],[58,66,59],[47,67,66],[37,46,39],[39,46,47],[39,47,40],[50,69,51],[50,65,64],[50,64,69],[51,69,62],[62,69,70],[60,62,70],[53,56,63],[37,53,57],[46,57,68],[37,57,46],[60,70,61]]]],[[0,[[53,56,71],[37,57,72,48],[60,73,61]]],[9,[[53,71,63],[57,68,72],[46,48,72,68],[56,63,71],[61,73,70]]],[10,[[37,48,46],[60,70,73],[37,57,53],[53,63,56],[37,46,57],[46,68,57],[60,61,70]]]],[[0,[[50,74,75,76,51],[75,77,76],[60,62,76,78],[51,76,62]]],[9,[[76,81,79,80,78],[64,82,65],[76,77,83,84,81],[64,69,85,82],[69,70,80,79,85]]],[10,[[50,81,74],[50,85,81],[50,65,85],[74,81,84],[74,84,86],[79,81,85],[65,82,85],[50,51,69],[51,62,69],[50,64,65],[50,69,64],[60,70,62],[62,70,69],[83,86,84],[74,86,75],[75,83,77],[75,86,83],[60,78,80],[60,80,70]]]],[[0,[[74,87,75],[75,87,88,89,77],[60,78,90,73]]],[9,[[78,80,90],[77,89,83],[70,73,90,80]]],[10,[[74,86,87],[86,88,87],[60,73,70],[83,88,86],[83,89,88],[75,77,83],[74,75,86],[75,83,86],[60,70,80],[60,80,78]]]],[[9,[[91,92,93],[83,93,92,84]]],[10,[[86,92,91],[84,92,86],[83,84,86],[83,86,93],[86,91,93]]]],[[0,[[88,94,95,89],[94,96,97,95]]],[9,[[91,93,95,97,98],[83,89,95,93]]],[10,[[86,94,88],[86,91,94],[91,98,94],[94,98,96],[83,88,89],[83,86,88],[96,98,99],[86,93,91],[83,93,86]]]],[[0,[[96,100,101,97]]],[9,[[102,103,104],[97,101,104,103,98]]],[10,[[96,103,105],[96,98,103],[102,105,103],[96,99,98],[101,105,104],[102,104,105]]]],[[0,[[100,106,107,101],[106,108,107]]],[9,[[107,108,109],[102,104,107,109],[101,107,104]]],[10,[[102,106,105],[106,109,108],[102,109,106],[101,104,105],[102,105,104]]]],[[9,[[110,111,112],[111,113,114,112]]],[10,[[110,112,114],[110,114,115],[113,115,114],[110,113,111],[110,115,113]]]],[[5,[[7,10,117,116]]],[9,[[10,11,111,110,118,117],[11,12,113,111]]],[10,[[7,12,10],[10,12,11],[110,115,118],[115,119,118],[7,116,113],[113,116,119],[7,113,12],[113,119,115],[110,111,113],[110,113,115],[116,117,119],[117,118,119]]]],[[5,[[116,117,121,120]]],[9,[[117,118,121]]],[10,[[118,119,121],[119,120,121],[116,120,119],[116,119,117],[117,119,118]]]],[[9,[[113,122,114]]],[10,[[114,122,115],[113,114,115],[113,115,122]]]],[[5,[[123,124,125],[7,116,125,124,13]]],[9,[[12,15,126,127,122,113],[126,128,127]]],[10,[[7,13,15],[7,15,12],[127,128,129],[122,127,129],[115,122,119],[119,122,129],[7,113,116],[7,12,113],[113,119,116],[113,115,119],[123,126,124],[123,129,126],[13,124,15],[15,124,126],[126,129,128],[113,122,115],[123,125,129],[116,129,125],[116,119,129]]]],[[5,[[123,125,130,131],[116,120,130,125]]],[10,[[119,130,120],[119,129,130],[129,131,130],[116,119,120],[123,131,129],[123,129,125],[116,125,129],[116,129,119]]]],[[5,[[16,124,123,17],[13,124,16]]],[9,[[15,22,126],[22,23,132,128,126]]],[10,[[17,24,23],[16,17,22],[17,23,22],[13,16,22],[13,22,15],[128,132,129],[129,132,133],[13,15,124],[123,124,126],[15,126,124],[123,126,129],[126,128,129],[23,133,132],[23,24,133],[123,129,133],[17,123,133],[17,133,24]]]],[[5,[[17,123,131,134,135,25]]],[8,[[25,135,136,26]]],[10,[[17,25,24],[24,25,26],[131,133,134],[129,133,131],[133,137,134],[123,129,131],[26,136,133],[133,136,137],[24,26,133],[17,24,133],[17,133,123],[123,133,129],[134,137,135],[135,137,136]]]],[[5,[[134,138,135]]],[8,[[135,138,139,136]]],[10,[[134,137,138],[137,139,138],[136,139,137],[134,135,137],[135,136,137]]]],[[9,[[140,141,142]]],[10,[[141,143,142],[140,143,141],[140,142,143]]]],[[9,[[23,30,144,145,132],[140,142,145,144]]],[10,[[23,24,30],[24,31,30],[132,145,133],[142,146,145],[133,145,146],[142,143,146],[23,132,133],[23,133,24],[30,31,144],[31,146,144],[140,144,146],[140,146,143],[140,143,142],[24,133,31],[31,133,146]]]],[[8,[[32,147,33],[26,136,148,149,147,32]]],[10,[[31,32,33],[24,26,32],[24,32,31],[133,148,137],[133,146,148],[146,149,148],[26,133,136],[24,133,26],[133,137,136],[33,147,146],[146,147,149],[31,33,146],[24,31,133],[31,146,133],[136,137,148]]]],[[8,[[136,139,148]]],[10,[[137,148,139],[136,137,139],[136,148,137]]]],[[9,[[150,151,152,153],[152,154,153]]],[10,[[151,155,152],[152,155,154],[150,155,151],[150,153,155],[153,154,155]]]],[[9,[[150,153,157,156],[140,157,153,154,141]]],[10,[[141,154,155],[141,158,143],[141,155,158],[140,141,143],[150,156,158],[150,158,155],[150,155,153],[153,155,154],[156,157,158],[140,143,157],[143,158,157]]]],[[0,[[34,36,160,159],[34,159,40]]],[8,[[36,42,161,162,160]]],[9,[[43,44,163,156,157],[30,45,144],[43,157,140,144,45],[44,47,163]]],[10,[[34,40,44],[34,44,43],[34,43,36],[36,45,42],[36,43,45],[40,47,44],[31,42,45],[30,31,45],[146,162,161],[143,158,162],[143,162,146],[30,144,31],[31,144,146],[140,146,144],[140,143,146],[158,159,160],[158,160,162],[156,159,158],[156,163,159],[40,159,163],[40,163,47],[156,158,157],[140,157,143],[143,157,158],[31,146,42],[42,146,161]]]],[[8,[[33,147,164,165,49],[147,149,164],[42,49,165,161]]],[10,[[31,49,42],[31,33,49],[146,164,149],[146,165,164],[146,161,165],[33,146,147],[31,146,33],[146,149,147],[42,161,146],[31,42,146]]]],[[9,[[150,166,167,151]]],[10,[[151,167,155],[155,167,168],[150,151,155],[166,168,167],[150,155,166],[155,168,166]]]],[[9,[[150,156,169,170,166],[171,172,173],[172,174,175,173],[169,175,174,170]]],[10,[[155,168,158],[158,168,176],[150,158,156],[150,155,158],[166,170,168],[170,174,172],[170,172,176],[168,170,176],[171,176,172],[150,166,155],[155,166,168],[156,158,169],[169,173,175],[169,176,173],[158,176,169],[171,173,176]]]],[[0,[[50,52,178,179,177],[178,180,179],[159,160,181,180,178],[40,159,178,58],[58,178,59],[52,59,178]]],[8,[[160,162,181]]],[9,[[156,163,169],[65,171,173,66],[66,173,175,67],[47,67,175,169,163]]],[10,[[50,65,52],[52,65,66],[52,66,59],[40,58,47],[58,59,66],[47,58,66],[47,66,67],[176,177,179],[176,179,180],[158,180,181],[158,176,180],[158,181,162],[40,163,159],[156,159,163],[158,160,159],[156,158,159],[158,162,160],[40,47,163],[171,177,176],[50,177,171],[50,171,65],[156,169,158],[169,175,173],[169,173,176],[158,169,176],[171,176,173]]]],[[9,[[182,183,184],[166,185,186,167],[187,188,189,190],[191,192,193,194],[193,195,196,194],[185,196,195,186],[183,190,189,184],[191,197,198,192],[187,198,197,188]]],[10,[[168,186,182],[182,186,199],[182,198,183],[182,199,198],[183,198,190],[167,186,168],[186,195,199],[187,190,198],[192,198,199],[166,167,168],[182,184,189],[168,182,200],[182,194,200],[182,197,194],[182,189,197],[166,168,200],[194,196,200],[188,197,189],[191,194,197]]]],[[9,[[201,202,203],[182,184,204,203,202],[166,170,185],[188,205,206,189],[171,207,191,194,172],[172,194,196,174],[170,174,196,185],[184,189,206,208,204],[191,207,209,197],[188,197,209,205]]],[10,[[176,202,201],[176,201,210],[168,182,202],[168,202,176],[166,168,170],[170,172,174],[168,176,170],[170,176,172],[171,172,176],[201,203,210],[203,204,210],[204,208,210],[168,200,182],[182,200,194],[182,194,197],[182,189,184],[182,197,189],[166,200,168],[194,200,196],[188,189,197],[191,197,194],[205,209,206],[206,210,208],[176,206,209],[176,210,206],[171,209,207],[171,176,209]]]],[[0,[[50,177,211,74]]],[9,[[79,81,206,205],[65,82,207,171],[81,84,208,206],[82,85,209,207],[79,205,209,85]]],[10,[[74,86,84],[50,74,81],[74,84,81],[50,81,85],[50,85,65],[79,85,81],[65,85,82],[177,210,212],[176,210,177],[210,213,212],[50,65,171],[50,171,177],[171,176,177],[84,86,213],[84,213,208],[208,213,210],[176,206,210],[206,208,210],[205,206,209],[176,209,206],[171,207,209],[171,209,176],[74,212,86],[86,212,213]]]],[[0,[[74,211,214,215,87],[87,215,88]]],[10,[[74,87,86],[86,87,88],[212,213,214],[213,215,214],[86,88,215],[86,215,213],[74,86,212],[86,213,212]]]],[[9,[[201,203,217,216],[203,204,218,217],[204,208,218]]],[10,[[201,216,210],[201,210,203],[203,210,204],[204,210,208],[210,216,217],[210,217,218],[208,210,218]]]],[[9,[[216,217,220,219],[91,221,220,217,218,92],[84,92,218,208]]],[10,[[84,86,92],[86,91,92],[213,216,219],[213,219,222],[210,216,213],[208,210,213],[84,208,213],[84,213,86],[219,220,222],[220,221,222],[210,217,216],[210,218,217],[208,218,210],[91,213,221],[86,213,91],[213,222,221]]]],[[0,[[214,223,215],[88,215,223,224,94],[94,224,225,226,96],[225,227,226]]],[9,[[91,98,221]]],[10,[[94,96,98],[91,94,98],[86,88,94],[86,94,91],[213,223,214],[213,224,223],[213,222,224],[222,225,224],[222,227,225],[86,215,88],[86,213,215],[213,214,215],[222,226,227],[96,226,98],[98,226,221],[221,226,222],[91,221,213],[213,221,222],[86,91,213]]]],[[9,[[219,220,229,228],[220,221,229]]],[10,[[219,228,222],[219,222,220],[220,222,221],[221,222,229],[222,228,229]]]],[[0,[[96,226,230,100],[226,227,231,232,230]]],[9,[[231,233,234,232],[102,234,233,228,229,103],[98,103,229,221]]],[10,[[96,105,103],[102,103,105],[96,103,98],[227,233,231],[222,233,227],[222,228,233],[96,98,226],[221,222,226],[222,227,226],[98,221,226],[222,229,228],[221,229,222],[230,232,235],[102,105,230],[102,230,235]]]],[[0,[[100,230,106],[106,230,232,108]]],[9,[[108,232,234,109],[102,109,234]]],[10,[[106,108,109],[102,105,106],[102,106,109],[102,230,105],[230,235,232],[102,235,230]]]],[[9,[[110,112,237,236],[112,114,237]]],[10,[[110,114,112],[110,115,114],[114,236,237],[114,115,236],[110,236,115]]]],[[9,[[110,236,238,118]]],[10,[[110,118,115],[115,118,119],[115,238,236],[115,119,238],[110,115,236],[118,238,119]]]],[[5,[[120,121,239]]],[9,[[118,238,239,121]]],[10,[[119,121,120],[118,121,119],[120,239,238],[119,120,238],[118,119,238]]]],[[9,[[236,237,241,240],[114,122,242,243,241,237],[242,244,245,243],[244,246,247,245]]],[10,[[114,115,122],[241,243,248],[243,245,248],[245,249,248],[245,247,249],[114,236,115],[114,237,236],[246,249,247],[236,248,244],[244,248,249],[236,244,242],[122,236,242],[115,236,122],[244,249,246]]]],[[9,[[236,240,250,238],[122,127,242],[127,128,251,244,242],[244,251,246]]],[10,[[115,119,122],[122,129,127],[119,129,122],[127,129,128],[248,249,250],[249,252,250],[115,238,119],[115,236,238],[128,129,251],[246,251,249],[249,251,252],[129,252,251],[115,122,236],[122,242,236],[236,244,248],[236,242,244],[244,249,248],[244,246,249],[238,250,252],[119,238,129],[129,238,252]]]],[[5,[[130,253,254,255,131],[120,239,256,253,130]]],[6,[[254,258,257,255]]],[9,[[238,250,256,239]]],[10,[[129,130,131],[119,120,130],[119,130,129],[250,253,256],[250,254,253],[252,258,254],[250,252,254],[252,259,258],[120,238,239],[119,238,120],[131,255,252],[252,255,257],[129,131,252],[252,257,259],[119,129,238],[238,252,250],[129,252,238],[257,258,259]]]],[[6,[[257,258,260]]],[10,[[258,259,260],[257,260,259],[257,259,258]]]],[[9,[[261,262,263]]],[10,[[262,264,263],[261,264,262],[261,263,264]]]],[[9,[[261,263,265,266],[246,267,266,265,247]]],[10,[[263,264,268],[263,268,265],[247,265,268],[247,268,249],[246,247,249],[261,266,264],[266,267,268],[264,266,268],[261,264,263],[246,268,267],[246,249,268]]]],[[9,[[128,132,269,251],[246,251,269,267]]],[10,[[128,129,132],[129,133,132],[249,268,252],[252,268,270],[128,251,129],[246,249,251],[129,251,252],[249,252,251],[132,133,269],[267,269,268],[133,270,269],[268,269,270],[246,267,268],[246,268,249],[129,252,133],[133,252,270]]]],[[5,[[131,255,271,134]]],[6,[[255,257,271]]],[10,[[131,134,133],[133,134,137],[129,131,133],[252,270,259],[259,270,272],[131,252,255],[129,252,131],[252,257,255],[252,259,257],[133,137,270],[137,272,270],[129,133,252],[133,270,252],[134,271,272],[257,259,271],[259,272,271],[134,272,137]]]],[[5,[[134,271,273,138]]],[6,[[257,260,274,273,271]]],[8,[[138,273,275,139],[273,274,276,275]]],[10,[[134,138,137],[137,138,139],[260,272,274],[259,272,260],[272,276,274],[257,259,260],[272,275,276],[137,139,275],[137,275,272],[134,137,272],[134,272,271],[257,271,259],[259,271,272]]]],[[9,[[277,278,279]]],[10,[[278,280,279],[277,280,278],[277,279,280]]]],[[9,[[261,283,284,281,282,262],[277,279,282,281],[283,285,284]]],[10,[[262,282,264],[279,286,282],[264,282,286],[279,280,286],[261,262,264],[284,285,286],[281,284,286],[277,281,286],[277,286,280],[277,280,279],[261,264,283],[283,286,285],[264,286,283]]]],[[9,[[261,266,283],[141,285,283,266,267,142]]],[10,[[141,142,143],[264,286,268],[268,286,287],[261,264,266],[266,268,267],[264,268,266],[141,286,285],[141,143,287],[141,287,286],[261,283,264],[283,285,286],[264,283,286],[142,267,268],[142,287,143],[142,268,287]]]],[[9,[[132,145,269],[142,267,269,145]]],[10,[[132,133,145],[133,146,145],[142,145,146],[142,146,143],[268,287,270],[270,287,288],[132,269,133],[133,269,270],[267,268,269],[268,270,269],[143,146,287],[146,288,287],[142,268,267],[142,143,287],[142,287,268],[133,270,146],[146,270,288]]]],[[8,[[148,289,149]]],[10,[[146,148,149],[133,137,148],[133,148,146],[270,288,272],[272,288,290],[133,270,137],[137,270,272],[288,289,290],[146,149,289],[146,289,288],[133,146,270],[146,288,270],[137,272,148],[148,290,289],[148,272,290]]]],[[2,[[291,292,293,294]]],[6,[[291,295,292]]],[8,[[139,275,296,289,148],[275,276,294,293,296]]],[10,[[137,139,148],[272,294,276],[290,291,294],[272,290,294],[290,295,291],[137,275,139],[137,272,275],[272,276,275],[290,293,292],[290,292,295],[290,296,293],[289,296,290],[148,289,290],[137,148,272],[148,290,272]]]],[[9,[[297,298,299,300],[277,300,299,278]]],[10,[[298,301,299],[278,299,280],[280,299,301],[277,278,280],[297,301,298],[297,300,301],[277,280,300],[280,301,300]]]],[[9,[[151,302,303,152],[302,304,303],[297,300,303,304],[281,284,303],[277,281,303,300],[152,303,284,285,154]]],[10,[[151,152,155],[152,154,155],[280,301,286],[286,301,305],[277,286,281],[281,286,284],[284,286,285],[277,280,286],[151,155,302],[302,305,304],[155,305,302],[297,304,301],[301,304,305],[297,301,300],[277,300,280],[280,300,301],[154,285,286],[154,305,155],[154,286,305]]]],[[9,[[141,154,285]]],[10,[[141,155,154],[141,158,155],[141,143,158],[286,305,287],[287,305,306],[141,285,286],[141,287,143],[141,286,287],[155,158,305],[158,306,305],[154,286,285],[154,155,305],[154,305,286],[143,287,158],[158,287,306]]]],[[8,[[161,307,162]]],[10,[[143,162,158],[143,146,162],[146,161,162],[287,306,288],[288,306,308],[143,287,146],[146,287,288],[306,307,308],[158,162,307],[158,307,306],[143,158,287],[158,306,287],[146,307,161],[146,288,307],[288,308,307]]]],[[5,[[309,310,311,312]]],[8,[[164,313,314,165],[149,289,313,164],[161,165,314,312,311,307]]],[10,[[146,165,161],[146,164,165],[146,149,164],[288,309,290],[288,310,309],[288,308,310],[146,289,149],[146,288,289],[288,290,289],[308,311,310],[307,311,308],[288,307,308],[146,161,307],[146,307,288],[312,314,315],[290,309,312],[290,312,315],[289,290,315]]]],[[2,[[292,316,293]]],[5,[[309,312,316,317]]],[6,[[292,295,317,316]]],[8,[[313,316,314],[289,296,316,313],[293,316,296],[312,314,316]]],[10,[[290,317,295],[290,309,317],[290,292,293],[290,293,296],[290,295,292],[289,290,296],[290,312,309],[312,315,314],[290,315,312],[289,315,290]]]],[[9,[[318,319,320],[297,320,319,321,298]]],[10,[[298,321,301],[301,321,322],[297,298,301],[318,322,319],[319,322,321],[297,301,320],[318,320,322],[301,322,320]]]],[[9,[[151,167,323,302],[302,323,318,320,304],[297,304,320]]],[10,[[151,155,167],[155,168,167],[301,322,305],[305,322,324],[151,302,155],[302,304,305],[155,302,305],[297,301,304],[301,305,304],[167,168,323],[318,323,324],[168,324,323],[318,324,322],[318,322,320],[297,320,301],[301,320,322],[155,305,168],[168,305,324]]]],[[10,[[155,158,168],[158,176,168],[305,324,306],[306,324,325],[155,305,158],[158,305,306],[168,176,324],[176,325,324],[155,168,305],[168,324,305],[158,306,176],[176,306,325]]]],[[0,[[177,179,326],[327,328,329,330,331],[179,180,329,328,326],[180,181,329]]],[5,[[329,334,332,333],[329,333,330]]],[8,[[162,307,334,329,181]]],[10,[[176,179,177],[176,180,179],[158,180,176],[158,181,180],[158,162,181],[306,330,308],[308,330,333],[325,331,330],[306,325,330],[325,335,331],[308,333,332],[158,307,162],[158,306,307],[306,308,307],[176,326,325],[176,177,326],[325,326,328],[325,328,327],[325,327,335],[158,176,306],[176,325,306],[327,331,335],[307,308,334],[308,332,334]]]],[[0,[[327,331,336]]],[5,[[310,332,334,311]]],[8,[[307,311,334]]],[10,[[331,335,336],[308,332,310],[307,308,311],[308,310,311],[327,336,335],[327,335,331],[308,334,332],[307,334,308]]]],[[9,[[337,338,339],[318,339,338,340,319],[319,340,321]]],[10,[[322,338,337],[322,340,338],[321,340,322],[318,319,322],[319,321,322],[318,322,339],[322,337,339]]]],[[9,[[341,342,343],[182,343,342,183],[341,344,345,342],[337,339,342,345,346],[167,186,342,323],[318,323,342,339],[187,190,342],[192,342,193],[193,342,195],[186,195,342],[183,342,190],[192,198,342],[187,342,198]]],[10,[[183,190,198],[182,183,198],[168,182,186],[182,199,186],[182,198,199],[167,168,186],[186,199,195],[187,198,190],[192,199,198],[337,346,347],[322,337,324],[324,337,347],[167,323,168],[318,324,323],[168,323,324],[318,322,324],[344,347,345],[345,347,346],[322,339,337],[318,339,322],[182,341,343],[168,324,341],[324,344,341],[168,341,182],[324,347,344]]]],[[9,[[201,348,341,343,202],[182,202,343],[341,348,344]]],[10,[[168,202,182],[176,201,202],[168,176,202],[176,210,201],[324,347,325],[325,347,349],[168,324,176],[176,324,325],[201,210,348],[344,348,347],[347,348,349],[210,349,348],[324,341,344],[168,341,324],[182,343,341],[168,182,341],[324,344,347],[176,325,210],[210,325,349]]]],[[0,[[177,326,350,211],[327,351,328],[326,328,351,350]]],[10,[[177,212,210],[210,212,213],[176,177,210],[325,349,335],[335,349,352],[176,326,177],[325,328,326],[176,325,326],[325,327,328],[325,335,327],[210,213,349],[213,352,349],[176,210,325],[210,349,325],[212,350,213],[213,350,352],[350,351,352],[327,335,351],[335,352,351]]]],[[0,[[211,350,353,214],[327,336,355,354,351],[350,351,354,353]]],[10,[[212,214,213],[335,352,336],[336,352,355],[327,335,336],[213,353,352],[213,214,353],[352,353,354],[352,354,355],[212,213,350],[213,352,350],[350,352,351],[327,351,335],[335,351,352]]]],[[9,[[344,356,357,345],[345,357,346]]],[10,[[347,357,356],[346,357,347],[344,345,347],[345,346,347],[344,347,356]]]],[[9,[[201,216,358,359,348],[344,348,359,356]]],[10,[[201,210,216],[349,359,358],[347,356,359],[347,359,349],[201,348,210],[344,347,348],[210,348,349],[347,349,348],[344,356,347],[210,349,216],[216,349,358]]]],[[9,[[360,361,362],[216,219,363,358]]],[10,[[213,219,216],[210,213,216],[213,222,219],[352,361,360],[352,363,361],[349,363,352],[349,358,363],[210,349,213],[213,349,352],[219,361,363],[219,362,361],[219,222,362],[216,358,349],[210,216,349],[213,362,222],[213,352,362],[352,360,362]]]],[[0,[[214,353,364,223],[223,364,224],[224,364,225],[354,355,365,364],[353,354,364],[225,364,365,366,367,227]]],[9,[[360,362,367,366]]],[10,[[213,214,223],[213,223,224],[222,224,225],[213,224,222],[222,225,227],[352,365,355],[360,366,365],[352,360,365],[213,353,214],[352,354,353],[213,352,353],[352,355,354],[222,227,367],[222,367,362],[352,362,360],[213,222,362],[213,362,352]]]],[[9,[[361,368,369,362],[219,228,369,368,363]]],[10,[[219,222,228],[361,363,368],[219,362,222],[219,361,362],[219,363,361],[222,369,228],[222,362,369]]]],[[0,[[227,367,231]]],[9,[[231,367,362,369,233],[228,233,369]]],[10,[[227,231,233],[222,227,233],[222,233,228],[222,367,227],[222,362,367],[222,369,362],[222,228,369]]]],[[9,[[370,371,372],[371,373,374,372]]],[10,[[373,375,374],[370,375,371],[371,375,373],[370,372,375],[372,374,375]]]],[[3,[[376,377,378],[376,378,380,379],[377,381,378],[378,381,382]]],[9,[[378,382,383],[240,241,378,383],[241,243,378],[243,245,378],[370,372,378,384],[245,247,384,378],[378,385,380],[372,374,385,378]]],[10,[[245,248,249],[241,248,243],[243,248,245],[245,249,247],[374,385,380],[379,380,386],[380,385,386],[374,375,385],[375,386,385],[247,386,384],[370,384,386],[370,386,375],[247,249,386],[370,375,372],[372,375,374],[376,379,386],[376,386,377],[377,382,381],[377,386,382],[249,383,382],[249,382,386],[248,383,249]]]],[[3,[[376,387,388,377],[376,379,387],[389,390,391],[377,388,393,392,381],[381,392,389,391,382]]],[9,[[382,391,390,394,383],[240,383,394,250]]],[10,[[248,250,249],[249,250,252],[386,388,387],[379,386,387],[388,395,393],[386,395,388],[249,252,386],[252,395,386],[377,381,382],[376,377,386],[377,382,386],[376,386,379],[249,382,383],[249,386,382],[248,249,383],[389,392,393],[389,393,395],[252,390,389],[252,389,395],[252,394,390],[250,394,252]]]],[[3,[[396,397,398],[389,399,398,397,390],[400,401,402],[392,393,401,400,403],[389,392,403,399]]],[4,[[396,404,397],[397,404,405]]],[5,[[397,405,406],[253,397,254],[253,256,397]]],[6,[[254,397,406,258]]],[9,[[390,397,394],[250,394,397,256]]],[10,[[252,254,258],[250,253,254],[250,254,252],[250,256,253],[252,258,259],[393,401,402],[393,395,401],[401,407,402],[395,407,401],[252,259,395],[259,407,395],[252,389,390],[252,390,394],[389,395,393],[389,393,392],[252,395,389],[250,252,394],[396,398,399],[396,405,404],[396,399,405],[399,407,406],[399,400,407],[399,403,400],[399,406,405],[400,402,407],[258,406,259],[259,406,407]]]],[[3,[[396,398,410,408,409],[408,410,411],[398,399,410],[400,402,412,410],[400,410,403],[399,403,410],[410,412,413,411]]],[4,[[396,409,414,404],[404,414,415,405]]],[5,[[405,415,416,417,406]]],[6,[[258,406,417,260]]],[10,[[258,260,259],[402,407,412],[412,418,413],[407,418,412],[407,417,416],[407,416,418],[259,260,417],[259,417,407],[396,399,398],[396,404,405],[396,405,399],[399,406,407],[399,400,403],[399,405,406],[399,407,400],[400,407,402],[259,407,406],[258,259,406],[408,411,413],[408,413,409],[409,415,414],[409,418,415],[409,413,418],[415,418,416]]]],[[3,[[408,419,420,409],[408,411,421,419],[411,413,421]]],[4,[[409,420,422,414],[414,422,423,424,415]]],[5,[[415,424,416]]],[10,[[413,419,421],[418,420,419],[413,418,419],[420,423,422],[418,423,420],[418,424,423],[416,424,418],[408,409,413],[409,414,415],[409,418,413],[409,415,418],[408,413,411],[415,416,418]]]],[[9,[[425,426,427],[426,428,429,427]]],[10,[[428,430,429],[425,430,426],[426,430,428],[425,427,430],[427,429,430]]]],[[9,[[262,431,432,371,370,263],[425,427,432,431],[427,429,433,432],[371,432,433,373]]],[10,[[262,263,264],[429,430,433],[373,433,434],[430,434,433],[373,434,375],[370,371,375],[371,373,375],[262,264,431],[425,431,434],[264,434,431],[425,434,430],[425,430,427],[427,430,429],[370,375,434],[263,370,434],[263,434,264]]]],[[9,[[263,370,384,265],[247,265,384]]],[10,[[247,268,265],[263,265,268],[263,268,264],[247,249,268],[375,434,386],[386,434,435],[370,375,386],[370,386,384],[247,384,386],[247,386,249],[264,268,434],[268,435,434],[263,264,434],[263,434,370],[370,434,375],[249,386,268],[268,386,435]]]],[[10,[[249,252,268],[252,270,268],[386,435,395],[395,435,436],[249,386,252],[252,386,395],[268,270,435],[270,436,435],[249,268,386],[268,435,386],[252,395,270],[270,395,436]]]],[[10,[[252,259,270],[259,272,270],[395,436,407],[407,436,437],[252,395,259],[259,395,407],[270,272,436],[272,437,436],[252,270,395],[270,436,395],[259,407,272],[272,407,437]]]],[[2,[[438,439,440]]],[5,[[416,441,439,417]]],[6,[[260,417,439,274]]],[8,[[274,439,438,276],[439,441,442,443],[439,443,440]]],[10,[[260,274,272],[272,274,276],[259,260,272],[407,437,418],[418,437,444],[259,417,260],[407,416,417],[259,407,417],[407,418,416],[437,440,443],[272,440,437],[272,438,440],[272,276,438],[442,444,443],[437,443,444],[259,272,407],[272,437,407],[416,418,441],[418,442,441],[418,444,442]]]],[[4,[[423,445,424]]],[5,[[416,424,445,446,441]]],[8,[[441,446,447,442]]],[10,[[418,448,423],[446,448,447],[418,447,448],[418,444,447],[416,418,424],[418,423,424],[442,447,444],[416,441,418],[418,441,442],[418,442,444]]]],[[9,[[278,449,426,425,279],[426,449,450,428]]],[10,[[278,279,280],[428,450,451],[428,451,430],[425,426,430],[426,428,430],[278,280,451],[278,451,449],[449,451,450],[425,430,451],[279,425,451],[279,451,280]]]],[[9,[[262,282,431],[279,425,431,282]]],[10,[[262,264,282],[279,282,286],[264,286,282],[279,286,280],[430,451,434],[434,451,452],[262,431,264],[425,434,431],[264,431,434],[425,430,434],[280,286,451],[286,452,451],[279,280,451],[279,451,425],[425,451,430],[264,434,286],[286,434,452]]]],[[10,[[264,268,286],[268,287,286],[434,452,435],[435,452,453],[264,434,268],[268,434,435],[286,287,452],[287,453,452],[264,286,434],[286,452,434],[268,435,287],[287,435,453]]]],[[10,[[268,270,287],[270,288,287],[435,453,436],[436,453,454],[268,435,270],[270,435,436],[287,288,453],[288,454,453],[268,287,435],[287,453,435],[270,436,288],[288,436,454]]]],[[10,[[270,272,288],[272,290,288],[436,454,437],[437,454,455],[270,436,272],[272,436,437],[288,290,454],[290,455,454],[270,288,436],[288,454,436],[272,437,290],[290,437,455]]]],[[1,[[456,457,458]]],[2,[[291,294,438,440,458]]],[6,[[291,458,459,295],[457,460,459,458]]],[8,[[276,438,294],[442,461,462,443],[440,443,462,456,458]]],[10,[[290,291,295],[290,294,291],[272,276,294],[272,294,290],[437,456,462],[437,457,456],[455,460,457],[437,455,457],[444,462,461],[437,462,444],[272,438,276],[272,440,438],[272,437,440],[437,443,440],[442,443,444],[437,444,443],[295,459,455],[455,459,460],[290,295,455],[272,290,437],[290,455,437],[442,444,461]]]],[[8,[[442,447,461]]],[10,[[444,461,447],[442,444,447],[442,461,444]]]],[[9,[[463,464,465],[464,466,467,465]]],[10,[[466,468,467],[463,468,464],[464,468,466],[463,465,467],[463,467,468]]]],[[9,[[463,465,470,469],[298,469,470,299],[278,299,470,449],[449,470,471,450],[470,472,471],[465,467,472,470]]],[10,[[298,299,301],[278,280,299],[280,301,299],[450,471,451],[471,472,473],[451,471,473],[467,473,472],[467,468,473],[449,450,451],[278,449,451],[278,451,280],[463,474,468],[298,473,474],[468,474,473],[298,301,473],[463,467,465],[463,468,467],[280,451,301],[301,451,473]]]],[[10,[[280,286,301],[286,305,301],[451,473,452],[452,473,475],[280,451,286],[286,451,452],[301,305,473],[305,475,473],[280,301,451],[301,473,451],[286,452,305],[305,452,475]]]],[[10,[[286,287,305],[287,306,305],[452,475,453],[453,475,476],[286,452,287],[287,452,453],[305,306,475],[306,476,475],[286,305,452],[305,475,452],[287,453,306],[306,453,476]]]],[[10,[[287,288,306],[288,308,306],[453,476,454],[454,476,477],[287,453,288],[288,453,454],[306,308,476],[308,477,476],[287,306,453],[306,476,453],[288,454,308],[308,454,477]]]],[[5,[[309,478,479,310],[478,480,481,479]]],[10,[[288,310,308],[288,309,310],[288,290,309],[454,480,455],[454,477,480],[477,481,480],[288,454,290],[290,454,455],[477,479,481],[308,310,479],[308,479,477],[288,308,454],[308,477,454],[290,478,309],[290,455,478],[455,480,478]]]],[[5,[[309,317,483,482,478],[478,482,480]]],[6,[[295,459,484,483,317],[459,460,484]]],[10,[[290,317,309],[290,295,317],[455,483,484],[455,482,483],[455,480,482],[455,484,460],[295,455,459],[290,455,295],[455,460,459],[455,478,480],[290,309,478],[290,478,455]]]],[[9,[[463,485,486,464],[464,486,487,488,466],[487,489,488]]],[10,[[466,488,468],[488,489,490],[468,488,490],[463,464,468],[464,466,468],[485,487,486],[485,490,487],[487,490,489],[463,468,485],[468,490,485]]]],[[9,[[463,469,491,485],[298,321,491,469]]],[10,[[298,301,321],[301,322,321],[468,490,473],[473,490,492],[463,468,474],[298,474,473],[468,473,474],[298,473,301],[485,491,492],[321,322,491],[322,492,491],[485,492,490],[463,485,468],[468,485,490],[301,473,322],[322,473,492]]]],[[10,[[301,305,322],[305,324,322],[473,492,475],[475,492,493],[301,473,305],[305,473,475],[322,324,492],[324,493,492],[301,322,473],[322,492,473],[305,475,324],[324,475,493]]]],[[10,[[305,306,324],[306,325,324],[475,493,476],[476,493,494],[305,475,306],[306,475,476],[324,325,493],[325,494,493],[305,324,475],[324,493,475],[306,476,325],[325,476,494]]]],[[0,[[330,495,331]]],[5,[[332,496,333],[330,333,496,495]]],[10,[[325,330,331],[325,331,335],[306,330,325],[308,333,330],[306,308,330],[308,332,333],[476,494,477],[477,494,497],[306,476,308],[308,476,477],[325,335,494],[335,497,494],[306,325,476],[325,494,476],[477,497,495],[331,495,335],[335,495,497],[477,495,496],[308,496,332],[308,477,496]]]],[[0,[[331,495,498,336]]],[5,[[310,479,496,332],[479,481,499,498,495,496]]],[10,[[331,336,335],[308,310,332],[477,499,481],[477,497,499],[308,479,310],[308,477,479],[477,481,479],[497,498,499],[335,336,498],[335,498,497],[331,335,495],[335,497,495],[477,496,495],[477,495,497],[308,496,477],[308,332,496]]]],[[9,[[500,501,502,503],[500,503,504],[503,505,504],[485,505,503,486],[486,503,487],[487,503,502,489]]],[10,[[490,502,501],[489,502,490],[485,486,487],[485,487,490],[487,489,490],[490,501,500],[485,490,500],[500,504,505],[485,500,505]]]],[[9,[[337,506,507,508,338],[338,508,340],[500,509,501],[500,504,511,510,509],[504,505,508,507,511],[485,491,508,505],[321,340,508,491]]],[10,[[322,337,338],[322,338,340],[321,322,340],[492,509,510],[490,501,509],[490,509,492],[492,510,512],[485,490,492],[485,492,491],[321,491,322],[322,491,492],[506,512,513],[511,513,512],[510,511,512],[490,500,501],[485,500,490],[500,505,504],[485,505,500],[337,492,506],[322,492,337],[492,512,506]]]],[[9,[[337,346,506]]],[10,[[322,324,337],[337,347,346],[324,347,337],[492,512,493],[493,512,514],[322,492,324],[324,492,493],[346,347,514],[346,514,506],[506,514,512],[337,506,492],[492,506,512],[322,337,492],[324,493,347],[347,493,514]]]],[[10,[[324,325,347],[325,349,347],[493,514,494],[494,514,515],[324,493,325],[325,493,494],[347,349,514],[349,515,514],[324,347,493],[347,514,493],[325,494,349],[349,494,515]]]],[[10,[[325,335,349],[335,352,349],[494,515,497],[497,515,516],[325,494,335],[335,494,497],[349,352,515],[352,516,515],[325,349,494],[349,515,494],[335,497,352],[352,497,516]]]],[[0,[[336,498,517,518,519,355],[518,520,521,519]]],[5,[[498,499,517]]],[9,[[520,522,521]]],[10,[[336,355,352],[335,336,352],[497,517,499],[516,518,517],[497,516,517],[518,522,520],[516,522,518],[335,498,336],[335,497,498],[497,499,498],[352,355,519],[352,519,521],[352,521,522],[352,522,516],[335,352,497],[352,516,497]]]],[[9,[[523,524,525],[523,526,527,524],[524,528,525],[506,528,524,507],[510,511,524,527],[507,524,511]]],[10,[[512,527,526],[510,527,512],[506,513,512],[511,512,513],[510,512,511],[523,525,528],[523,528,526],[512,526,528],[506,512,528]]]],[[9,[[523,525,531,529,530],[523,530,526],[356,532,531,525,528,357],[346,357,528,506]]],[10,[[346,347,357],[347,356,357],[514,530,529],[514,529,533],[512,526,530],[512,530,514],[506,512,514],[346,506,514],[346,514,347],[529,531,533],[531,532,533],[523,528,525],[523,526,528],[512,528,526],[506,528,512],[356,514,532],[347,514,356],[514,533,532]]]],[[9,[[358,534,535,359],[356,359,535,532]]],[10,[[347,359,356],[347,349,359],[349,358,359],[514,533,515],[515,533,536],[347,514,349],[349,514,515],[534,536,535],[532,535,536],[532,536,533],[356,532,514],[514,532,533],[347,356,514],[349,534,358],[349,515,534],[515,536,534]]]],[[8,[[537,538,539]]],[9,[[360,540,539,538,361],[358,363,534]]],[10,[[352,360,361],[352,361,363],[349,363,358],[349,352,363],[516,539,540],[515,539,516],[515,537,539],[515,536,537],[349,515,352],[352,515,516],[536,538,537],[361,538,363],[363,538,534],[534,538,536],[515,534,536],[349,358,534],[349,534,515],[352,540,360],[352,516,540]]]],[[0,[[355,519,365],[365,519,521,366]]],[9,[[360,366,521,522,540]]],[10,[[360,365,366],[352,355,365],[352,365,360],[516,540,522],[352,519,355],[352,521,519],[352,522,521],[352,516,522],[352,540,516],[352,360,540]]]],[[9,[[529,531,542,541],[531,532,542]]],[10,[[529,541,533],[529,533,531],[531,533,532],[532,533,542],[533,541,542]]]],[[9,[[534,543,535],[541,542,545,544],[532,535,543,545,542]]],[10,[[536,541,544],[533,541,536],[534,535,536],[532,536,535],[532,533,536],[533,542,541],[532,542,533],[534,536,543],[536,545,543],[536,544,545]]]],[[8,[[537,546,547,538]]],[9,[[361,538,547,368],[363,368,547,543,534],[544,545,547,546],[543,547,545]]],[10,[[361,368,363],[536,546,537],[536,544,546],[534,536,538],[536,537,538],[361,363,538],[363,534,538],[534,543,536],[536,543,545],[536,545,544]]]],[[9,[[373,548,549,374]]],[10,[[373,374,375],[548,550,549],[373,375,548],[375,550,548],[374,549,375],[375,549,550]]]],[[3,[[379,380,552,551]]],[9,[[380,385,553,552],[374,549,553,385]]],[10,[[379,386,380],[374,380,385],[380,386,385],[374,385,375],[375,385,386],[549,553,552],[551,552,554],[552,553,554],[549,550,553],[550,554,553],[375,386,550],[386,554,550],[374,375,549],[375,550,549],[379,551,386],[386,551,554]]]],[[3,[[387,555,556,557,388],[379,551,555,387],[388,557,393]]],[10,[[386,387,388],[388,393,395],[386,388,395],[379,387,386],[555,558,556],[551,554,555],[554,558,555],[386,395,554],[395,558,554],[379,386,551],[386,554,551],[556,558,557],[393,557,395],[395,557,558]]]],[[3,[[556,559,560,557],[401,560,561,402],[393,557,560,401],[559,562,560],[560,562,563,561]]],[10,[[393,402,401],[401,402,407],[393,401,395],[395,401,407],[556,558,559],[558,562,559],[562,564,563],[558,564,562],[395,407,558],[407,564,558],[393,395,557],[556,557,558],[395,558,557],[402,561,407],[561,563,564],[407,561,564]]]],[[3,[[402,561,565,412],[565,566,567],[565,569,568,566],[561,563,569,565],[412,565,567,413]]],[10,[[402,412,407],[412,413,418],[407,412,418],[563,564,569],[568,569,570],[564,570,569],[407,418,564],[418,570,564],[402,407,561],[561,564,563],[407,564,561],[418,567,566],[566,568,570],[418,566,570],[413,567,418]]]],[[3,[[419,571,572,420],[419,421,573,571],[566,574,575,576,567],[566,568,574],[413,567,576,573,421]]],[4,[[420,572,577,422],[422,577,578,423]]],[10,[[418,419,420],[418,420,423],[420,422,423],[413,421,419],[413,419,418],[568,575,574],[568,570,574],[574,579,575],[570,579,574],[423,578,579],[418,423,570],[423,579,570],[418,566,567],[413,418,567],[566,570,568],[418,570,566],[571,579,572],[571,573,576],[571,576,579],[572,579,577],[575,579,576],[577,579,578]]]],[[3,[[580,581,582],[580,583,584,585,581],[583,586,587,584],[584,587,588],[571,588,572],[571,573,584,588],[575,585,584,576],[573,576,584]]],[4,[[572,588,587,577],[577,587,589,578]]],[7,[[586,590,589,587]]],[10,[[579,581,585],[581,591,582],[579,591,581],[575,579,585],[578,589,579],[589,590,591],[579,589,591],[572,577,579],[571,572,579],[571,576,573],[571,579,576],[575,576,579],[577,578,579],[580,582,591],[580,590,586],[580,586,583],[580,591,590]]]],[[3,[[580,582,592,593],[580,593,583],[583,593,586]]],[7,[[586,593,594,590],[593,595,594],[593,596,595],[592,597,596,593]]],[10,[[582,591,592],[591,597,592],[594,595,596],[590,594,596],[590,596,591],[591,596,597],[580,583,586],[580,586,590],[580,591,582],[580,590,591]]]],[[9,[[428,598,599,429]]],[10,[[428,429,430],[598,600,599],[428,430,598],[430,600,598],[429,599,430],[430,599,600]]]],[[9,[[429,599,601,433],[373,433,601,548]]],[10,[[429,433,430],[373,434,433],[430,433,434],[373,375,434],[599,600,601],[548,601,602],[600,602,601],[548,602,550],[373,548,375],[375,548,550],[430,434,600],[434,602,600],[429,430,599],[430,600,599],[375,550,434],[434,550,602]]]],[[10,[[375,386,434],[386,435,434],[550,602,554],[554,602,603],[375,550,386],[386,550,554],[434,435,602],[435,603,602],[375,434,550],[434,602,550],[386,554,435],[435,554,603]]]],[[10,[[386,395,435],[395,436,435],[554,603,558],[558,603,604],[386,554,395],[395,554,558],[435,436,603],[436,604,603],[386,435,554],[435,603,554],[395,558,436],[436,558,604]]]],[[10,[[395,407,436],[407,437,436],[558,604,564],[564,604,605],[395,558,407],[407,558,564],[436,437,604],[437,605,604],[395,436,558],[436,604,558],[407,564,437],[437,564,605]]]],[[10,[[407,418,437],[418,444,437],[564,605,570],[570,605,606],[407,564,418],[418,564,570],[437,444,605],[444,606,605],[407,437,564],[437,605,564],[418,570,444],[444,570,606]]]],[[2,[[607,608,609]]],[4,[[423,578,610,445]]],[5,[[445,610,611,446]]],[8,[[446,611,612,613,447],[608,613,612,609]]],[10,[[418,448,447],[418,423,448],[446,447,448],[418,447,444],[570,606,579],[579,606,614],[418,570,423],[423,579,578],[423,570,579],[607,614,608],[606,613,608],[606,608,614],[447,613,606],[444,447,606],[418,444,570],[444,606,570],[579,609,612],[579,614,609],[607,609,614],[578,579,610],[610,612,611],[579,612,610]]]],[[2,[[607,609,616,615]]],[4,[[578,589,617,610]]],[5,[[610,617,611]]],[7,[[616,618,619,620],[616,621,618],[589,590,622,617],[617,622,623],[617,623,624],[616,617,624,621]]],[8,[[611,617,612],[609,612,617,616],[615,616,625],[616,620,626,625]]],[10,[[591,620,619],[579,626,620],[579,620,591],[579,614,626],[578,579,589],[589,591,590],[579,591,589],[607,615,625],[607,625,614],[614,625,626],[607,614,609],[579,612,609],[579,609,614],[578,610,579],[610,611,612],[579,610,612],[591,619,618],[591,618,622],[618,623,622],[618,621,624],[618,624,623],[590,591,622]]]],[[7,[[618,627,619],[618,621,628,629,627],[590,594,622],[594,595,630,623,622],[623,630,628,624],[621,624,628],[628,630,632,631],[628,631,629],[595,596,633,632,630],[596,597,633]]],[10,[[619,627,633],[627,629,631],[627,631,632],[627,632,633],[591,619,633],[591,633,597],[590,596,594],[590,591,596],[594,596,595],[591,597,596],[591,618,619],[591,622,618],[618,622,623],[618,624,621],[618,623,624],[590,622,591]]]],[[9,[[428,450,634,635,598],[634,636,635]]],[10,[[428,451,450],[428,430,451],[598,635,600],[635,636,637],[600,635,637],[428,598,430],[430,598,600],[450,451,634],[634,637,636],[451,637,634],[430,600,451],[451,600,637]]]],[[10,[[430,434,451],[434,452,451],[600,637,602],[602,637,638],[430,600,434],[434,600,602],[451,452,637],[452,638,637],[430,451,600],[451,637,600],[434,602,452],[452,602,638]]]],[[10,[[434,435,452],[435,453,452],[602,638,603],[603,638,639],[434,602,435],[435,602,603],[452,453,638],[453,639,638],[434,452,602],[452,638,602],[435,603,453],[453,603,639]]]],[[10,[[435,436,453],[436,454,453],[603,639,604],[604,639,640],[435,603,436],[436,603,604],[453,454,639],[454,640,639],[435,453,603],[453,639,603],[436,604,454],[454,604,640]]]],[[10,[[436,437,454],[437,455,454],[604,640,605],[605,640,641],[436,604,437],[437,604,605],[454,455,640],[455,641,640],[436,454,604],[454,640,604],[437,605,455],[455,605,641]]]],[[1,[[456,642,643,457]]],[2,[[642,645,644]]],[6,[[457,643,646,460],[642,647,646,643]]],[8,[[648,649,650],[648,652,653,651,649],[461,654,642,462],[642,654,645],[456,462,642]]],[9,[[642,644,653,652,647]]],[10,[[437,457,455],[455,457,460],[437,456,457],[437,462,456],[437,444,462],[444,461,462],[641,650,649],[641,649,651],[605,651,606],[605,641,651],[437,605,444],[444,605,606],[455,460,646],[455,646,647],[641,647,648],[647,652,648],[455,647,641],[641,648,650],[437,455,605],[455,641,605],[606,644,645],[606,645,654],[606,651,644],[644,651,653],[444,654,461],[444,606,654]]]],[[2,[[607,655,656,644,645,608]]],[8,[[651,653,656,657],[447,613,654,461],[608,645,654,613],[655,658,657,656]]],[9,[[644,656,653]]],[10,[[444,447,461],[606,657,658],[606,651,657],[606,658,614],[606,614,608],[607,608,614],[606,608,613],[447,606,613],[444,606,447],[606,644,651],[606,645,644],[644,653,651],[606,654,645],[444,654,606],[444,461,654],[607,614,655],[614,658,655]]]],[[2,[[607,615,655]]],[8,[[615,625,659,658,655],[625,626,659]]],[10,[[614,659,626],[614,658,659],[626,659,658],[607,625,615],[607,614,625],[614,626,625],[607,655,614],[614,655,658]]]],[[9,[[466,660,661,467]]],[10,[[466,467,468],[660,662,661],[466,468,660],[468,662,660],[467,661,468],[468,661,662]]]],[[9,[[450,471,634],[471,472,663,636,634],[467,661,663,472]]],[10,[[450,451,471],[471,473,472],[451,473,471],[467,472,473],[467,473,468],[661,664,663],[636,663,664],[636,664,637],[661,662,664],[450,634,451],[634,636,637],[451,634,637],[468,473,662],[473,664,662],[467,468,661],[468,662,661],[451,637,473],[473,637,664]]]],[[10,[[451,452,473],[452,475,473],[637,664,638],[638,664,665],[451,637,452],[452,637,638],[473,475,664],[475,665,664],[451,473,637],[473,664,637],[452,638,475],[475,638,665]]]],[[10,[[452,453,475],[453,476,475],[638,665,639],[639,665,666],[452,638,453],[453,638,639],[475,476,665],[476,666,665],[452,475,638],[475,665,638],[453,639,476],[476,639,666]]]],[[10,[[453,454,476],[454,477,476],[639,666,640],[640,666,667],[453,639,454],[454,639,640],[476,477,666],[477,667,666],[453,476,639],[476,666,639],[454,640,477],[477,640,667]]]],[[5,[[480,668,481]]],[10,[[477,480,481],[454,455,480],[454,480,477],[640,667,641],[641,667,669],[454,640,455],[455,640,641],[667,668,669],[477,481,668],[477,668,667],[454,477,640],[477,667,640],[455,641,480],[480,669,668],[480,641,669]]]],[[5,[[482,483,670],[480,482,670,671,668]]],[6,[[483,484,670],[460,646,670,484],[646,647,670]]],[8,[[648,650,672,670],[648,670,652],[670,673,671],[670,672,674,673]]],[9,[[647,652,670]]],[10,[[455,482,480],[455,483,482],[455,484,483],[455,460,484],[641,672,650],[641,674,672],[641,669,674],[455,646,460],[455,647,646],[641,648,647],[455,641,647],[647,648,652],[641,650,648],[668,671,669],[669,671,673],[669,673,674],[480,668,669],[455,480,641],[480,669,641]]]],[[9,[[466,488,675,660],[488,489,676,675]]],[10,[[466,468,488],[488,490,489],[468,490,488],[660,675,662],[675,676,677],[662,675,677],[466,660,468],[468,660,662],[489,490,676],[490,677,676],[468,662,490],[490,662,677]]]],[[10,[[468,473,490],[473,492,490],[662,677,664],[664,677,678],[468,662,473],[473,662,664],[490,492,677],[492,678,677],[468,490,662],[490,677,662],[473,664,492],[492,664,678]]]],[[10,[[473,475,492],[475,493,492],[664,678,665],[665,678,679],[473,664,475],[475,664,665],[492,493,678],[493,679,678],[473,492,664],[492,678,664],[475,665,493],[493,665,679]]]],[[10,[[475,476,493],[476,494,493],[665,679,666],[666,679,680],[475,665,476],[476,665,666],[493,494,679],[494,680,679],[475,493,665],[493,679,665],[476,666,494],[494,666,680]]]],[[10,[[476,477,494],[477,497,494],[666,680,667],[667,680,681],[476,666,477],[477,666,667],[494,497,680],[497,681,680],[476,494,666],[494,680,666],[477,667,497],[497,667,681]]]],[[5,[[481,668,682,683,499]]],[8,[[682,684,685,683]]],[10,[[477,499,497],[477,481,499],[667,684,669],[667,685,684],[667,681,685],[477,668,481],[477,667,668],[667,669,668],[681,683,685],[497,499,683],[497,683,681],[477,497,667],[497,681,667],[668,669,682],[669,684,682]]]],[[5,[[668,671,682]]],[8,[[671,673,686,684,682],[673,674,686]]],[10,[[669,686,674],[669,684,686],[674,686,684],[668,669,671],[669,673,671],[669,674,673],[668,682,669],[669,682,684]]]],[[9,[[501,687,688,502],[489,502,688,676]]],[10,[[489,490,502],[490,501,502],[677,688,687],[676,688,677],[489,676,490],[490,676,677],[490,677,501],[501,677,687]]]],[[9,[[501,509,689,687],[509,510,690,689]]],[10,[[490,509,501],[492,510,509],[490,492,509],[492,512,510],[678,687,689],[689,690,691],[678,689,691],[677,687,678],[490,677,492],[492,677,678],[510,512,690],[512,691,690],[501,687,677],[490,501,677],[492,678,512],[512,678,691]]]],[[10,[[492,493,512],[493,514,512],[678,691,679],[679,691,692],[492,678,493],[493,678,679],[512,514,691],[514,692,691],[492,512,678],[512,691,678],[493,679,514],[514,679,692]]]],[[10,[[493,494,514],[494,515,514],[679,692,680],[680,692,693],[493,679,494],[494,679,680],[514,515,692],[515,693,692],[493,514,679],[514,692,679],[494,680,515],[515,680,693]]]],[[8,[[694,695,696,697],[696,698,699,697]]],[9,[[698,700,699]]],[10,[[494,497,515],[497,516,515],[680,694,681],[680,693,694],[693,695,694],[494,680,497],[497,680,681],[693,696,695],[693,698,696],[515,698,693],[515,516,698],[516,700,698],[494,515,680],[515,693,680],[681,694,697],[681,697,699],[497,699,516],[516,699,700],[497,681,699]]]],[[0,[[517,701,518],[518,701,520]]],[5,[[499,683,701,517]]],[8,[[694,697,701,702],[697,699,701],[683,685,702,701]]],[9,[[520,701,699,700,522]]],[10,[[518,520,522],[516,517,518],[516,518,522],[497,517,516],[497,499,517],[681,702,685],[681,694,702],[497,683,499],[497,681,683],[681,685,683],[516,522,700],[681,697,694],[681,699,697],[497,699,681],[497,516,699],[516,700,699]]]],[[9,[[526,703,704,527],[510,527,704,690]]],[10,[[510,512,527],[512,526,527],[691,704,703],[690,704,691],[510,690,512],[512,690,691],[512,691,526],[526,691,703]]]],[[9,[[529,705,530],[526,530,705,706,703]]],[10,[[512,530,526],[514,529,530],[512,514,530],[514,533,529],[692,703,706],[692,706,707],[691,703,692],[512,691,514],[514,691,692],[529,533,705],[705,707,706],[533,707,705],[526,703,691],[512,526,691],[514,692,533],[533,692,707]]]],[[10,[[514,515,533],[515,536,533],[692,707,693],[693,707,708],[514,692,515],[515,692,693],[533,536,707],[536,708,707],[514,533,692],[533,707,692],[515,693,536],[536,693,708]]]],[[8,[[695,709,696],[537,539,698,696,709,710]]],[9,[[539,540,700,698]]],[10,[[515,537,536],[515,539,537],[515,516,539],[516,540,539],[693,709,695],[695,709,710],[693,710,709],[693,708,710],[693,695,696],[693,696,698],[515,698,516],[516,698,700],[515,693,698],[537,710,708],[536,537,708],[515,536,693],[536,708,693],[516,700,540]]]],[[9,[[522,700,540]]],[10,[[516,522,540],[516,700,522],[516,540,700]]]],[[9,[[529,541,711,712,705],[705,712,706]]],[10,[[529,533,541],[707,712,711],[706,712,707],[529,705,533],[705,706,707],[533,705,707],[533,707,541],[541,707,711]]]],[[9,[[541,544,713,711]]],[10,[[533,536,541],[536,544,541],[708,711,713],[707,711,708],[533,707,536],[536,707,708],[541,711,707],[533,541,707],[536,708,544],[544,708,713]]]],[[8,[[537,710,714,546]]],[9,[[544,546,714,713]]],[10,[[536,546,544],[536,537,546],[708,714,710],[708,713,714],[536,708,537],[537,708,710],[544,713,708],[536,544,708]]]],[[9,[[715,716,717,718],[548,716,715,549]]],[10,[[548,549,550],[717,719,718],[548,550,716],[716,719,717],[550,719,716],[715,718,719],[549,715,550],[550,715,719]]]],[[3,[[551,552,720,721]]],[9,[[552,553,715,718,720],[549,715,553]]],[10,[[551,554,552],[549,552,553],[552,554,553],[549,553,550],[550,553,554],[720,722,721],[718,722,720],[718,719,722],[550,554,719],[554,722,719],[549,550,715],[715,719,718],[550,719,715],[551,721,554],[554,721,722]]]],[[3,[[723,724,725],[555,726,556],[551,721,725,724,726,555]]],[10,[[555,556,558],[551,555,554],[554,555,558],[721,725,723],[721,722,725],[723,725,727],[722,727,725],[554,558,722],[558,727,722],[551,554,721],[554,722,721],[723,727,724],[724,727,726],[556,726,558],[558,726,727]]]],[[3,[[728,729,730,731],[723,728,731,724],[556,726,731,559],[724,731,726],[559,731,730,732,562],[562,732,563]]],[10,[[556,559,558],[558,559,562],[562,563,564],[558,562,564],[723,728,729],[723,727,728],[728,733,729],[727,733,728],[558,564,727],[564,733,727],[723,724,727],[724,726,727],[556,558,726],[558,727,726],[729,733,730],[730,733,732],[563,732,564],[564,732,733]]]],[[3,[[729,734,735,730],[568,569,735,736],[730,735,732],[563,732,735,569],[734,737,736,735]]],[10,[[568,570,569],[563,569,564],[564,569,570],[729,733,734],[734,738,737],[733,738,734],[564,570,733],[570,738,733],[729,730,733],[730,732,733],[563,564,732],[564,733,732],[568,736,570],[736,737,738],[570,736,738]]]],[[3,[[739,740,741,742],[739,743,744,740],[574,745,575],[568,736,746,745,574],[736,737,742,741,746]]],[4,[[743,747,748,744],[747,749,750,748]]],[10,[[568,574,575],[574,575,579],[568,574,570],[570,574,579],[737,739,742],[738,743,739],[737,738,739],[743,749,747],[738,749,743],[570,749,738],[570,579,749],[579,750,749],[568,570,736],[736,738,737],[570,738,736],[579,740,744],[740,746,741],[740,745,746],[579,745,740],[579,744,748],[575,745,579],[579,748,750]]]],[[3,[[751,752,753],[751,753,754,755],[740,752,751,741],[740,744,752],[581,751,755,582],[581,585,751],[575,745,751,585],[745,746,751],[741,751,746]]],[4,[[744,748,753,752],[748,750,756,753]]],[7,[[753,756,757,754]]],[10,[[581,582,591],[579,585,581],[579,581,591],[575,585,579],[579,756,750],[579,591,756],[591,757,756],[740,741,746],[740,746,745],[579,744,740],[579,740,745],[579,748,744],[575,579,745],[579,750,748],[754,757,755],[582,755,591],[591,755,757]]]],[[3,[[754,758,755],[582,755,758,592]]],[7,[[758,759,760],[754,757,759,758],[592,758,760,597]]],[10,[[582,592,591],[591,592,597],[591,759,757],[591,760,759],[591,597,760],[754,755,757],[582,591,755],[591,757,755]]]],[[9,[[598,761,762,599],[761,763,764,762]]],[10,[[598,599,600],[763,765,764],[598,600,761],[761,765,763],[600,765,761],[599,762,600],[762,764,765],[600,762,765]]]],[[9,[[599,762,766,767,601],[762,764,766],[716,768,717],[548,601,767,768,716]]],[10,[[599,601,600],[548,602,601],[600,601,602],[548,550,602],[766,769,767],[764,766,767],[764,765,766],[765,769,766],[717,767,768],[767,769,768],[717,768,719],[719,768,769],[716,717,719],[548,716,550],[550,716,719],[600,602,765],[602,769,765],[599,600,762],[762,765,764],[600,765,762],[550,719,602],[602,719,769]]]],[[10,[[550,554,602],[554,603,602],[719,769,722],[722,769,770],[550,719,554],[554,719,722],[602,603,769],[603,770,769],[550,602,719],[602,769,719],[554,722,603],[603,722,770]]]],[[10,[[554,558,603],[558,604,603],[722,770,727],[727,770,771],[554,722,558],[558,722,727],[603,604,770],[604,771,770],[554,603,722],[603,770,722],[558,727,604],[604,727,771]]]],[[10,[[558,564,604],[564,605,604],[727,771,733],[733,771,772],[558,727,564],[564,727,733],[604,605,771],[605,772,771],[558,604,727],[604,771,727],[564,733,605],[605,733,772]]]],[[10,[[564,570,605],[570,606,605],[733,772,738],[738,772,773],[564,733,570],[570,733,738],[605,606,772],[606,773,772],[564,605,733],[605,772,733],[570,738,606],[606,738,773]]]],[[2,[[774,775,776]]],[4,[[749,777,778,750]]],[5,[[777,779,780,778]]],[8,[[775,781,782,776],[779,783,782,781,780]]],[10,[[570,579,606],[579,614,606],[738,784,749],[779,784,783],[738,783,784],[738,773,783],[579,749,750],[570,738,749],[570,749,579],[606,776,782],[614,774,776],[606,614,776],[606,782,783],[606,783,773],[570,606,738],[606,773,738],[614,775,774],[579,781,775],[579,775,614],[579,778,781],[579,750,778],[778,780,781]]]],[[2,[[774,785,786,775]]],[4,[[750,778,787,756]]],[5,[[778,780,787]]],[7,[[619,788,786,620],[787,790,789],[756,787,789,757],[786,788,791,787],[787,791,790]]],[8,[[775,786,787,781],[780,781,787],[620,786,785,626]]],[10,[[579,620,626],[579,591,620],[591,619,620],[579,626,614],[579,750,756],[591,756,757],[579,756,591],[614,785,774],[614,626,785],[579,775,781],[614,774,775],[579,614,775],[579,778,750],[778,781,780],[579,781,778],[591,788,619],[788,790,791],[788,789,790],[591,789,788],[591,757,789]]]],[[7,[[619,627,792,788],[627,629,792],[759,789,790,793,760],[757,789,759],[788,792,791],[790,791,792,793],[631,632,793],[629,631,793,792],[632,633,793],[597,760,793,633]]],[10,[[619,633,627],[591,633,619],[627,631,629],[627,633,632],[627,632,631],[591,597,633],[591,760,597],[591,759,760],[591,757,759],[591,619,788],[591,788,789],[788,790,789],[788,791,790],[591,789,757]]]],[[9,[[598,635,761],[635,636,794,763,761]]],[10,[[598,600,635],[635,637,636],[600,637,635],[763,794,795],[763,795,765],[598,761,600],[761,763,765],[600,761,765],[636,637,794],[637,795,794],[600,765,637],[637,765,795]]]],[[10,[[600,602,637],[602,638,637],[765,795,769],[769,795,796],[600,765,602],[602,765,769],[637,638,795],[638,796,795],[600,637,765],[637,795,765],[602,769,638],[638,769,796]]]],[[10,[[602,603,638],[603,639,638],[769,796,770],[770,796,797],[602,769,603],[603,769,770],[638,639,796],[639,797,796],[602,638,769],[638,796,769],[603,770,639],[639,770,797]]]],[[10,[[603,604,639],[604,640,639],[770,797,771],[771,797,798],[603,770,604],[604,770,771],[639,640,797],[640,798,797],[603,639,770],[639,797,770],[604,771,640],[640,771,798]]]],[[10,[[604,605,640],[605,641,640],[771,798,772],[772,798,799],[604,771,605],[605,771,772],[640,641,798],[641,799,798],[604,640,771],[640,798,771],[605,772,641],[641,772,799]]]],[[1,[[800,801,802,803]]],[2,[[800,804,805],[800,806,807,808,804]]],[6,[[802,809,810,803],[800,803,810,806]]],[8,[[800,805,811],[800,811,812,813],[800,813,801],[649,814,808,807,650],[649,651,814]]],[10,[[641,649,650],[641,651,649],[605,606,651],[605,651,641],[772,801,813],[772,802,801],[799,809,802],[772,799,802],[773,813,812],[772,813,773],[605,772,606],[606,772,773],[799,806,810],[641,806,799],[641,650,806],[650,807,806],[799,810,809],[605,641,772],[641,799,772],[606,804,814],[606,805,804],[804,808,814],[606,811,805],[606,773,811],[773,812,811],[606,814,651]]]],[[2,[[774,776,805,804,815,816],[804,808,815]]],[8,[[776,782,811,805],[782,783,812,811],[808,814,815],[651,657,815,814],[657,658,817,815],[815,817,816]]],[10,[[606,657,651],[606,658,657],[606,614,658],[773,812,783],[614,776,774],[606,782,776],[606,776,614],[606,783,782],[606,773,783],[606,805,811],[606,804,805],[606,814,804],[804,814,808],[606,811,773],[773,811,812],[606,651,814],[614,816,817],[614,774,816],[614,817,658]]]],[[2,[[774,816,785]]],[8,[[658,659,817],[626,785,816,817,659]]],[10,[[614,659,658],[626,658,659],[614,626,659],[614,785,626],[614,774,785],[614,816,774],[614,817,816],[614,658,817]]]],[[9,[[660,818,819,661],[818,820,821,819]]],[10,[[660,661,662],[820,822,821],[660,662,818],[818,822,820],[662,822,818],[661,819,662],[819,821,822],[662,819,822]]]],[[9,[[636,663,823,794],[661,819,824,823,663],[819,821,824]]],[10,[[636,637,664],[636,664,663],[661,663,664],[661,664,662],[794,823,824],[794,824,795],[795,824,825],[821,825,824],[821,822,825],[636,794,637],[637,794,795],[662,664,822],[664,825,822],[661,662,819],[819,822,821],[662,822,819],[637,795,664],[664,795,825]]]],[[10,[[637,638,664],[638,665,664],[795,825,796],[796,825,826],[637,795,638],[638,795,796],[664,665,825],[665,826,825],[637,664,795],[664,825,795],[638,796,665],[665,796,826]]]],[[10,[[638,639,665],[639,666,665],[796,826,797],[797,826,827],[638,796,639],[639,796,797],[665,666,826],[666,827,826],[638,665,796],[665,826,796],[639,797,666],[666,797,827]]]],[[10,[[639,640,666],[640,667,666],[797,827,798],[798,827,828],[639,797,640],[640,797,798],[666,667,827],[667,828,827],[639,666,797],[666,827,797],[640,798,667],[667,798,828]]]],[[5,[[829,830,831]]],[10,[[640,641,667],[641,669,667],[798,829,799],[798,828,829],[828,830,829],[640,798,641],[641,798,799],[828,831,830],[667,669,831],[667,831,828],[640,667,798],[667,828,798],[669,829,831],[641,799,829],[641,829,669]]]],[[2,[[806,832,807]]],[5,[[829,831,834,832,833],[832,835,833]]],[6,[[809,836,832,810],[832,836,835],[806,810,832]]],[8,[[650,807,832,672],[672,832,834,674]]],[10,[[641,672,674],[641,650,672],[641,674,669],[799,833,835],[799,829,833],[799,835,836],[799,836,809],[650,806,807],[641,799,806],[799,810,806],[641,806,650],[799,809,810],[669,834,831],[669,674,834],[641,829,799],[641,669,829],[669,831,829]]]],[[9,[[660,675,818],[675,676,837,820,818]]],[10,[[660,662,675],[675,677,676],[662,677,675],[820,837,838],[820,838,822],[660,818,662],[818,820,822],[662,818,822],[676,677,837],[677,838,837],[662,822,677],[677,822,838]]]],[[10,[[662,664,677],[664,678,677],[822,838,825],[825,838,839],[662,822,664],[664,822,825],[677,678,838],[678,839,838],[662,677,822],[677,838,822],[664,825,678],[678,825,839]]]],[[10,[[664,665,678],[665,679,678],[825,839,826],[826,839,840],[664,825,665],[665,825,826],[678,679,839],[679,840,839],[664,678,825],[678,839,825],[665,826,679],[679,826,840]]]],[[10,[[665,666,679],[666,680,679],[826,840,827],[827,840,841],[665,826,666],[666,826,827],[679,680,840],[680,841,840],[665,679,826],[679,840,826],[666,827,680],[680,827,841]]]],[[10,[[666,667,680],[667,681,680],[827,841,828],[828,841,842],[666,827,667],[667,827,828],[680,681,841],[681,842,841],[666,680,827],[680,841,827],[667,828,681],[681,828,842]]]],[[5,[[830,843,844,845,831]]],[8,[[684,846,847,685],[844,847,846,845]]],[10,[[667,685,681],[667,684,685],[667,669,684],[828,843,830],[828,842,843],[667,831,669],[667,828,831],[828,830,831],[843,847,844],[842,847,843],[681,685,847],[681,847,842],[667,681,828],[681,842,828],[669,845,846],[669,831,845],[669,846,684]]]],[[5,[[831,845,834]]],[8,[[684,686,846],[674,834,845,846,686]]],[10,[[669,686,684],[674,684,686],[669,674,686],[669,834,674],[669,831,834],[669,845,831],[669,846,845],[669,684,846]]]],[[9,[[687,848,849,688],[676,688,849,837]]],[10,[[676,677,688],[677,687,688],[838,849,848],[837,849,838],[676,837,677],[677,837,838],[677,838,687],[687,838,848]]]],[[9,[[687,689,850,851,848],[689,690,850]]],[10,[[678,689,687],[677,678,687],[689,691,690],[678,691,689],[839,848,851],[839,851,852],[838,848,839],[677,838,678],[678,838,839],[690,691,850],[850,852,851],[691,852,850],[687,848,838],[677,687,838],[678,839,691],[691,839,852]]]],[[10,[[678,679,691],[679,692,691],[839,852,840],[840,852,853],[678,839,679],[679,839,840],[691,692,852],[692,853,852],[678,691,839],[691,852,839],[679,840,692],[692,840,853]]]],[[10,[[679,680,692],[680,693,692],[840,853,841],[841,853,854],[679,840,680],[680,840,841],[692,693,853],[693,854,853],[679,692,840],[692,853,840],[680,841,693],[693,841,854]]]],[[5,[[855,856,857]]],[8,[[694,857,856,695]]],[10,[[693,694,695],[680,681,694],[680,694,693],[841,854,842],[842,854,858],[680,841,681],[681,841,842],[855,858,856],[693,856,854],[693,695,856],[854,856,858],[680,693,841],[693,854,841],[681,857,694],[681,842,857],[855,857,858],[842,858,857]]]],[[0,[[859,860,861],[860,862,861]]],[5,[[843,862,860,844],[855,857,860,859,863]]],[8,[[694,702,860,857],[685,847,860,702],[844,860,847]]],[10,[[681,702,694],[681,685,702],[859,861,863],[858,863,861],[858,861,862],[842,862,843],[842,858,862],[843,844,847],[842,843,847],[681,847,685],[681,842,847],[855,863,858],[855,858,857],[681,857,842],[681,694,857],[842,857,858]]]],[[9,[[703,864,865,704],[850,866,851],[690,704,865,866,850]]],[10,[[690,691,704],[691,703,704],[864,866,865],[852,866,864],[851,865,866],[851,866,852],[850,851,852],[690,850,691],[691,850,852],[691,852,703],[703,852,864]]]],[[9,[[703,706,867,864]]],[10,[[692,706,703],[691,692,703],[692,707,706],[853,864,867],[853,867,868],[852,864,853],[691,852,692],[692,852,853],[706,707,867],[707,868,867],[703,864,852],[691,703,852],[692,853,707],[707,853,868]]]],[[10,[[692,693,707],[693,708,707],[853,868,854],[854,868,869],[692,853,693],[693,853,854],[707,708,868],[708,869,868],[692,707,853],[707,868,853],[693,854,708],[708,854,869]]]],[[5,[[855,870,871,856]]],[8,[[695,856,871,872,709],[709,872,873,710]]],[10,[[693,709,710],[693,695,709],[695,710,709],[693,710,708],[858,871,870],[854,872,871],[854,871,858],[854,869,872],[869,873,872],[693,856,695],[693,854,856],[855,856,858],[854,858,856],[710,873,869],[708,710,869],[693,708,854],[708,869,854],[855,858,870]]]],[[5,[[855,863,870]]],[10,[[858,870,863],[855,858,863],[855,870,858]]]],[[9,[[711,874,712],[706,712,874,875,867]]],[10,[[706,707,712],[707,711,712],[867,875,868],[706,867,707],[707,867,868],[707,874,711],[707,868,874],[868,875,874]]]],[[9,[[711,713,876,877,874],[874,877,875]]],[10,[[707,708,711],[708,713,711],[869,877,876],[868,875,877],[868,877,869],[707,868,708],[708,868,869],[868,874,875],[707,711,874],[707,874,868],[708,869,713],[713,869,876]]]],[[8,[[710,873,878,714]]],[9,[[713,714,878,876]]],[10,[[708,714,713],[708,710,714],[869,878,873],[869,876,878],[708,869,710],[710,869,873],[713,876,869],[708,713,869]]]],[[9,[[879,880,881],[717,881,880,718]]],[10,[[717,718,719],[717,719,881],[719,879,881],[719,880,879],[718,880,719]]]],[[3,[[882,883,884],[882,884,885],[720,884,883,721]]],[9,[[884,887,888,886],[884,886,885],[884,889,887],[884,890,889],[879,891,884,880],[884,891,892,890],[718,880,884,720]]],[10,[[720,721,722],[718,720,722],[718,722,719],[887,889,893],[889,890,893],[890,894,893],[890,892,894],[722,891,879],[719,722,879],[722,892,891],[722,894,892],[718,719,880],[719,879,880],[882,885,883],[721,883,722],[722,883,885],[885,886,894],[722,885,894],[886,893,894]]]],[[3,[[895,896,897],[723,725,883,882,898],[882,885,896,895,898],[721,883,725]]],[9,[[886,888,900,899],[885,886,899,897,896]]],[10,[[721,723,725],[723,727,725],[721,725,722],[722,725,727],[893,894,900],[894,901,900],[722,727,894],[727,901,894],[882,883,885],[722,885,883],[721,722,883],[885,894,886],[722,894,885],[886,894,893],[895,897,901],[897,899,901],[727,895,901],[723,898,895],[723,895,727],[899,900,901]]]],[[3,[[902,903,904],[895,897,903,902,905],[728,906,729],[723,898,907,906,728],[895,905,907,898]]],[4,[[903,908,904],[903,909,908]]],[5,[[903,910,909],[903,912,911],[903,911,913]]],[6,[[903,913,914,910]]],[9,[[899,900,912,903],[897,899,903]]],[10,[[723,729,728],[728,729,733],[723,728,727],[727,728,733],[900,911,912],[900,913,911],[901,914,913],[900,901,913],[901,915,914],[727,733,901],[733,915,901],[723,895,898],[727,901,895],[895,901,897],[723,727,895],[897,901,899],[899,901,900],[904,908,909],[902,904,905],[904,909,905],[733,906,905],[905,906,907],[905,909,910],[733,905,910],[729,906,733],[733,910,915],[910,914,915]]]],[[3,[[916,917,918],[902,904,919,916,918],[902,918,905],[729,906,918,734],[906,907,918],[905,918,907],[734,918,917,737]]],[4,[[904,908,920,919],[908,909,921,920]]],[5,[[909,910,923,922,921]]],[6,[[910,914,924,923]]],[10,[[729,734,733],[734,737,738],[733,734,738],[914,915,924],[915,923,924],[733,923,915],[733,922,923],[733,738,922],[902,905,904],[904,909,908],[904,905,909],[905,907,906],[905,910,909],[733,905,906],[733,910,905],[729,733,906],[910,915,914],[733,915,910],[737,917,916],[737,916,919],[919,920,921],[738,919,921],[737,919,738],[738,921,922]]]],[[3,[[739,742,917,916],[739,916,919,743],[737,917,742]]],[4,[[743,919,920,747],[747,920,921,925,749]]],[5,[[921,922,925]]],[10,[[738,739,743],[737,742,739],[737,739,738],[738,743,749],[743,747,749],[738,925,922],[738,749,925],[737,916,917],[737,919,916],[919,921,920],[737,738,919],[738,921,919],[738,922,921]]]],[[9,[[926,927,928],[763,928,927,764]]],[10,[[763,764,765],[763,765,928],[765,926,928],[765,927,926],[764,927,765]]]],[[9,[[926,929,930,927],[879,881,930,929,931,932],[766,930,767],[764,927,930,766],[717,768,930,881],[767,930,768]]],[10,[[764,767,766],[767,768,769],[717,768,767],[766,767,769],[764,766,765],[765,766,769],[717,719,768],[719,769,768],[931,933,932],[719,881,879],[717,881,719],[769,929,926],[765,769,926],[929,933,931],[769,933,929],[764,765,927],[765,926,927],[769,879,932],[769,932,933],[719,879,769]]]],[[9,[[879,932,934,891],[891,934,892]]],[10,[[719,722,769],[722,770,769],[932,933,935],[932,935,934],[892,934,935],[892,935,894],[722,879,891],[722,891,892],[719,879,722],[722,892,894],[769,770,933],[770,935,933],[769,932,879],[719,769,879],[769,933,932],[722,894,770],[770,894,935]]]],[[10,[[722,727,770],[727,771,770],[894,935,901],[901,935,936],[722,894,727],[727,894,901],[770,771,935],[771,936,935],[722,770,894],[770,935,894],[727,901,771],[771,901,936]]]],[[10,[[727,733,771],[733,772,771],[901,936,915],[915,936,937],[727,901,733],[733,901,915],[771,772,936],[772,937,936],[727,771,901],[771,936,901],[733,915,772],[772,915,937]]]],[[2,[[938,939,940]]],[5,[[922,923,940,941]]],[6,[[923,924,942,940]]],[8,[[938,940,942,943],[940,945,944,941],[939,945,940]]],[10,[[733,738,772],[738,773,772],[924,937,942],[915,937,924],[937,943,942],[733,922,738],[733,923,922],[733,915,923],[915,924,923],[937,938,943],[937,939,938],[772,939,937],[772,945,939],[773,944,945],[772,773,945],[733,772,915],[772,937,915],[738,922,941],[738,941,944],[738,944,773]]]],[[4,[[749,925,777]]],[5,[[777,925,922,941,779]]],[8,[[779,941,944,783]]],[10,[[738,784,783],[738,749,784],[779,783,784],[738,783,773],[738,925,749],[738,922,925],[773,783,944],[738,941,922],[738,944,941],[738,773,944]]]],[[9,[[926,928,948,946,947],[763,794,948,928]]],[10,[[763,795,794],[763,765,795],[946,949,947],[765,928,926],[763,928,765],[795,946,948],[794,795,948],[795,949,946],[795,926,947],[795,947,949],[765,926,795]]]],[[9,[[926,947,950,929],[929,950,931]]],[10,[[765,769,795],[769,796,795],[947,949,951],[947,951,950],[931,950,933],[933,950,951],[769,926,929],[929,931,933],[769,929,933],[765,926,769],[795,796,949],[796,951,949],[795,947,926],[765,795,926],[795,949,947],[769,933,796],[796,933,951]]]],[[10,[[769,770,796],[770,797,796],[933,951,935],[935,951,952],[769,933,770],[770,933,935],[796,797,951],[797,952,951],[769,796,933],[796,951,933],[770,935,797],[797,935,952]]]],[[10,[[770,771,797],[771,798,797],[935,952,936],[936,952,953],[770,935,771],[771,935,936],[797,798,952],[798,953,952],[770,797,935],[797,952,935],[771,936,798],[798,936,953]]]],[[10,[[771,772,798],[772,799,798],[936,953,937],[937,953,954],[771,936,772],[772,936,937],[798,799,953],[799,954,953],[771,798,936],[798,953,936],[772,937,799],[799,937,954]]]],[[1,[[801,955,802]]],[2,[[938,956,957,955,939]]],[6,[[802,955,958,809],[955,957,959,958]]],[8,[[938,943,956],[812,944,945,813],[801,813,945,939,955]]],[10,[[772,802,799],[799,802,809],[772,801,802],[772,813,801],[772,773,813],[773,812,813],[937,956,943],[954,957,956],[937,954,956],[954,959,957],[772,939,945],[937,938,939],[772,937,939],[937,943,938],[773,945,944],[772,945,773],[799,809,958],[799,958,959],[799,959,954],[772,799,937],[799,954,937],[773,944,812]]]],[[8,[[783,944,812]]],[10,[[773,783,812],[773,944,783],[773,812,944]]]],[[9,[[960,961,962],[820,962,961,821]]],[10,[[820,821,822],[820,822,962],[822,960,962],[821,960,822],[821,961,960]]]],[[9,[[963,964,965,966],[960,963,966,961],[946,948,966,965],[794,823,966,948],[823,824,966],[821,961,966,824]]],[10,[[794,824,823],[794,795,824],[821,824,825],[795,825,824],[821,825,822],[964,967,965],[946,965,949],[949,965,967],[795,948,946],[795,946,949],[794,948,795],[822,968,960],[825,964,968],[822,825,968],[825,967,964],[821,960,961],[821,822,960],[795,949,825],[825,949,967]]]],[[10,[[795,796,825],[796,826,825],[949,967,951],[951,967,969],[795,949,796],[796,949,951],[825,826,967],[826,969,967],[795,825,949],[825,967,949],[796,951,826],[826,951,969]]]],[[10,[[796,797,826],[797,827,826],[951,969,952],[952,969,970],[796,951,797],[797,951,952],[826,827,969],[827,970,969],[796,826,951],[826,969,951],[797,952,827],[827,952,970]]]],[[10,[[797,798,827],[798,828,827],[952,970,953],[953,970,971],[797,952,798],[798,952,953],[827,828,970],[828,971,970],[797,827,952],[827,970,952],[798,953,828],[828,953,971]]]],[[5,[[829,972,973,830],[972,974,975,973]]],[10,[[828,829,830],[798,799,829],[798,829,828],[953,974,954],[953,975,974],[953,971,975],[798,953,799],[799,953,954],[828,830,973],[971,973,975],[828,973,971],[798,828,953],[828,971,953],[799,972,829],[799,954,972],[954,974,972]]]],[[5,[[829,833,972],[833,835,976,974,972]]],[6,[[809,958,836],[835,836,958,959,976]]],[10,[[799,833,829],[799,835,833],[799,836,835],[799,809,836],[954,976,959],[954,974,976],[799,958,809],[799,959,958],[799,954,959],[799,829,972],[954,972,974],[799,972,954]]]],[[9,[[960,962,978,977],[820,837,978,962]]],[10,[[820,838,837],[820,822,838],[822,962,960],[820,962,822],[837,838,978],[838,977,978],[822,977,838],[822,960,977]]]],[[9,[[963,979,980,964],[960,977,979,963]]],[10,[[822,825,838],[825,839,838],[964,980,967],[967,980,981],[825,968,964],[825,964,967],[822,960,968],[822,968,825],[839,979,977],[979,981,980],[839,981,979],[838,839,977],[822,977,960],[822,838,977],[825,967,839],[839,967,981]]]],[[10,[[825,826,839],[826,840,839],[967,981,969],[969,981,982],[825,967,826],[826,967,969],[839,840,981],[840,982,981],[825,839,967],[839,981,967],[826,969,840],[840,969,982]]]],[[10,[[826,827,840],[827,841,840],[969,982,970],[970,982,983],[826,969,827],[827,969,970],[840,841,982],[841,983,982],[826,840,969],[840,982,969],[827,970,841],[841,970,983]]]],[[0,[[984,985,986]]],[5,[[985,987,988,986],[987,989,988]]],[10,[[827,828,841],[828,842,841],[970,986,971],[971,986,988],[983,984,986],[970,983,986],[983,990,984],[971,988,989],[827,970,828],[828,970,971],[841,842,983],[842,990,983],[827,841,970],[841,983,970],[984,990,985],[828,985,842],[828,987,985],[842,985,990],[828,971,987],[971,989,987]]]],[[0,[[984,991,992,985]]],[5,[[830,973,987,985,992,843],[973,975,989,987]]],[10,[[828,843,842],[828,830,843],[984,990,991],[971,989,975],[828,973,830],[828,971,973],[971,975,973],[990,992,991],[842,843,992],[842,992,990],[828,985,987],[842,990,985],[984,985,990],[828,842,985],[828,987,971],[971,987,989]]]],[[9,[[993,994,995],[977,978,995,994],[848,993,995,849],[837,849,995,978]]],[10,[[837,838,849],[838,848,849],[838,978,977],[837,978,838],[838,993,848],[977,994,993],[838,977,993]]]],[[9,[[996,997,998,999,1000],[998,1001,999],[993,1002,1000,999,994],[979,999,1001,980],[977,994,999,979],[848,851,1002,993]]],[10,[[839,851,848],[838,839,848],[839,852,851],[981,998,997],[981,1001,998],[980,1001,981],[979,980,981],[839,977,979],[839,979,981],[838,977,839],[852,996,1003],[852,1003,1002],[851,852,1002],[977,993,994],[838,848,993],[838,993,977],[839,996,852],[839,997,996],[839,981,997]]]],[[9,[[996,1004,997]]],[10,[[839,840,852],[840,853,852],[997,1004,1005],[981,997,982],[982,997,1005],[839,981,840],[840,981,982],[853,1004,996],[852,853,996],[853,1005,1004],[839,997,981],[839,996,997],[839,852,996],[840,982,853],[853,982,1005]]]],[[10,[[840,841,853],[841,854,853],[982,1005,983],[983,1005,1006],[840,982,841],[841,982,983],[853,854,1005],[854,1006,1005],[840,853,982],[853,1005,982],[841,983,854],[854,983,1006]]]],[[10,[[841,842,854],[842,858,854],[983,1006,990],[990,1006,1007],[841,983,842],[842,983,990],[854,858,1006],[858,1007,1006],[841,854,983],[854,1006,983],[842,990,858],[858,990,1007]]]],[[0,[[859,861,1009,1008],[861,862,992,991,1010,1009]]],[5,[[843,992,862],[859,1008,863]]],[10,[[859,863,861],[858,862,861],[858,861,863],[842,862,858],[842,843,862],[990,1007,991],[991,1007,1010],[842,992,843],[842,990,992],[990,991,992],[1007,1009,1010],[1007,1008,1009],[863,1008,1007],[858,863,1007],[842,858,990],[858,1007,990]]]],[[9,[[996,1000,1012,1011],[1011,1012,1013],[1000,1002,1012],[864,1013,1012,865],[851,866,1012,1002],[865,1012,866]]],[10,[[851,866,865],[864,865,866],[852,864,866],[851,852,866],[852,1003,996],[852,1002,1003],[851,1002,852],[852,996,1011],[864,1011,1013],[852,1011,864]]]],[[9,[[996,1011,1014,1004],[1011,1013,1016,1017,1015,1014],[864,867,1016,1013]]],[10,[[853,867,864],[852,853,864],[853,868,867],[1004,1014,1005],[1005,1014,1015],[853,996,1004],[853,1004,1005],[852,996,853],[867,868,1016],[868,1017,1016],[852,1011,996],[852,864,1011],[864,1013,1011],[853,1017,868],[853,1015,1017],[853,1005,1015]]]],[[9,[[1018,1019,1020,1021],[1015,1017,1021,1020]]],[10,[[853,854,868],[854,869,868],[1006,1020,1019],[1005,1015,1020],[1005,1020,1006],[853,1005,854],[854,1005,1006],[869,1018,1021],[869,1021,1017],[868,869,1017],[853,1015,1005],[853,1017,1015],[853,868,1017],[854,1018,869],[854,1006,1018],[1006,1019,1018]]]],[[5,[[870,1023,1024,1022,871]]],[8,[[871,1022,1025,872],[872,1025,873]]],[9,[[1018,1026,1019]]],[10,[[854,871,872],[854,858,871],[858,870,871],[869,872,873],[854,872,869],[1007,1024,1023],[1007,1026,1024],[1006,1026,1007],[1006,1019,1026],[854,1006,858],[858,1006,1007],[1022,1024,1026],[1018,1022,1026],[869,1025,1022],[869,1022,1018],[869,873,1025],[1006,1018,1019],[854,869,1018],[854,1018,1006],[858,1007,870],[870,1007,1023]]]],[[0,[[1008,1009,1028,1027],[1009,1010,1028]]],[5,[[863,1008,1027,1023,870]]],[10,[[858,863,870],[1007,1028,1010],[1023,1027,1028],[1007,1023,1028],[1007,1009,1008],[863,1007,1008],[1007,1010,1009],[858,1007,863],[870,1023,1007],[858,870,1007]]]],[[9,[[1016,1029,1017],[867,875,1029,1016]]],[10,[[867,868,875],[868,1016,1017],[867,1016,868],[868,1029,875],[868,1017,1029]]]],[[9,[[1018,1021,1030],[1017,1029,1031,1030,1021],[876,1032,877],[875,877,1032,1031,1029]]],[10,[[868,877,875],[868,869,877],[869,876,877],[869,1021,1018],[869,1017,1021],[868,1017,869],[868,1029,1017],[868,875,1029],[869,1018,1030],[1030,1031,1032],[869,1030,1032],[869,1032,876]]]],[[5,[[1022,1024,1033,1034]]],[8,[[1022,1034,1025],[873,1025,1034,878]]],[9,[[1018,1030,1034,1033,1026],[1030,1031,1034],[876,878,1034,1032],[1031,1032,1034]]],[10,[[869,878,876],[869,873,878],[1024,1026,1033],[869,1022,1025],[869,1018,1022],[1018,1026,1022],[1022,1026,1024],[869,1025,873],[869,1030,1018],[1030,1032,1031],[869,1032,1030],[869,876,1032]]]],[[9,[[1035,1036,1037,1038],[1036,1039,1037]]],[10,[[1037,1039,1038],[1038,1039,1040],[1035,1039,1036],[1035,1040,1039],[1035,1038,1040]]]],[[9,[[1035,1038,1042,1041]]],[10,[[1038,1040,1042],[1040,1043,1042],[1035,1041,1040],[1040,1041,1043],[1035,1040,1038],[1041,1042,1043]]]],[[5,[[1044,1045,1046]]],[9,[[1041,1042,1046,1045]]],[10,[[1042,1043,1046],[1043,1044,1046],[1041,1044,1043],[1041,1045,1044],[1041,1043,1042]]]],[[9,[[887,1036,1035,888],[887,889,1048,1047,1039,1036],[889,890,1049,1048],[890,892,1050,1049]]],[10,[[890,893,894],[887,893,889],[889,893,890],[890,894,892],[1039,1047,1040],[1035,1036,1039],[1035,1039,1040],[892,894,1050],[893,1035,1049],[1035,1048,1049],[1035,1047,1048],[1035,1040,1047],[893,1049,894],[894,1049,1050]]]],[[9,[[888,1035,1041,900],[1047,1048,1051],[1048,1049,1053,1052,1051],[1049,1050,1053]]],[10,[[893,900,894],[894,900,901],[1051,1052,1054],[1047,1051,1054],[1040,1047,1043],[1043,1047,1054],[1035,1040,1041],[1040,1043,1041],[894,1053,1050],[894,901,1053],[1052,1053,1054],[901,1054,1053],[893,894,1049],[893,1049,1035],[1035,1047,1040],[1035,1048,1047],[1035,1049,1048],[894,1050,1049],[900,1041,901],[901,1041,1054],[1041,1043,1054]]]],[[5,[[911,912,1045,1044,1055],[911,1055,1056,1057,913]]],[6,[[913,1057,1058,914]]],[9,[[900,1041,1045,912]]],[10,[[900,912,911],[900,911,913],[901,913,914],[900,913,901],[901,914,915],[1043,1055,1044],[1043,1054,1055],[1054,1056,1055],[1041,1044,1045],[1041,1043,1044],[901,1056,1054],[901,1057,1056],[901,1058,1057],[901,915,1058],[900,901,1041],[1041,1054,1043],[901,1054,1041],[914,1058,915]]]],[[6,[[914,1058,924]]],[10,[[914,924,915],[915,924,1058],[914,915,1058]]]],[[9,[[931,1059,932]]],[10,[[931,932,933],[931,933,1059],[932,1059,933]]]],[[9,[[932,1059,1060,934],[892,934,1060,1061,1050]]],[10,[[892,935,934],[932,934,935],[932,935,933],[892,894,935],[892,1050,894],[933,1060,1059],[933,935,1060],[935,1061,1060],[932,933,1059],[935,1050,1061],[894,1050,935]]]],[[9,[[1052,1053,1063,1062],[1050,1061,1063,1053]]],[10,[[894,901,935],[901,936,935],[1052,1062,1054],[1054,1062,1064],[1052,1054,1053],[894,1053,901],[894,1050,1053],[901,1053,1054],[935,1063,1061],[935,936,1063],[1062,1063,1064],[936,1064,1063],[894,935,1050],[935,1061,1050],[901,1054,936],[936,1054,1064]]]],[[5,[[1056,1065,1066,1057]]],[6,[[1057,1066,1058]]],[10,[[901,915,936],[915,937,936],[1056,1064,1065],[1054,1064,1056],[1064,1067,1065],[901,1057,1058],[901,1056,1057],[901,1054,1056],[901,1058,915],[936,937,1064],[937,1067,1064],[901,936,1054],[936,1064,1054],[937,1066,1065],[937,1065,1067],[915,1058,1066],[915,1066,937]]]],[[5,[[1065,1068,1069,1066]]],[6,[[924,1058,1066,1069,942]]],[8,[[942,1069,1070,943],[1068,1071,1070,1069]]],[10,[[924,942,937],[937,942,943],[915,924,937],[1065,1067,1068],[1067,1071,1068],[915,1058,924],[937,943,1070],[1067,1070,1071],[937,1070,1067],[915,1066,1058],[937,1065,1066],[915,937,1066],[937,1067,1065]]]],[[9,[[946,1072,947]]],[10,[[946,947,949],[946,949,1072],[947,1072,949]]]],[[9,[[947,1072,1073,950],[931,950,1073,1074,1075,1059],[1074,1076,1075]]],[10,[[947,950,951],[931,933,950],[933,951,950],[947,951,949],[931,1059,933],[951,1073,1072],[949,951,1072],[951,1074,1073],[951,1076,1074],[947,949,1072],[951,1075,1076],[933,1059,1075],[933,1075,951]]]],[[9,[[1059,1075,1060],[1060,1075,1076,1077,1078,1061]]],[10,[[933,935,951],[935,952,951],[1077,1079,1078],[935,1060,1061],[933,1059,1060],[933,1060,935],[951,1077,1076],[951,952,1077],[952,1079,1077],[933,1075,1059],[933,951,1075],[951,1076,1075],[952,1078,1079],[935,1061,1078],[935,1078,952]]]],[[9,[[1062,1063,1080],[1061,1078,1080,1063]]],[10,[[935,936,952],[936,953,952],[1062,1080,1064],[1078,1081,1080],[1064,1080,1081],[1078,1079,1081],[1062,1064,1063],[935,1063,936],[935,1061,1063],[936,1063,1064],[952,953,1079],[953,1081,1079],[935,1078,1061],[935,952,1078],[952,1079,1078],[936,1064,953],[953,1064,1081]]]],[[8,[[1082,1083,1084]]],[10,[[936,937,953],[937,954,953],[1064,1083,1067],[1064,1081,1083],[1081,1084,1083],[936,1064,937],[937,1064,1067],[1081,1082,1084],[953,954,1082],[953,1082,1081],[936,953,1064],[953,1081,1064],[954,1083,1082],[937,1067,1083],[937,1083,954]]]],[[2,[[956,1085,1086,957]]],[6,[[957,1086,959]]],[8,[[943,1070,1087,1085,956],[1070,1071,1083,1082,1087]]],[10,[[954,957,959],[954,956,957],[937,943,956],[937,956,954],[1067,1083,1071],[937,1070,943],[937,1067,1070],[1067,1071,1070],[954,1085,1087],[954,1086,1085],[954,959,1086],[954,1087,1082],[937,1083,1067],[937,954,1083],[954,1082,1083]]]],[[9,[[964,1088,1089,965],[946,965,1089,1072]]],[10,[[964,965,967],[946,949,965],[949,967,965],[946,1072,949],[964,967,1088],[967,1089,1088],[949,1072,1089],[949,1089,967]]]],[[9,[[1090,1091,1092],[1090,1093,1094,1091],[1088,1092,1091,1089],[1072,1089,1091,1073],[1073,1091,1074],[1074,1091,1094,1095,1076]]],[10,[[949,951,967],[951,969,967],[1093,1096,1094],[1094,1096,1095],[951,1072,1073],[951,1073,1074],[949,1072,951],[951,1074,1076],[967,1092,1088],[969,1090,1092],[967,969,1092],[1090,1096,1093],[969,1096,1090],[949,1089,1072],[949,967,1089],[967,1088,1089],[969,1095,1096],[951,1076,1095],[951,1095,969]]]],[[9,[[1076,1095,1077]]],[10,[[951,952,969],[952,970,969],[1077,1095,1096],[1077,1097,1079],[1077,1096,1097],[952,1077,1079],[951,1076,1077],[951,1077,952],[969,970,1096],[970,1097,1096],[951,1095,1076],[951,969,1095],[969,1096,1095],[952,1079,970],[970,1079,1097]]]],[[8,[[1098,1099,1100]]],[10,[[952,953,970],[953,971,970],[1081,1099,1098],[1079,1097,1099],[1079,1099,1081],[952,1079,953],[953,1079,1081],[1097,1100,1099],[970,971,1100],[970,1100,1097],[952,970,1079],[970,1097,1079],[953,1100,971],[953,1081,1100],[1081,1098,1100]]]],[[5,[[974,1101,1102,975]]],[8,[[1103,1104,1105,1106],[1082,1084,1106,1105],[1098,1100,1102,1101,1104,1103]]],[10,[[953,975,971],[953,974,975],[953,954,974],[1081,1106,1084],[1081,1103,1106],[1081,1098,1103],[953,1082,954],[953,1081,1082],[1081,1084,1082],[971,1102,1100],[971,975,1102],[1081,1100,1098],[953,971,1100],[953,1100,1081],[954,1101,974],[1101,1107,1104],[954,1107,1101],[954,1082,1107]]]],[[2,[[1085,1108,1086]]],[5,[[974,976,1108,1101]]],[6,[[959,1086,1108,976]]],[8,[[1104,1108,1105],[1085,1087,1108],[1082,1105,1108,1087],[1101,1108,1104]]],[10,[[954,976,974],[954,959,976],[954,1086,959],[954,1085,1086],[954,1087,1085],[954,1082,1087],[954,974,1101],[1101,1104,1107],[954,1101,1107],[954,1107,1082]]]],[[9,[[1109,1110,1111],[964,980,1111,1110,1088]]],[10,[[964,967,980],[967,981,980],[964,1088,967],[980,981,1111],[981,1109,1111],[981,1110,1109],[967,1088,1110],[967,1110,981]]]],[[9,[[1090,1092,1110,1109,1112],[1090,1112,1113,1093],[1088,1110,1092]]],[10,[[967,969,981],[969,982,981],[1093,1113,1096],[1096,1113,1114],[969,1092,1090],[1090,1093,1096],[969,1090,1096],[967,1088,1092],[967,1092,969],[982,1112,1109],[981,982,1109],[1112,1114,1113],[982,1114,1112],[967,1110,1088],[967,981,1110],[981,1109,1110],[969,1096,982],[982,1096,1114]]]],[[10,[[969,970,982],[970,983,982],[1096,1114,1097],[1097,1114,1115],[969,1096,970],[970,1096,1097],[982,983,1114],[983,1115,1114],[969,982,1096],[982,1114,1096],[970,1097,983],[983,1097,1115]]]],[[0,[[1116,1117,1118],[1117,1119,1120,1121,1118],[984,986,1120,1119,1122],[1120,1123,1121]]],[5,[[986,988,1120],[988,989,1124,1120]]],[8,[[1099,1123,1120,1124,1100]]],[10,[[983,986,984],[983,984,990],[970,986,983],[971,988,986],[970,971,986],[971,989,988],[1115,1116,1118],[1115,1118,1121],[1097,1121,1123],[1097,1115,1121],[1097,1123,1099],[970,1100,971],[970,1097,1100],[1097,1099,1100],[1115,1117,1116],[983,1117,1115],[983,1119,1117],[983,1122,1119],[983,990,1122],[970,983,1097],[983,1115,1097],[984,1122,990],[971,1124,989],[971,1100,1124]]]],[[0,[[984,1122,991]]],[5,[[975,1102,1124,989]]],[8,[[1100,1124,1102]]],[10,[[984,991,990],[971,975,989],[971,1102,975],[971,1100,1102],[990,991,1122],[984,990,1122],[971,1124,1100],[971,989,1124]]]],[[9,[[997,1125,998],[998,1125,1109,1111,1001],[980,1001,1111]]],[10,[[981,997,998],[981,998,1001],[980,981,1001],[981,1111,1109],[980,1111,981],[981,1125,997],[981,1109,1125]]]],[[9,[[1126,1127,1128],[1127,1129,1130,1128],[997,1004,1131,1128,1125],[1126,1128,1131,1132],[1109,1125,1128,1112],[1112,1128,1133,1113],[1128,1135,1134],[1128,1136,1137],[1128,1137,1138],[1128,1138,1133],[1128,1130,1135],[1128,1139,1136],[1128,1134,1139]]],[10,[[981,982,997],[997,1005,1004],[982,1005,997],[1114,1133,1129],[1129,1133,1140],[1129,1139,1130],[1129,1140,1139],[1130,1139,1135],[1113,1133,1114],[1133,1138,1140],[1134,1135,1139],[1136,1139,1140],[982,1109,1112],[1112,1113,1114],[982,1112,1114],[981,1109,982],[1004,1005,1131],[1005,1132,1131],[981,1125,1109],[981,997,1125],[982,1126,1132],[982,1114,1126],[1126,1129,1127],[1114,1129,1126],[982,1132,1005]]]],[[9,[[1126,1141,1142,1143,1127],[1127,1143,1129],[1126,1132,1141]]],[10,[[982,983,1005],[983,1006,1005],[1115,1143,1142],[1115,1142,1144],[1114,1129,1143],[1114,1143,1115],[982,1114,983],[983,1114,1115],[1005,1141,1132],[1005,1006,1141],[1141,1144,1142],[1006,1144,1141],[1126,1127,1129],[1114,1126,1129],[982,1126,1114],[982,1132,1126],[982,1005,1132],[983,1115,1006],[1006,1115,1144]]]],[[0,[[1116,1145,1146,1117],[1117,1146,1147,1119],[1119,1147,1122]]],[10,[[983,990,1006],[990,1007,1006],[1116,1144,1148],[1115,1144,1116],[1144,1149,1148],[983,1117,1119],[983,1115,1117],[1115,1116,1117],[983,1119,1122],[983,1122,990],[1006,1007,1144],[1007,1149,1144],[983,1006,1115],[1006,1144,1115],[1146,1148,1149],[1007,1147,1146],[1007,1146,1149],[990,1122,1147],[990,1147,1007]]]],[[0,[[1145,1150,1151,1146],[1146,1151,1152,1147],[991,1122,1147,1152,1010]]],[10,[[991,1010,1007],[990,991,1007],[1148,1149,1150],[990,1122,991],[1149,1151,1150],[1007,1151,1149],[1007,1152,1151],[1007,1010,1152],[1007,1149,1146],[1146,1149,1148],[1007,1146,1147],[990,1147,1122],[990,1007,1147]]]],[[9,[[1004,1014,1131],[1014,1015,1132,1131]]],[10,[[1004,1005,1014],[1005,1015,1014],[1004,1131,1005],[1005,1131,1132],[1005,1132,1015]]]],[[9,[[1019,1153,1142,1141,1020],[1015,1020,1141,1132]]],[10,[[1005,1020,1015],[1005,1006,1020],[1006,1019,1020],[1142,1153,1144],[1141,1142,1144],[1005,1141,1006],[1005,1132,1141],[1006,1141,1144],[1005,1015,1132],[1006,1153,1019],[1006,1144,1153]]]],[[5,[[1023,1154,1024]]],[9,[[1019,1026,1155,1153]]],[10,[[1007,1023,1024],[1007,1024,1026],[1006,1026,1019],[1006,1007,1026],[1149,1153,1155],[1149,1155,1156],[1144,1153,1149],[1006,1144,1007],[1007,1144,1149],[1024,1154,1155],[1154,1156,1155],[1024,1155,1026],[1006,1153,1144],[1006,1019,1153],[1007,1154,1023],[1007,1149,1154],[1149,1156,1154]]]],[[0,[[1157,1158,1159],[1150,1157,1159,1151],[1027,1028,1159,1160,1161,1162],[1151,1159,1152],[1010,1152,1159,1028],[1158,1160,1159]]],[5,[[1023,1027,1162,1154]]],[10,[[1023,1028,1027],[1007,1010,1028],[1007,1028,1023],[1149,1157,1150],[1149,1158,1157],[1149,1156,1158],[1156,1160,1158],[1156,1161,1160],[1007,1151,1152],[1007,1149,1151],[1149,1150,1151],[1007,1152,1010],[1156,1162,1161],[1154,1162,1156],[1149,1154,1156],[1007,1023,1154],[1007,1154,1149]]]],[[5,[[1024,1154,1163,1033]]],[9,[[1026,1033,1163,1164,1155]]],[10,[[1024,1033,1026],[1155,1164,1156],[1024,1155,1154],[1024,1026,1155],[1154,1155,1156],[1154,1156,1163],[1156,1164,1163]]]],[[0,[[1161,1165,1162]]],[5,[[1154,1162,1165,1166,1163]]],[9,[[1163,1166,1164]]],[10,[[1161,1166,1165],[1156,1166,1161],[1156,1164,1166],[1154,1156,1162],[1156,1161,1162],[1154,1163,1156],[1156,1163,1164]]]],[[9,[[1037,1167,1038],[1037,1039,1168,1167]]],[10,[[1037,1038,1039],[1038,1040,1039],[1039,1040,1168],[1038,1167,1168],[1038,1168,1040]]]],[[5,[[1169,1170,1171,1172]]],[9,[[1038,1167,1173,1172,1171,1042],[1167,1168,1174,1173]]],[10,[[1038,1042,1040],[1040,1042,1043],[1172,1173,1174],[1169,1172,1174],[1168,1169,1174],[1168,1170,1169],[1043,1170,1168],[1040,1043,1168],[1038,1168,1167],[1038,1040,1168],[1043,1171,1170],[1042,1171,1043]]]],[[5,[[1044,1046,1171,1170]]],[9,[[1042,1171,1046]]],[10,[[1043,1046,1044],[1042,1046,1043],[1043,1044,1170],[1042,1043,1171],[1043,1170,1171]]]],[[9,[[1039,1047,1168]]],[10,[[1039,1040,1047],[1039,1168,1040],[1040,1168,1047]]]],[[5,[[1169,1175,1176,1177,1170],[1176,1178,1177]]],[9,[[1047,1051,1180,1179,1174,1168],[1051,1052,1180]]],[10,[[1040,1043,1047],[1047,1054,1051],[1043,1054,1047],[1051,1054,1052],[1169,1174,1179],[1169,1179,1175],[1043,1168,1170],[1168,1169,1170],[1168,1174,1169],[1040,1168,1043],[1175,1179,1176],[1176,1180,1178],[1176,1179,1180],[1054,1178,1180],[1052,1054,1180],[1040,1047,1168],[1054,1170,1177],[1054,1177,1178],[1043,1170,1054]]]],[[5,[[1044,1170,1177,1055],[1055,1177,1178,1056]]],[10,[[1054,1055,1056],[1043,1044,1055],[1043,1055,1054],[1043,1170,1044],[1054,1056,1178],[1054,1177,1170],[1043,1054,1170],[1054,1178,1177]]]],[[5,[[1175,1181,1176],[1176,1181,1182,1178]]],[9,[[1179,1180,1183],[1052,1062,1184,1183,1180]]],[10,[[1052,1054,1062],[1054,1064,1062],[1175,1183,1181],[1175,1179,1183],[1181,1183,1182],[1182,1183,1184],[1182,1184,1185],[1176,1178,1180],[1176,1180,1179],[1175,1176,1179],[1054,1180,1178],[1052,1180,1054],[1062,1064,1184],[1064,1185,1184],[1064,1178,1182],[1064,1182,1185],[1054,1178,1064]]]],[[5,[[1056,1178,1182,1186,1187,1065]]],[8,[[1186,1189,1188,1187]]],[10,[[1056,1065,1064],[1064,1065,1067],[1054,1056,1064],[1182,1185,1186],[1185,1189,1186],[1054,1178,1056],[1064,1189,1185],[1064,1188,1189],[1064,1067,1188],[1064,1182,1178],[1054,1064,1178],[1064,1185,1182],[1065,1187,1067],[1067,1187,1188]]]],[[5,[[1065,1187,1068]]],[8,[[1068,1187,1188,1071]]],[10,[[1065,1068,1067],[1067,1068,1071],[1067,1071,1188],[1065,1067,1187],[1067,1188,1187]]]],[[9,[[1077,1190,1078]]],[10,[[1077,1078,1079],[1077,1079,1190],[1078,1190,1079]]]],[[9,[[1062,1080,1192,1191,1184],[1078,1190,1192,1080]]],[10,[[1062,1064,1080],[1064,1081,1080],[1078,1080,1081],[1078,1081,1079],[1184,1191,1185],[1185,1191,1193],[1062,1184,1064],[1064,1184,1185],[1191,1192,1193],[1081,1193,1192],[1081,1192,1190],[1079,1081,1190],[1078,1079,1190],[1064,1185,1081],[1081,1185,1193]]]],[[8,[[1194,1195,1196],[1083,1188,1189,1196,1195,1084]]],[10,[[1081,1083,1084],[1064,1067,1083],[1064,1083,1081],[1185,1196,1189],[1185,1193,1196],[1193,1194,1196],[1064,1188,1067],[1064,1189,1188],[1064,1185,1189],[1081,1194,1193],[1081,1195,1194],[1081,1084,1195],[1064,1081,1185],[1081,1193,1185],[1067,1188,1083]]]],[[8,[[1071,1188,1083]]],[10,[[1067,1071,1083],[1067,1188,1071],[1067,1083,1188]]]],[[9,[[1093,1197,1198,1094],[1094,1198,1095]]],[10,[[1093,1094,1096],[1094,1095,1096],[1093,1096,1197],[1096,1198,1197],[1095,1198,1096]]]],[[9,[[1197,1199,1200,1198],[1077,1095,1198,1200,1190]]],[10,[[1077,1096,1095],[1077,1097,1096],[1077,1079,1097],[1077,1190,1079],[1096,1097,1197],[1097,1199,1197],[1095,1096,1198],[1096,1197,1198],[1097,1200,1199],[1079,1190,1200],[1079,1200,1097]]]],[[0,[[1201,1202,1203,1204],[1203,1205,1204]]],[8,[[1098,1206,1202,1201,1099]]],[9,[[1199,1207,1208,1209,1200],[1191,1192,1210],[1190,1200,1209,1210,1192],[1207,1211,1208]]],[10,[[1079,1099,1097],[1079,1081,1099],[1081,1098,1099],[1202,1210,1209],[1202,1209,1203],[1202,1206,1210],[1203,1209,1208],[1203,1208,1205],[1205,1208,1211],[1193,1210,1206],[1191,1210,1193],[1191,1193,1192],[1081,1190,1192],[1081,1192,1193],[1079,1190,1081],[1199,1204,1207],[1097,1201,1204],[1097,1204,1199],[1204,1205,1207],[1097,1099,1201],[1205,1211,1207],[1079,1200,1190],[1079,1097,1200],[1097,1199,1200],[1081,1206,1098],[1081,1193,1206]]]],[[8,[[1103,1106,1195,1194,1212],[1084,1195,1106],[1098,1103,1212,1206]]],[10,[[1081,1103,1098],[1081,1106,1103],[1081,1084,1106],[1193,1212,1194],[1193,1206,1212],[1081,1195,1084],[1081,1194,1195],[1081,1193,1194],[1081,1206,1193],[1081,1098,1206]]]],[[9,[[1093,1113,1213,1197]]],[10,[[1093,1096,1113],[1096,1114,1113],[1093,1197,1096],[1113,1114,1213],[1096,1213,1114],[1096,1197,1213]]]],[[9,[[1197,1213,1214,1215,1199],[1216,1217,1218],[1217,1219,1220,1218],[1214,1220,1219,1215]]],[10,[[1096,1097,1114],[1097,1115,1114],[1097,1197,1199],[1096,1197,1097],[1114,1214,1213],[1214,1218,1220],[1115,1218,1214],[1114,1115,1214],[1115,1216,1218],[1096,1213,1197],[1096,1114,1213],[1097,1215,1115],[1097,1199,1215],[1115,1215,1217],[1215,1219,1217],[1115,1217,1216]]]],[[0,[[1116,1118,1222,1223,1221],[1118,1121,1222],[1121,1123,1201,1204,1222],[1204,1205,1224,1222],[1222,1224,1225],[1222,1225,1223]]],[8,[[1099,1201,1123]]],[9,[[1199,1215,1207],[1216,1226,1227,1217],[1217,1227,1228,1219],[1207,1215,1219,1228,1211]]],[10,[[1115,1118,1116],[1115,1121,1118],[1097,1121,1115],[1097,1123,1121],[1097,1099,1123],[1223,1225,1227],[1221,1223,1226],[1223,1227,1226],[1205,1211,1224],[1211,1227,1224],[1224,1227,1225],[1211,1228,1227],[1097,1201,1099],[1097,1204,1201],[1204,1207,1205],[1199,1207,1204],[1097,1199,1204],[1205,1207,1211],[1116,1221,1216],[1216,1221,1226],[1115,1116,1216],[1097,1215,1199],[1215,1217,1219],[1115,1217,1215],[1097,1115,1215],[1115,1216,1217]]]],[[9,[[1129,1229,1130],[1113,1133,1230,1213],[1134,1135,1232,1231],[1136,1233,1234,1137],[1137,1234,1235,1138],[1133,1138,1235,1230],[1130,1229,1232,1135],[1136,1139,1236,1233],[1134,1231,1236,1139]]],[10,[[1130,1135,1139],[1129,1130,1139],[1114,1129,1133],[1129,1140,1133],[1129,1139,1140],[1113,1114,1133],[1133,1140,1138],[1134,1139,1135],[1136,1140,1139],[1113,1213,1114],[1114,1237,1129],[1129,1237,1234],[1129,1234,1236],[1129,1232,1229],[1129,1236,1232],[1114,1213,1237],[1234,1237,1235],[1231,1232,1236],[1233,1236,1234]]]],[[9,[[1142,1238,1143],[1129,1143,1238,1239,1229],[1213,1230,1214],[1231,1232,1241,1240],[1216,1218,1234,1233,1242],[1218,1220,1235,1234],[1214,1230,1235,1220],[1229,1239,1243,1241,1232],[1233,1236,1244,1242],[1231,1240,1244,1236]]],[10,[[1114,1143,1129],[1115,1142,1143],[1114,1115,1143],[1115,1144,1142],[1115,1214,1218],[1214,1220,1218],[1114,1213,1214],[1114,1214,1115],[1115,1218,1216],[1142,1144,1238],[1144,1239,1238],[1144,1243,1239],[1129,1229,1232],[1114,1129,1237],[1129,1234,1237],[1129,1236,1234],[1129,1232,1236],[1114,1237,1213],[1234,1235,1237],[1231,1236,1232],[1233,1234,1236],[1240,1241,1244],[1115,1244,1241],[1144,1241,1243],[1115,1241,1144],[1216,1242,1244],[1115,1216,1244]]]],[[0,[[1116,1221,1245,1145]]],[9,[[1240,1241,1247,1246],[1216,1242,1248,1226],[1241,1243,1249,1247],[1242,1244,1250,1248],[1240,1246,1250,1244]]],[10,[[1116,1148,1144],[1144,1148,1149],[1115,1116,1144],[1221,1247,1245],[1221,1250,1247],[1221,1226,1250],[1245,1247,1249],[1245,1249,1251],[1246,1247,1250],[1226,1248,1250],[1115,1216,1116],[1116,1216,1221],[1216,1226,1221],[1149,1249,1243],[1144,1149,1243],[1149,1251,1249],[1240,1244,1241],[1115,1144,1241],[1144,1243,1241],[1115,1241,1244],[1216,1244,1242],[1115,1244,1216],[1148,1245,1251],[1148,1251,1149]]]],[[0,[[1252,1253,1254],[1145,1245,1253,1252,1150]]],[10,[[1148,1150,1149],[1245,1251,1253],[1251,1254,1253],[1251,1252,1254],[1149,1150,1252],[1149,1252,1251],[1148,1251,1245],[1148,1149,1251]]]],[[9,[[1142,1153,1255,1238],[1238,1255,1256,1239],[1239,1256,1243]]],[10,[[1142,1144,1153],[1142,1238,1144],[1144,1238,1239],[1144,1239,1243],[1144,1255,1153],[1144,1256,1255],[1144,1243,1256]]]],[[9,[[1153,1155,1257,1255],[1255,1257,1258,1259,1260,1256],[1243,1256,1260,1249]]],[10,[[1149,1155,1153],[1144,1149,1153],[1149,1156,1155],[1251,1260,1259],[1249,1260,1251],[1149,1243,1249],[1149,1249,1251],[1144,1243,1149],[1155,1156,1257],[1156,1258,1257],[1144,1255,1256],[1144,1153,1255],[1144,1256,1243],[1149,1258,1156],[1149,1259,1258],[1149,1251,1259]]]],[[0,[[1157,1252,1254,1261,1158],[1150,1252,1157],[1160,1262,1161],[1158,1261,1263,1262,1160]]],[9,[[1258,1264,1259]]],[10,[[1156,1158,1160],[1149,1158,1156],[1149,1157,1158],[1149,1150,1157],[1156,1160,1161],[1251,1261,1254],[1251,1259,1261],[1259,1264,1261],[1261,1264,1263],[1149,1252,1150],[1149,1251,1252],[1251,1254,1252],[1262,1263,1264],[1156,1161,1262],[1258,1262,1264],[1156,1262,1258],[1149,1259,1251],[1149,1258,1259],[1149,1156,1258]]]],[[9,[[1155,1164,1265,1257],[1257,1265,1258]]],[10,[[1155,1156,1164],[1155,1257,1156],[1156,1257,1258],[1156,1265,1164],[1156,1258,1265]]]],[[0,[[1161,1262,1266,1267,1165],[1262,1263,1268,1266]]],[5,[[1165,1267,1269,1166]]],[9,[[1164,1166,1269,1270,1271,1265],[1258,1265,1271,1264]]],[10,[[1161,1165,1166],[1156,1161,1166],[1156,1166,1164],[1263,1271,1272],[1263,1264,1271],[1270,1272,1271],[1156,1262,1161],[1156,1258,1262],[1258,1264,1262],[1262,1264,1263],[1156,1265,1258],[1156,1164,1265],[1266,1273,1267],[1266,1272,1270],[1266,1270,1273]]]],[[0,[[1266,1274,1275,1267],[1266,1268,1274]]],[5,[[1267,1275,1276,1269]]],[9,[[1269,1276,1270]]],[10,[[1270,1274,1272],[1274,1276,1275],[1270,1276,1274],[1266,1267,1273],[1266,1270,1272],[1266,1273,1270]]]],[[5,[[1169,1172,1277,1278]]],[9,[[1172,1173,1277],[1173,1174,1278,1277]]],[10,[[1169,1174,1172],[1172,1174,1173],[1169,1278,1174]]]],[[5,[[1169,1278,1279,1175]]],[9,[[1174,1179,1279,1278]]],[10,[[1169,1175,1179],[1169,1179,1174],[1169,1174,1278],[1175,1279,1179]]]],[[5,[[1175,1279,1281,1280,1181],[1181,1280,1282,1283,1182]]],[8,[[1284,1285,1286,1287],[1282,1285,1284,1288,1283]]],[9,[[1179,1183,1289,1281,1279],[1183,1184,1287,1286,1289]]],[10,[[1175,1181,1183],[1181,1182,1183],[1175,1183,1179],[1182,1185,1184],[1182,1184,1183],[1280,1281,1289],[1280,1289,1282],[1282,1289,1285],[1285,1289,1286],[1175,1179,1279],[1184,1284,1287],[1184,1185,1284],[1185,1288,1284],[1182,1283,1185],[1185,1283,1288]]]],[[5,[[1182,1283,1186]]],[8,[[1186,1283,1288,1189]]],[10,[[1182,1186,1185],[1185,1186,1189],[1185,1189,1288],[1182,1185,1283],[1185,1288,1283]]]],[[8,[[1284,1287,1292,1290,1291],[1284,1291,1288]]],[9,[[1184,1191,1292,1287]]],[10,[[1184,1185,1191],[1185,1193,1191],[1184,1287,1284],[1185,1284,1288],[1184,1284,1185],[1191,1290,1292],[1191,1193,1290],[1193,1291,1290],[1185,1288,1291],[1185,1291,1193]]]],[[8,[[1194,1196,1291,1290],[1189,1288,1291,1196]]],[10,[[1193,1196,1194],[1185,1189,1196],[1185,1196,1193],[1185,1288,1189],[1193,1194,1290],[1185,1291,1288],[1185,1193,1291],[1193,1290,1291]]]],[[0,[[1202,1293,1203],[1293,1296,1294,1295],[1203,1293,1295,1205]]],[8,[[1290,1292,1293,1297],[1202,1206,1297,1293]]],[9,[[1208,1293,1209],[1191,1210,1293,1292],[1209,1293,1210],[1208,1211,1298,1296,1293]]],[10,[[1203,1205,1208],[1203,1208,1209],[1202,1203,1209],[1202,1210,1206],[1202,1209,1210],[1205,1211,1208],[1193,1206,1210],[1191,1193,1210],[1191,1290,1193],[1191,1292,1290],[1294,1298,1295],[1205,1295,1211],[1211,1295,1298],[1294,1296,1298],[1193,1297,1206],[1193,1290,1297]]]],[[0,[[1294,1296,1299]]],[8,[[1194,1290,1297,1212],[1206,1212,1297]]],[9,[[1296,1298,1299]]],[10,[[1193,1212,1206],[1193,1194,1212],[1193,1290,1194],[1294,1299,1298],[1294,1298,1296],[1193,1297,1290],[1193,1206,1297]]]],[[0,[[1221,1223,1300],[1301,1302,1303,1304],[1294,1305,1301,1295],[1205,1295,1301,1224],[1224,1301,1304,1225],[1304,1306,1307,1308],[1223,1225,1304,1308,1300]]],[9,[[1226,1309,1310,1302,1301,1227],[1227,1301,1305,1311,1228],[1211,1228,1311,1298],[1303,1310,1309,1312,1304],[1304,1312,1313,1306]]],[10,[[1221,1226,1223],[1223,1226,1227],[1223,1227,1225],[1205,1224,1211],[1224,1225,1227],[1211,1224,1227],[1211,1227,1228],[1205,1211,1295],[1294,1295,1298],[1211,1298,1295],[1221,1300,1312],[1300,1308,1312],[1221,1309,1226],[1221,1312,1309],[1307,1313,1308],[1308,1313,1312],[1294,1305,1302],[1302,1310,1303],[1294,1298,1305],[1298,1311,1305],[1306,1313,1307]]]],[[0,[[1302,1314,1303],[1294,1299,1315,1305],[1306,1316,1307]]],[9,[[1302,1310,1314],[1305,1315,1311],[1298,1311,1315,1299],[1303,1314,1310],[1306,1313,1316]]],[10,[[1294,1298,1299],[1307,1316,1313],[1302,1303,1310],[1294,1302,1305],[1294,1305,1298],[1298,1305,1311],[1306,1307,1313]]]],[[0,[[1317,1318,1319],[1221,1300,1318,1317,1245],[1307,1320,1318,1308],[1300,1308,1318]]],[9,[[1246,1247,1318,1320,1321],[1226,1248,1309],[1247,1249,1322,1319,1318],[1248,1250,1312,1309],[1246,1321,1313,1312,1250]]],[10,[[1245,1251,1249],[1221,1245,1247],[1245,1249,1247],[1221,1247,1250],[1221,1250,1226],[1246,1250,1247],[1226,1250,1248],[1221,1226,1309],[1221,1309,1312],[1221,1312,1300],[1300,1312,1308],[1307,1308,1313],[1308,1312,1313],[1249,1251,1322],[1317,1319,1322],[1245,1317,1251],[1251,1317,1322],[1307,1321,1320],[1307,1313,1321]]]],[[0,[[1253,1317,1319,1323,1254],[1245,1317,1253],[1307,1316,1324,1320]]],[9,[[1320,1324,1321],[1319,1322,1323],[1313,1321,1324,1316]]],[10,[[1251,1253,1254],[1245,1253,1251],[1307,1313,1316],[1254,1323,1322],[1251,1254,1322],[1251,1322,1317],[1317,1322,1319],[1245,1251,1317],[1307,1320,1321],[1307,1321,1313]]]],[[9,[[1259,1325,1260],[1249,1260,1325,1322]]],[10,[[1249,1251,1260],[1251,1259,1260],[1249,1322,1251],[1251,1325,1259],[1251,1322,1325]]]],[[0,[[1254,1323,1326,1261],[1261,1326,1327,1263]]],[9,[[1259,1264,1327,1326,1325],[1322,1325,1326,1323]]],[10,[[1261,1263,1264],[1259,1261,1264],[1251,1254,1261],[1251,1261,1259],[1251,1322,1254],[1254,1322,1323],[1263,1328,1264],[1251,1325,1322],[1251,1259,1325]]]],[[0,[[1263,1327,1329,1268]]],[9,[[1270,1330,1271],[1264,1271,1330,1329,1327]]],[10,[[1263,1272,1271],[1270,1271,1272],[1263,1271,1264],[1263,1264,1328],[1272,1329,1330],[1270,1272,1330]]]],[[0,[[1274,1331,1275],[1268,1329,1331,1274]]],[5,[[1275,1331,1276]]],[9,[[1270,1276,1331,1330],[1329,1330,1331]]],[10,[[1274,1275,1276],[1270,1272,1274],[1270,1274,1276],[1272,1330,1329],[1270,1330,1272]]]],[[5,[[1280,1281,1332],[1280,1332,1282]]],[8,[[1285,1332,1286],[1282,1332,1285]]],[9,[[1281,1289,1332],[1286,1332,1289]]],[10,[[1280,1289,1281],[1280,1282,1289],[1282,1285,1289],[1285,1286,1289]]]]]}', +); diff --git a/packages/test-snaps/src/components/Logo/fox-geometry.ts b/packages/test-snaps/src/components/Logo/fox-geometry.ts new file mode 100644 index 0000000000..6b0ef7232e --- /dev/null +++ b/packages/test-snaps/src/components/Logo/fox-geometry.ts @@ -0,0 +1,114 @@ +/* eslint-disable */ + +import { vec3 } from 'gl-matrix'; +import { FOX_BOXES } from './fox-data'; + +export interface FoxBox { + cx: number; + cy: number; + cz: number; + bx: number; + by: number; + bz: number; + bw: number; + start: number; + end: number; +} + +const ab = vec3.create(); +const ac = vec3.create(); +const normal = vec3.create(); +/** + * + * @param a + * @param b + * @param c + */ +function triNormal(a: vec3, b: vec3, c: vec3) { + vec3.sub(ab, b, a); + vec3.sub(ac, c, a); + vec3.cross(normal, ab, ac); + vec3.normalize(normal, normal); + return normal; +} + +// unpacks mesh data from the fox into a webgl-renderable array buffer +// +// output vertex format is 16-component float, 4 attributes: +// +// position = px, py, pz, 1 +// normal = nx, ny, nz, 0 +// color = r, g, b, 1 +// box index = cx, cy, cz, 0 +// +/** + * + */ +export function unpackFox() { + const vbuffer: number[] = []; + const ibuffer: number[] = []; + + const { colors, lo, hi, verts, centers, boundary } = FOX_BOXES; + + const boxes = FOX_BOXES.boxes.map((chunks, offset) => { + const start = ibuffer.length; + const [cx, cy, cz] = centers[offset]; + const [bx, by, bz] = boundary[offset]; + const bw = Math.hypot(bx, by, bz); + for (const [material, polygons] of chunks) { + for (const poly of polygons) { + const [nx, ny, nz] = triNormal( + verts[poly[0]] as any, + verts[poly[1]] as any, + verts[poly[2]] as any, + ); + const [r, g, b] = colors[material]; + const basePtr = vbuffer.length / 16; + for (const vertIndex of poly) { + const [px, py, pz] = verts[vertIndex]; + vbuffer.push( + px, + py, + pz, + 1, + nx, + ny, + nz, + 0, + r / 255, + g / 255, + b / 255, + material === colors.length - 1 ? 1 : 0, + cx, + cy, + cz, + 0, + ); + } + + for (let i = 2; i < poly.length; ++i) { + ibuffer.push(basePtr, basePtr + i - 1, basePtr + i); + } + } + } + return { + cx, + cy, + cz, + bx, + by, + bz, + bw, + start, + end: ibuffer.length, + }; + }); + + return { + vbuffer, + ibuffer, + boxes, + lo: vec3.fromValues(lo[0], lo[1], lo[2]), + hi: vec3.fromValues(hi[0], hi[1], hi[2]), + }; +} diff --git a/packages/test-snaps/src/components/Logo/fox-render.ts b/packages/test-snaps/src/components/Logo/fox-render.ts new file mode 100644 index 0000000000..bfcdabf36a --- /dev/null +++ b/packages/test-snaps/src/components/Logo/fox-render.ts @@ -0,0 +1,343 @@ +/* eslint-disable */ +// contains webgl code for rendering 3d fox animation + +import { mat4, quat, vec3, vec4 } from 'gl-matrix'; +import { FoxAnimation } from './fox-animate'; +import { FoxBox, unpackFox } from './fox-geometry'; +import { FOX_FRAG_SHADER, FOX_VERT_SHADER } from './fox-shader'; + +export class FoxRenderer { + public animation: FoxAnimation; + + public animationTick = 0; + + private initShader(type: number, src: string) { + const { gl } = this; + const shader = gl.createShader(type); + if (!shader) { + throw new Error('Error creating vertex shader'); + } + gl.shaderSource(shader, src); + gl.compileShader(shader); + return shader; + } + + private initProgram(spec: { vert: string; frag: string }) { + const { gl } = this; + const vs = this.initShader(gl.VERTEX_SHADER, spec.vert); + const fs = this.initShader(gl.FRAGMENT_SHADER, spec.frag); + const prog = gl.createProgram(); + if (!prog) { + throw new Error('Error creating shader program'); + } + gl.attachShader(prog, vs); + gl.attachShader(prog, fs); + gl.linkProgram(prog); + + if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { + console.error('link failed', { + prog: gl.getProgramInfoLog(prog), + frag: gl.getShaderInfoLog(fs), + vert: gl.getShaderInfoLog(vs), + }); + } + return prog; + } + + private foxShader: WebGLProgram; + + private vPosition: number; + + private vNormal: number; + + private vColor: number; + + private vCenter: number; + + private uAnimate: WebGLUniformLocation; + + private uViewProj: WebGLUniformLocation; + + private uTick: WebGLUniformLocation; + + private uEye: WebGLUniformLocation; + + private uHemisphereAxis: WebGLUniformLocation; + + private uHemisphereColor0: WebGLUniformLocation; + + private uHemisphereColor1: WebGLUniformLocation; + + private uInteriorColor0: WebGLUniformLocation; + + private uInteriorColor1: WebGLUniformLocation; + + private uFogColor: WebGLUniformLocation; + + private initFoxShader() { + const program = (this.foxShader = this.initProgram({ + vert: FOX_VERT_SHADER, + frag: FOX_FRAG_SHADER, + })); + + const { gl } = this; + + this.vPosition = gl.getAttribLocation(program, 'vPosition'); + this.vNormal = gl.getAttribLocation(program, 'vNormal'); + this.vColor = gl.getAttribLocation(program, 'vColor'); + this.vCenter = gl.getAttribLocation(program, 'vCenter'); + + this.uAnimate = gl.getUniformLocation(program, 'uAnimate'); + this.uViewProj = gl.getUniformLocation(program, 'uViewProj'); + this.uTick = gl.getUniformLocation(program, 'uTick'); + + this.uEye = gl.getUniformLocation(program, 'uEye'); + + this.uHemisphereAxis = gl.getUniformLocation(program, 'uHemisphereAxis'); + this.uHemisphereColor0 = gl.getUniformLocation( + program, + 'uHemisphereColor0', + ); + + this.uHemisphereColor1 = gl.getUniformLocation( + program, + 'uHemisphereColor1', + ); + + this.uInteriorColor0 = gl.getUniformLocation(program, 'uInteriorColor0'); + this.uInteriorColor1 = gl.getUniformLocation(program, 'uInteriorColor1'); + this.uFogColor = gl.getUniformLocation(program, 'uFogColor'); + } + + private foxVBuffer: WebGLBuffer; + + private foxIBuffer: WebGLBuffer; + + private foxBoxes: FoxBox[]; + + private foxVertCount: number; + + private initGeometry() { + const { gl } = this; + const { vbuffer, ibuffer, boxes, lo, hi } = unpackFox(); + this.foxBoxes = boxes; + this.foxVertCount = ibuffer.length; + + vec3.copy(this.lo, lo); + vec3.copy(this.hi, hi); + + vec3.add(this.center, this.lo, this.hi); + vec3.scale(this.center, this.center, 0.5); + + const foxVerts = gl.createBuffer(); + if (!foxVerts) { + throw new Error('Error allocating fox vertex buffer'); + } + this.foxVBuffer = foxVerts; + gl.bindBuffer(gl.ARRAY_BUFFER, foxVerts); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vbuffer), gl.STATIC_DRAW); + + const foxFaces = gl.createBuffer(); + if (!foxFaces) { + throw new Error('Error allocating fox face buffer'); + } + this.foxIBuffer = foxFaces; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, foxFaces); + gl.bufferData( + gl.ELEMENT_ARRAY_BUFFER, + new Uint16Array(ibuffer), + gl.STATIC_DRAW, + ); + + this.animation = new FoxAnimation(boxes); + } + + private bindFoxBuffer() { + const { gl } = this; + + gl.bindBuffer(gl.ARRAY_BUFFER, this.foxVBuffer); + if (this.vPosition >= 0) { + gl.enableVertexAttribArray(this.vPosition); + gl.vertexAttribPointer(this.vPosition, 4, gl.FLOAT, false, 64, 0); + } + + if (this.vNormal >= 0) { + gl.enableVertexAttribArray(this.vNormal); + gl.vertexAttribPointer(this.vNormal, 4, gl.FLOAT, false, 64, 16); + } + + if (this.vColor >= 0) { + gl.enableVertexAttribArray(this.vColor); + gl.vertexAttribPointer(this.vColor, 4, gl.FLOAT, false, 64, 32); + } + + if (this.vCenter >= 0) { + gl.enableVertexAttribArray(this.vCenter); + gl.vertexAttribPointer(this.vCenter, 4, gl.FLOAT, false, 64, 48); + } + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.foxIBuffer); + } + + public theta = Math.PI / 2; + + public phi = 0; + + public distance = 400; + + private eye = vec3.fromValues(0, 0, -2); + + private center = vec3.fromValues(0, 0, 0); + + private lo = vec3.fromValues(-1, -1, -1); + + private hi = vec3.fromValues(1, 1, 1); + + private view = mat4.identity(mat4.create()); + + private proj = mat4.identity(mat4.create()); + + private viewProj = mat4.identity(mat4.create()); + + private invViewProj = mat4.identity(mat4.create()); + + private updateCamera() { + // calculate transformations + const { eye } = this; + const { center } = this; + const { theta } = this; + const { phi } = this; + const { distance } = this; + + // calculate center + const { lo } = this; + const { hi } = this; + center[0] = 0.5 * (lo[0] + hi[0]); + center[1] = 0.5 * (lo[1] + hi[1]); + center[2] = 0.5 * (lo[2] + hi[2]); + + // calculate eye + eye[0] = Math.cos(theta) * Math.cos(phi) * distance + center[0]; + eye[1] = Math.sin(phi) * distance + center[1]; + eye[2] = Math.sin(theta) * Math.cos(phi) * distance + center[2]; + + // calculate view projection matrix + mat4.lookAt(mat4.identity(this.view), eye, center, [0, 1, 0]); + mat4.perspective( + mat4.identity(this.proj), + Math.PI / 4, + this.gl.drawingBufferWidth / this.gl.drawingBufferHeight, + 0.5, + 1600, + ); + mat4.mul(this.viewProj, this.proj, this.view); + mat4.invert(this.invViewProj, this.viewProj); + } + + public foxLookAt(x: number, y: number) { + console.log('bound2', x, y, this.gl); + const pick = vec4.fromValues( + (2 * x * window.devicePixelRatio) / this.gl.drawingBufferWidth - 1, + 1 - (2 * y * window.devicePixelRatio) / this.gl.drawingBufferHeight, + 1, + 1, + ); + vec4.transformMat4(pick, pick, this.invViewProj); + const point = vec3.fromValues( + pick[0] / pick[3], + pick[1] / pick[3], + pick[2] / pick[3], + ); + vec3.normalize(point, point); + const up = vec3.fromValues(0, 1, 0); + vec3.scaleAndAdd(up, up, point, -vec3.dot(point, up)); + vec3.normalize(up, up); + quat.setAxes( + this.animation.animRotation, + point, + vec3.cross(vec3.create(), point, up), + up, + ); + } + + constructor(private gl: WebGLRenderingContext) { + this.initFoxShader(); + this.initGeometry(); + } + + private _lastTimestamp = 0; + + public animate(timestamp: number) { + const dt = (timestamp - this._lastTimestamp) / 16; + this._lastTimestamp = timestamp; + this.animationTick = 10 * (1 + Math.cos(timestamp * 0.001)); + this.animation.update(timestamp / 16, Math.min(0.5, dt)); + } + + public explodeRay(x: number, y: number, mag: number) { + const pickDir = vec4.fromValues( + (2 * x * window.devicePixelRatio) / this.gl.drawingBufferWidth - 1, + 1 - (2 * y * window.devicePixelRatio) / this.gl.drawingBufferHeight, + 1, + 1, + ); + vec4.transformMat4(pickDir, pickDir, this.invViewProj); + const dir = vec3.fromValues( + pickDir[0] / pickDir[3] - this.eye[0], + pickDir[1] / pickDir[3] - this.eye[1], + pickDir[2] / pickDir[3] - this.eye[2], + ); + vec3.normalize(dir, dir); + this.animation.explode(this.eye, dir, mag); + } + + public hemisphereAxis = vec3.create(); + + public hemisphereColor0 = vec3.create(); + + public hemisphereColor1 = vec3.create(); + + public interiorColor0 = vec3.create(); + + public interiorColor1 = vec3.create(); + + public fogColor = vec3.create(); + + public draw() { + // Clear drawing buffer + const { gl } = this; + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.clearColor(0, 0, 0, 0); + gl.clearDepth(1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + // update camera state + this.updateCamera(); + + // draw animation + gl.disable(gl.BLEND); + gl.enable(gl.DEPTH_TEST); + gl.depthMask(true); + gl.enable(gl.CULL_FACE); + gl.useProgram(this.foxShader); + + this.bindFoxBuffer(); + gl.uniformMatrix4fv(this.uViewProj, false, this.viewProj); + gl.uniform1f(this.uTick, this.animationTick); + gl.uniform3fv(this.uEye, this.eye); + gl.uniform3fv(this.uHemisphereAxis, this.hemisphereAxis); + gl.uniform3fv(this.uHemisphereColor0, this.hemisphereColor0); + gl.uniform3fv(this.uHemisphereColor1, this.hemisphereColor1); + gl.uniform3fv(this.uInteriorColor0, this.interiorColor0); + gl.uniform3fv(this.uInteriorColor1, this.interiorColor1); + gl.uniform3fv(this.uFogColor, this.fogColor); + + const boxes = this.foxBoxes; + const xforms = this.animation.boxTransforms; + for (let i = 0; i < boxes.length; ++i) { + const { start, end } = boxes[i]; + gl.uniformMatrix4fv(this.uAnimate, false, xforms[i]); + gl.drawElements(gl.TRIANGLES, end - start, gl.UNSIGNED_SHORT, 2 * start); + } + } +} diff --git a/packages/test-snaps/src/components/Logo/fox-shader.ts b/packages/test-snaps/src/components/Logo/fox-shader.ts new file mode 100644 index 0000000000..97402a8722 --- /dev/null +++ b/packages/test-snaps/src/components/Logo/fox-shader.ts @@ -0,0 +1,45 @@ +/* eslint-disable */ + +export const FOX_VERT_SHADER = ` +precision highp float; +attribute vec4 vPosition; +attribute vec4 vNormal; +attribute vec4 vColor; +attribute vec4 vCenter; + +varying vec3 fColor; +varying float fDepth; + +uniform float uTick; +uniform vec3 uEye; +uniform mat4 uViewProj; +uniform mat4 uAnimate; +uniform vec3 uHemisphereAxis; +uniform vec3 uHemisphereColor0; +uniform vec3 uHemisphereColor1; +uniform vec3 uInteriorColor0; +uniform vec3 uInteriorColor1; + +void main () { + vec3 normal = normalize((uAnimate * vec4(vNormal.xyz, 0)).xyz); + vec3 light = mix(uHemisphereColor0, uHemisphereColor1, 0.5 * (1. + dot(normal, uHemisphereAxis))); + vec3 interiorColor = mix(uInteriorColor0, uInteriorColor1, + fract(dot(vec3(0.7436455, 0.11173, 0.576165), vCenter.xyz))); + fColor = light * mix(vColor.rgb, interiorColor, vColor.a); + vec4 worldPos = uAnimate * vec4(vPosition.xyz - vCenter.xyz, 1.); + fDepth = distance(worldPos.xyz, uEye); + gl_Position = uViewProj * worldPos; +} +`; + +export const FOX_FRAG_SHADER = ` +precision mediump float; + +uniform vec3 uFogColor; +varying vec3 fColor; +varying float fDepth; + +void main () { + float fogExp = exp(-0.0002 * fDepth); + gl_FragColor = vec4(mix(uFogColor, fColor, fogExp), 1.); +}`; diff --git a/packages/test-snaps/src/components/Logo/index.ts b/packages/test-snaps/src/components/Logo/index.ts new file mode 100644 index 0000000000..9da0646e68 --- /dev/null +++ b/packages/test-snaps/src/components/Logo/index.ts @@ -0,0 +1,2 @@ +export * from './Fox'; +export * from './Logo'; diff --git a/packages/test-snaps/src/components/Result.tsx b/packages/test-snaps/src/components/Result.tsx new file mode 100644 index 0000000000..39375fb0a7 --- /dev/null +++ b/packages/test-snaps/src/components/Result.tsx @@ -0,0 +1,19 @@ +import { FunctionComponent, ReactNode } from 'react'; +import { Alert, AlertProps } from 'react-bootstrap'; + +export type ResultProps = { + children: ReactNode; +}; + +export const Result: FunctionComponent = ({ + children, + className, + ...props +}) => ( + + {children} + +); diff --git a/packages/test-snaps/src/components/Root.tsx b/packages/test-snaps/src/components/Root.tsx new file mode 100644 index 0000000000..c07d50add1 --- /dev/null +++ b/packages/test-snaps/src/components/Root.tsx @@ -0,0 +1,24 @@ +import { FunctionComponent, ReactElement, StrictMode } from 'react'; +import { Provider } from 'react-redux'; + +import type createStore from '../store'; + +export type RootProps = { + store: ReturnType; + children: ReactElement; +}; + +/** + * Render the root component. This is the top-level component that wraps the + * entire application. + * + * @param props - The props. + * @param props.store - The Redux store. + * @param props.children - The children to render. + * @returns The root component. + */ +export const Root: FunctionComponent = ({ store, children }) => ( + + {children} + +); diff --git a/packages/test-snaps/src/components/Snap.tsx b/packages/test-snaps/src/components/Snap.tsx new file mode 100644 index 0000000000..73d985ee11 --- /dev/null +++ b/packages/test-snaps/src/components/Snap.tsx @@ -0,0 +1,66 @@ +import { FunctionComponent, ReactNode } from 'react'; +import { Card, Col } from 'react-bootstrap'; +import CardHeader from 'react-bootstrap/CardHeader'; + +import { getSnapId } from '../utils'; +import { Connect } from './Connect'; + +export type SnapProps = { + /** + * The name of the snap. + */ + name: string; + + /** + * The `data-testid` of the Snap. + */ + testId: string; + + /** + * The snap ID. This is only used in production. + */ + snapId?: `npm:${string}`; + + /** + * The port that the Snap is listening on. This is only used in development. + */ + port?: number; + + /** + * The version of the Snap. This overrides the version in the `package.json`. + */ + version?: string; + + hideConnect?: boolean; + children?: ReactNode; +}; + +export const Snap: FunctionComponent = ({ + name, + snapId, + testId, + port, + version, + hideConnect, + children, +}) => ( + + + +

{name}

+
+
+ {!hideConnect && ( + + )} + + {children} +
+
+ +); diff --git a/packages/test-snaps/src/components/index.ts b/packages/test-snaps/src/components/index.ts new file mode 100644 index 0000000000..22ee984ae4 --- /dev/null +++ b/packages/test-snaps/src/components/index.ts @@ -0,0 +1,6 @@ +export * from './ButtonSpinner'; +export * from './Connect'; +export * from './Logo'; +export * from './Result'; +export * from './Root'; +export * from './Snap'; diff --git a/packages/test-snaps/src/features/index.ts b/packages/test-snaps/src/features/index.ts new file mode 100644 index 0000000000..35e686cd5d --- /dev/null +++ b/packages/test-snaps/src/features/index.ts @@ -0,0 +1,3 @@ +export * from './installed-snaps'; +export * from './snaps'; +export * as snaps from './snaps'; diff --git a/packages/test-snaps/src/features/installed-snaps/InstalledSnaps.tsx b/packages/test-snaps/src/features/installed-snaps/InstalledSnaps.tsx new file mode 100644 index 0000000000..6fe7a544c9 --- /dev/null +++ b/packages/test-snaps/src/features/installed-snaps/InstalledSnaps.tsx @@ -0,0 +1,20 @@ +import { FunctionComponent } from 'react'; + +import { useGetSnapsQuery } from '../../api'; +import { Result, Snap } from '../../components'; + +export const InstalledSnaps: FunctionComponent = () => { + const { data: installedSnaps } = useGetSnapsQuery(); + + return ( + + + + {installedSnaps && Object.keys(installedSnaps).length > 0 + ? Object.keys(installedSnaps).join(', ') + : 'No Snaps installed.'} + + + + ); +}; diff --git a/packages/test-snaps/src/features/installed-snaps/index.ts b/packages/test-snaps/src/features/installed-snaps/index.ts new file mode 100644 index 0000000000..144e73d1d3 --- /dev/null +++ b/packages/test-snaps/src/features/installed-snaps/index.ts @@ -0,0 +1 @@ +export * from './InstalledSnaps'; diff --git a/packages/test-snaps/src/features/snaps/bip32/BIP32.tsx b/packages/test-snaps/src/features/snaps/bip32/BIP32.tsx new file mode 100644 index 0000000000..38af3915c6 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip32/BIP32.tsx @@ -0,0 +1,20 @@ +import { FunctionComponent } from 'react'; + +import { Snap } from '../../../components'; +import { PublicKey, SignMessage } from './components'; +import { BIP_32_PORT, BIP_32_SNAP_ID } from './constants'; + +export const BIP32: FunctionComponent = () => { + return ( + + + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/bip32/components/PublicKey.tsx b/packages/test-snaps/src/features/snaps/bip32/components/PublicKey.tsx new file mode 100644 index 0000000000..0315e40895 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip32/components/PublicKey.tsx @@ -0,0 +1,65 @@ +import { logError } from '@metamask/snaps-utils'; +import { JsonRpcParams } from '@metamask/utils'; +import { FunctionComponent } from 'react'; +import { Button, ButtonGroup } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { BIP_32_PORT, BIP_32_SNAP_ID } from '../constants'; + +export const PublicKey: FunctionComponent = () => { + const [invokeSnap, { isLoading, data }] = useInvokeMutation(); + + const handleClick = (method: string, params: JsonRpcParams) => () => { + invokeSnap({ + snapId: getSnapId(BIP_32_SNAP_ID, BIP_32_PORT), + method, + params, + }).catch(logError); + }; + + return ( + <> + + + + + + + {JSON.stringify(data, null, 2)} + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/bip32/components/SignMessage.tsx b/packages/test-snaps/src/features/snaps/bip32/components/SignMessage.tsx new file mode 100644 index 0000000000..ad911710f5 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip32/components/SignMessage.tsx @@ -0,0 +1,61 @@ +import { logError } from '@metamask/snaps-utils'; +import { ChangeEvent, FormEvent, FunctionComponent, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { BIP_32_PORT, BIP_32_SNAP_ID } from '../constants'; + +export type SignMessageProps = { + curve: 'secp256k1' | 'ed25519'; +}; + +export const SignMessage: FunctionComponent = ({ curve }) => { + const [message, setMessage] = useState(''); + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleChange = (event: ChangeEvent) => { + setMessage(event.target.value); + }; + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + + invokeSnap({ + snapId: getSnapId(BIP_32_SNAP_ID, BIP_32_PORT), + method: 'signMessage', + params: { + message, + curve, + path: ['m', "44'", "0'"], + }, + }).catch(logError); + }; + + return ( + <> +
+ Message + + + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/bip32/components/index.ts b/packages/test-snaps/src/features/snaps/bip32/components/index.ts new file mode 100644 index 0000000000..2ff6564479 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip32/components/index.ts @@ -0,0 +1,2 @@ +export * from './PublicKey'; +export * from './SignMessage'; diff --git a/packages/test-snaps/src/features/snaps/bip32/constants.ts b/packages/test-snaps/src/features/snaps/bip32/constants.ts new file mode 100644 index 0000000000..6af4fbf758 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip32/constants.ts @@ -0,0 +1,2 @@ +export const BIP_32_SNAP_ID = 'npm:@metamask/bip32-example-snap'; +export const BIP_32_PORT = 8001; diff --git a/packages/test-snaps/src/features/snaps/bip32/index.ts b/packages/test-snaps/src/features/snaps/bip32/index.ts new file mode 100644 index 0000000000..8ea62e096d --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip32/index.ts @@ -0,0 +1 @@ +export * from './BIP32'; diff --git a/packages/test-snaps/src/features/snaps/bip44/BIP44.tsx b/packages/test-snaps/src/features/snaps/bip44/BIP44.tsx new file mode 100644 index 0000000000..b782ba1014 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip44/BIP44.tsx @@ -0,0 +1,60 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button, ButtonGroup } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../api'; +import { Result, Snap } from '../../../components'; +import { getSnapId } from '../../../utils'; +import { SignMessage } from './components'; +import { BIP_44_PORT, BIP_44_SNAP_ID } from './constants'; + +export const BIP44: FunctionComponent = () => { + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleClick = (method: string, coinType: number) => () => { + invokeSnap({ + snapId: getSnapId(BIP_44_SNAP_ID, BIP_44_PORT), + method, + params: { + coinType, + }, + }).catch(logError); + }; + + return ( + + + + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/bip44/components/SignMessage.tsx b/packages/test-snaps/src/features/snaps/bip44/components/SignMessage.tsx new file mode 100644 index 0000000000..8ca282105b --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip44/components/SignMessage.tsx @@ -0,0 +1,55 @@ +import { logError } from '@metamask/snaps-utils'; +import { ChangeEvent, FormEvent, FunctionComponent, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { BIP_44_PORT, BIP_44_SNAP_ID } from '../constants'; + +export const SignMessage: FunctionComponent = () => { + const [message, setMessage] = useState(''); + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleChange = (event: ChangeEvent) => { + setMessage(event.target.value); + }; + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + + invokeSnap({ + snapId: getSnapId(BIP_44_SNAP_ID, BIP_44_PORT), + method: 'signMessage', + params: { + message, + }, + }).catch(logError); + }; + + return ( + <> +
+ Message + + + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/bip44/components/index.ts b/packages/test-snaps/src/features/snaps/bip44/components/index.ts new file mode 100644 index 0000000000..bc16f14a77 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip44/components/index.ts @@ -0,0 +1 @@ +export * from './SignMessage'; diff --git a/packages/test-snaps/src/features/snaps/bip44/constants.ts b/packages/test-snaps/src/features/snaps/bip44/constants.ts new file mode 100644 index 0000000000..623ec6512a --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip44/constants.ts @@ -0,0 +1,2 @@ +export const BIP_44_SNAP_ID = 'npm:@metamask/bip44-example-snap'; +export const BIP_44_PORT = 8002; diff --git a/packages/test-snaps/src/features/snaps/bip44/index.ts b/packages/test-snaps/src/features/snaps/bip44/index.ts new file mode 100644 index 0000000000..39a276facf --- /dev/null +++ b/packages/test-snaps/src/features/snaps/bip44/index.ts @@ -0,0 +1 @@ +export * from './BIP44'; diff --git a/packages/test-snaps/src/features/snaps/cronjobs/Cronjobs.tsx b/packages/test-snaps/src/features/snaps/cronjobs/Cronjobs.tsx new file mode 100644 index 0000000000..12ce52cf12 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/cronjobs/Cronjobs.tsx @@ -0,0 +1,15 @@ +import { FunctionComponent } from 'react'; + +import { Snap } from '../../../components'; +import { CRONJOBS_SNAP_ID, CRONJOBS_SNAP_PORT } from './constants'; + +export const Cronjobs: FunctionComponent = () => { + return ( + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/cronjobs/constants.ts b/packages/test-snaps/src/features/snaps/cronjobs/constants.ts new file mode 100644 index 0000000000..63236d00f6 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/cronjobs/constants.ts @@ -0,0 +1,2 @@ +export const CRONJOBS_SNAP_ID = 'npm:@metamask/cronjobs-example-snap'; +export const CRONJOBS_SNAP_PORT = 8004; diff --git a/packages/test-snaps/src/features/snaps/cronjobs/index.ts b/packages/test-snaps/src/features/snaps/cronjobs/index.ts new file mode 100644 index 0000000000..06f942bb25 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/cronjobs/index.ts @@ -0,0 +1 @@ +export * from './Cronjobs'; diff --git a/packages/test-snaps/src/features/snaps/dialogs/Dialogs.tsx b/packages/test-snaps/src/features/snaps/dialogs/Dialogs.tsx new file mode 100644 index 0000000000..356d5692a2 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/dialogs/Dialogs.tsx @@ -0,0 +1,71 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button, ButtonGroup } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../api'; +import { Result, Snap } from '../../../components'; +import { getSnapId } from '../../../utils'; +import { DIALOGS_SNAP_ID, DIALOGS_SNAP_PORT } from './constants'; + +export const Dialogs: FunctionComponent = () => { + const [invokeSnap, { isLoading, data }] = useInvokeMutation(); + const snapId = getSnapId(DIALOGS_SNAP_ID, DIALOGS_SNAP_PORT); + + const handleSubmitAlert = () => { + invokeSnap({ + snapId, + method: 'showAlert', + }).catch(logError); + }; + + const handleSubmitConfirmation = () => { + invokeSnap({ + snapId, + method: 'showConfirmation', + }).catch(logError); + }; + + const handleSubmitPrompt = () => { + invokeSnap({ + snapId, + method: 'showPrompt', + }).catch(logError); + }; + + return ( + + + + + + + + + {JSON.stringify(data, null, 2)} + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/dialogs/constants.ts b/packages/test-snaps/src/features/snaps/dialogs/constants.ts new file mode 100644 index 0000000000..10773a48a2 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/dialogs/constants.ts @@ -0,0 +1,2 @@ +export const DIALOGS_SNAP_ID = 'npm:@metamask/dialogs-example-snap'; +export const DIALOGS_SNAP_PORT = 8005; diff --git a/packages/test-snaps/src/features/snaps/dialogs/index.ts b/packages/test-snaps/src/features/snaps/dialogs/index.ts new file mode 100644 index 0000000000..4ca8f96658 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/dialogs/index.ts @@ -0,0 +1 @@ +export * from './Dialogs'; diff --git a/packages/test-snaps/src/features/snaps/errors/Errors.tsx b/packages/test-snaps/src/features/snaps/errors/Errors.tsx new file mode 100644 index 0000000000..638d32fd8a --- /dev/null +++ b/packages/test-snaps/src/features/snaps/errors/Errors.tsx @@ -0,0 +1,44 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../api'; +import { Result, Snap } from '../../../components'; +import { getSnapId } from '../../../utils'; +import { ERRORS_SNAP_ID, ERRORS_SNAP_PORT } from './constants'; + +export const Errors: FunctionComponent = () => { + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleSubmit = () => { + invokeSnap({ + snapId: getSnapId(ERRORS_SNAP_ID, ERRORS_SNAP_PORT), + method: 'hello', + }).catch(logError); + }; + + return ( + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/errors/constants.ts b/packages/test-snaps/src/features/snaps/errors/constants.ts new file mode 100644 index 0000000000..a83ada1dd9 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/errors/constants.ts @@ -0,0 +1,2 @@ +export const ERRORS_SNAP_ID = 'npm:@metamask/errors-example-snap'; +export const ERRORS_SNAP_PORT = 8006; diff --git a/packages/test-snaps/src/features/snaps/errors/index.ts b/packages/test-snaps/src/features/snaps/errors/index.ts new file mode 100644 index 0000000000..2eb99ca811 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/errors/index.ts @@ -0,0 +1 @@ +export * from './Errors'; diff --git a/packages/test-snaps/src/features/snaps/ethereum-provider/EthereumProvider.tsx b/packages/test-snaps/src/features/snaps/ethereum-provider/EthereumProvider.tsx new file mode 100644 index 0000000000..2a403de5ae --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethereum-provider/EthereumProvider.tsx @@ -0,0 +1,47 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../api'; +import { Result, Snap } from '../../../components'; +import { getSnapId } from '../../../utils'; +import { + ETHEREUM_PROVIDER_SNAP_ID, + ETHEREUM_PROVIDER_SNAP_PORT, +} from './constants'; + +export const EthereumProvider: FunctionComponent = () => { + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleSubmit = () => { + invokeSnap({ + snapId: getSnapId(ETHEREUM_PROVIDER_SNAP_ID, ETHEREUM_PROVIDER_SNAP_PORT), + method: 'getVersion', + }).catch(logError); + }; + + return ( + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/ethereum-provider/constants.ts b/packages/test-snaps/src/features/snaps/ethereum-provider/constants.ts new file mode 100644 index 0000000000..7b5087cdfd --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethereum-provider/constants.ts @@ -0,0 +1,3 @@ +export const ETHEREUM_PROVIDER_SNAP_ID = + 'npm:@metamask/ethereum-provider-example-snap'; +export const ETHEREUM_PROVIDER_SNAP_PORT = 8007; diff --git a/packages/test-snaps/src/features/snaps/ethereum-provider/index.ts b/packages/test-snaps/src/features/snaps/ethereum-provider/index.ts new file mode 100644 index 0000000000..188ef3d949 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethereum-provider/index.ts @@ -0,0 +1 @@ +export * from './EthereumProvider'; diff --git a/packages/test-snaps/src/features/snaps/ethers-js/EthersJs.tsx b/packages/test-snaps/src/features/snaps/ethers-js/EthersJs.tsx new file mode 100644 index 0000000000..56a6574687 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethers-js/EthersJs.tsx @@ -0,0 +1,18 @@ +import { FunctionComponent } from 'react'; + +import { Snap } from '../../../components'; +import { SignMessage } from './components'; +import { ETHERS_JS_PORT, ETHERS_JS_SNAP_ID } from './constants'; + +export const EthersJs: FunctionComponent = () => { + return ( + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/ethers-js/components/SignMessage.tsx b/packages/test-snaps/src/features/snaps/ethers-js/components/SignMessage.tsx new file mode 100644 index 0000000000..af1e74a825 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethers-js/components/SignMessage.tsx @@ -0,0 +1,55 @@ +import { logError } from '@metamask/snaps-utils'; +import { ChangeEvent, FormEvent, FunctionComponent, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { ETHERS_JS_PORT, ETHERS_JS_SNAP_ID } from '../constants'; + +export const SignMessage: FunctionComponent = () => { + const [message, setMessage] = useState(''); + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleChange = (event: ChangeEvent) => { + setMessage(event.target.value); + }; + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + + invokeSnap({ + snapId: getSnapId(ETHERS_JS_SNAP_ID, ETHERS_JS_PORT), + method: 'signMessage', + params: { + message, + }, + }).catch(logError); + }; + + return ( + <> +
+ Message + + + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/ethers-js/components/index.ts b/packages/test-snaps/src/features/snaps/ethers-js/components/index.ts new file mode 100644 index 0000000000..bc16f14a77 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethers-js/components/index.ts @@ -0,0 +1 @@ +export * from './SignMessage'; diff --git a/packages/test-snaps/src/features/snaps/ethers-js/constants.ts b/packages/test-snaps/src/features/snaps/ethers-js/constants.ts new file mode 100644 index 0000000000..dd775749ec --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethers-js/constants.ts @@ -0,0 +1,2 @@ +export const ETHERS_JS_SNAP_ID = 'npm:@metamask/ethers-js-example-snap'; +export const ETHERS_JS_PORT = 8008; diff --git a/packages/test-snaps/src/features/snaps/ethers-js/index.ts b/packages/test-snaps/src/features/snaps/ethers-js/index.ts new file mode 100644 index 0000000000..f2107e3484 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/ethers-js/index.ts @@ -0,0 +1 @@ +export * from './EthersJs'; diff --git a/packages/test-snaps/src/features/snaps/get-entropy/GetEntropy.tsx b/packages/test-snaps/src/features/snaps/get-entropy/GetEntropy.tsx new file mode 100644 index 0000000000..6fe437d5d7 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/get-entropy/GetEntropy.tsx @@ -0,0 +1,18 @@ +import { FunctionComponent } from 'react'; + +import { Snap } from '../../../components'; +import { SignMessage } from './components'; +import { GET_ENTROPY_PORT, GET_ENTROPY_SNAP_ID } from './constants'; + +export const GetEntropy: FunctionComponent = () => { + return ( + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/get-entropy/components/SignMessage.tsx b/packages/test-snaps/src/features/snaps/get-entropy/components/SignMessage.tsx new file mode 100644 index 0000000000..f3a1941992 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/get-entropy/components/SignMessage.tsx @@ -0,0 +1,55 @@ +import { logError } from '@metamask/snaps-utils'; +import { ChangeEvent, FormEvent, FunctionComponent, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { GET_ENTROPY_SNAP_ID, GET_ENTROPY_PORT } from '../constants'; + +export const SignMessage: FunctionComponent = () => { + const [message, setMessage] = useState(''); + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleChange = (event: ChangeEvent) => { + setMessage(event.target.value); + }; + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + + invokeSnap({ + snapId: getSnapId(GET_ENTROPY_SNAP_ID, GET_ENTROPY_PORT), + method: 'signMessage', + params: { + message, + }, + }).catch(logError); + }; + + return ( + <> +
+ Message + + + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/get-entropy/components/index.ts b/packages/test-snaps/src/features/snaps/get-entropy/components/index.ts new file mode 100644 index 0000000000..bc16f14a77 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/get-entropy/components/index.ts @@ -0,0 +1 @@ +export * from './SignMessage'; diff --git a/packages/test-snaps/src/features/snaps/get-entropy/constants.ts b/packages/test-snaps/src/features/snaps/get-entropy/constants.ts new file mode 100644 index 0000000000..8372483665 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/get-entropy/constants.ts @@ -0,0 +1,2 @@ +export const GET_ENTROPY_SNAP_ID = 'npm:@metamask/get-entropy-example-snap'; +export const GET_ENTROPY_PORT = 8009; diff --git a/packages/test-snaps/src/features/snaps/get-entropy/index.ts b/packages/test-snaps/src/features/snaps/get-entropy/index.ts new file mode 100644 index 0000000000..9b44c5fafb --- /dev/null +++ b/packages/test-snaps/src/features/snaps/get-entropy/index.ts @@ -0,0 +1 @@ +export * from './GetEntropy'; diff --git a/packages/test-snaps/src/features/snaps/index.ts b/packages/test-snaps/src/features/snaps/index.ts new file mode 100644 index 0000000000..646c605d81 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/index.ts @@ -0,0 +1,15 @@ +export * from './bip32'; +export * from './bip44'; +export * from './cronjobs'; +export * from './dialogs'; +export * from './errors'; +export * from './ethereum-provider'; +export * from './ethers-js'; +export * from './get-entropy'; +export * from './json-rpc'; +export * from './manage-state'; +export * from './network-access'; +export * from './notifications'; +export * from './transaction-insights'; +export * from './updates'; +export * from './wasm'; diff --git a/packages/test-snaps/src/features/snaps/json-rpc/JsonRpc.tsx b/packages/test-snaps/src/features/snaps/json-rpc/JsonRpc.tsx new file mode 100644 index 0000000000..3e205ca27f --- /dev/null +++ b/packages/test-snaps/src/features/snaps/json-rpc/JsonRpc.tsx @@ -0,0 +1,44 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../api'; +import { Result, Snap } from '../../../components'; +import { getSnapId } from '../../../utils'; +import { JSON_RPC_SNAP_ID, JSON_RPC_SNAP_PORT } from './constants'; + +export const JsonRpc: FunctionComponent = () => { + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleSubmit = () => { + invokeSnap({ + snapId: getSnapId(JSON_RPC_SNAP_ID, JSON_RPC_SNAP_PORT), + method: 'invokeSnap', + }).catch(logError); + }; + + return ( + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/json-rpc/constants.ts b/packages/test-snaps/src/features/snaps/json-rpc/constants.ts new file mode 100644 index 0000000000..0a6b287f20 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/json-rpc/constants.ts @@ -0,0 +1,2 @@ +export const JSON_RPC_SNAP_ID = 'npm:@metamask/json-rpc-example-snap'; +export const JSON_RPC_SNAP_PORT = 8013; diff --git a/packages/test-snaps/src/features/snaps/json-rpc/index.ts b/packages/test-snaps/src/features/snaps/json-rpc/index.ts new file mode 100644 index 0000000000..bbbc4a3471 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/json-rpc/index.ts @@ -0,0 +1 @@ +export * from './JsonRpc'; diff --git a/packages/test-snaps/src/features/snaps/manage-state/ManageState.tsx b/packages/test-snaps/src/features/snaps/manage-state/ManageState.tsx new file mode 100644 index 0000000000..68208971d7 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/ManageState.tsx @@ -0,0 +1,28 @@ +import { FunctionComponent } from 'react'; + +import { Result, Snap } from '../../../components'; +import { ClearData, SendData } from './components'; +import { MANAGE_STATE_SNAP_ID, MANAGE_STATE_PORT } from './constants'; +import { useSnapState } from './hooks'; + +export const ManageState: FunctionComponent = () => { + const state = useSnapState(); + + return ( + + + + {JSON.stringify(state, null, 2)} + + + + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/manage-state/components/ClearData.tsx b/packages/test-snaps/src/features/snaps/manage-state/components/ClearData.tsx new file mode 100644 index 0000000000..3e13ddf312 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/components/ClearData.tsx @@ -0,0 +1,39 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button } from 'react-bootstrap'; + +import { Tag, useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { MANAGE_STATE_PORT, MANAGE_STATE_SNAP_ID } from '../constants'; + +export const ClearData: FunctionComponent = () => { + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleClick = () => { + invokeSnap({ + snapId: getSnapId(MANAGE_STATE_SNAP_ID, MANAGE_STATE_PORT), + method: 'clearState', + tags: [Tag.TestState], + }).catch(logError); + }; + + return ( + <> + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/manage-state/components/SendData.tsx b/packages/test-snaps/src/features/snaps/manage-state/components/SendData.tsx new file mode 100644 index 0000000000..ab99cbee1d --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/components/SendData.tsx @@ -0,0 +1,60 @@ +import { logError } from '@metamask/snaps-utils'; +import { ChangeEvent, FormEvent, FunctionComponent, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; + +import { Tag, useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { MANAGE_STATE_PORT, MANAGE_STATE_SNAP_ID } from '../constants'; +import { useSnapState } from '../hooks'; + +export const SendData: FunctionComponent = () => { + const [value, setValue] = useState(''); + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + const snapState = useSnapState(); + + const handleChange = (event: ChangeEvent) => { + setValue(event.target.value); + }; + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + invokeSnap({ + snapId: getSnapId(MANAGE_STATE_SNAP_ID, MANAGE_STATE_PORT), + method: 'setState', + params: { + items: [...snapState.items, value], + }, + tags: [Tag.TestState], + }).catch(logError); + }; + + return ( + <> +
+ + Value + + + + +
+ + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/manage-state/components/index.ts b/packages/test-snaps/src/features/snaps/manage-state/components/index.ts new file mode 100644 index 0000000000..5d6360e318 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/components/index.ts @@ -0,0 +1,2 @@ +export * from './ClearData'; +export * from './SendData'; diff --git a/packages/test-snaps/src/features/snaps/manage-state/constants.ts b/packages/test-snaps/src/features/snaps/manage-state/constants.ts new file mode 100644 index 0000000000..a132f35a7a --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/constants.ts @@ -0,0 +1,2 @@ +export const MANAGE_STATE_SNAP_ID = 'npm:@metamask/manage-state-example-snap'; +export const MANAGE_STATE_PORT = 8014; diff --git a/packages/test-snaps/src/features/snaps/manage-state/hooks/index.ts b/packages/test-snaps/src/features/snaps/manage-state/hooks/index.ts new file mode 100644 index 0000000000..3a6999aa10 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/hooks/index.ts @@ -0,0 +1 @@ +export * from './useSnapState'; diff --git a/packages/test-snaps/src/features/snaps/manage-state/hooks/useSnapState.ts b/packages/test-snaps/src/features/snaps/manage-state/hooks/useSnapState.ts new file mode 100644 index 0000000000..a7acf83552 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/hooks/useSnapState.ts @@ -0,0 +1,30 @@ +import { Tag, useInvokeQuery } from '../../../../api'; +import { getSnapId, useInstalled } from '../../../../utils'; +import { MANAGE_STATE_PORT, MANAGE_STATE_SNAP_ID } from '../constants'; + +export type State = { + items: string[]; +}; + +/** + * Hook to retrieve the state of the snap. + * + * @returns The state of the snap. + */ +export function useSnapState() { + const snapId = getSnapId(MANAGE_STATE_SNAP_ID, MANAGE_STATE_PORT); + const isInstalled = useInstalled(snapId); + + const { data: state } = useInvokeQuery<{ data: State }>( + { + snapId, + method: 'getState', + tags: [Tag.TestState], + }, + { + skip: !isInstalled, + }, + ); + + return state; +} diff --git a/packages/test-snaps/src/features/snaps/manage-state/index.ts b/packages/test-snaps/src/features/snaps/manage-state/index.ts new file mode 100644 index 0000000000..65d95d15b4 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/manage-state/index.ts @@ -0,0 +1 @@ +export * from './ManageState'; diff --git a/packages/test-snaps/src/features/snaps/network-access/NetworkAccess.tsx b/packages/test-snaps/src/features/snaps/network-access/NetworkAccess.tsx new file mode 100644 index 0000000000..4c43b8a736 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/network-access/NetworkAccess.tsx @@ -0,0 +1,38 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../api'; +import { Snap } from '../../../components'; +import { getSnapId } from '../../../utils'; +import { NETWORK_ACCESS_PORT, NETWORK_ACCESS_SNAP_ID } from './constants'; + +export const NetworkAccess: FunctionComponent = () => { + const [invokeSnap, { isLoading }] = useInvokeMutation(); + + const handleSubmit = () => { + invokeSnap({ + snapId: getSnapId(NETWORK_ACCESS_SNAP_ID, NETWORK_ACCESS_PORT), + method: 'fetch', + }).catch(logError); + }; + + return ( + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/network-access/constants.ts b/packages/test-snaps/src/features/snaps/network-access/constants.ts new file mode 100644 index 0000000000..946bc7dd0d --- /dev/null +++ b/packages/test-snaps/src/features/snaps/network-access/constants.ts @@ -0,0 +1,3 @@ +export const NETWORK_ACCESS_SNAP_ID = + 'npm:@metamask/network-access-example-snap'; +export const NETWORK_ACCESS_PORT = 8015; diff --git a/packages/test-snaps/src/features/snaps/network-access/index.ts b/packages/test-snaps/src/features/snaps/network-access/index.ts new file mode 100644 index 0000000000..db6f0b1eea --- /dev/null +++ b/packages/test-snaps/src/features/snaps/network-access/index.ts @@ -0,0 +1 @@ +export * from './NetworkAccess'; diff --git a/packages/test-snaps/src/features/snaps/notifications/Notifications.tsx b/packages/test-snaps/src/features/snaps/notifications/Notifications.tsx new file mode 100644 index 0000000000..bf7499a203 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/notifications/Notifications.tsx @@ -0,0 +1,47 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button, ButtonGroup } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../api'; +import { Snap } from '../../../components'; +import { getSnapId } from '../../../utils'; +import { NOTIFICATIONS_SNAP_ID, NOTIFICATIONS_SNAP_PORT } from './constants'; + +export const Notifications: FunctionComponent = () => { + const [invokeSnap, { isLoading }] = useInvokeMutation(); + + const handleClick = (method: string) => () => { + invokeSnap({ + snapId: getSnapId(NOTIFICATIONS_SNAP_ID, NOTIFICATIONS_SNAP_PORT), + method, + }).catch(logError); + }; + + return ( + + + + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/notifications/constants.ts b/packages/test-snaps/src/features/snaps/notifications/constants.ts new file mode 100644 index 0000000000..3f4722d442 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/notifications/constants.ts @@ -0,0 +1,2 @@ +export const NOTIFICATIONS_SNAP_ID = 'npm:@metamask/notifications-example-snap'; +export const NOTIFICATIONS_SNAP_PORT = 8016; diff --git a/packages/test-snaps/src/features/snaps/notifications/index.ts b/packages/test-snaps/src/features/snaps/notifications/index.ts new file mode 100644 index 0000000000..e7825351af --- /dev/null +++ b/packages/test-snaps/src/features/snaps/notifications/index.ts @@ -0,0 +1 @@ +export * from './Notifications'; diff --git a/packages/test-snaps/src/features/snaps/transaction-insights/TransactionInsights.tsx b/packages/test-snaps/src/features/snaps/transaction-insights/TransactionInsights.tsx new file mode 100644 index 0000000000..3dbf61ccda --- /dev/null +++ b/packages/test-snaps/src/features/snaps/transaction-insights/TransactionInsights.tsx @@ -0,0 +1,77 @@ +import { logError } from '@metamask/snaps-utils'; +import { assert } from '@metamask/utils'; +import { FunctionComponent } from 'react'; +import { Button, ButtonGroup } from 'react-bootstrap'; + +import { useLazyGetAccountsQuery, useLazyRequestQuery } from '../../../api'; +import { Snap, Result } from '../../../components'; +import { + TRANSACTION_INSIGHTS_SNAP_ID, + TRANSACTION_INSIGHTS_SNAP_PORT, +} from './constants'; + +export const TransactionInsights: FunctionComponent = () => { + const [getAccounts, { isLoading: isLoadingAccounts, data: accounts }] = + useLazyGetAccountsQuery(); + const [request, { isLoading: isLoadingRequest, data: transaction, error }] = + useLazyRequestQuery(); + + const isLoading = isLoadingAccounts || isLoadingRequest; + + const handleGetAccounts = () => { + getAccounts().catch(logError); + }; + + const handleSendTransaction = () => { + assert(accounts?.length); + + const account = accounts[0]; + request({ + method: 'eth_sendTransaction', + params: [ + { + from: account, + to: account, + value: '0x0', + data: '0xa9059cbb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + }, + ], + }).catch(logError); + }; + + return ( + + + + + + + + {JSON.stringify(transaction, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/transaction-insights/constants.ts b/packages/test-snaps/src/features/snaps/transaction-insights/constants.ts new file mode 100644 index 0000000000..08b5fb8acc --- /dev/null +++ b/packages/test-snaps/src/features/snaps/transaction-insights/constants.ts @@ -0,0 +1,3 @@ +export const TRANSACTION_INSIGHTS_SNAP_ID = + 'npm:@metamask/transaction-insights-example-snap'; +export const TRANSACTION_INSIGHTS_SNAP_PORT = 8018; diff --git a/packages/test-snaps/src/features/snaps/transaction-insights/index.ts b/packages/test-snaps/src/features/snaps/transaction-insights/index.ts new file mode 100644 index 0000000000..7f2f177275 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/transaction-insights/index.ts @@ -0,0 +1 @@ +export * from './TransactionInsights'; diff --git a/packages/test-snaps/src/features/snaps/updates/Updates.tsx b/packages/test-snaps/src/features/snaps/updates/Updates.tsx new file mode 100644 index 0000000000..513ea3ea2c --- /dev/null +++ b/packages/test-snaps/src/features/snaps/updates/Updates.tsx @@ -0,0 +1,50 @@ +import { logError } from '@metamask/snaps-utils'; +import { FunctionComponent } from 'react'; +import { Button, ButtonGroup } from 'react-bootstrap'; + +import { useGetSnapsQuery, useInstallSnapMutation } from '../../../api'; +import { Result, Snap } from '../../../components'; +import { + UPDATES_SNAP_ID, + UPDATES_SNAP_NEW_VERSION, + UPDATES_SNAP_OLD_VERSION, +} from './constants'; + +export const Updates: FunctionComponent = () => { + const [installSnap, { isLoading }] = useInstallSnapMutation(); + const { data: snaps } = useGetSnapsQuery(); + + const currentVersion = snaps?.[UPDATES_SNAP_ID]?.version; + + const handleUpdate = () => { + installSnap({ + snapId: UPDATES_SNAP_ID, + version: UPDATES_SNAP_NEW_VERSION, + }).catch(logError); + }; + + return ( + + + + {JSON.stringify(currentVersion, null, 2)} + + + + + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/updates/constants.ts b/packages/test-snaps/src/features/snaps/updates/constants.ts new file mode 100644 index 0000000000..ab3d1bf24d --- /dev/null +++ b/packages/test-snaps/src/features/snaps/updates/constants.ts @@ -0,0 +1,3 @@ +export const UPDATES_SNAP_ID = 'npm:@metamask/bip32-example-snap'; +export const UPDATES_SNAP_OLD_VERSION = '0.35.0-flask.1'; +export const UPDATES_SNAP_NEW_VERSION = '0.35.2-flask.1'; diff --git a/packages/test-snaps/src/features/snaps/updates/index.ts b/packages/test-snaps/src/features/snaps/updates/index.ts new file mode 100644 index 0000000000..ec22c9f2d9 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/updates/index.ts @@ -0,0 +1 @@ +export * from './Updates'; diff --git a/packages/test-snaps/src/features/snaps/wasm/WebAssembly.tsx b/packages/test-snaps/src/features/snaps/wasm/WebAssembly.tsx new file mode 100644 index 0000000000..8789f3fe22 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/wasm/WebAssembly.tsx @@ -0,0 +1,18 @@ +import { FunctionComponent } from 'react'; + +import { Snap } from '../../../components'; +import { FibonacciInput } from './components'; +import { WASM_SNAP_ID, WASM_SNAP_PORT } from './constants'; + +export const WASM: FunctionComponent = () => { + return ( + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/wasm/components/FibonacciInput.tsx b/packages/test-snaps/src/features/snaps/wasm/components/FibonacciInput.tsx new file mode 100644 index 0000000000..b6af6f76fb --- /dev/null +++ b/packages/test-snaps/src/features/snaps/wasm/components/FibonacciInput.tsx @@ -0,0 +1,53 @@ +import { logError } from '@metamask/snaps-utils'; +import { ChangeEvent, FormEvent, FunctionComponent, useState } from 'react'; +import { Button, Form } from 'react-bootstrap'; + +import { useInvokeMutation } from '../../../../api'; +import { Result } from '../../../../components'; +import { getSnapId } from '../../../../utils'; +import { WASM_SNAP_ID, WASM_SNAP_PORT } from '../constants'; + +export const FibonacciInput: FunctionComponent = () => { + const [message, setMessage] = useState(''); + const [invokeSnap, { isLoading, data, error }] = useInvokeMutation(); + + const handleChange = (event: ChangeEvent) => { + setMessage(event.target.value); + }; + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + + invokeSnap({ + snapId: getSnapId(WASM_SNAP_ID, WASM_SNAP_PORT), + method: 'fibonacci', + params: [message], + }).catch(logError); + }; + + return ( + <> +
+ Input + + + + + + + {JSON.stringify(data, null, 2)} + {JSON.stringify(error, null, 2)} + + + + ); +}; diff --git a/packages/test-snaps/src/features/snaps/wasm/components/index.ts b/packages/test-snaps/src/features/snaps/wasm/components/index.ts new file mode 100644 index 0000000000..49e9ff0697 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/wasm/components/index.ts @@ -0,0 +1 @@ +export * from './FibonacciInput'; diff --git a/packages/test-snaps/src/features/snaps/wasm/constants.ts b/packages/test-snaps/src/features/snaps/wasm/constants.ts new file mode 100644 index 0000000000..967b67100f --- /dev/null +++ b/packages/test-snaps/src/features/snaps/wasm/constants.ts @@ -0,0 +1,2 @@ +export const WASM_SNAP_ID = 'npm:@metamask/wasm-example-snap'; +export const WASM_SNAP_PORT = 8019; diff --git a/packages/test-snaps/src/features/snaps/wasm/index.ts b/packages/test-snaps/src/features/snaps/wasm/index.ts new file mode 100644 index 0000000000..7d92e1aca5 --- /dev/null +++ b/packages/test-snaps/src/features/snaps/wasm/index.ts @@ -0,0 +1 @@ +export * from './WebAssembly'; diff --git a/packages/test-snaps/src/index.html b/packages/test-snaps/src/index.html new file mode 100644 index 0000000000..6ba4dff6f9 --- /dev/null +++ b/packages/test-snaps/src/index.html @@ -0,0 +1,11 @@ + + + + + + Test Snaps + + +
+ + diff --git a/packages/test-snaps/src/index.tsx b/packages/test-snaps/src/index.tsx new file mode 100644 index 0000000000..2edfdc9e1b --- /dev/null +++ b/packages/test-snaps/src/index.tsx @@ -0,0 +1,21 @@ +import { assert } from '@metamask/utils'; +import { createRoot } from 'react-dom/client'; + +import { App } from './App'; +import { Root } from './components'; +import createStore from './store'; + +// eslint-disable-next-line import/no-unassigned-import +import 'bootstrap/dist/css/bootstrap.min.css'; + +const rootElement = document.getElementById('root'); +assert(rootElement, 'Root element not found.'); + +const store = createStore(); +const root = createRoot(rootElement); + +root.render( + + + , +); diff --git a/packages/test-snaps/src/store.ts b/packages/test-snaps/src/store.ts new file mode 100644 index 0000000000..32cd4ade28 --- /dev/null +++ b/packages/test-snaps/src/store.ts @@ -0,0 +1,26 @@ +import { configureStore } from '@reduxjs/toolkit'; +import { setupListeners } from '@reduxjs/toolkit/query'; + +import { baseApi } from './api'; + +const createStore = () => { + const store = configureStore({ + reducer: { + [baseApi.reducerPath]: baseApi.reducer, + }, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat(baseApi.middleware), + }); + + setupListeners(store.dispatch); + + return store; +}; + +export type ApplicationState = ReturnType< + ReturnType['getState'] +>; + +export type ApplicationDispatch = ReturnType['dispatch']; + +export default createStore; diff --git a/packages/test-snaps/src/utils/id.ts b/packages/test-snaps/src/utils/id.ts new file mode 100644 index 0000000000..af49a76e69 --- /dev/null +++ b/packages/test-snaps/src/utils/id.ts @@ -0,0 +1,30 @@ +import { assert } from '@metamask/utils'; + +/** + * Get the actual snap ID to use, for a given NPM snap ID and port. + * + * If the current environment is production, the NPM snap ID is used. Otherwise, + * the local ID, based on the port, is used. + * + * @param snapId - The NPM snap ID, if any. + * @param port - The port to use for the local ID, if any. + * @returns The snap ID to use. + */ +export function getSnapId( + snapId: `npm:${string}` | undefined, + port: number | undefined, +) { + assert(snapId ?? port); + + if (!port) { + return snapId as string; + } + + const localId = `local:http://localhost:${port}`; + if (!snapId) { + return localId; + } + + const isProduction = process.env.NODE_ENV === 'production'; + return isProduction ? snapId : localId; +} diff --git a/packages/test-snaps/src/utils/index.ts b/packages/test-snaps/src/utils/index.ts new file mode 100644 index 0000000000..6c52d7bffb --- /dev/null +++ b/packages/test-snaps/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './id'; +export * from './use-installed'; diff --git a/packages/test-snaps/src/utils/use-installed.ts b/packages/test-snaps/src/utils/use-installed.ts new file mode 100644 index 0000000000..6e11111f3c --- /dev/null +++ b/packages/test-snaps/src/utils/use-installed.ts @@ -0,0 +1,14 @@ +import { useGetSnapsQuery } from '../api'; + +/** + * A React hook that returns a boolean indicating whether the given Snap is + * installed. + * + * @param snapId - The ID of the Snap to check. + * @returns A boolean indicating whether the given Snap is installed. + */ +export const useInstalled = (snapId: string): boolean => { + const { data: snaps } = useGetSnapsQuery(); + + return Boolean(snaps?.[snapId]); +}; diff --git a/packages/test-snaps/static/test-data.json b/packages/test-snaps/static/test-data.json new file mode 100644 index 0000000000..f2a886f39d --- /dev/null +++ b/packages/test-snaps/static/test-data.json @@ -0,0 +1,3 @@ +{ + "hello": "world" +} diff --git a/packages/test-snaps/tsconfig.json b/packages/test-snaps/tsconfig.json new file mode 100644 index 0000000000..3343910d65 --- /dev/null +++ b/packages/test-snaps/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.packages.json", + "compilerOptions": { + "baseUrl": "./", + "jsx": "preserve", + "resolveJsonModule": true + }, + "include": ["./src", "webpack.config.ts", "package.json"], + "references": [ + { + "path": "../snaps-utils" + } + ] +} diff --git a/packages/test-snaps/webpack.config.ts b/packages/test-snaps/webpack.config.ts new file mode 100644 index 0000000000..eee13d0db6 --- /dev/null +++ b/packages/test-snaps/webpack.config.ts @@ -0,0 +1,113 @@ +import ReactRefreshPlugin from '@pmmmwh/react-refresh-webpack-plugin'; +// eslint-disable-next-line import/default +import CopyPlugin from 'copy-webpack-plugin'; +import FaviconsWebpackPlugin from 'favicons-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import { resolve } from 'path'; +import TerserPlugin from 'terser-webpack-plugin'; +import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; +import { Configuration, EnvironmentPlugin } from 'webpack'; +import { Configuration as DevServerConfiguration } from 'webpack-dev-server'; + +const STATIC_PATH = resolve(__dirname, 'static'); + +const config: Configuration & Record<'devServer', DevServerConfiguration> = { + entry: './src/index.tsx', + stats: 'errors-only', + output: { + path: resolve(__dirname, 'dist'), + }, + module: { + rules: [ + { + test: /\.tsx?$/u, + use: { + loader: 'swc-loader', + options: {}, + }, + }, + { + test: /\.m?js$/u, + include: /node_modules/u, + type: 'javascript/auto', + resolve: { + fullySpecified: false, + }, + }, + { + test: /\.(png|jpe?g|gif|svg)$/u, + type: 'asset', + }, + { + test: /\.woff2?$/u, + type: 'asset/resource', + }, + { + test: /\.css$/u, + use: ['style-loader', 'css-loader'], + }, + ], + }, + resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + plugins: [ + new TsconfigPathsPlugin({ + configFile: resolve(__dirname, 'tsconfig.json'), + baseUrl: __dirname, + }), + ], + /* eslint-disable @typescript-eslint/naming-convention */ + fallback: { + assert: false, + child_process: false, + constants: false, + crypto: false, + fs: false, + http: false, + https: false, + module: false, + stream: false, + os: false, + path: false, + util: false, + worker_threads: false, + zlib: false, + }, + /* eslint-enable @typescript-eslint/naming-convention */ + }, + plugins: [ + new ReactRefreshPlugin(), + new HtmlWebpackPlugin({ + template: './src/index.html', + }), + new EnvironmentPlugin(['NODE_ENV']), + new FaviconsWebpackPlugin('./src/assets/icon.svg'), + new CopyPlugin({ + patterns: [ + { + from: STATIC_PATH, + }, + ], + }), + ], + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + minify: TerserPlugin.swcMinify, + }), + ], + }, + cache: { + type: 'filesystem', + buildDependencies: { + config: [__filename], + }, + }, + devServer: { + port: 8000, + historyApiFallback: true, + }, +}; + +export default config; diff --git a/scripts/verify-tsconfig.mjs b/scripts/verify-tsconfig.mjs index edddae60f8..b8b3c864f1 100644 --- a/scripts/verify-tsconfig.mjs +++ b/scripts/verify-tsconfig.mjs @@ -5,7 +5,7 @@ import { fileURLToPath } from 'url'; const cwd = pathUtils.dirname(fileURLToPath(import.meta.url)) // These are the packages we expect to _not_ be referenced in the root tsconfig. -const IGNORE_LIST = new Set(['examples', 'snaps-types']); +const IGNORE_LIST = new Set(['examples', 'snaps-types', 'test-snaps']); // Get reference paths from root tsconfig.json const rootTsconfig = JSON.parse(await fs.readFile('./tsconfig.json', { encoding: 'utf8' })); diff --git a/yarn.lock b/yarn.lock index faa3bc53ab..bf9d6e10e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1343,12 +1343,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": - version: 7.22.3 - resolution: "@babel/runtime@npm:7.22.3" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.22.5 + resolution: "@babel/runtime@npm:7.22.5" dependencies: regenerator-runtime: ^0.13.11 - checksum: 8fc50785ca4cba749fed90bffca7e6fd52d4709755654e95b8d2a945fc034b56fb8c2e8a0183fea7c4abb86bf5fa77678c0ea35163b6920649833d180c34c234 + checksum: 12a50b7de2531beef38840d17af50c55a094253697600cee255311222390c68eed704829308d4fd305e1b3dfbce113272e428e9d9d45b1730e0fede997eaceb1 languageName: node linkType: hard @@ -5360,6 +5360,65 @@ __metadata: languageName: node linkType: hard +"@metamask/test-snaps@workspace:packages/test-snaps": + version: 0.0.0-use.local + resolution: "@metamask/test-snaps@workspace:packages/test-snaps" + dependencies: + "@metamask/auto-changelog": ^3.1.0 + "@metamask/eslint-config": ^11.0.0 + "@metamask/eslint-config-jest": ^11.0.0 + "@metamask/eslint-config-nodejs": ^11.0.1 + "@metamask/eslint-config-typescript": ^11.0.0 + "@metamask/providers": ^11.0.0 + "@metamask/snaps-utils": "workspace:^" + "@metamask/utils": ^6.0.1 + "@pmmmwh/react-refresh-webpack-plugin": ^0.5.10 + "@popperjs/core": ^2.11.8 + "@reduxjs/toolkit": ^1.9.5 + "@swc/core": ^1.3.66 + "@swc/jest": ^0.2.26 + "@types/jest": ^27.5.1 + "@types/node": ^20.3.1 + "@types/webpack-env": ^1.18.1 + "@typescript-eslint/eslint-plugin": ^5.42.1 + "@typescript-eslint/parser": ^5.42.1 + bootstrap: ^5.2.2 + copy-webpack-plugin: ^11.0.0 + cross-env: ^7.0.3 + css-loader: ^6.7.3 + deepmerge: ^4.2.2 + eslint: ^8.27.0 + eslint-config-prettier: ^8.5.0 + eslint-plugin-import: ^2.26.0 + eslint-plugin-jest: ^27.1.5 + eslint-plugin-jsdoc: ^39.6.2 + eslint-plugin-node: ^11.1.0 + eslint-plugin-prettier: ^4.2.1 + favicons: ^7.1.2 + favicons-webpack-plugin: ^6.0.0 + gl-matrix: ^3.4.3 + html-webpack-plugin: ^5.5.0 + jest: ^29.0.2 + jest-it-up: ^2.0.0 + prettier: ^2.7.1 + react: ^18.2.0 + react-bootstrap: ^2.5.0 + react-dom: ^18.2.0 + react-redux: ^8.0.5 + rimraf: ^4.1.2 + simplex-noise: ^4.0.0 + style-loader: ^3.3.2 + swc-loader: ^0.2.3 + terser-webpack-plugin: ^5.3.9 + ts-node: ^10.9.1 + tsconfig-paths-webpack-plugin: ^4.0.1 + typescript: ~4.8.4 + webpack: ^5.86.0 + webpack-cli: ^5.1.4 + webpack-dev-server: ^4.13.3 + languageName: unknown + linkType: soft + "@metamask/types@npm:^1.1.0": version: 1.1.0 resolution: "@metamask/types@npm:1.1.0" @@ -5430,6 +5489,7 @@ __metadata: "@typescript-eslint/parser": ^5.42.1 assemblyscript: ^0.27.5 buffer: ^6.0.3 + concurrently: ^8.2.0 deepmerge: ^4.2.2 eslint: ^8.27.0 eslint-config-prettier: ^8.5.0 @@ -5438,6 +5498,7 @@ __metadata: eslint-plugin-jsdoc: ^39.6.2 eslint-plugin-node: ^11.1.0 eslint-plugin-prettier: ^4.2.1 + http-server: ^14.1.1 jest: ^29.0.2 prettier: ^2.7.1 prettier-plugin-packagejson: ^2.2.11 @@ -5447,6 +5508,7 @@ __metadata: typescript: ~4.8.4 webpack: ^5.86.0 webpack-cli: ^5.1.4 + webpack-dev-server: ^4.13.3 languageName: unknown linkType: soft @@ -5821,10 +5883,10 @@ __metadata: languageName: node linkType: hard -"@popperjs/core@npm:^2.9.3": - version: 2.11.7 - resolution: "@popperjs/core@npm:2.11.7" - checksum: 5b6553747899683452a1d28898c1b39173a4efd780e74360bfcda8eb42f1c5e819602769c81a10920fc68c881d07fb40429604517d499567eac079cfa6470f19 +"@popperjs/core@npm:^2.11.6, @popperjs/core@npm:^2.11.8, @popperjs/core@npm:^2.9.3": + version: 2.11.8 + resolution: "@popperjs/core@npm:2.11.8" + checksum: e5c69fdebf52a4012f6a1f14817ca8e9599cb1be73dd1387e1785e2ed5e5f0862ff817f420a87c7fc532add1f88a12e25aeb010ffcbdc98eace3d55ce2139cf0 languageName: node linkType: hard @@ -5852,6 +5914,17 @@ __metadata: languageName: node linkType: hard +"@react-aria/ssr@npm:^3.5.0": + version: 3.7.0 + resolution: "@react-aria/ssr@npm:3.7.0" + dependencies: + "@swc/helpers": ^0.5.0 + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + checksum: cf4af47feb47c72ad1a5987b6ca341cba44687fd9bea6155e672c44dcb575e6801c3aaf4a036bb36da9e72f509eaf99c35c993a121017a8c0b0569125b27edfe + languageName: node + linkType: hard + "@react-dnd/asap@npm:^5.0.1": version: 5.0.2 resolution: "@react-dnd/asap@npm:5.0.2" @@ -5956,6 +6029,37 @@ __metadata: languageName: node linkType: hard +"@restart/hooks@npm:^0.4.9": + version: 0.4.9 + resolution: "@restart/hooks@npm:0.4.9" + dependencies: + dequal: ^2.0.2 + peerDependencies: + react: ">=16.8.0" + checksum: 2481b21ee984328f41134d94c23b244aff0b82091b9ae6252b9ec9408634bed13473e2e74959c898a198b88602521a021f1c1b9683d52cf0878fea6e0f2b47df + languageName: node + linkType: hard + +"@restart/ui@npm:^1.6.3": + version: 1.6.6 + resolution: "@restart/ui@npm:1.6.6" + dependencies: + "@babel/runtime": ^7.21.0 + "@popperjs/core": ^2.11.6 + "@react-aria/ssr": ^3.5.0 + "@restart/hooks": ^0.4.9 + "@types/warning": ^3.0.0 + dequal: ^2.0.3 + dom-helpers: ^5.2.0 + uncontrollable: ^8.0.1 + warning: ^4.0.3 + peerDependencies: + react: ">=16.14.0" + react-dom: ">=16.14.0" + checksum: c2d1b56a0a6c3afadd98f1adf3cf16897b86752464d1f17f81f3611c99b2aada0c6701944807bcc997f1095dd2c3f4dac8b83ef515bac560b40a8060663871cf + languageName: node + linkType: hard + "@rollup/plugin-babel@npm:^6.0.3": version: 6.0.3 resolution: "@rollup/plugin-babel@npm:6.0.3" @@ -6336,6 +6440,15 @@ __metadata: languageName: node linkType: hard +"@swc/helpers@npm:^0.5.0": + version: 0.5.1 + resolution: "@swc/helpers@npm:0.5.1" + dependencies: + tslib: ^2.4.0 + checksum: 71e0e27234590435e4c62b97ef5e796f88e786841a38c7116a5e27a3eafa7b9ead7cdec5249b32165902076de78446945311c973e59bddf77c1e24f33a8f272a + languageName: node + linkType: hard + "@swc/jest@npm:^0.2.26": version: 0.2.26 resolution: "@swc/jest@npm:0.2.26" @@ -7033,14 +7146,23 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:^18.2.5": - version: 18.2.6 - resolution: "@types/react@npm:18.2.6" +"@types/react-transition-group@npm:^4.4.5": + version: 4.4.6 + resolution: "@types/react-transition-group@npm:4.4.6" + dependencies: + "@types/react": "*" + checksum: 0872143821d7ee20a1d81e965f8b1e837837f11cd2206973f1f98655751992d9390304d58bac192c9cd923eca95bff107d8c9e3364a180240d5c2a6fd70fd7c3 + languageName: node + linkType: hard + +"@types/react@npm:*, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.5": + version: 18.2.14 + resolution: "@types/react@npm:18.2.14" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: dea9d232d8df7ac357367a69dcb557711ab3d5501807ffa77cebeee73d49ee94d095f298e36853c63ed47cce097eee4c7eae2aaa8c02fac3f0171ec1b523a819 + checksum: a6a5e8cc78f486b9020d1ad009aa6c56943c68c7c6376e0f8399e9cbcd950b7b8f5d73f00200f5379f5e58d31d57d8aed24357f301d8e86108cd438ce6c8b3dd languageName: node linkType: hard @@ -7208,6 +7330,13 @@ __metadata: languageName: node linkType: hard +"@types/warning@npm:^3.0.0": + version: 3.0.0 + resolution: "@types/warning@npm:3.0.0" + checksum: 120dcf90600d583c68a60872200061eab9318ae15ea898581f8e9a6dc71b7941095dd81d8324e36d2a6006e5e12b6fc1cf8eda00cc514ee12bb39a912cc4e040 + languageName: node + linkType: hard + "@types/webpack-env@npm:^1.18.1": version: 1.18.1 resolution: "@types/webpack-env@npm:1.18.1" @@ -8660,6 +8789,15 @@ __metadata: languageName: node linkType: hard +"async@npm:^2.6.4": + version: 2.6.4 + resolution: "async@npm:2.6.4" + dependencies: + lodash: ^4.17.14 + checksum: a52083fb32e1ebe1d63e5c5624038bb30be68ff07a6c8d7dfe35e47c93fc144bd8652cbec869e0ac07d57dde387aa5f1386be3559cdee799cb1f789678d88e19 + languageName: node + linkType: hard + "async@npm:^3.2.3": version: 3.2.4 resolution: "async@npm:3.2.4" @@ -8907,7 +9045,7 @@ __metadata: languageName: node linkType: hard -"basic-auth@npm:~2.0.1": +"basic-auth@npm:^2.0.1, basic-auth@npm:~2.0.1": version: 2.0.1 resolution: "basic-auth@npm:2.0.1" dependencies: @@ -9095,6 +9233,15 @@ __metadata: languageName: node linkType: hard +"bootstrap@npm:^5.2.2": + version: 5.3.0 + resolution: "bootstrap@npm:5.3.0" + peerDependencies: + "@popperjs/core": ^2.11.7 + checksum: 29a83cc8cac96d70051e265a5da342cc488df8fc76dff6746ef7d155698286cd5bdfa3e52c6ebf09f8e5a97f25929ee97aee36237117732e52b0d3276a72c45c + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -9614,7 +9761,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.1": +"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -9794,6 +9941,13 @@ __metadata: languageName: node linkType: hard +"classnames@npm:^2.3.2": + version: 2.3.2 + resolution: "classnames@npm:2.3.2" + checksum: 2c62199789618d95545c872787137262e741f9db13328e216b093eea91c85ef2bfb152c1f9e63027204e2559a006a92eb74147d46c800a9f96297ae1d9f96f4e + languageName: node + linkType: hard + "clean-css@npm:^5.2.2": version: 5.3.0 resolution: "clean-css@npm:5.3.0" @@ -10242,6 +10396,26 @@ __metadata: languageName: node linkType: hard +"concurrently@npm:^8.2.0": + version: 8.2.0 + resolution: "concurrently@npm:8.2.0" + dependencies: + chalk: ^4.1.2 + date-fns: ^2.30.0 + lodash: ^4.17.21 + rxjs: ^7.8.1 + shell-quote: ^1.8.1 + spawn-command: 0.0.2 + supports-color: ^8.1.1 + tree-kill: ^1.2.2 + yargs: ^17.7.2 + bin: + conc: dist/bin/concurrently.js + concurrently: dist/bin/concurrently.js + checksum: eafe6a4d9b7fda87f55ea285cfc6acd937a5286ceec8991ab48e6cc27c45fce6a5c6f45e18d7555defa15dc7d7e8941bc5a9d1ceaf182e31441d420e00333434 + languageName: node + linkType: hard + "connect-history-api-fallback@npm:^2.0.0": version: 2.0.0 resolution: "connect-history-api-fallback@npm:2.0.0" @@ -10376,6 +10550,13 @@ __metadata: languageName: node linkType: hard +"corser@npm:^2.0.1": + version: 2.0.1 + resolution: "corser@npm:2.0.1" + checksum: 9ff6944eda760c8c3118747a636afc3ede53b41e7b9960513a15b88032209a728e630ae4b41e20a941e34da129fe9094d1f5d95123ef64ac2e16cdad8dce9c87 + languageName: node + linkType: hard + "cosmiconfig@npm:8.1.3": version: 8.1.3 resolution: "cosmiconfig@npm:8.1.3" @@ -10473,6 +10654,18 @@ __metadata: languageName: node linkType: hard +"cross-env@npm:^7.0.3": + version: 7.0.3 + resolution: "cross-env@npm:7.0.3" + dependencies: + cross-spawn: ^7.0.1 + bin: + cross-env: src/bin/cross-env.js + cross-env-shell: src/bin/cross-env-shell.js + checksum: 26f2f3ea2ab32617f57effb70d329c2070d2f5630adc800985d8b30b56e8bf7f5f439dd3a0358b79cee6f930afc23cf8e23515f17ccfb30092c6b62c6b630a79 + languageName: node + linkType: hard + "cross-fetch@npm:3.1.5": version: 3.1.5 resolution: "cross-fetch@npm:3.1.5" @@ -10512,7 +10705,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" dependencies: @@ -10913,6 +11106,13 @@ __metadata: languageName: node linkType: hard +"dequal@npm:^2.0.2, dequal@npm:^2.0.3": + version: 2.0.3 + resolution: "dequal@npm:2.0.3" + checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90 + languageName: node + linkType: hard + "des.js@npm:^1.0.0": version: 1.0.1 resolution: "des.js@npm:1.0.1" @@ -11225,6 +11425,16 @@ __metadata: languageName: node linkType: hard +"dom-helpers@npm:^5.0.1, dom-helpers@npm:^5.2.0, dom-helpers@npm:^5.2.1": + version: 5.2.1 + resolution: "dom-helpers@npm:5.2.1" + dependencies: + "@babel/runtime": ^7.8.7 + csstype: ^3.0.2 + checksum: 863ba9e086f7093df3376b43e74ce4422571d404fc9828bf2c56140963d5edf0e56160f9b2f3bb61b282c07f8fc8134f023c98fd684bddcb12daf7b0f14d951c + languageName: node + linkType: hard + "dom-serializer@npm:^1.0.1": version: 1.4.1 resolution: "dom-serializer@npm:1.4.1" @@ -13454,6 +13664,13 @@ __metadata: languageName: node linkType: hard +"gl-matrix@npm:^3.4.3": + version: 3.4.3 + resolution: "gl-matrix@npm:3.4.3" + checksum: c47830ba727f3d0fab635c48135af96aef66274079a3e0afd6f68b68c98eae9fc1bcfdc7312fe2301e4fd22dd24c5e0f1b5d025960a208e50d07101ed8d940f9 + languageName: node + linkType: hard + "glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -14071,6 +14288,29 @@ __metadata: languageName: node linkType: hard +"http-server@npm:^14.1.1": + version: 14.1.1 + resolution: "http-server@npm:14.1.1" + dependencies: + basic-auth: ^2.0.1 + chalk: ^4.1.2 + corser: ^2.0.1 + he: ^1.2.0 + html-encoding-sniffer: ^3.0.0 + http-proxy: ^1.18.1 + mime: ^1.6.0 + minimist: ^1.2.6 + opener: ^1.5.1 + portfinder: ^1.0.28 + secure-compare: 3.0.1 + union: ~0.5.0 + url-join: ^4.0.1 + bin: + http-server: bin/http-server + checksum: 4f9674289195eaf9f3e408e093d2080b0d4647559a32c9e7868639c327cab62efd0bb8bc9ded9a625d9ce982cbb03517d4472400af5ecf36eeb5b4fa62d113fe + languageName: node + linkType: hard + "http2-wrapper@npm:^1.0.0-beta.5.2": version: 1.0.3 resolution: "http2-wrapper@npm:1.0.3" @@ -16299,7 +16539,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.20, lodash@npm:^4.17.21": +"lodash@npm:^4.17.14, lodash@npm:^4.17.20, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -16735,7 +16975,7 @@ __metadata: languageName: node linkType: hard -"mime@npm:1.6.0": +"mime@npm:1.6.0, mime@npm:^1.6.0": version: 1.6.0 resolution: "mime@npm:1.6.0" bin: @@ -16971,6 +17211,17 @@ __metadata: languageName: node linkType: hard +"mkdirp@npm:^0.5.6": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: ^1.2.6 + bin: + mkdirp: bin/cmd.js + checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 + languageName: node + linkType: hard + "mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" @@ -17660,6 +17911,15 @@ __metadata: languageName: node linkType: hard +"opener@npm:^1.5.1": + version: 1.5.2 + resolution: "opener@npm:1.5.2" + bin: + opener: bin/opener-bin.js + checksum: 33b620c0d53d5b883f2abc6687dd1c5fd394d270dbe33a6356f2d71e0a2ec85b100d5bac94694198ccf5c30d592da863b2292c5539009c715a9c80c697b4f6cc + languageName: node + linkType: hard + "optionator@npm:^0.8.1": version: 0.8.3 resolution: "optionator@npm:0.8.3" @@ -18297,6 +18557,17 @@ __metadata: languageName: node linkType: hard +"portfinder@npm:^1.0.28": + version: 1.0.32 + resolution: "portfinder@npm:1.0.32" + dependencies: + async: ^2.6.4 + debug: ^3.2.7 + mkdirp: ^0.5.6 + checksum: 116b4aed1b9e16f6d5503823d966d9ffd41b1c2339e27f54c06cd2f3015a9d8ef53e2a53b57bc0a25af0885977b692007353aa28f9a0a98a44335cb50487240d + languageName: node + linkType: hard + "postcss-modules-extract-imports@npm:^3.0.0": version: 3.0.0 resolution: "postcss-modules-extract-imports@npm:3.0.0" @@ -18561,6 +18832,18 @@ __metadata: languageName: node linkType: hard +"prop-types-extra@npm:^1.1.0": + version: 1.1.1 + resolution: "prop-types-extra@npm:1.1.1" + dependencies: + react-is: ^16.3.2 + warning: ^4.0.0 + peerDependencies: + react: ">=0.14.0" + checksum: ebf1c048687bb538457f91a3610abb36ca0f50587a6afae80443a9e65b9db96882d18c3511175a8967fad4ca5dcd804913bbc241d7b5160c74cf69aacdd054f0 + languageName: node + linkType: hard + "prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" @@ -18805,6 +19088,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.4.0": + version: 6.11.2 + resolution: "qs@npm:6.11.2" + dependencies: + side-channel: ^1.0.4 + checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b + languageName: node + linkType: hard + "query-selector-shadow-dom@npm:^1.0.0": version: 1.0.1 resolution: "query-selector-shadow-dom@npm:1.0.1" @@ -18899,6 +19191,33 @@ __metadata: languageName: node linkType: hard +"react-bootstrap@npm:^2.5.0": + version: 2.8.0 + resolution: "react-bootstrap@npm:2.8.0" + dependencies: + "@babel/runtime": ^7.21.0 + "@restart/hooks": ^0.4.9 + "@restart/ui": ^1.6.3 + "@types/react-transition-group": ^4.4.5 + classnames: ^2.3.2 + dom-helpers: ^5.2.1 + invariant: ^2.2.4 + prop-types: ^15.8.1 + prop-types-extra: ^1.1.0 + react-transition-group: ^4.4.5 + uncontrollable: ^7.2.1 + warning: ^4.0.3 + peerDependencies: + "@types/react": ">=16.14.8" + react: ">=16.14.0" + react-dom: ">=16.14.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 589f64354ae03872a111fe3d37ad9b5dc2c69480edfd4b4f912a7d59cc15311df3f0374def08d5d6b63024b1674483daa862004e53bc5fac426d891993484ddc + languageName: node + linkType: hard + "react-clientside-effect@npm:^1.2.6": version: 1.2.6 resolution: "react-clientside-effect@npm:1.2.6" @@ -19002,7 +19321,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.13.1, react-is@npm:^16.7.0": +"react-is@npm:^16.13.1, react-is@npm:^16.3.2, react-is@npm:^16.7.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f @@ -19023,6 +19342,13 @@ __metadata: languageName: node linkType: hard +"react-lifecycles-compat@npm:^3.0.4": + version: 3.0.4 + resolution: "react-lifecycles-compat@npm:3.0.4" + checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f + languageName: node + linkType: hard + "react-markdown@npm:^6.0.3": version: 6.0.3 resolution: "react-markdown@npm:6.0.3" @@ -19175,6 +19501,21 @@ __metadata: languageName: node linkType: hard +"react-transition-group@npm:^4.4.5": + version: 4.4.5 + resolution: "react-transition-group@npm:4.4.5" + dependencies: + "@babel/runtime": ^7.5.5 + dom-helpers: ^5.0.1 + loose-envify: ^1.4.0 + prop-types: ^15.6.2 + peerDependencies: + react: ">=16.6.0" + react-dom: ">=16.6.0" + checksum: 75602840106aa9c6545149d6d7ae1502fb7b7abadcce70a6954c4b64a438ff1cd16fc77a0a1e5197cdd72da398f39eb929ea06f9005c45b132ed34e056ebdeb1 + languageName: node + linkType: hard + "react-use-measure@npm:^2.1.1": version: 2.1.1 resolution: "react-use-measure@npm:2.1.1" @@ -19872,12 +20213,12 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.5.5, rxjs@npm:^7.8.0": - version: 7.8.0 - resolution: "rxjs@npm:7.8.0" +"rxjs@npm:^7.5.5, rxjs@npm:^7.8.0, rxjs@npm:^7.8.1": + version: 7.8.1 + resolution: "rxjs@npm:7.8.1" dependencies: tslib: ^2.1.0 - checksum: 61b4d4fd323c1043d8d6ceb91f24183b28bcf5def4f01ca111511d5c6b66755bc5578587fe714ef5d67cf4c9f2e26f4490d4e1d8cabf9bd5967687835e9866a2 + checksum: de4b53db1063e618ec2eca0f7965d9137cabe98cf6be9272efe6c86b47c17b987383df8574861bcced18ebd590764125a901d5506082be84a8b8e364bf05f119 languageName: node linkType: hard @@ -19987,6 +20328,13 @@ __metadata: languageName: node linkType: hard +"secure-compare@npm:3.0.1": + version: 3.0.1 + resolution: "secure-compare@npm:3.0.1" + checksum: 0a8d8d3e54d5772d2cf1c02325f01fc7366d0bd33f964a08a84fe3ee5f34d46435a6ae729c1d239c750e160ef9b58c764d3efb945a1d07faf47978a8e4161594 + languageName: node + linkType: hard + "select-hose@npm:^2.0.0": version: 2.0.0 resolution: "select-hose@npm:2.0.0" @@ -20274,7 +20622,7 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.3": +"shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.3, shell-quote@npm:^1.8.1": version: 1.8.1 resolution: "shell-quote@npm:1.8.1" checksum: 5f01201f4ef504d4c6a9d0d283fa17075f6770bfbe4c5850b074974c68062f37929ca61700d95ad2ac8822e14e8c4b990ca0e6e9272e64befd74ce5e19f0736b @@ -20342,6 +20690,13 @@ __metadata: languageName: node linkType: hard +"simplex-noise@npm:^4.0.0": + version: 4.0.1 + resolution: "simplex-noise@npm:4.0.1" + checksum: b5458713337129016ae71182e20d2e2e0d01bb62c78cf180276dafe8a59bf1814a66aedd0dfc9bbb70cc549a9bc02f1c9773e4f222a2cff4692cd48e7a2b348b + languageName: node + linkType: hard + "sisteransi@npm:^1.0.5": version: 1.0.5 resolution: "sisteransi@npm:1.0.5" @@ -20551,6 +20906,13 @@ __metadata: languageName: node linkType: hard +"spawn-command@npm:0.0.2": + version: 0.0.2 + resolution: "spawn-command@npm:0.0.2" + checksum: e35c5d28177b4d461d33c88cc11f6f3a5079e2b132c11e1746453bbb7a0c0b8a634f07541a2a234fa4758239d88203b758def509161b651e81958894c0b4b64b + languageName: node + linkType: hard + "spdx-correct@npm:^3.0.0": version: 3.1.1 resolution: "spdx-correct@npm:3.1.1" @@ -21035,7 +21397,7 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:8.1.1, supports-color@npm:^8.0.0": +"supports-color@npm:8.1.1, supports-color@npm:^8.0.0, supports-color@npm:^8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1" dependencies: @@ -21392,6 +21754,15 @@ __metadata: languageName: node linkType: hard +"tree-kill@npm:^1.2.2": + version: 1.2.2 + resolution: "tree-kill@npm:1.2.2" + bin: + tree-kill: cli.js + checksum: 49117f5f410d19c84b0464d29afb9642c863bc5ba40fcb9a245d474c6d5cc64d1b177a6e6713129eb346b40aebb9d4631d967517f9fbe8251c35b21b13cd96c7 + languageName: node + linkType: hard + "trim-repeated@npm:^2.0.0": version: 2.0.0 resolution: "trim-repeated@npm:2.0.0" @@ -21741,6 +22112,29 @@ __metadata: languageName: node linkType: hard +"uncontrollable@npm:^7.2.1": + version: 7.2.1 + resolution: "uncontrollable@npm:7.2.1" + dependencies: + "@babel/runtime": ^7.6.3 + "@types/react": ">=16.9.11" + invariant: ^2.2.4 + react-lifecycles-compat: ^3.0.4 + peerDependencies: + react: ">=15.0.0" + checksum: 3345c0c1916193ddb9cc6f2b78711dc9f22b919d780485e15b95690722e9d1797fc702c4ebb30c0acaae6a772b865d0a9ddc83fa1da44958f089aee78f2f5eab + languageName: node + linkType: hard + +"uncontrollable@npm:^8.0.1": + version: 8.0.2 + resolution: "uncontrollable@npm:8.0.2" + peerDependencies: + react: ">=16.14.0" + checksum: d6097c78467234a2e7f69e7845d0439cfba365cd0d8c401517eb066807401f7355d5812ebf146bb5f364fa7d3404efc01fc4bd7cc0b9aae02ab194e311da1c5b + languageName: node + linkType: hard + "undeclared-identifiers@npm:^1.1.2": version: 1.1.3 resolution: "undeclared-identifiers@npm:1.1.3" @@ -21801,6 +22195,15 @@ __metadata: languageName: node linkType: hard +"union@npm:~0.5.0": + version: 0.5.0 + resolution: "union@npm:0.5.0" + dependencies: + qs: ^6.4.0 + checksum: 021530d02363fb7470ce45d4cb06ae28a97d5a245666e6d0fca6bab0673bea8c7988e7d2f8046acfbab120908cedcb099ca216b357d4483bcd96518b39101be0 + languageName: node + linkType: hard + "unique-filename@npm:^1.1.1": version: 1.1.1 resolution: "unique-filename@npm:1.1.1" @@ -21921,6 +22324,13 @@ __metadata: languageName: node linkType: hard +"url-join@npm:^4.0.1": + version: 4.0.1 + resolution: "url-join@npm:4.0.1" + checksum: f74e868bf25dbc8be6a8d7237d4c36bb5b6c62c72e594d5ab1347fe91d6af7ccd9eb5d621e30152e4da45c2e9a26bec21390e911ab54a62d4d82e76028374ee5 + languageName: node + linkType: hard + "url-parse@npm:^1.5.3": version: 1.5.10 resolution: "url-parse@npm:1.5.10" @@ -22224,6 +22634,15 @@ __metadata: languageName: node linkType: hard +"warning@npm:^4.0.0, warning@npm:^4.0.3": + version: 4.0.3 + resolution: "warning@npm:4.0.3" + dependencies: + loose-envify: ^1.0.0 + checksum: 4f2cb6a9575e4faf71ddad9ad1ae7a00d0a75d24521c193fa464f30e6b04027bd97aa5d9546b0e13d3a150ab402eda216d59c1d0f2d6ca60124d96cd40dfa35c + languageName: node + linkType: hard + "watchpack@npm:^2.4.0": version: 2.4.0 resolution: "watchpack@npm:2.4.0"